Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added Environment Variables for Authentication to Vault DB Secret Engine #23

Merged
merged 3 commits into from
Aug 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,12 @@ public final class EnvironmentVariables {

public static final String HASHICORP_TOKEN = "HASHICORP_TOKEN";

public static final String HASHICORP_DSE_ROLE_ID = "HASHICORP_DSE_ROLE_ID";

public static final String HASHICORP_DSE_SECRET_ID = "HASHICORP_DSE_SECRET_ID";

public static final String HASHICORP_DSE_TOKEN = "HASHICORP_DSE_TOKEN";

public static final String HASHICORP_CLIENT_KEYSTORE_PWD = "HASHICORP_CLIENT_KEYSTORE_PWD";

public static final String HASHICORP_CLIENT_TRUSTSTORE_PWD = "HASHICORP_CLIENT_TRUSTSTORE_PWD";
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package com.quorum.tessera.key.vault.hashicorp;

import static com.quorum.tessera.config.util.EnvironmentVariables.*;

import com.quorum.tessera.config.Config;
import com.quorum.tessera.config.ConfigException;
import com.quorum.tessera.config.KeyVaultConfig;
Expand Down Expand Up @@ -32,7 +34,10 @@ HashicorpDbCredentialsVaultService create(
envProvider,
util,
this::getKeyVaultConfig,
HashicorpDbCredentialsVaultService::new);
HashicorpDbCredentialsVaultService::new,
HASHICORP_DSE_ROLE_ID,
HASHICORP_DSE_SECRET_ID,
HASHICORP_DSE_TOKEN);
}

private KeyVaultConfig getKeyVaultConfig(Config config) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,10 +77,28 @@ ClientAuthentication configureClientAuthentication(
EnvironmentVariableProvider envProvider,
ClientHttpRequestFactory clientHttpRequestFactory,
VaultEndpoint vaultEndpoint) {
return configureClientAuthentication(
keyVaultConfig,
envProvider,
clientHttpRequestFactory,
vaultEndpoint,
HASHICORP_ROLE_ID,
HASHICORP_SECRET_ID,
HASHICORP_TOKEN);
}

