diff --git a/DEV_GUIDE.md b/DEV_GUIDE.md
index df8299aa3b..6324b0d388 100644
--- a/DEV_GUIDE.md
+++ b/DEV_GUIDE.md
@@ -337,6 +337,7 @@ has been applied ineffectively.
* `SKIP_TEARDOWN`: variable for development purposes to avoid keep deploying and deleting deployments each run. Default value: `false`
* `CONTAINER_CONFIG_PATH`: directory where `config.json` file is located. This file contains the pull secrets to be used by
the container engine. Default value: `$HOME/.docker/config.json`
+* `VAULT_CHART_VERSION`: version of Vault Helm Chart to be used by the System Tests for Envelope Encryption. Default value: `0.27.0`
* `SKIP_STRIMZI_INSTALL`: skip strimzi installation. Default value: `false`
diff --git a/kroxylicious-kms-provider-hashicorp-vault-test-support/src/main/java/io/kroxylicious/kms/provider/hashicorp/vault/VaultTestKmsFacade.java b/kroxylicious-kms-provider-hashicorp-vault-test-support/src/main/java/io/kroxylicious/kms/provider/hashicorp/vault/VaultTestKmsFacade.java
index 1c0b7d6df6..e629fc5aa9 100644
--- a/kroxylicious-kms-provider-hashicorp-vault-test-support/src/main/java/io/kroxylicious/kms/provider/hashicorp/vault/VaultTestKmsFacade.java
+++ b/kroxylicious-kms-provider-hashicorp-vault-test-support/src/main/java/io/kroxylicious/kms/provider/hashicorp/vault/VaultTestKmsFacade.java
@@ -20,6 +20,7 @@
import java.util.function.Supplier;
import org.testcontainers.DockerClientFactory;
+import org.testcontainers.utility.DockerImageName;
import org.testcontainers.vault.VaultContainer;
import com.fasterxml.jackson.core.JsonProcessingException;
@@ -36,7 +37,7 @@
import static java.nio.charset.StandardCharsets.UTF_8;
public class VaultTestKmsFacade extends AbstractVaultTestKmsFacade {
- private static final String HASHICORP_VAULT = "hashicorp/vault:1.15";
+ public static final DockerImageName HASHICORP_VAULT = DockerImageName.parse("hashicorp/vault:1.15");
private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
private final HttpClient vaultClient = HttpClient.newHttpClient();
diff --git a/kroxylicious-systemtests/pom.xml b/kroxylicious-systemtests/pom.xml
index e18362dafb..e38e2b3477 100644
--- a/kroxylicious-systemtests/pom.xml
+++ b/kroxylicious-systemtests/pom.xml
@@ -122,6 +122,10 @@
io.kroxylicious
kroxylicious-kms-provider-hashicorp-vault-test-support
+
+ org.testcontainers
+ testcontainers
+
diff --git a/kroxylicious-systemtests/src/main/java/io/kroxylicious/systemtests/Environment.java b/kroxylicious-systemtests/src/main/java/io/kroxylicious/systemtests/Environment.java
index 298760cd83..4086083e84 100644
--- a/kroxylicious-systemtests/src/main/java/io/kroxylicious/systemtests/Environment.java
+++ b/kroxylicious-systemtests/src/main/java/io/kroxylicious/systemtests/Environment.java
@@ -30,6 +30,7 @@ private Environment() {
private static final String SKIP_TEARDOWN_ENV = "SKIP_TEARDOWN";
public static final String STRIMZI_FEATURE_GATES_ENV = "STRIMZI_FEATURE_GATES";
private static final String CONTAINER_CONFIG_PATH_ENV = "CONTAINER_CONFIG_PATH";
+ private static final String VAULT_CHART_VERSION_ENV = "VAULT_CHART_VERSION";
private static final String SKIP_STRIMZI_INSTALL_ENV = "SKIP_STRIMZI_INSTALL";
/**
@@ -65,6 +66,7 @@ private Environment() {
private static final String SKIP_TEARDOWN_DEFAULT = "false";
private static final String STRIMZI_FEATURE_GATES_DEFAULT = "";
private static final String CONTAINER_CONFIG_PATH_DEFAULT = System.getProperty("user.home") + "/.docker/config.json";
+ private static final String VAULT_CHART_VERSION_DEFAULT = "0.27.0";
private static final String SKIP_STRIMZI_INSTALL_DEFAULT = "false";
/**
@@ -95,6 +97,8 @@ private Environment() {
public static final boolean SKIP_STRIMZI_INSTALL = Boolean.parseBoolean(getOrDefault(SKIP_STRIMZI_INSTALL_ENV, SKIP_STRIMZI_INSTALL_DEFAULT));
+ public static final String VAULT_CHART_VERSION = getOrDefault(VAULT_CHART_VERSION_ENV, VAULT_CHART_VERSION_DEFAULT);
+
private static String getOrDefault(String varName, String defaultValue) {
return getOrDefault(varName, String::toString, defaultValue);
}
diff --git a/kroxylicious-systemtests/src/main/java/io/kroxylicious/systemtests/installation/vault/Vault.java b/kroxylicious-systemtests/src/main/java/io/kroxylicious/systemtests/installation/vault/Vault.java
index fa6e602cf4..6df46813a9 100644
--- a/kroxylicious-systemtests/src/main/java/io/kroxylicious/systemtests/installation/vault/Vault.java
+++ b/kroxylicious-systemtests/src/main/java/io/kroxylicious/systemtests/installation/vault/Vault.java
@@ -20,6 +20,7 @@
import io.fabric8.kubernetes.api.model.ServicePort;
+import io.kroxylicious.systemtests.Environment;
import io.kroxylicious.systemtests.k8s.exception.KubeClusterException;
import io.kroxylicious.systemtests.resources.manager.ResourceManager;
import io.kroxylicious.systemtests.utils.DeploymentUtils;
@@ -88,6 +89,36 @@ public boolean isAvailable() {
}
}
+ /**
+ * Gets the installed version.
+ *
+ * @return the version
+ */
+ public String getVersionInstalled() {
+ try (var output = new ByteArrayOutputStream();
+ var error = new ByteArrayOutputStream();
+ var exec = kubeClient().getClient().pods()
+ .inNamespace(deploymentNamespace)
+ .withName(VAULT_POD_NAME)
+ .writingOutput(output)
+ .writingError(error)
+ .exec("sh", "-c", VAULT_CMD + " version")) {
+ int exitCode = exec.exitCode().join();
+ if (exitCode != 0) {
+ throw new UnsupportedOperationException(error.toString());
+ }
+ // version returned with format: Vault v1.15.2 (blah blah), build blah
+ String version = output.toString().split("\\s+")[1].replace("v", "");
+ if (!version.matches("^(\\d+)(?:\\.(\\d+))?(?:\\.(\\*|\\d+))?$")) {
+ throw new NumberFormatException("Invalid version format: " + version);
+ }
+ return version;
+ }
+ catch (IOException e) {
+ throw new UncheckedIOException(e);
+ }
+ }
+
/**
* Deploy.
*
@@ -100,7 +131,8 @@ public void deploy() {
}
ResourceManager.helmClient().addRepository(VAULT_HELM_REPOSITORY_NAME, VAULT_HELM_REPOSITORY_URL);
- ResourceManager.helmClient().namespace(deploymentNamespace).install(VAULT_HELM_CHART_NAME, VAULT_SERVICE_NAME, Optional.empty(),
+ ResourceManager.helmClient().namespace(deploymentNamespace).install(VAULT_HELM_CHART_NAME, VAULT_SERVICE_NAME,
+ Optional.of(Environment.VAULT_CHART_VERSION),
Optional.of(getHelmOverridePath()),
Optional.of(Map.of("server.dev.devRootToken", vaultRootToken)));
diff --git a/kroxylicious-systemtests/src/main/java/io/kroxylicious/systemtests/k8s/HelmClient.java b/kroxylicious-systemtests/src/main/java/io/kroxylicious/systemtests/k8s/HelmClient.java
index bd7a043009..f97ccf759d 100644
--- a/kroxylicious-systemtests/src/main/java/io/kroxylicious/systemtests/k8s/HelmClient.java
+++ b/kroxylicious-systemtests/src/main/java/io/kroxylicious/systemtests/k8s/HelmClient.java
@@ -35,6 +35,9 @@ public class HelmClient {
private static String helmCommand;
private Optional namespace = Optional.empty();
+ /**
+ * Instantiates a new Helm client.
+ */
public HelmClient() {
if (!clientAvailable()) {
throw new KubeClusterException.NotFound("No helm client found on $PATH. $PATH=" + System.getenv("PATH"));
diff --git a/kroxylicious-systemtests/src/main/java/io/kroxylicious/systemtests/resources/vault/KubeVaultTestKmsFacade.java b/kroxylicious-systemtests/src/main/java/io/kroxylicious/systemtests/resources/vault/KubeVaultTestKmsFacade.java
index da2cf9ec01..a63873da71 100644
--- a/kroxylicious-systemtests/src/main/java/io/kroxylicious/systemtests/resources/vault/KubeVaultTestKmsFacade.java
+++ b/kroxylicious-systemtests/src/main/java/io/kroxylicious/systemtests/resources/vault/KubeVaultTestKmsFacade.java
@@ -21,6 +21,7 @@
import com.fasterxml.jackson.databind.ObjectMapper;
import io.kroxylicious.kms.provider.hashicorp.vault.AbstractVaultTestKmsFacade;
+import io.kroxylicious.kms.provider.hashicorp.vault.VaultTestKmsFacade;
import io.kroxylicious.kms.service.TestKekManager;
import io.kroxylicious.kms.service.UnknownAliasException;
import io.kroxylicious.systemtests.executor.ExecResult;
@@ -49,6 +50,12 @@ public class KubeVaultTestKmsFacade extends AbstractVaultTestKmsFacade {
private final String podName;
private final Vault vault;
+ /**
+ * Instantiates a new Kube vault test kms facade.
+ *
+ * @param namespace the namespace
+ * @param podName the pod name
+ */
public KubeVaultTestKmsFacade(String namespace, String podName) {
this.namespace = namespace;
this.podName = podName;
@@ -63,6 +70,10 @@ public boolean isAvailable() {
@Override
public void startVault() {
vault.deploy();
+ if (!isCorrectVersionInstalled()) {
+ throw new KubeClusterException("Vault version installed " + getVaultVersion() + " does not match with the expected: '"
+ + VaultTestKmsFacade.HASHICORP_VAULT + "'");
+ }
runVaultCommand(VAULT_CMD, LOGIN, VAULT_ROOT_TOKEN);
}
@@ -126,11 +137,44 @@ protected URI getVaultUrl() {
return URI.create("http://" + vault.getVaultUrl());
}
+ /**
+ * Gets vault version.
+ *
+ * @return the vault version
+ */
+ public String getVaultVersion() {
+ return vault.getVersionInstalled();
+ }
+
@Override
public TestKekManager getTestKekManager() {
return new VaultTestKekManager();
}
+ private boolean isCorrectVersionInstalled() {
+ String installedVersion = getVaultVersion();
+ String expectedVersion = VaultTestKmsFacade.HASHICORP_VAULT.getVersionPart();
+
+ return compareVersions(installedVersion, expectedVersion) == 0;
+ }
+
+ private int compareVersions(String currentVersion, String expectedVersion) {
+ Objects.requireNonNull(expectedVersion);
+
+ String[] currentParts = currentVersion.split("\\.");
+ String[] expectedParts = expectedVersion.split("\\.");
+
+ for (int i = 0; i < expectedParts.length; i++) {
+ int currentPart = i < currentParts.length ? Integer.parseInt(currentParts[i]) : 0;
+ int expectedPart = Integer.parseInt(expectedParts[i]);
+ int comparison = Integer.compare(currentPart, expectedPart);
+ if (comparison != 0) {
+ return comparison;
+ }
+ }
+ return 0;
+ }
+
private class VaultTestKekManager implements TestKekManager {
public void generateKek(String alias) {
@@ -202,5 +246,4 @@ private ExecResult runVaultCommand(String... command) {
}
return execResult;
}
-
}