Skip to content

Commit

Permalink
Refactor secrets cache to sdk client
Browse files Browse the repository at this point in the history
Signed-off-by: Tanner Lewis <[email protected]>
  • Loading branch information
lewijacn committed Aug 21, 2023
1 parent 3fd28dd commit 2448c98
Show file tree
Hide file tree
Showing 4 changed files with 34 additions and 22 deletions.
4 changes: 1 addition & 3 deletions TrafficCapture/trafficReplayer/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,7 @@ dependencies {

implementation 'software.amazon.awssdk:sdk-core:2.20.102'
implementation 'software.amazon.awssdk:auth:2.20.102'

// TODO - upgrade this to 2.x so that we don't pollute the jar-space with two versions of AWS SDK
implementation group: 'com.amazonaws.secretsmanager', name: 'aws-secretsmanager-caching-java', version: '1.0.2'
implementation group: 'software.amazon.awssdk', name: 'secretsmanager', version: '2.20.127'

implementation group: 'com.beust', name: 'jcommander', version: '1.82'
implementation group: 'com.bazaarvoice.jolt', name: 'jolt-core', version: '0.1.7'
Expand Down
Original file line number Diff line number Diff line change
@@ -1,43 +1,47 @@
package org.opensearch.migrations.replay;

import com.amazonaws.secretsmanager.caching.SecretCache;
import lombok.extern.slf4j.Slf4j;
import software.amazon.awssdk.services.secretsmanager.SecretsManagerAsyncClient;
import software.amazon.awssdk.services.secretsmanager.model.GetSecretValueResponse;

import java.nio.charset.Charset;
import java.util.Base64;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;

@Slf4j
public class AWSAuthService implements AutoCloseable {

private final SecretCache secretCache;
private final SecretsManagerAsyncClient secretsManagerClient;

public AWSAuthService(SecretCache secretCache) {
this.secretCache = secretCache;
public AWSAuthService(SecretsManagerAsyncClient secretsManagerClient) {
this.secretsManagerClient = secretsManagerClient;
}

public AWSAuthService() {
this(new SecretCache());
this(SecretsManagerAsyncClient.builder().build());
}

// SecretId here can be either the unique name of the secret or the secret ARN
public String getSecret(String secretId) {
return secretCache.getSecretString(secretId);
public CompletableFuture<GetSecretValueResponse> getSecret(String secretId) {
return secretsManagerClient.getSecretValue(builder -> builder.secretId(secretId));
}

/**
* This method returns a Basic Auth header string, with the username:password Base64 encoded
* This method synchronously returns a Basic Auth header string, with the username:password Base64 encoded
* @param username The plaintext username
* @param secretId The unique name of the secret or the secret ARN from AWS Secrets Manager. Its retrieved value
* will fill the password part of the Basic Auth header
* @return Basic Auth header string
*/
public String getBasicAuthHeaderFromSecret(String username, String secretId) {
String authHeaderString = username + ":" + getSecret(secretId);
public String getBasicAuthHeaderFromSecret(String username, String secretId) throws ExecutionException, InterruptedException {
String secretValue = getSecret(secretId).get().secretString();
String authHeaderString = username + ":" + secretValue;
return "Basic " + Base64.getEncoder().encodeToString(authHeaderString.getBytes(Charset.defaultCharset()));
}

@Override
public void close() {
secretCache.close();
secretsManagerClient.close();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,8 @@ private static String formatAuthArgFlagsAsString() {
.collect(Collectors.joining(", "));
}

private static IAuthTransformerFactory buildAuthTransformerFactory(Parameters params) {
private static IAuthTransformerFactory buildAuthTransformerFactory(Parameters params)
throws ExecutionException, InterruptedException {
if (params.removeAuthHeader &&
params.authHeaderValue != null &&
params.useSigV4ServiceAndRegion != null &&
Expand Down
Original file line number Diff line number Diff line change
@@ -1,32 +1,41 @@
package org.opensearch.migrations.replay;

import com.amazonaws.secretsmanager.caching.SecretCache;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import software.amazon.awssdk.services.secretsmanager.SecretsManagerAsyncClient;
import software.amazon.awssdk.services.secretsmanager.model.GetSecretValueResponse;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.function.Consumer;

import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.when;

@ExtendWith(MockitoExtension.class)
public class AWSAuthServiceTest {

@Mock
private SecretCache secretCache;
private SecretsManagerAsyncClient secretsManagerClient;

@Test
public void testBasicAuthHeaderFromSecret() {
public void testBasicAuthHeaderFromSecret() throws ExecutionException, InterruptedException {
String testSecretId = "testSecretId";
String testUsername = "testAdmin";
String expectedResult = "Basic dGVzdEFkbWluOmFkbWluUGFzcw==";

when(secretCache.getSecretString(testSecretId)).thenReturn("adminPass");
GetSecretValueResponse response = GetSecretValueResponse.builder().secretString("adminPass").build();
CompletableFuture<GetSecretValueResponse> responseFuture = CompletableFuture.completedFuture(response);

when(secretsManagerClient.getSecretValue(any(Consumer.class))).thenReturn(responseFuture);

AWSAuthService awsAuthService = new AWSAuthService(secretCache);
AWSAuthService awsAuthService = new AWSAuthService(secretsManagerClient);
String header = awsAuthService.getBasicAuthHeaderFromSecret(testUsername, testSecretId);
Assertions.assertEquals(expectedResult, header);
}


}
}

0 comments on commit 2448c98

Please sign in to comment.