What do you need to know about storing passwords in AWS?

In this article, I am going to show you how to use the AWS Secrets Manager to store the passwords used by your applications.

I am going to cover:

  • generating a random password

  • storing the password in the Secrets Manager

  • retrieving the password

  • securely passing the password to an application

Before we start, make sure that you have installed and configured AWS CLI and jq (a command-line JSON parser).

Generating a random password

We can use the AWS Secrets Manager to create a random password. It is going to be the initial password that we will later retrieve.

I want a password that is 32-characters long and contains all special characters, so I have to run the following command:

aws secretsmanager get-random-password --password-length 32 --require-each-included-type

That command produces the output which may look like this:

{
    "RandomPassword": "X#=a[ACfO5XY2U>rW<W7kXgzOjf^f~gj"
}

It is not very useful to have a password in a JSON, so I must modify the command to get only the password string:

aws secretsmanager get-random-password --password-length 32 --require-each-included-type | jq '.RandomPassword'
"X#=a[ACfO5XY2U>rW<W7kXgzOjf^f~gj"

Storing the password

I already have a command that generates a secure, random password. Now it is time to save the password in the Secrets Manager.

aws secretsmanager create-secret --name TutorialPassword --secret-string "$(aws secretsmanager get-random-password --password-length 32 --require-each-included-type | jq '.RandomPassword')"
``

```json
{
    "ARN": "arn:aws:secretsmanager:moon-1:1234:secret:TutorialPassword-yPT8Ns",
    "Name": "TutorialPassword",
    "VersionId": "48f6ddc5-4f16-47c7-8732-3221c599dab1"
}

Retrieving the password

To retrieve the password, I must use the get-secret-value command:

aws secretsmanager get-secret-value --secret-id TutorialPassword
{
    "ARN": "arn:aws:secretsmanager:moon-1:1234:secret:TutorialPassword-yPT8Ns",
    "Name": "TutorialPassword",
    "VersionId": "48f6ddc5-4f16-47c7-8732-3221c599dab1",
    "SecretString": "X#=a[ACfO5XY2U>rW<W7kXgzOjf^f~gj",
    "VersionStages": [
        "AWSCURRENT"
    ],
    "CreatedDate": 1575806162.892
}

Pass the secret to the application

Let’s start with a terrible idea. Never, ever pass any sensitive data as environment variables or runtime parameters. Such parameters are visible to anyone who has access to the machine that is running the program.

If the application is running in AWS ECS, I can add the following code to the container definition. It will create an environment variable inside the Docker container without displaying it anywhere.

{
    "containerDefinitions": [{
        "secrets": [{
            "name": "environment_variable_name",
            "valueFrom": "arn:aws:secretsmanager:moon-1:1234:secret:TutorialPassword-yPT8Ns"
        }]
    }]
}

Docker Swarm

If I managed running Docker containers on my own, I could use the “docker secret” command to add the secret to Docker Swarm:

aws secretsmanager get-secret-value --secret-id TutorialPassword | jq '.SecretString' | docker secret create my_password -

and later, when I run a new container, specify the secret parameter to automatically mount the password as a file available in the /run/secrets/my_password path.

docker service  create --name some_name --secret my_password docker_image_name:and_version

AWS SDK

It is also possible to use the AWS SDK to read the secrets directly in the application that needs them. This approach has an additional benefit because it allows us to change the password without restarting the application.

Obviously, it works only if the application reads the password from the Secrets Manager before every usage. It will not work if it loads all passwords once and keeps reusing them.

The implementation depends on the programming language you are using, so please check the official documentation.

Older post

Apache Spark: should we use RDD, Dataset, or DataFrame?

Is there a difference between Dataset and DataFrame? Why do we even have both?