Skip to main content

Working with secrets

Database credentials are considered sensitive information and should be treated as such. In this guide, we will show how to use Atlas to handle database credentials in a secure manner. We will present two strategies for handling database credentials, and show how to use Atlas to implement them: IAM Authentication and Secret Stores.

Secret Stores

Secret stores are systems or services that allow users to store and retrieve sensitive information. The main features of secret stores are encryption, access control, and auditing. All cloud providers offer some form of secret store service, and there are also many open-source alternatives.

When working with secret stores, Atlas assumes that the secret store is already provisioned and configured. Atlas supports the following secret stores:

Support for other secret stores is planned, if you have a specific request, please open an issue.

IAM Authentication

IAM authentication is a mechanism that allows users to authenticate to a database using their cloud provider credentials. The main advantage of IAM authentication is that it allows users to avoid storing database credentials altogether. Although setting this up may be more cumbersome, it is considered a best practice for many cloud providers. IAM authentication is also more secure than using passwords. Even strong passwords stored in encrypted form can be leaked and used by attackers. IAM authentication allows users to avoid storing database credentials altogether.

IAM authentication is currently supported on GCP and AWS. Support for other cloud providers is planned as well, if you have a specific request, please open an issue.

Retrieving Credentials from a Secret Store

Atlas can retrieve information from a secret store at runtime using the runtimevar data source. The runtimevar data source uses the runtimevar package from the Go CDK. To read more about using runtimevar with Atlas, view the data source documentation.

  1. Create a secret a secret to store the database password using the AWS CLI:

    aws secretsmanager create-secret \
    --name db-pass-demo \
    --secret-string "p455w0rd"

    The CLI prints out:

    {
    "ARN": "arn:aws:secretsmanager:us-east-1:1111111111:secret:db-pass-demo-aBiM5k",
    "Name": "db-pass-demo",
    "VersionId": "b702431d-174f-4a8f-aee5-b80e687b8bf1"
    }

    Note the database secret name and the region (us-east-1), we will use them in the next part.

  2. Create a new file named atlas.hcl with the following contents:

    data "runtimevar" "pass" {
    url = "awssecretsmanager://db-pass-demo?region=us-east-1"
    }

    env "dev" {
    url = "mysql://root:${data.runtimevar.pass}@host:3306/database"
    }

    Let's breakdown the configuration:

    • The runtimevar data source is used to retrieve the database password from AWS Secrets Manager.
    • We define an env named dev. The value retrieved by the runtimevar data source is interpolated into the url attribute using the ${data.runtimevar.pass} expression.
  3. Run atlas schema inspect --env dev to verify that Atlas is able to connect to the database.

note

If you using RDS Password Management, RDS will maintain a secret in JSON format similar to:

{
"username": "admin",
"password": "p455w0rd"
}

To decode the json payload and retrieve the password from it, use the jsondecode standard lib func. also notice this password may contain special characters and therefore must be escaped using the urlescape func.

Use the next atlas.hcl file as an example:

data "runtimevar" "pass" {
url = "awssecretsmanager://<rds_secret_name>?region=us-east-1"
}
locals {
pass = jsondecode(data.runtimevar.pass).password
}
env "dev" {
url = "mysql://root:${urlescape(local.pass)}@host:3306/database"
}

Using IAM Authentication

Atlas can retrieve short-lived credentials from the cloud provider and use them to connect to the database. The passwords are retrieved using special data sources that are specific to each cloud provider.

  1. Enable IAM Authentication for your database. For instructions on how to do this, see the AWS documentation.

  2. Create a database user and grant it permission to authenticate using IAM, see the AWS documentation for instructions.

  3. Create an IAM role with the "rds-db:connect" permission for the specific database and user. For instructions on how to do this, see the AWS documentation.

  4. Create a new file named atlas.hcl with the following contents:

    locals {
    user = "iamuser"
    endpoint = "hostname-of-db.example9y7k.us-east-1.rds.amazonaws.com:5432"
    }

    data "aws_rds_token" "db" {
    region = "us-east-1"
    endpoint = local.endpoint
    username = local.user
    }

    env "rds" {
    url = "postgres://${local.user}:${urlescape(data.aws_rds_token.db)}@${local.endpoint}/postgres"
    }

    Let's breakdown the configuration:

    • The aws_rds_token data source is used to retrieve the database password from AWS Secrets Manager.
    • We define an env named rds. The value retrieved by the aws_rds_token data source is interpolated into the url attribute using the ${data.aws_rds_token.db} expression.