Skip to content

Commit

Permalink
Polishing.
Browse files Browse the repository at this point in the history
Add author tags. Let VaultConfigLocation accept PropertyTransformer. Extract prefix computation into its own method. Tweak documentation wording.

See gh-488
Original pull request: gh-582.
  • Loading branch information
mp911de committed Jun 18, 2021
1 parent 0d9475d commit c147a0f
Show file tree
Hide file tree
Showing 4 changed files with 55 additions and 31 deletions.
28 changes: 16 additions & 12 deletions docs/src/main/asciidoc/config-data.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,22 @@ spring.config.import: vault://first/context/path, vault://other/path, vault://
----
====

Property names within a Spring `Environment` must be unique to avoid shadowing.
If you use the same secret names in different context paths and you want to expose these as individual properties you can distinguish them by adding a `prefix` query parameter to the location.

.application.yml
====
[source,yaml]
----
spring.config.import: vault://my/path?prefix=foo., vault://my/other/path?prefix=bar.
secret: ${foo.secret}
other.secret: ${bar.secret}
----
NOTE: Prefixes are added as-is to all property names returned by Vault. If you want key names to be separated with a dot between the prefix and key name, make sure to add a trailing dot to the prefix.
====

[[vault.configdata.location.optional]]
=== Conditionally enable/disable Vault Configuration

Expand All @@ -50,18 +66,6 @@ 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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@
* required later on by {@link VaultConfigDataLoader}.
*
* @author Mark Paluch
* @author Jeffrey van der Laan
* @since 3.0
* @see VaultConfigurer
* @see BootstrapRegistry
Expand Down Expand Up @@ -118,17 +119,20 @@ public List<VaultConfigLocation> resolveProfileSpecific(ConfigDataLocationResolv
contextPath = contextPath.substring(1);
}

return Collections.singletonList(
new VaultConfigLocation(contextPath, getPropertyTransformer(contextPath), location.isOptional()));
}

private static PropertyTransformer getPropertyTransformer(String contextPath) {

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()));

if (StringUtils.hasText(prefix) && StringUtils.hasText(uriComponents.getPath())) {
return PropertyTransformers.propertyNamePrefix(prefix);
}

return PropertyTransformers.noop();
}

private static void registerVaultProperties(ConfigDataLocationResolverContext context) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@
import org.springframework.boot.context.config.ConfigDataResource;
import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils;
import org.springframework.vault.core.util.PropertyTransformer;
import org.springframework.vault.core.util.PropertyTransformers;

/**
* Vault-specific implementation for a {@link ConfigDataLocation}. Consists of a
Expand All @@ -40,17 +42,38 @@ public class VaultConfigLocation extends ConfigDataResource {

private final boolean optional;

/**
* Create a new {@link VaultConfigLocation} instance.
* @param contextPath the context path
* @param optional if the resource is optional
*/
public VaultConfigLocation(String contextPath, boolean optional) {
this(contextPath, PropertyTransformers.noop(), optional);
}

/**
* Create a new {@link VaultConfigLocation} instance.
* @param contextPath the context path
* @param propertyTransformer the property transformer
* @param optional if the resource is optional
* @since 3.0.4
*/
public VaultConfigLocation(String contextPath, PropertyTransformer propertyTransformer, boolean optional) {

super(optional);

Assert.hasText(contextPath, "Location must not be empty");
validatePath(contextPath);

this.secretBackendMetadata = KeyValueSecretBackendMetadata.create(contextPath);
this.secretBackendMetadata = KeyValueSecretBackendMetadata.create(contextPath, propertyTransformer);
this.optional = optional;
}

/**
* Create a new {@link VaultConfigLocation} instance.
* @param secretBackendMetadata the backend descriptor.
* @param optional if the resource is optional
*/
public VaultConfigLocation(SecretBackendMetadata secretBackendMetadata, boolean optional) {

Assert.notNull(secretBackendMetadata, "SecretBackendMetadata must not be null");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,25 +16,19 @@

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;
Expand All @@ -44,6 +38,7 @@
* Unit tests for {@link VaultConfigDataLocationResolver}.
*
* @author Mark Paluch
* @author Jeffrey van der Laan
*/
public class VaultConfigDataLocationResolverUnitTests {

Expand Down Expand Up @@ -106,10 +101,9 @@ public void shouldDiscoverContextualLocationsWithPrefix() {
VaultConfigDataLocationResolver resolver = new VaultConfigDataLocationResolver();

List<VaultConfigLocation> locations = resolver.resolveProfileSpecific(this.contextMock,
ConfigDataLocation.of("vault://my/context/path?prefix=myPrefix"), this.profilesMock);
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");
}
Expand All @@ -123,7 +117,6 @@ public void shouldNotPrefixWhenPrefixIsEmpty() {
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");
}
Expand Down

0 comments on commit c147a0f

Please sign in to comment.