Working with AWS Secrets Manager

Photo by Jason Dent on Unsplash

Problem

We want to be able to use secret credentials in our application without leaving them hard-coded or in a configuration file.

AWS Secrets Manager is an AWS service that provides us with an encrypted database were we can store our secrets securely in the cloud. Our application will connect to Secrets Manager at startup and retrieve all the secrets it needs.

Storing generic secrets in AWS Secrets Manager

  1. Open the AWS console and go to Services / Security, Identity, & Compliance / Secrets Manager.
  2. Click on Store a new secret.
  3. In Select secret type, choose “Other type of secrets”.
  4. Click on “Plaintext”.
    1. Why is this important? Storing secrets as plaintext instead of key-value pairs means that you won’t need to parse the secret contents as a json when you retrieve it. For this reason the plaintext option should be preferred by default.
  5. Delete the empty json object that AWS puts in the plaintext field, and replace it with the secret value you want to store
  6. In Select the encryption key, select “DefaultEncryptionKey“.
    1. AWS Secrets Manager works based on a separate AWS service called Key Management Service (KMS), which stores the key that will be use to encrypt your secret. AWS KMS doesn’t charge a fee if you use the default AWS managed key Secrets Manager creates in your account. If you choose to use a custom KMS key, then you can be charged at the standard AWS KMS rate.
  7. Click Next.
  8. In Secret name, enter a suitable name for the secret. This is the name we will use to retrieve the secret from the application. Secret name must contain only alphanumeric characters and the characters /_+=.@-.
  9. In Description, enter some text that allows to know the purpose of the secret.
  10. Click Next.
  11. In Configure automatic rotation, select “Disable automatic rotation”.
  12. Click Next.
  13. Click Store.

Retrieving secrets from AWS Secrets Manager

Follow these steps to retrieve a secret value from Secrets Manager in your application:

  1. If you haven’t done so, follow the steps at my previous post How to integrate a Java application with the AWS Java SDK to add the AWS SDK to the application.
  2. An EC2 instance can only have one role associated at any given time. This role can be changed at runtime, but the new role replaces the old one, so it’s not possible to attach more than
    one role to an instance. What you can do though, is attach any number of policies (i.e. rules) to the existing role. To enable access to AWS Secrets Manager, attach the SecretsManagerReadWrite policy to the instances’s role.
  3. In the code, use the following code snippet to create a bean that queries the secret from Secrets Manager in its construction (replace the_secret_name for the secret name and the_aws_region_where_you_are_operating for the appropriate region):
import com.amazonaws.services.secretsmanager.AWSSecretsManagerClientBuilder;
import com.amazonaws.services.secretsmanager.model.GetSecretValueRequest;
import com.amazonaws.services.secretsmanager.AWSSecretsManager;

import org.springframework.stereotype.Service;

@Service
public class MyPasswordRetriever {
    private String password;

    public MyPasswordRetriever() {
        this.password = "";

        String secretName = "<the_secret_name>";
        String region = "<the_aws_region_where_you_are_operating>";

        // Create a Secrets Manager client
        AWSSecretsManager client  = AWSSecretsManagerClientBuilder.standard()
                .withRegion(region)
                .build();

        GetSecretValueRequest getSecretValueRequest = new GetSecretValueRequest().withSecretId(secretName);
        // Retrieve value from Secrets Manager and decrypt it using the associated KMS CMK.
        this.password = client.getSecretValue(getSecretValueRequest).getSecretString();
    }
}

(Optional) Retrieving secrets from AWS Secrets Manager with the AWS CLI

  1. If you haven’t done so, install and configure the AWS CLI following the instructions at my previous post How to configure the AWS CLI.
  2. Use this command to retrieve a secret: aws secretsmanager get-secret-value --secret-id <the_secret_name>

Sources

Leave a comment