ClientAuthentication configureClientAuthentication(
KeyVaultConfig keyVaultConfig,
EnvironmentVariableProvider envProvider,
ClientHttpRequestFactory clientHttpRequestFactory,
VaultEndpoint vaultEndpoint,
String envVarHashicorpRoleId,
String envVarHashicorpSecretId,
String envVarHashicorpToken) {

final String roleId = envProvider.getEnv(HASHICORP_ROLE_ID);
final String secretId = envProvider.getEnv(HASHICORP_SECRET_ID);
final String authToken = envProvider.getEnv(HASHICORP_TOKEN);
final String roleId = envProvider.getEnv(envVarHashicorpRoleId);
final String secretId = envProvider.getEnv(envVarHashicorpSecretId);
final String authToken = envProvider.getEnv(envVarHashicorpToken);

if (roleId != null && secretId != null) {

Expand Down Expand Up @@ -110,20 +128,20 @@ ClientAuthentication configureClientAuthentication(

throw new HashicorpCredentialNotSetException(
"Both "
+ HASHICORP_ROLE_ID
+ envVarHashicorpRoleId
+ " and "
+ HASHICORP_SECRET_ID
+ envVarHashicorpSecretId
+ " environment variables must be set to use the AppRole authentication method");

} else if (authToken == null) {

throw new HashicorpCredentialNotSetException(
"Both "
+ HASHICORP_ROLE_ID
+ envVarHashicorpRoleId
+ " and "
+ HASHICORP_SECRET_ID
+ envVarHashicorpSecretId
+ " environment variables must be set to use the AppRole authentication method. Alternatively set "
+ HASHICORP_TOKEN
+ envVarHashicorpToken
+ " to authenticate using the Token method");
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,32 +36,52 @@ <R> R create(
HashicorpKeyVaultServiceFactoryUtil util,
Function<Config, KeyVaultConfig> keyVaultConfigProvider,
BiFunction<VaultOperations, KeyVaultConfig, R> keyVaultServiceProvider) {
return create(
config,
envProvider,
util,
keyVaultConfigProvider,
keyVaultServiceProvider,
HASHICORP_ROLE_ID,
HASHICORP_SECRET_ID,
HASHICORP_TOKEN);
}

<R> R create(
Config config,
EnvironmentVariableProvider envProvider,
HashicorpKeyVaultServiceFactoryUtil util,
Function<Config, KeyVaultConfig> keyVaultConfigProvider,
BiFunction<VaultOperations, KeyVaultConfig, R> keyVaultServiceProvider,
String envVarHashicorpRoleId,
String envVarHashicorpSecretId,
String envVarHashicorpToken) {

Objects.requireNonNull(config);
Objects.requireNonNull(envProvider);
Objects.requireNonNull(util);
Objects.requireNonNull(keyVaultConfigProvider);
Objects.requireNonNull(keyVaultServiceProvider);

final String roleId = envProvider.getEnv(HASHICORP_ROLE_ID);
final String secretId = envProvider.getEnv(HASHICORP_SECRET_ID);
final String authToken = envProvider.getEnv(HASHICORP_TOKEN);
final String roleId = envProvider.getEnv(envVarHashicorpRoleId);
final String secretId = envProvider.getEnv(envVarHashicorpSecretId);
final String authToken = envProvider.getEnv(envVarHashicorpToken);

if (roleId == null && secretId == null && authToken == null) {
throw new HashicorpCredentialNotSetException(
"Environment variables must be set to authenticate with Hashicorp Vault. Set the "
+ HASHICORP_ROLE_ID
+ envVarHashicorpRoleId
+ " and "
+ HASHICORP_SECRET_ID
+ envVarHashicorpSecretId
+ " environment variables if using the AppRole authentication method. Set the "
+ HASHICORP_TOKEN
+ envVarHashicorpToken
+ " environment variable if using another authentication method.");
} else if (isOnlyOneInputNull(roleId, secretId)) {
throw new HashicorpCredentialNotSetException(
"Only one of the "
+ HASHICORP_ROLE_ID
+ envVarHashicorpRoleId
+ " and "
+ HASHICORP_SECRET_ID
+ envVarHashicorpSecretId
+ " environment variables to authenticate with Hashicorp Vault using the AppRole method has been set");
}

Expand All @@ -87,7 +107,13 @@ <R> R create(

ClientAuthentication clientAuthentication =
util.configureClientAuthentication(
keyVaultConfig, envProvider, clientHttpRequestFactory, vaultEndpoint);
keyVaultConfig,
envProvider,
clientHttpRequestFactory,
vaultEndpoint,
envVarHashicorpRoleId,
envVarHashicorpSecretId,
envVarHashicorpToken);

SessionManager sessionManager = new SimpleSessionManager(clientAuthentication);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,15 @@ private void setUpUtilMocks(KeyVaultConfig keyVaultConfig) {
eq(clientHttpRequestFactory),
any(VaultEndpoint.class)))
.thenReturn(clientAuthentication);
when(keyVaultServiceFactoryUtil.configureClientAuthentication(
eq(keyVaultConfig),
eq(envProvider),
eq(clientHttpRequestFactory),
any(VaultEndpoint.class),
anyString(),
anyString(),
anyString()))
.thenReturn(clientAuthentication);
when(keyVaultServiceFactoryUtil.getRestTemplateWithVaultNamespace(
anyString(), eq(clientHttpRequestFactory), any(VaultEndpoint.class)))
.thenReturn(restTemplateBuilder);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -786,6 +786,21 @@ public HashicorpStepDefs() {
startTessera(args, jvmArgs, null, authMethod);
});

Then(
"Tessera will fetch a missing transaction and successfully get a response of not found",
() -> {
var response =
makeHttpRequestAndGetResponse(
"http://localhost:18080",
"/transaction/c2FtcGxldGVzc2VyYWtleQ==",
"GET",
null,
Map.of());
assertThat(response.getResponseCode()).isEqualTo(HttpsURLConnection.HTTP_NOT_FOUND);
assertThat(response.getResponseBody())
.startsWith("Message with hash c2FtcGxldGVzc2VyYWtleQ== was not found");
});

Then(
"Tessera will retrieve the key pair from the vault",
() -> {
Expand Down Expand Up @@ -974,7 +989,7 @@ private TestHttpReponse makeHttpRequestAndGetResponse(
private TestHttpReponse makeHttpRequestAndGetResponse(
URL url, String method, String data, Map<String, String> headers) {
try {
HttpsURLConnection urlConnection = (HttpsURLConnection) url.openConnection();
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();

urlConnection.setDoOutput(true);
urlConnection.setRequestMethod(method);
Expand All @@ -992,7 +1007,11 @@ private TestHttpReponse makeHttpRequestAndGetResponse(

StringBuilder stringBodyContent = new StringBuilder();
try (BufferedReader reader =
new BufferedReader(new InputStreamReader(urlConnection.getInputStream()))) {
new BufferedReader(
new InputStreamReader(
urlConnection.getResponseCode() == HttpURLConnection.HTTP_NOT_FOUND
? urlConnection.getErrorStream()
: urlConnection.getInputStream()))) {
String line;
while ((line = reader.readLine()) != null) {
stringBodyContent.append(line);
Expand Down Expand Up @@ -1041,11 +1060,14 @@ private void startTessera(
if ("token".equals(authMethod)) {
Objects.requireNonNull(vaultToken);
tesseraEnvironment.put(HASHICORP_TOKEN, vaultToken);
tesseraEnvironment.put(HASHICORP_DSE_TOKEN, vaultToken);
} else {
Objects.requireNonNull(approleRoleId);
Objects.requireNonNull(approleSecretId);
tesseraEnvironment.put(HASHICORP_ROLE_ID, approleRoleId);
tesseraEnvironment.put(HASHICORP_SECRET_ID, approleSecretId);
tesseraEnvironment.put(HASHICORP_DSE_ROLE_ID, approleRoleId);
tesseraEnvironment.put(HASHICORP_DSE_SECRET_ID, approleSecretId);
}

try {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,4 @@ Feature: Hashicorp Vault support with DB Secret Engine
-configfile %s -pidfile %s -o jdbc.autoCreateTables=true
"""
Then Tessera will retrieve the key pair from the vault
Then Tessera will fetch a missing transaction and successfully get a response of not found
Loading