Skip to content

Commit

Permalink
feat(vault): implements custom secret folder config (#4385)
Browse files Browse the repository at this point in the history
* feat(vault): implements custom secret folder config

Signed-off-by: Sascha Isele <sascha.isele.external@zf.com>

* feat(vault): review suggestions

Signed-off-by: Sascha Isele <s.isele@cluetec.de>

* feat(vault): more efficient null handling

* feat(vault): avoid duplication

---------

Signed-off-by: Sascha Isele <sascha.isele.external@zf.com>
Signed-off-by: Sascha Isele <s.isele@cluetec.de>
Co-authored-by: Sascha Isele <s.isele@cluetec.de>
  • Loading branch information
saschaisele-zf and SaschaIsele authored Sep 19, 2024
1 parent 5774b8c commit efdeccd
Show file tree
Hide file tree
Showing 5 changed files with 68 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,9 @@ public class HashicorpVaultExtension implements ServiceExtension {
@Setting(value = "The URL path of the vault's /secret endpoint", defaultValue = VAULT_API_SECRET_PATH_DEFAULT)
public static final String VAULT_API_SECRET_PATH = "edc.vault.hashicorp.api.secret.path";

@Setting(value = "The path of the folder that the secret is stored in, relative to VAULT_FOLDER_PATH")
public static final String VAULT_FOLDER_PATH = "edc.vault.hashicorp.folder";

@Inject
private EdcHttpClient httpClient;

Expand Down Expand Up @@ -144,6 +147,7 @@ private HashicorpVaultSettings getSettings(ServiceExtensionContext context) {
var ttl = context.getSetting(VAULT_TOKEN_TTL, VAULT_TOKEN_TTL_DEFAULT);
var renewBuffer = context.getSetting(VAULT_TOKEN_RENEW_BUFFER, VAULT_TOKEN_RENEW_BUFFER_DEFAULT);
var secretPath = context.getSetting(VAULT_API_SECRET_PATH, VAULT_API_SECRET_PATH_DEFAULT);
var folderPath = context.getSetting(VAULT_FOLDER_PATH, null);

return HashicorpVaultSettings.Builder.newInstance()
.url(url)
Expand All @@ -155,6 +159,7 @@ private HashicorpVaultSettings getSettings(ServiceExtensionContext context) {
.ttl(ttl)
.renewBuffer(renewBuffer)
.secretPath(secretPath)
.folderPath(folderPath)
.build();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -276,11 +276,18 @@ private HttpUrl getSecretUrl(String key, String entryType) {
key = key.replace("%2F", "/");

var vaultApiPath = settings.secretPath();
var folderPath = settings.getFolderPath();

return settings.url()
var builder = settings.url()
.newBuilder()
.addPathSegments(PathUtil.trimLeadingOrEndingSlash(vaultApiPath))
.addPathSegment(entryType)
.addPathSegment(entryType);

if (folderPath != null) {
builder.addPathSegments(PathUtil.trimLeadingOrEndingSlash(folderPath));
}

return builder
.addPathSegments(key)
.build();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ public class HashicorpVaultSettings {
private long renewBuffer;
private String secretPath;

private String folderPath;

private HashicorpVaultSettings() {
}

Expand Down Expand Up @@ -72,6 +74,10 @@ public String secretPath() {
return secretPath;
}

public String getFolderPath() {
return folderPath;
}

public static class Builder {
private final HashicorpVaultSettings values;

Expand Down Expand Up @@ -129,6 +135,11 @@ public Builder secretPath(String secretPath) {
return this;
}

public Builder folderPath(String folderPath) {
values.folderPath = folderPath;
return this;
}

public HashicorpVaultSettings build() {
requireNonNull(values.url, "Vault url must be valid");
requireNonNull(values.healthCheckPath, "Vault health check path must not be null");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@
class HashicorpVaultClientTest {

private static final String VAULT_URL = "https://mock.url";
private static final String SECRET_FOLDER = "/foo";
private static final String HEALTH_PATH = "sys/health";
private static final String VAULT_TOKEN = UUID.randomUUID().toString();
private static final long VAULT_TOKEN_TTL = 5L;
Expand All @@ -87,6 +88,17 @@ class HashicorpVaultClientTest {
.secretPath(CUSTOM_SECRET_PATH)
.build();

private static final HashicorpVaultSettings HASHICORP_VAULT_CLIENT_CONFIG_VALUES_WITH_FOLDER = HashicorpVaultSettings.Builder.newInstance()
.url(VAULT_URL)
.healthCheckPath(HEALTH_PATH)
.healthStandbyOk(false)
.token(VAULT_TOKEN)
.ttl(VAULT_TOKEN_TTL)
.renewBuffer(RENEW_BUFFER)
.secretPath(CUSTOM_SECRET_PATH)
.folderPath(SECRET_FOLDER)
.build();

private final EdcHttpClient httpClient = mock();
private final Monitor monitor = mock();
private final HashicorpVaultClient vaultClient = new HashicorpVaultClient(
Expand All @@ -95,6 +107,12 @@ class HashicorpVaultClientTest {
monitor,
HASHICORP_VAULT_CLIENT_CONFIG_VALUES);

private final HashicorpVaultClient vaultClientWithFolder = new HashicorpVaultClient(
httpClient,
OBJECT_MAPPER,
monitor,
HASHICORP_VAULT_CLIENT_CONFIG_VALUES_WITH_FOLDER);

@Nested
class HealthCheck {
@Test
Expand Down Expand Up @@ -393,6 +411,30 @@ void getSecret_whenApiReturns200_shouldSucceed() throws IOException {
request.url().encodedPathSegments().contains(KEY)));
}

@Test
void getSecret_with_folder_whenApiReturns200_shouldSucceed() throws IOException {
var ow = new ObjectMapper().writer();
var data = GetEntryResponsePayloadGetVaultEntryData.Builder.newInstance().data(new HashMap<>(0)).build();
var body = GetEntryResponsePayload.Builder.newInstance().data(data).build();
var bodyString = ow.writeValueAsString(body);
var response = new Response.Builder()
.code(200)
.message("any")
.body(ResponseBody.create(bodyString, MediaType.get("application/json")))
.protocol(Protocol.HTTP_1_1)
.request(new Request.Builder().url("http://any").build())
.build();

when(httpClient.execute(any(Request.class))).thenReturn(response);

var result = vaultClientWithFolder.getSecretValue(KEY);

assertNotNull(result);
verify(httpClient).execute(argThat(request -> request.method().equalsIgnoreCase("GET") &&
request.url().encodedPath().contains(CUSTOM_SECRET_PATH + "/data" + SECRET_FOLDER) &&
request.url().encodedPathSegments().contains(KEY)));
}

@Test
void setSecret_whenApiReturns200_shouldSucceed() throws IOException {
var ow = new ObjectMapper().writer();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ void createSettings_withDefaultValues_shouldSucceed() {
assertThat(settings.ttl()).isEqualTo(VAULT_TOKEN_TTL_DEFAULT);
assertThat(settings.renewBuffer()).isEqualTo(VAULT_TOKEN_RENEW_BUFFER_DEFAULT);
assertThat(settings.secretPath()).isEqualTo(SECRET_PATH);
assertThat(settings.getFolderPath()).isNull();
}

@Test
Expand Down

0 comments on commit efdeccd

Please sign in to comment.