Feature(Vault KV2): to support a path after mount-path (backend) under which the key(s)/application(s) be found (#1833)
* adding changes to support a path after mount-path (for KV2) under which applications/keys can be located Co-authored-by: cah-venkatasuryasasikala-peri <venkatasuryasasikala.peri@cardinalhealth.com> Co-authored-by: Sasi Peri <pvssasikala@gmil.com>
This commit is contained in:
@@ -59,6 +59,16 @@ public class VaultEnvironmentProperties implements HttpEnvironmentRepositoryProp
|
||||
*/
|
||||
private String defaultKey = "application";
|
||||
|
||||
/**
|
||||
* KV2 API required "data" after "mount-path". There could be folder/path structure,
|
||||
* where the keys/applications are grouped. This property is the path after
|
||||
* mount-path, under which application(s) are located (appended after "data") Default
|
||||
* value is blank, which means all grouped applications are located right under the
|
||||
* mount-path
|
||||
*
|
||||
*/
|
||||
private String pathToKey = "";
|
||||
|
||||
/** Vault profile separator. Defaults to comma. */
|
||||
private String profileSeparator = ",";
|
||||
|
||||
@@ -263,6 +273,14 @@ public class VaultEnvironmentProperties implements HttpEnvironmentRepositoryProp
|
||||
return authentication;
|
||||
}
|
||||
|
||||
public String getPathToKey() {
|
||||
return pathToKey;
|
||||
}
|
||||
|
||||
public void setPathToKey(String pathToKey) {
|
||||
this.pathToKey = pathToKey;
|
||||
}
|
||||
|
||||
public enum AuthenticationMethod {
|
||||
|
||||
/**
|
||||
|
||||
@@ -92,7 +92,8 @@ public class VaultEnvironmentRepository extends AbstractVaultEnvironmentReposito
|
||||
|
||||
String baseUrl = String.format("%s://%s:%s", this.scheme, this.host, this.port);
|
||||
|
||||
this.accessStrategy = VaultKvAccessStrategyFactory.forVersion(rest, baseUrl, properties.getKvVersion());
|
||||
this.accessStrategy = VaultKvAccessStrategyFactory.forVersion(rest, baseUrl, properties.getKvVersion(),
|
||||
properties.getPathToKey());
|
||||
}
|
||||
|
||||
/* for testing */ void setAccessStrategy(VaultKvAccessStrategy accessStrategy) {
|
||||
|
||||
@@ -18,6 +18,7 @@ package org.springframework.cloud.config.server.environment;
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.client.RestOperations;
|
||||
|
||||
/**
|
||||
@@ -39,15 +40,16 @@ public final class VaultKvAccessStrategyFactory {
|
||||
* @param rest must not be {@literal null}.
|
||||
* @param baseUrl the Vault base URL.
|
||||
* @param version version of the Vault key-value backend.
|
||||
* @param pathToKey path after the mount-path, under which the key(s) can be found.
|
||||
* @return the access strategy.
|
||||
*/
|
||||
public static VaultKvAccessStrategy forVersion(RestOperations rest, String baseUrl, int version) {
|
||||
public static VaultKvAccessStrategy forVersion(RestOperations rest, String baseUrl, int version, String pathToKey) {
|
||||
|
||||
switch (version) {
|
||||
case 1:
|
||||
return new V1VaultKvAccessStrategy(baseUrl, rest);
|
||||
case 2:
|
||||
return new V2VaultKvAccessStrategy(baseUrl, rest);
|
||||
return new V2VaultKvAccessStrategy(baseUrl, pathToKey, rest);
|
||||
default:
|
||||
throw new IllegalArgumentException("No support for given Vault k/v backend version " + version);
|
||||
}
|
||||
@@ -79,12 +81,20 @@ public final class VaultKvAccessStrategyFactory {
|
||||
*/
|
||||
static class V2VaultKvAccessStrategy extends VaultKvAccessStrategySupport {
|
||||
|
||||
V2VaultKvAccessStrategy(String baseUrl, RestOperations rest) {
|
||||
private String pathToKey;
|
||||
|
||||
V2VaultKvAccessStrategy(String baseUrl, String pathToKey, RestOperations rest) {
|
||||
super(baseUrl, rest);
|
||||
this.pathToKey = pathToKey;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPath() {
|
||||
|
||||
if (StringUtils.hasText(pathToKey)) {
|
||||
return "data/" + pathToKey + "/{key}";
|
||||
}
|
||||
|
||||
return "data/{key}";
|
||||
}
|
||||
|
||||
|
||||
@@ -333,6 +333,43 @@ public class VaultEnvironmentRepositoryTests {
|
||||
.isEqualTo(firstResult);
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void testVaultKV2WithPath2Key() {
|
||||
RestTemplate rest = mock(RestTemplate.class);
|
||||
|
||||
ResponseEntity<VaultResponse> myAppResp = mock(ResponseEntity.class);
|
||||
when(myAppResp.getStatusCode()).thenReturn(HttpStatus.OK);
|
||||
VaultResponse myAppVaultResp = getVaultResponse("{\"data\": {\"data\": {\"foo\": \"bar\"}}}");
|
||||
when(myAppResp.getBody()).thenReturn(myAppVaultResp);
|
||||
when(rest.exchange(eq("http://127.0.0.1:8200/v1/secret/data/myorg/{key}"), eq(HttpMethod.GET),
|
||||
any(HttpEntity.class), eq(VaultResponse.class), eq("myapp"))).thenReturn(myAppResp);
|
||||
|
||||
ResponseEntity<VaultResponse> appResp = mock(ResponseEntity.class);
|
||||
when(appResp.getStatusCode()).thenReturn(HttpStatus.OK);
|
||||
VaultResponse appVaultResp = getVaultResponse("{\"data\": {\"data\": {\"def-foo\":\"def-bar\"}}}");
|
||||
when(appResp.getBody()).thenReturn(appVaultResp);
|
||||
when(rest.exchange(eq("http://127.0.0.1:8200/v1/secret/data/myorg/{key}"), eq(HttpMethod.GET),
|
||||
any(HttpEntity.class), eq(VaultResponse.class), eq("application"))).thenReturn(appResp);
|
||||
|
||||
final VaultEnvironmentProperties vaultEnvironmentProperties = new VaultEnvironmentProperties();
|
||||
vaultEnvironmentProperties.setKvVersion(2);
|
||||
vaultEnvironmentProperties.setPathToKey("myorg");
|
||||
VaultEnvironmentRepository repo = new VaultEnvironmentRepository(mockHttpRequest(),
|
||||
new EnvironmentWatch.Default(), rest, vaultEnvironmentProperties, mockTokenProvider());
|
||||
|
||||
Environment e = repo.findOne("myapp", null, null);
|
||||
assertThat(e.getName()).as("Name should be the same as the application argument").isEqualTo("myapp");
|
||||
assertThat(e.getPropertySources().size()).as(
|
||||
"Properties for specified application and default application with key 'application' should be returned")
|
||||
.isEqualTo(2);
|
||||
Map<String, String> firstResult = new HashMap<>();
|
||||
firstResult.put("foo", "bar");
|
||||
assertThat(e.getPropertySources().get(0).getSource())
|
||||
.as("Properties for specified application should be returned in priority position")
|
||||
.isEqualTo(firstResult);
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings({ "Duplicates", "unchecked" })
|
||||
public void testNamespaceHeaderSent() {
|
||||
@@ -401,7 +438,7 @@ public class VaultEnvironmentRepositoryTests {
|
||||
String baseUrl = String.format("%s://%s:%s", properties.getScheme(), properties.getHost(),
|
||||
properties.getPort());
|
||||
this.accessStrategy = VaultKvAccessStrategyFactory.forVersion(restTemplate, baseUrl,
|
||||
properties.getKvVersion());
|
||||
properties.getKvVersion(), "");
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -30,19 +30,19 @@ public class VaultKvAccessStrategyFactoryTest {
|
||||
|
||||
@Test
|
||||
public void testGetV1Strategy() {
|
||||
VaultKvAccessStrategy vaultKvAccessStrategy = VaultKvAccessStrategyFactory.forVersion(null, "foo", 1);
|
||||
VaultKvAccessStrategy vaultKvAccessStrategy = VaultKvAccessStrategyFactory.forVersion(null, "foo", 1, "");
|
||||
assertThat(vaultKvAccessStrategy instanceof V1VaultKvAccessStrategy).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetV2Strategy() {
|
||||
VaultKvAccessStrategy vaultKvAccessStrategy = VaultKvAccessStrategyFactory.forVersion(null, "foo", 2);
|
||||
VaultKvAccessStrategy vaultKvAccessStrategy = VaultKvAccessStrategyFactory.forVersion(null, "foo", 2, "");
|
||||
assertThat(vaultKvAccessStrategy instanceof V2VaultKvAccessStrategy).isTrue();
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testGetUnsupportedStrategy() {
|
||||
VaultKvAccessStrategyFactory.forVersion(null, "foo", 0);
|
||||
VaultKvAccessStrategyFactory.forVersion(null, "foo", 0, "");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ public class VaultKvAccessStrategyTest {
|
||||
private ObjectMapper objectMapper = new ObjectMapper();
|
||||
|
||||
private static VaultKvAccessStrategySupport getStrategy(int version) {
|
||||
return (VaultKvAccessStrategySupport) VaultKvAccessStrategyFactory.forVersion(null, "foo", version);
|
||||
return (VaultKvAccessStrategySupport) VaultKvAccessStrategyFactory.forVersion(null, "foo", version, "");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
Reference in New Issue
Block a user