Manage RDS access with AWS Secrets Manager

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


I think the main problem was in lack of dependencies to AWS SDK v2.

Adding a code snippet here that utilizes AWS SDK v2. Just in case anybody is looking for this.

package com.may.util;

import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.secretsmanager.SecretsManagerClient;
import software.amazon.awssdk.services.secretsmanager.model.DecryptionFailureException;
import software.amazon.awssdk.services.secretsmanager.model.GetSecretValueRequest;
import software.amazon.awssdk.services.secretsmanager.model.GetSecretValueResponse;
import software.amazon.awssdk.services.secretsmanager.model.InternalServiceErrorException;
import software.amazon.awssdk.services.secretsmanager.model.InvalidParameterException;
import software.amazon.awssdk.services.secretsmanager.model.InvalidRequestException;
import software.amazon.awssdk.services.secretsmanager.model.ResourceNotFoundException;

public class SecretsManagerUtil {

    public static String obtainSecret() {
        String secretName = "db_secret_name";
        String region = "us-east-1";

        SecretsManagerClient client = SecretsManagerClient.builder().region(Region.of(region)).build();
        GetSecretValueResponse response = null;

        try {
            response = client.getSecretValue(GetSecretValueRequest.builder().secretId(secretName).build());
        } catch (DecryptionFailureException e) {
            // Secrets Manager can't decrypt the protected secret text using the provided KMS key.
            // Deal with the exception here, and/or rethrow at your discretion.
            throw e;
        } catch (InternalServiceErrorException e) {
            // An error occurred on the server side.
            // Deal with the exception here, and/or rethrow at your discretion.
            throw e;
        } catch (InvalidParameterException e) {
            // You provided an invalid value for a parameter.
            // Deal with the exception here, and/or rethrow at your discretion.
            throw e;
        } catch (InvalidRequestException e) {
            // You provided a parameter value that is not valid for the current state of the resource.
            // Deal with the exception here, and/or rethrow at your discretion.
            throw e;
        } catch (ResourceNotFoundException e) {
            // We can't find the resource that you asked for.
            // Deal with the exception here, and/or rethrow at your discretion.
            throw e;
        }

        return response.secretString();
    }
}

Deserialize and print secret:

public class SecretPrinter {

private static final Logger logger = LoggerFactory.getLogger(SecretPrinter.class);

public void printSecret() {
    String json = SecretsManagerUtil.obtainSecret(); // secret in json format

    RdsSecret secret;
    try {
        secret = new ObjectMapper().disable(FAIL_ON_UNKNOWN_PROPERTIES).readValue(json, RdsSecret.class);
    } catch (IOException e) {
        logger.error("Couldn't parse secret obtained from AWS Secrets Manager!");
        throw new RuntimeException(e);
    }

    System.out.println("username: " + secret.getUsername());
    System.out.println("password: " + secret.getPassword());
}

static class RdsSecret {
    private String username;
    private String password;

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }
}

}

Maven:

<dependencyManagement>
  <dependencies>
    <dependency>
      <groupId>software.amazon.awssdk</groupId>
      <artifactId>bom</artifactId>
      <version>2.6.3</version>
      <type>pom</type>
      <scope>import</scope>
    </dependency>
  </dependencies>
</dependencyManagement>

<dependency>
  <groupId>software.amazon.awssdk</groupId>
  <artifactId>secretsmanager</artifactId>
</dependency>

Gradle:

implementation platform('software.amazon.awssdk:bom:2.6.3')
implementation 'software.amazon.awssdk:secretsmanager'

aws-secretsmanager-jdbc can be used to access AWS RDS via AWS secrete manager. https://github.com/aws/aws-secretsmanager-jdbc

Below is the content of my application.properties

spring.datasource.url=jdbc-secretsmanager:mysql://dev-xxxx-database.cluster-xxxxxxxxx.ap-southeast-1.rds.amazonaws.com:3306/dev_xxxxxx

spring.datasource.username=/secret/application
spring.datasource.driver-class-name=com.amazonaws.secretsmanager.sql.AWSSecretsManagerMySQLDriver

spring.jpa.database-platform = org.hibernate.dialect.MySQL5Dialect

Below is the secret in AWS secret manager.

enter image description here

By using this method, you don't need to obtain username and password manually and create data sources.