diff --git a/config/src/main/java/com/quorum/tessera/config/util/EnvironmentVariables.java b/config/src/main/java/com/quorum/tessera/config/util/EnvironmentVariables.java index ef03be1bb..4a86824b5 100644 --- a/config/src/main/java/com/quorum/tessera/config/util/EnvironmentVariables.java +++ b/config/src/main/java/com/quorum/tessera/config/util/EnvironmentVariables.java @@ -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"; diff --git a/key-vault/hashicorp-key-vault/src/main/java/com/quorum/tessera/key/vault/hashicorp/HashicorpDbCredentialsVaultServiceFactory.java b/key-vault/hashicorp-key-vault/src/main/java/com/quorum/tessera/key/vault/hashicorp/HashicorpDbCredentialsVaultServiceFactory.java index 9784fa156..7d1f9bbc2 100644 --- a/key-vault/hashicorp-key-vault/src/main/java/com/quorum/tessera/key/vault/hashicorp/HashicorpDbCredentialsVaultServiceFactory.java +++ b/key-vault/hashicorp-key-vault/src/main/java/com/quorum/tessera/key/vault/hashicorp/HashicorpDbCredentialsVaultServiceFactory.java @@ -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; @@ -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) { diff --git a/key-vault/hashicorp-key-vault/src/main/java/com/quorum/tessera/key/vault/hashicorp/HashicorpKeyVaultServiceFactoryUtil.java b/key-vault/hashicorp-key-vault/src/main/java/com/quorum/tessera/key/vault/hashicorp/HashicorpKeyVaultServiceFactoryUtil.java index 0eb1e0c7c..0a821e9ce 100644 --- a/key-vault/hashicorp-key-vault/src/main/java/com/quorum/tessera/key/vault/hashicorp/HashicorpKeyVaultServiceFactoryUtil.java +++ b/key-vault/hashicorp-key-vault/src/main/java/com/quorum/tessera/key/vault/hashicorp/HashicorpKeyVaultServiceFactoryUtil.java @@ -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) { @@ -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"); } diff --git a/key-vault/hashicorp-key-vault/src/main/java/com/quorum/tessera/key/vault/hashicorp/HashicorpVaultServiceFactory.java b/key-vault/hashicorp-key-vault/src/main/java/com/quorum/tessera/key/vault/hashicorp/HashicorpVaultServiceFactory.java index 6230302cb..2817413cd 100644 --- a/key-vault/hashicorp-key-vault/src/main/java/com/quorum/tessera/key/vault/hashicorp/HashicorpVaultServiceFactory.java +++ b/key-vault/hashicorp-key-vault/src/main/java/com/quorum/tessera/key/vault/hashicorp/HashicorpVaultServiceFactory.java @@ -36,6 +36,26 @@ R create( HashicorpKeyVaultServiceFactoryUtil util, Function keyVaultConfigProvider, BiFunction keyVaultServiceProvider) { + return create( + config, + envProvider, + util, + keyVaultConfigProvider, + keyVaultServiceProvider, + HASHICORP_ROLE_ID, + HASHICORP_SECRET_ID, + HASHICORP_TOKEN); + } + + R create( + Config config, + EnvironmentVariableProvider envProvider, + HashicorpKeyVaultServiceFactoryUtil util, + Function keyVaultConfigProvider, + BiFunction keyVaultServiceProvider, + String envVarHashicorpRoleId, + String envVarHashicorpSecretId, + String envVarHashicorpToken) { Objects.requireNonNull(config); Objects.requireNonNull(envProvider); @@ -43,25 +63,25 @@ R create( 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"); } @@ -87,7 +107,13 @@ R create( ClientAuthentication clientAuthentication = util.configureClientAuthentication( - keyVaultConfig, envProvider, clientHttpRequestFactory, vaultEndpoint); + keyVaultConfig, + envProvider, + clientHttpRequestFactory, + vaultEndpoint, + envVarHashicorpRoleId, + envVarHashicorpSecretId, + envVarHashicorpToken); SessionManager sessionManager = new SimpleSessionManager(clientAuthentication); diff --git a/key-vault/hashicorp-key-vault/src/test/java/com/quorum/tessera/key/vault/hashicorp/HashicorpKeyVaultServiceFactoryTest.java b/key-vault/hashicorp-key-vault/src/test/java/com/quorum/tessera/key/vault/hashicorp/HashicorpKeyVaultServiceFactoryTest.java index 18fe6fd94..c7dac4bf3 100644 --- a/key-vault/hashicorp-key-vault/src/test/java/com/quorum/tessera/key/vault/hashicorp/HashicorpKeyVaultServiceFactoryTest.java +++ b/key-vault/hashicorp-key-vault/src/test/java/com/quorum/tessera/key/vault/hashicorp/HashicorpKeyVaultServiceFactoryTest.java @@ -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); diff --git a/tests/acceptance-test/src/test/java/com/quorum/tessera/test/vault/hashicorp/HashicorpStepDefs.java b/tests/acceptance-test/src/test/java/com/quorum/tessera/test/vault/hashicorp/HashicorpStepDefs.java index cc7fee443..d4a87f5cb 100644 --- a/tests/acceptance-test/src/test/java/com/quorum/tessera/test/vault/hashicorp/HashicorpStepDefs.java +++ b/tests/acceptance-test/src/test/java/com/quorum/tessera/test/vault/hashicorp/HashicorpStepDefs.java @@ -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", () -> { @@ -974,7 +989,7 @@ private TestHttpReponse makeHttpRequestAndGetResponse( private TestHttpReponse makeHttpRequestAndGetResponse( URL url, String method, String data, Map headers) { try { - HttpsURLConnection urlConnection = (HttpsURLConnection) url.openConnection(); + HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection(); urlConnection.setDoOutput(true); urlConnection.setRequestMethod(method); @@ -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); @@ -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 { diff --git a/tests/acceptance-test/src/test/resources/features/vault/hashicorp-db-secret-engine.feature b/tests/acceptance-test/src/test/resources/features/vault/hashicorp-db-secret-engine.feature index b3acf066f..8c99cbff4 100644 --- a/tests/acceptance-test/src/test/resources/features/vault/hashicorp-db-secret-engine.feature +++ b/tests/acceptance-test/src/test/resources/features/vault/hashicorp-db-secret-engine.feature @@ -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