Manage RDS access with AWS Secrets Manager

monkey intern picture monkey intern · Jun 11, 2018 · Viewed 9.6k times · Source

I am currently working with Eclipse and the AWS Toolkit for Eclipse. My project already works and it is doing its job, which is to connect to an RDS instance and return JSON objects to API Gateway calls.

I just got a new requirement, we are to use the service SecretsManager to authomatically rotate RDS configuration such as Users, passwords and so on.

The problem is when I try to import classes such as GetSecretValueResponse, I get a The import com.amazonaws.services.secretsmanager cannot be resolved. When I explore the documentation and the SDK, there exists a GetSecretValueRequest but not a GetSecretValueResponse, so I am not being able to make sense on what should I do, nor I have found anything similar to an example I can study.

The following code is what I am trying to implement and is given by Amazon itself (in the Secrets Manager page there is a button you can click to see how it would go with Java, in this case), and it is presented without any modification yet because as I said I do not know how to import several classes:

// Use this code snippet in your app.
public static void getSecret() {
String secretName = "secretName";
String endpoint = "secretEndpoint";
String region = "region";

AwsClientBuilder.EndpointConfiguration config = new AwsClientBuilder.EndpointConfiguration(endpoint, region);
AWSSecretsManagerClientBuilder clientBuilder = AWSSecretsManagerClientBuilder.standard();
clientBuilder.setEndpointConfiguration(config);
AWSSecretsManager client = clientBuilder.build();

String secret;
ByteBuffer binarySecretData;
GetSecretValueRequest getSecretValueRequest = GetSecretValueRequest.builder()
        .withSecretId(secretName)
        .build();
GetSecretValueResponse getSecretValueResponse = null;
try {
    getSecretValueResponse = client.getSecretValue(getSecretValueRequest);

} catch(ResourceNotFoundException e) {
    System.out.println("The requested secret " + secretName + " was not found");
} catch (InvalidRequestException e) {
    System.out.println("The request was invalid due to: " + e.getMessage());
} catch (InvalidParameterException e) {
    System.out.println("The request had invalid params: " + e.getMessage());
}

if(getSecretValueResponse == null) {
    return;
}

// Decrypted secret using the associated KMS CMK
// Depending on whether the secret was a string or binary, one of these fields will be populated
if(getSecretValueResponse.getSecretString() != null) {
    secret = getSecretValueResponse.getSecretString();
}
else {
    binarySecretData = getSecretValueResponse.getSecretBinary();
}

// Your code goes here. 
}

Answer

Nune Isabekyan picture Nune Isabekyan · Jun 13, 2018

I had the same problem, the code that is present on AWS page doesn't work out of the box. The class you are looking for is GetSecretValueResult Here are the latest java docs

https://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/services/secretsmanager/model/GetSecretValueResult.html

Here is a piece that shall work:

public void printRdsSecret() throws IOException {
    String secretName = "mySecretName";

    System.out.println("Requesting secret...");
    AWSSecretsManager client = AWSSecretsManagerClientBuilder.standard().build();

    GetSecretValueRequest getSecretValueRequest = new GetSecretValueRequest().withSecretId(secretName);

    GetSecretValueResult getSecretValueResult = client.getSecretValue(getSecretValueRequest);

    System.out.println("secret retrieved ");
    final String secretBinaryString = getSecretValueResult.getSecretString();
    final ObjectMapper objectMapper = new ObjectMapper();

    final HashMap<String, String> secretMap = objectMapper.readValue(secretBinaryString, HashMap.class);

    String url = String.format("jdbc:postgresql://%s:%s/dbName", secretMap.get("host"), secretMap.get("port"));
    System.out.println("Secret url = "+url);
    System.out.println("Secret username = "+secretMap.get("username"));
    System.out.println("Secret password = "+secretMap.get("password"));
 }

This was tested with aws-java-sdk-secretsmanager of version 1.11.337