This guide will walk you through setting up AWS IAM authentication on your RDS Database, setup attribute based access control on your Identity Center roles. Then connect to that database using IAM with CLI and DataGrip clients.

RDS Database Setup

First, before we begin we must have IAM Authentication enabled on our RDS database. It can be checked by substituting the database name in this command.

export DATABASE_INSTANCE=<YOUR_RDS_DATABASE>

aws rds describe-db-instances \
    --db-instance-identifier $DATABASE_INSTANCE \
    --query 'DBInstances[].IAMDatabaseAuthenticationEnabled'

If its disabled run this command to enable it

aws rds modify-db-instance \
    --db-instance-identifier $DATABASE_INSTANCE \
    --apply-immediately \
    --enable-iam-database-authentication

User Creation

Once thats enabled we need to create a database user (or role) that is configured for IAM authentication.

Keep in mine that the username should correspond to a primary identity attribute for the connecting user. This could be an email or username, but groups/departments should be avoided since individual member actions cannot be tracked (non-repudiation)

MySQL

1
2
CREATE USER 'jane_doe' IDENTIFIED WITH AWSAuthenticationPlugin AS 'RDS';
ALTER USER 'jane_doe'@'%' REQUIRE SSL;

PostgreSQL

1
2
CREATE USER jane_doe;
GRANT rds_iam TO jane_doe;

Identity Center

ℹ️
The IAM policy for granting access can be used on IAM Users, but this should be avoided since they rely on hardcoded credentials for access.

To map AWS Identity Center attributes into permission policies we need to setup attribute based access control (ABAC). I’m doing it through Terraform (#IaC4tW), but this can be done through the console.

IAM Identity Center → Settings → Attributes for access control → Manage Attributes

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
data "aws_ssoadmin_instances" "this" {}

resource "aws_ssoadmin_instance_access_control_attributes" "this" {
  instance_arn = data.aws_ssoadmin_instances.this.arns[0]
  attribute {
    key = "username"
    value {
      # Note: The double dollar signs are used in Terraform to escape the inline variable declaration
      source = ["$${path:userName}"]
    }
  }
}

There are other IdP attributes that can be found here

Policy

How that the attribute is mapped lets create the policy that we can assign our Identity Center permission set.

I’m doing this again through Terraform which does the following things

  1. Queries to retrieve the RDS database information
  2. Creates a policy that grants RDS connect access to only the specified database and as the user (their username)
    1. The special sauce in the policy is the argument ${aws:PrincipalTag/username} which links to the attribute we setup in identity center
  3. The policy is attached to an existing group
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
data "aws_db_instance" "example" {
  db_instance_identifier = "your-db-instance-identifier"
}

resource "aws_iam_policy" "database_iam_authentication" {
  name        = "rds-database-iam-authentication"
  description = "RDS IAM RDS Authentication access"

  policy = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Sid      = "DatabaseConnect"
        Effect   = "Allow"
        Action   = "rds-db:connect"
        Resource = "arn:aws:rds-db:us-east-1:0123456789:dbuser:${data.aws_db_instance.example.resource_id}/$${aws:PrincipalTag/username}"
      }
    ]
  })
}

data "aws_ssoadmin_instances" "this" {}

resource "aws_ssoadmin_customer_managed_policy_attachment" "group_db_iam" {
  instance_arn       = data.aws_ssoadmin_instances.this.arns[0]
  permission_set_arn = aws_ssoadmin_permission_set.group.arn

  customer_managed_policy_reference {
    name = aws_iam_policy.database_iam_authentication.name
    path = aws_iam_policy.database_iam_authentication.path
  }
}

Usage

First, the RDS certificates needs to be downloaded or a specific region certificate can be downloaded here.

mkdir $HOME/.aws/rds/

curl https://truststore.pki.rds.amazonaws.com/global/global-bundle.pem > $HOME/.aws/rds/global-bundle.pem

CLI

export DATABASE_INSTANCE=<YOUR_RDS_DATABASE_ENDPOINT>
export PORT=<YOUR_RDS_DATABASE_PORT>

export TOKEN="$(aws rds generate-db-auth-token \
   --hostname $DATABASE_INSTANCE \
   --port $PORT \
   --region us-east-1 \
   --username jane_doe)"

MySQL

mysql --host=$DATABASE_INSTANCE \
      --port=$PORT \
      --ssl-ca=$HOME/.aws/rds/global-bundle.pem \
      --enable-cleartext-plugin \
      --user=jane_doe \
      --password=$TOKEN

PostgreSQL

PGPASSWORD=$TOKEN psql -h $DATABASE_INSTANCE -p $PORT \
    --username jane_doe \
    --dbname postgres \
    --set=sslmode=verify-full \
    --set=sslrootcert=$HOME/.aws/rds/global-bundle.pem

DataGrip

There are only a few UI database clients that support built in AWS IAM authentication and as a bonus it can do multiple DB types (mysql/postgresql)

If you don’t have DataGrip installed yet you can download it with brew or from the official website.

brew install --cask datagrip

By default DataGrip does not support IAM authentication, so we need to install the AWS plugin.

Click on the gear in the top right → PluginsMarketplace → Search for AWS ToolkitInstall

Once its been installed restart DataGrip

Database Setup

Adding a new database

Select “AWS IAM” for the authentication method Selecting the correct authentication method

Fill in the rest of the information:

  1. Name: The friendly DB name
  2. Host: The domain of the database
  3. Port: Database port
  4. User: The primary identity (The AWS Identity Center attribute)
  5. Credential profile: Corresponding profile to the permission set
  6. Region: AWS RDS region
  7. Database: Database to connect to

Switch to the SSH/SSL:

  1. put in the following path for the CA file ~/.aws/rds/global-bundle.pem
  2. Switch the mode to Full verification

Configure encrypted connection

Additional setup documentation can be found here

TablePlus

TablePlus is another one of the databases the supports AWS IAM Authentication in a roundabout manner.

It can be installed using Brew or downloaded directly from the website.

brew install --cask tableplus

Setup a new database and fill out the following information.

  • Name
  • Host
  • Port
  • Database

Click on the button to the right of the password field and select “Command Line”

TablePlus authentication method

Then for the password put in the following AWS command that generates the connection token.

Replace the following arguments in the command:

  • RDS Endpoint
  • RDS Port
  • AWS Region
  • Username
  • AWS Profile
aws rds generate-db-auth-token --hostname <YOUR_RDS_DATABASE_ENDPOINT> --port <YOUR_RDS_DATABASE_PORT> --region us-east-1 --username jane_doe --profile <DATABASE_PROFILE>

Finally, for SSL Mode choose “Verify CA” and import the CA certificate from where we downloaded it earlier $HOME/.aws/rds/global-bundle.pem

Configure TablePlus CA certificate

Now test the connection to make sure everything worked.