diff --git a/docs/modules/vault.md b/docs/modules/vault.md index 4a232361464..e32abfd1c60 100644 --- a/docs/modules/vault.md +++ b/docs/modules/vault.md @@ -4,31 +4,31 @@ Testcontainers module for [Vault](https://github.com/hashicorp/vault). Vault is ## Usage example -Running Vault in your Junit tests is easily done with an @Rule or @ClassRule such as the following: - -```java -public class SomeTest { - - @ClassRule - public static VaultContainer vaultContainer = new VaultContainer<>() - .withVaultToken("my-root-token") - .withVaultPort(8200) - .withSecretInVault("secret/testing", "top_secret=password1","db_password=dbpassword1"); - - @Test - public void someTestMethod() { - //interact with Vault via the container's host, port and Vault token. - - //There are many integration clients for Vault so let's just define a general one here: - VaultClient client = new VaultClient( - vaultContainer.getHost(), - vaultContainer.getMappedPort(8200), - "my-root-token"); - - List secrets = client.readSecret("secret/testing"); - - } -``` +Start Vault container as a `@ClassRule`: + + +[Starting a Vault container](../../modules/vault/src/test/java/org/testcontainers/vault/VaultContainerTest.java) inside_block:vaultContainer + + +Use CLI to read data from Vault container: + + +[Use CLI to read data](../../modules/vault/src/test/java/org/testcontainers/vault/VaultContainerTest.java) inside_block:readFirstSecretPathWithCli + + +Use Http API to read data from Vault container: + + +[Use Http API to read data](../../modules/vault/src/test/java/org/testcontainers/vault/VaultContainerTest.java) inside_block:readFirstSecretPathOverHttpApi + + +Use client library to read data from Vault container: + + +[Use library to read data](../../modules/vault/src/test/java/org/testcontainers/vault/VaultContainerTest.java) inside_block:readWithLibrary + + +[See full example.](https://github.com/testcontainers/testcontainers-java/blob/master/modules/vault/src/test/java/org/testcontainers/vault/VaultContainerTest.java) ## Why Vault in Junit tests? diff --git a/modules/vault/src/main/java/org/testcontainers/vault/VaultContainer.java b/modules/vault/src/main/java/org/testcontainers/vault/VaultContainer.java index 31bb1f31d9f..4c44668d565 100644 --- a/modules/vault/src/main/java/org/testcontainers/vault/VaultContainer.java +++ b/modules/vault/src/main/java/org/testcontainers/vault/VaultContainer.java @@ -60,6 +60,10 @@ public VaultContainer(final DockerImageName dockerImageName) { withExposedPorts(port); } + public String getHttpHostAddress() { + return String.format("http://%s:%s", getHost(), getMappedPort(port)); + } + @Override protected void containerIsStarted(InspectContainerResponse containerInfo) { addSecrets(); @@ -182,8 +186,8 @@ public SELF withSecretInVault(String path, String firstSecret, String... remaini /** * Run initialization commands using the vault cli. - * - * Useful for enableing more secret engines like: + *

+ * Useful for enabling more secret engines like: *

      *     .withInitCommand("secrets enable pki")
      *     .withInitCommand("secrets enable transit")
diff --git a/modules/vault/src/test/java/org/testcontainers/vault/VaultClientTest.java b/modules/vault/src/test/java/org/testcontainers/vault/VaultClientTest.java
index cd1f1a8acea..eebf73a5e62 100644
--- a/modules/vault/src/test/java/org/testcontainers/vault/VaultClientTest.java
+++ b/modules/vault/src/test/java/org/testcontainers/vault/VaultClientTest.java
@@ -17,10 +17,7 @@ public class VaultClientTest {
 
     @Test
     public void writeAndReadMultipleValues() throws VaultException {
-        try (
-            VaultContainer vaultContainer = new VaultContainer<>(VaultTestImages.VAULT_IMAGE)
-                .withVaultToken(VAULT_TOKEN)
-        ) {
+        try (VaultContainer vaultContainer = new VaultContainer<>("vault:1.1.3").withVaultToken(VAULT_TOKEN)) {
             vaultContainer.start();
 
             final VaultConfig config = new VaultConfig()
diff --git a/modules/vault/src/test/java/org/testcontainers/vault/VaultContainerTest.java b/modules/vault/src/test/java/org/testcontainers/vault/VaultContainerTest.java
index f7a7cd49eaf..608d8bbb8a7 100644
--- a/modules/vault/src/test/java/org/testcontainers/vault/VaultContainerTest.java
+++ b/modules/vault/src/test/java/org/testcontainers/vault/VaultContainerTest.java
@@ -1,25 +1,30 @@
 package org.testcontainers.vault;
 
+import com.bettercloud.vault.Vault;
+import com.bettercloud.vault.VaultConfig;
+import com.bettercloud.vault.response.LogicalResponse;
 import io.restassured.response.Response;
 import org.junit.ClassRule;
 import org.junit.Test;
 import org.testcontainers.containers.GenericContainer;
 
-import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
 
 import static io.restassured.RestAssured.given;
 import static org.assertj.core.api.Assertions.assertThat;
 
 /**
  * This test shows the pattern to use the VaultContainer @ClassRule for a junit test. It also has tests that ensure
- * the secrets were added correctly by reading from Vault with the CLI and over HTTP.
+ * the secrets were added correctly by reading from Vault with the CLI, over HTTP and over Client Library.
  */
 public class VaultContainerTest {
 
     private static final String VAULT_TOKEN = "my-root-token";
 
     @ClassRule
-    public static VaultContainer vaultContainer = new VaultContainer<>(VaultTestImages.VAULT_IMAGE)
+    // vaultContainer {
+    public static VaultContainer vaultContainer = new VaultContainer<>("vault:1.6.1")
         .withVaultToken(VAULT_TOKEN)
         .withSecretInVault("secret/testing1", "top_secret=password123")
         .withSecretInVault(
@@ -32,8 +37,10 @@ public class VaultContainerTest {
         )
         .withInitCommand("secrets enable transit", "write -f transit/keys/my-key");
 
+    // }
+
     @Test
-    public void readFirstSecretPathWithCli() throws IOException, InterruptedException {
+    public void readFirstSecretPathWithCli() throws Exception {
         GenericContainer.ExecResult result = vaultContainer.execInContainer(
             "vault",
             "kv",
@@ -41,12 +48,11 @@ public void readFirstSecretPathWithCli() throws IOException, InterruptedExceptio
             "-format=json",
             "secret/testing1"
         );
-        final String output = result.getStdout().replaceAll("\\r?\\n", "");
-        assertThat(output).contains("password123");
+        assertThat(result.getStdout()).contains("password123");
     }
 
     @Test
-    public void readSecondSecretPathWithCli() throws IOException, InterruptedException {
+    public void readSecondSecretPathWithCli() throws Exception {
         GenericContainer.ExecResult result = vaultContainer.execInContainer(
             "vault",
             "kv",
@@ -54,6 +60,7 @@ public void readSecondSecretPathWithCli() throws IOException, InterruptedExcepti
             "-format=json",
             "secret/testing2"
         );
+
         final String output = result.getStdout().replaceAll("\\r?\\n", "");
         System.out.println("output = " + output);
         assertThat(output).contains("password1");
@@ -63,11 +70,11 @@ public void readSecondSecretPathWithCli() throws IOException, InterruptedExcepti
     }
 
     @Test
-    public void readFirstSecretPathOverHttpApi() throws InterruptedException {
+    public void readFirstSecretPathOverHttpApi() {
         Response response = given()
             .header("X-Vault-Token", VAULT_TOKEN)
             .when()
-            .get("http://" + getHostAndPort() + "/v1/secret/data/testing1")
+            .get(vaultContainer.getHttpHostAddress() + "/v1/secret/data/testing1")
             .thenReturn();
         assertThat(response.body().jsonPath().getString("data.data.top_secret")).isEqualTo("password123");
     }
@@ -77,7 +84,7 @@ public void readSecondSecretPathOverHttpApi() throws InterruptedException {
         Response response = given()
             .header("X-Vault-Token", VAULT_TOKEN)
             .when()
-            .get("http://" + getHostAndPort() + "/v1/secret/data/testing2")
+            .get(vaultContainer.getHttpHostAddress() + "/v1/secret/data/testing2")
             .andReturn();
 
         assertThat(response.body().jsonPath().getString("data.data.secret_one")).contains("password1");
@@ -91,13 +98,67 @@ public void readTransitKeyOverHttpApi() throws InterruptedException {
         Response response = given()
             .header("X-Vault-Token", VAULT_TOKEN)
             .when()
-            .get("http://" + getHostAndPort() + "/v1/transit/keys/my-key")
+            .get(vaultContainer.getHttpHostAddress() + "/v1/transit/keys/my-key")
             .thenReturn();
 
         assertThat(response.body().jsonPath().getString("data.name")).isEqualTo("my-key");
     }
 
-    private String getHostAndPort() {
-        return vaultContainer.getHost() + ":" + vaultContainer.getMappedPort(8200);
+    @Test
+    // readWithLibrary {
+    public void readFirstSecretPathOverClientLibrary() throws Exception {
+        final VaultConfig config = new VaultConfig()
+            .address(vaultContainer.getHttpHostAddress())
+            .token(VAULT_TOKEN)
+            .build();
+
+        final Vault vault = new Vault(config);
+
+        final Map value = vault.logical().read("secret/testing1").getData();
+
+        assertThat(value).containsEntry("top_secret", "password123");
+    }
+
+    // }
+
+    @Test
+    public void readSecondSecretPathOverClientLibrary() throws Exception {
+        final VaultConfig config = new VaultConfig()
+            .address(vaultContainer.getHttpHostAddress())
+            .token(VAULT_TOKEN)
+            .build();
+
+        final Vault vault = new Vault(config);
+        final Map value = vault.logical().read("secret/testing2").getData();
+
+        assertThat(value)
+            .containsEntry("secret_one", "password1")
+            .containsEntry("secret_two", "password2")
+            .containsEntry("secret_three", "[\"password3\",\"password3\"]")
+            .containsEntry("secret_four", "password4");
+    }
+
+    @Test
+    public void writeSecretOverClientLibrary() throws Exception {
+        final VaultConfig config = new VaultConfig()
+            .address(vaultContainer.getHttpHostAddress())
+            .token(VAULT_TOKEN)
+            .build();
+
+        final Vault vault = new Vault(config);
+
+        final Map secrets = new HashMap<>();
+        secrets.put("value", "world");
+        secrets.put("other_value", "another world");
+
+        // Write operation
+        final LogicalResponse writeResponse = vault.logical().write("secret/hello", secrets);
+
+        assertThat(writeResponse.getRestResponse().getStatus()).isEqualTo(200);
+
+        // Read operation
+        final Map value = vault.logical().read("secret/hello").getData();
+
+        assertThat(value).containsEntry("value", "world").containsEntry("other_value", "another world");
     }
 }
diff --git a/modules/vault/src/test/java/org/testcontainers/vault/VaultTestImages.java b/modules/vault/src/test/java/org/testcontainers/vault/VaultTestImages.java
deleted file mode 100644
index 9afecdcffb9..00000000000
--- a/modules/vault/src/test/java/org/testcontainers/vault/VaultTestImages.java
+++ /dev/null
@@ -1,7 +0,0 @@
-package org.testcontainers.vault;
-
-import org.testcontainers.utility.DockerImageName;
-
-public interface VaultTestImages {
-    DockerImageName VAULT_IMAGE = DockerImageName.parse("vault:1.1.3");
-}