Skip to content

Commit e0d3660

Browse files
Add the full vault path to the PropertySource. (#3180)
* Add option to add the full vault path to the PropertySource. This allows clients to use properties from multiple vault sources that end in the same key, e.g. foo/bar/application and bar/baz/application Signed-off-by: Tristan Stenner <ts@ppi.de> * Adjust the return propertySource names in unit tests to the full vault path Signed-off-by: Tristan Stenner <ts@ppi.de> * Add fullKeyPath documentation Signed-off-by: Tristan Stenner <ts@ppi.de> * polishing documentation --------- Signed-off-by: Tristan Stenner <ts@ppi.de> Co-authored-by: Ryan Baxter <ryan.baxter@broadcom.com>
1 parent 3e25a67 commit e0d3660

4 files changed

Lines changed: 66 additions & 1 deletion

File tree

docs/modules/ROOT/pages/server/environment-repository/vault-backend.adoc

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,9 @@ The following table describes configurable Vault properties:
5656
|backend
5757
|secret
5858

59+
|fullKeyPath
60+
|false
61+
5962
|defaultKey
6063
|application
6164

@@ -164,6 +167,28 @@ Properties written to `secret/application` are available to <<_vault_server,all
164167
An application with the name, `myApp`, would have any properties written to `secret/myApp` and `secret/application` available to it.
165168
When `myApp` has the `dev` profile enabled, properties written to all of the above paths would be available to it, with properties in the first path in the list taking priority over the others.
166169

170+
[[full-key-path]]
171+
== Disambiguating Composite Property Sources
172+
173+
By default, the config server generates property source names based on the vault key, e.g. `vault:myApp` in the example above.
174+
When composite vault backends have the same vault key, the config server client will overwrite preceding property sources.
175+
176+
With `fullKeyPath` set to `true`, the property sources will contain the full backend path,
177+
e.g. `vault:secret/backendA/myApp` and `vault:secret/backendB/myApp`, preventing overwriting the preceding property source.
178+
179+
[source,yaml]
180+
----
181+
spring.cloud.config.server.composite:
182+
- type: vault
183+
fullKeyPath: true
184+
# ...
185+
backend: secret/backendA
186+
- type: vault
187+
fullKeyPath: true
188+
# ...
189+
backend: secret/backendB
190+
----
191+
167192
[[enabling-serach-by-label]]
168193
== Enabling Search by Label
169194

spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/AbstractVaultEnvironmentRepository.java

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,14 @@ public abstract class AbstractVaultEnvironmentRepository implements EnvironmentR
6363
*/
6464
protected String defaultKey;
6565

66+
/**
67+
* The backend path in Vault where the secrets are stored. Used to disambiguate
68+
* multiple vault paths ending in the same key.
69+
*/
70+
protected String backend;
71+
72+
protected Boolean fullKeyPath;
73+
6674
/**
6775
* Vault profile separator. Defaults to comma.
6876
*/
@@ -81,6 +89,8 @@ public AbstractVaultEnvironmentRepository(ObjectProvider<HttpServletRequest> req
8189
this.profileSeparator = properties.getProfileSeparator();
8290
this.enableLabel = properties.isEnableLabel();
8391
this.defaultLabel = properties.getDefaultLabel();
92+
this.backend = properties.getBackend();
93+
this.fullKeyPath = properties.isFullKeyPath();
8494
this.order = properties.getOrder();
8595
this.request = request;
8696
this.watch = watch;
@@ -100,6 +110,8 @@ public Environment findOne(String application, String profile, String label) {
100110
var profiles = normalize(profile, DEFAULT_PROFILE);
101111
var applications = normalize(application, this.defaultKey);
102112

113+
var backendPathPrefix = "vault:" + (this.fullKeyPath ? this.backend + "/" : "");
114+
103115
for (String prof : profiles) {
104116
for (String app : applications) {
105117
var key = vaultKey(app, prof, label);
@@ -112,7 +124,7 @@ public Environment findOne(String application, String profile, String label) {
112124
var properties = yaml.getObject();
113125

114126
if (properties != null && !properties.isEmpty()) {
115-
environment.add(new PropertySource("vault:" + key, properties));
127+
environment.add(new PropertySource(backendPathPrefix + key, properties));
116128
}
117129
}
118130
}

spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/VaultEnvironmentProperties.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,9 @@ public class VaultEnvironmentProperties implements HttpEnvironmentRepositoryProp
5252
/** Vault backend. Defaults to secret. */
5353
private String backend = "secret";
5454

55+
/** Include the full key path in the PropertySource name. Defaults to false */
56+
private boolean fullKeyPath = false;
57+
5558
/**
5659
* The key in vault shared by all applications. Defaults to application. Set to empty
5760
* to disable.
@@ -163,6 +166,14 @@ public void setBackend(String backend) {
163166
this.backend = backend;
164167
}
165168

169+
public boolean isFullKeyPath() {
170+
return fullKeyPath;
171+
}
172+
173+
public void setFullKeyPath(boolean fullKeyPath) {
174+
this.fullKeyPath = fullKeyPath;
175+
}
176+
166177
public String getDefaultKey() {
167178
return this.defaultKey;
168179
}

spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/environment/vault/SpringVaultEnvironmentRepositoryTests.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,23 @@ private void defaultKeyTest(String myPathKey, int version) {
8383
assertThat(e.getPropertySources().get(1).getSource()).isEqualTo(Map.of("def-foo", "def-bar"));
8484
}
8585

86+
@Test
87+
public void findOneWithBackend() {
88+
when(keyValueTemplate.get("myapp")).thenReturn(withVaultResponse("foo", "bar"));
89+
90+
var properties = new VaultEnvironmentProperties();
91+
properties.setBackend("custom-path");
92+
properties.setFullKeyPath(true);
93+
94+
var e = springVaultEnvironmentRepository(properties).findOne("myapp", null, null);
95+
96+
assertThat(e.getName()).isEqualTo("myapp");
97+
98+
assertThat(e.getPropertySources()).hasSize(1);
99+
assertThat(e.getPropertySources().get(0).getName()).isEqualTo("vault:custom-path/myapp");
100+
assertThat(e.getPropertySources().get(0).getSource()).isEqualTo(Map.of("foo", "bar"));
101+
}
102+
86103
@Test
87104
public void findOneWithSlashesInBackend() {
88105
when(keyValueTemplate.get("myapp")).thenReturn(withVaultResponse("foo", "bar"));

0 commit comments

Comments
 (0)