Add options to VaultMount.

Original pull request: gh-435.
Closes gh-433.
This commit is contained in:
Maciej Drozdzowski
2019-06-12 10:11:06 +10:00
committed by Mark Paluch
parent 7460d5058b
commit fbe69bfb7c
3 changed files with 117 additions and 5 deletions

View File

@@ -152,6 +152,11 @@ public class VaultVersionedKeyValueTemplate extends VaultKeyValue2Accessor imple
VaultResponse response = doWrite(createDataPath(path), data);
if (response == null) {
throw new IllegalStateException(
"VaultVersionedKeyValueOperations cannot be used with a kv version 1 mount");
}
return getMetadata(response.getRequiredData());
}

View File

@@ -50,13 +50,20 @@ public class VaultMount {
*/
private final Map<String, Object> config;
/**
* Mount type specific options.
*/
private final Map<String, String> options;
VaultMount(@JsonProperty("type") String type,
@Nullable @JsonProperty("description") String description,
@Nullable @JsonProperty("config") Map<String, Object> config) {
@Nullable @JsonProperty("config") Map<String, Object> config,
@Nullable @JsonProperty("options") Map<String, String> options) {
this.type = type;
this.description = description;
this.config = config != null ? config : Collections.emptyMap();
this.options = options != null ? options : Collections.emptyMap();
}
/**
@@ -99,6 +106,16 @@ public class VaultMount {
return config;
}
/**
* @return mount type specific options.
*
* @since 2.2
*/
@Nullable
public Map<String, String> getOptions() {
return options;
}
/**
* Builder to build a {@link VaultMount}.
*/
@@ -112,6 +129,8 @@ public class VaultMount {
private Map<String, Object> config = Collections.emptyMap();
private Map<String, String> options = Collections.emptyMap();
VaultMountBuilder() {
}
@@ -155,6 +174,22 @@ public class VaultMount {
return this;
}
/**
* Set mount type specific options for this mount.
*
* @param options mount type specific options for this mount.
* @return {@literal this} {@link VaultMountBuilder}.
*
* @since 2.2
*/
public VaultMountBuilder options(Map<String, String> options) {
Assert.notNull(options, "Options map must not be null");
this.options = options;
return this;
}
/**
* Build a new {@link VaultMount} instance. Requires {@link #type(String)} to be
* configured.
@@ -166,7 +201,7 @@ public class VaultMount {
Assert.notNull(type, "Type must not be null");
Assert.hasText(type, "Type must not be empty or null");
return new VaultMount(type, description, config);
return new VaultMount(type, description, config, options);
}
}
}

View File

@@ -30,12 +30,14 @@ import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.vault.support.Policy;
import org.springframework.vault.support.VaultMount;
import org.springframework.vault.support.VaultResponse;
import org.springframework.vault.support.VaultUnsealStatus;
import org.springframework.vault.support.Policy.Rule;
import org.springframework.vault.util.IntegrationTestSupport;
import org.springframework.vault.util.VaultRule;
import org.springframework.vault.util.Version;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.*;
import static org.junit.Assume.assumeTrue;
import static org.springframework.vault.support.Policy.BuiltinCapabilities.READ;
import static org.springframework.vault.support.Policy.BuiltinCapabilities.UPDATE;
@@ -82,8 +84,8 @@ public class VaultSysTemplateIntegrationTests extends IntegrationTestSupport {
adminOperations.unmount("other");
}
VaultMount mount = VaultMount.builder().type("generic") //
.config(Collections.singletonMap("default_lease_ttl", (Object) "1h")) //
VaultMount mount = VaultMount.builder().type("generic")
.config(Collections.singletonMap("default_lease_ttl", "1h"))
.description("hello, world").build();
adminOperations.mount("other", mount);
@@ -98,6 +100,76 @@ public class VaultSysTemplateIntegrationTests extends IntegrationTestSupport {
assertThat(Arrays.asList("kv", "generic")).contains(secret.getType());
}
@Test
public void mountShouldMountKv1Secret() {
assumeTrue(vaultVersion.isGreaterThanOrEqualTo(
VaultRule.VERSIONING_INTRODUCED_WITH));
if (adminOperations.getMounts().containsKey("kVv1/")) {
adminOperations.unmount("kVv1");
}
VaultMount mount = VaultMount.builder().type("kv")
.config(Collections.singletonMap("default_lease_ttl", "1h"))
.description("hello, world").build();
adminOperations.mount("kVv1", mount);
Map<String, VaultMount> mounts = adminOperations.getMounts();
assertThat(mounts).containsKey("kVv1/");
VaultMount kVv1 = mounts.get("kVv1/");
assertThat(kVv1.getDescription()).isEqualTo(mount.getDescription());
assertThat(kVv1.getConfig()).containsEntry("default_lease_ttl", 3600);
assertThat(kVv1.getType()).isEqualTo("kv");
// a versioned write (kv put) will fail for a kv (default version: 1, not versioned) store
// make sure regular VaultTemplate.write/read operations work
vaultOperations.write("secret/mykey", Collections.singletonMap("hello", "world"));
VaultResponse read = vaultOperations.read("secret/mykey");
assertThat(read).isNotNull();
assertThat(read.getData()).containsEntry("hello", "world");
}
@Test
public void mountShouldMountKv2Secret() {
assumeTrue(vaultVersion.isGreaterThanOrEqualTo(
VaultRule.VERSIONING_INTRODUCED_WITH));
if (adminOperations.getMounts().containsKey("kVv2/")) {
adminOperations.unmount("kVv2");
}
VaultMount mount = VaultMount.builder().type("kv")
.config(Collections.singletonMap("default_lease_ttl", "1h"))
.options(Collections.singletonMap("version", "2"))
.description("hello, world").build();
adminOperations.mount("kVv2", mount);
Map<String, VaultMount> mounts = adminOperations.getMounts();
assertThat(mounts).containsKey("kVv2/");
VaultMount kVv2 = mounts.get("kVv2/");
assertThat(kVv2.getDescription()).isEqualTo(mount.getDescription());
assertThat(kVv2.getConfig()).containsEntry("default_lease_ttl", 3600);
assertThat(kVv2.getType()).isEqualTo("kv");
assertThat(kVv2.getOptions()).containsEntry("version", "2");
VaultVersionedKeyValueOperations versionedOperations =
vaultOperations.opsForVersionedKeyValue("kVv2");
versionedOperations.put("secret/mykey", Collections.singletonMap("key", "value"));
assertThat(versionedOperations.get("secret/mykey").getData())
.containsEntry("key", "value");
}
@Test
public void getAuthMountsShouldContainSecretBackend() {