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.
- AWS Secret Manager
- AWS Systems Manager Parameter Store
- GCP Secret Manager
-
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. -
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
nameddev
. The value retrieved by theruntimevar
data source is interpolated into theurl
attribute using the${data.runtimevar.pass}
expression.
- The
-
Run
atlas schema inspect --env dev
to verify that Atlas is able to connect to the database.
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"
}
-
Create a encrypted parameter to store the database password using the AWS CLI:
aws ssm put-parameter \
--name "db-pass-demo" \
--value "p455w0rd" \
--region "us-east-1" \
--type "SecureString" \
--tags "Key=Env,Value=AtlasDemo"The CLI prints out:
{
"Version": 1,
"Tier": "Standard"
}Note the database parameter name and the region (
us-east-1
), we will use them in the next part. -
Create a new file named
atlas.hcl
with the following contents:data "runtimevar" "pass" {
url = "awsparamstore://db-pass-demo?region=us-east-1&decoder=string"
}
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 Parameter Store. - We define an
env
nameddev
. The value retrieved by theruntimevar
data source is interpolated into theurl
attribute using the${data.runtimevar.pass}
expression.
- The
-
Run
atlas schema inspect --env dev
to verify that Atlas is able to connect to the database.
-
Create a secret a secret to store the database password using the GCP CLI:
printf "p455w0rd" | gcloud secrets create db-pass-demo --data-file=-
The CLI prints out:
Created version [1] of the secret [db-pass-demo].
-
Create a new file named
atlas.hcl
with the following contents:data "runtimevar" "pass" {
url = "gcpsecretmanager://projects/my-project/secrets/db-pass-demo"
}
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 GCP Secret Manager. The URL is composed of the project and secret name. If you are working locally in a multi-project environment, you can find out the name of the active project by runninggcloud config get-value project
. - We define an
env
nameddev
. The value retrieved by theruntimevar
data source is interpolated into theurl
attribute using the${data.runtimevar.pass}
expression.
- The
-
Run
atlas schema inspect --env dev
to verify that Atlas is able to connect to the 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.
- aws_rds_token
- gcp_cloudsql_token
-
Enable IAM Authentication for your database. For instructions on how to do this, see the AWS documentation.
-
Create a database user and grant it permission to authenticate using IAM, see the AWS documentation for instructions.
-
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.
-
Create a new file named
atlas.hcl
with the following contents:- postgres
- mysql
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"
}locals {
user = "iamuser"
endpoint = "hostname-of-db.example9y7k.us-east-1.rds.amazonaws.com:3306"
}
data "aws_rds_token" "db" {
region = "us-east-1"
endpoint = local.endpoint
username = local.user
}
env "rds" {
url = "mysql://${local.user}:${urlescape(data.aws_rds_token.db)}@${local.endpoint}?tls=preferred&allowCleartextPasswords=true"
}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
namedrds
. The value retrieved by theaws_rds_token
data source is interpolated into theurl
attribute using the${data.aws_rds_token.db}
expression.
The gcp_cloudsql_token
data source generates a short-lived token for an GCP CloudSQL database
using IAM Authentication.
To use this data source:
-
Enable IAM Authentication for your database. For instructions on how to do this, see the GCP documentation.
-
Create a database user and grant it permission to authenticate using IAM, see the GCP documentation for instructions.
-
Create a file named
atlas.hcl
with the following contents:atlas.hcllocals {
user = "iamuser"
endpoint = "34.143.100.1:3306"
}
data "gcp_cloudsql_token" "db" {}
env "cloudsql" {
url = "mysql://${local.user}:${urlescape(data.gcp_cloudsql_token.db)}@${local.endpoint}/?allowCleartextPasswords=1&tls=skip-verify&parseTime=true"
}noteThe
allowCleartextPasswords
andtls
parameters are required for the MySQL driver to connect to CloudSQL. For PostgreSQL, usesslmode=require
to connect to the database.Let's breakdown the configuration:
- The
gcp_cloudsql_token
data source is used to retrieve the database password from GCP CloudSQL. - We define an
env
namedcloudsql
. The value retrieved by thegcp_cloudsql_token
data source is interpolated into theurl
attribute using the${data.gcp_cloudsql_token.db}
expression.
- The