Add support for key prefixes in vault paths.
See gh-488 Original pull request: gh-582.
This commit is contained in:
committed by
Mark Paluch
parent
d4de4b6416
commit
6505bde94d
@@ -50,6 +50,19 @@ Optional locations are skipped during application startup if Vault support was d
|
||||
|
||||
NOTE: Vault context paths that cannot be found (HTTP Status 404) are skipped regardless of whether the config location is marked optional. <<vault.config.fail-fast>> allows failing on start if a Vault context path cannot be found because of HTTP Status 404.
|
||||
|
||||
If you have the same secret names in different paths, you can distinguish them by using a prefix on the path.
|
||||
|
||||
.application.yml
|
||||
====
|
||||
[source,yaml]
|
||||
----
|
||||
spring.config.import: vault://my/prefixed/path?prefix=prefix1, vault://my/other/path?prefix=prefix2
|
||||
secret: ${prefix1.secret}
|
||||
other.secret: ${prefix2.secret}
|
||||
----
|
||||
|
||||
====
|
||||
|
||||
[[vault.configdata.customization]]
|
||||
=== Infrastructure Customization
|
||||
|
||||
|
||||
@@ -37,6 +37,11 @@ import org.springframework.core.annotation.MergedAnnotations;
|
||||
import org.springframework.core.io.support.SpringFactoriesLoader;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.vault.core.util.PropertyTransformer;
|
||||
import org.springframework.vault.core.util.PropertyTransformers;
|
||||
import org.springframework.web.util.UriComponents;
|
||||
import org.springframework.web.util.UriComponentsBuilder;
|
||||
|
||||
/**
|
||||
* {@link ConfigDataLocationResolver} for Vault resolving {@link VaultConfigLocation}
|
||||
@@ -113,7 +118,17 @@ public class VaultConfigDataLocationResolver implements ConfigDataLocationResolv
|
||||
contextPath = contextPath.substring(1);
|
||||
}
|
||||
|
||||
return Collections.singletonList(new VaultConfigLocation(contextPath, location.isOptional()));
|
||||
UriComponents uriComponents = UriComponentsBuilder.fromUriString(contextPath).build();
|
||||
String prefix = uriComponents.getQueryParams().getFirst("prefix");
|
||||
String path = uriComponents.getPath();
|
||||
if (StringUtils.hasLength(prefix) && StringUtils.hasLength(path)) {
|
||||
PropertyTransformer keyPrefixPropertyTransformer = PropertyTransformers.propertyNamePrefix(prefix);
|
||||
SecretBackendMetadata secretBackendMetadata = KeyValueSecretBackendMetadata.create(path, keyPrefixPropertyTransformer);
|
||||
return Collections.singletonList(new VaultConfigLocation(secretBackendMetadata, location.isOptional()));
|
||||
}
|
||||
else {
|
||||
return Collections.singletonList(new VaultConfigLocation(contextPath, location.isOptional()));
|
||||
}
|
||||
}
|
||||
|
||||
private static void registerVaultProperties(ConfigDataLocationResolverContext context) {
|
||||
|
||||
@@ -19,15 +19,22 @@ package org.springframework.cloud.vault.config;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.boot.DefaultBootstrapContext;
|
||||
import org.springframework.boot.context.config.ConfigDataLocation;
|
||||
import org.springframework.boot.context.config.ConfigDataLocationResolverContext;
|
||||
import org.springframework.boot.context.config.Profiles;
|
||||
import org.springframework.boot.context.properties.bind.Binder;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
|
||||
import static org.mockito.Mockito.mock;
|
||||
@@ -89,6 +96,36 @@ public class VaultConfigDataLocationResolverUnitTests {
|
||||
|
||||
assertThat(locations).hasSize(1);
|
||||
assertThat(locations.get(0)).hasToString("VaultConfigLocation [path='my/context/path', optional=false]");
|
||||
assertThat(locations.get(0).getSecretBackendMetadata().getPropertyTransformer()
|
||||
.transformProperties(Collections.singletonMap("key", "value"))).containsEntry("key", "value");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldDiscoverContextualLocationsWithPrefix() {
|
||||
|
||||
VaultConfigDataLocationResolver resolver = new VaultConfigDataLocationResolver();
|
||||
|
||||
List<VaultConfigLocation> locations = resolver.resolveProfileSpecific(this.contextMock,
|
||||
ConfigDataLocation.of("vault://my/context/path?prefix=myPrefix"), this.profilesMock);
|
||||
|
||||
assertThat(locations).hasSize(1);
|
||||
assertThat(locations.get(0)).hasToString("VaultConfigLocation [path='my/context/path', optional=false]");
|
||||
assertThat(locations.get(0).getSecretBackendMetadata().getPropertyTransformer()
|
||||
.transformProperties(Collections.singletonMap("key", "value"))).containsEntry("myPrefix.key", "value");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldNotPrefixWhenPrefixIsEmpty() {
|
||||
|
||||
VaultConfigDataLocationResolver resolver = new VaultConfigDataLocationResolver();
|
||||
|
||||
List<VaultConfigLocation> locations = resolver.resolveProfileSpecific(this.contextMock,
|
||||
ConfigDataLocation.of("vault://my/context/path?prefix="), this.profilesMock);
|
||||
|
||||
assertThat(locations).hasSize(1);
|
||||
assertThat(locations.get(0)).hasToString("VaultConfigLocation [path='my/context/path', optional=false]");
|
||||
assertThat(locations.get(0).getSecretBackendMetadata().getPropertyTransformer()
|
||||
.transformProperties(Collections.singletonMap("key", "value"))).containsEntry("key", "value");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user