AWS RDS database access via AWS SSM

Draft

Table of Contents

RDS IAM Authentication + SSM port forwarding

You CANNOT connect to a private RDS database using IAM auth without something inside the VPC.

User (IAM) > SSM tunnel > RDS PostgreSQL
                |
         IAM token used as DB password

There is no static database password anywhere.

Enable IAM auth on RDS using Terraform

This does NOT disable password authentication on your RDS PostgreSQL database. It simply adds IAM as an additional authentication method. Passwords will continue to work exactly as before.

resource "aws_db_instance" "postgres" {
  ...

  iam_database_authentication_enabled = true

  backup_retention_period = 7
}

This does NOT cause downtime.

Allow IAM to connect to PostgreSQL

Connect once using a normal admin user, then run:

CREATE USER iam_user WITH LOGIN;
GRANT rds_iam TO iam_user;

That user will never have a password — only IAM permissions.

You can create multiple IAM users/roles:

CREATE USER dev_user WITH LOGIN;
GRANT rds_iam TO dev_user;

IAM policy for AWS users

You should add outputs to your module/rds.tf:

output "db_identifier" {
  value       = aws_db_instance.this.id   # or .identifier
  description = "RDS DB identifier"
}

output "db_arn" {
  value = aws_db_instance.this.arn
}

You also need your data "aws_caller_identity" "current" {} somewhere in environment code. Without the account ID, the ARN is not valid and AWS will reject the policy.

Attach this to the AWS users or roles that should access the DB:

Also you can get the DB Resource ID from:

aws rds describe-db-instances \
  --db-instance-identifier <your-db> \
  --query "DBInstances[0].DbiResourceId"

IAM DB authentication only works with STS credentials, not long-term IAM user keys.

aws sts assume-role \
  --role-arn arn:aws:iam::<ACCOUNT_ID>:role/RDSAccessRole \
  --role-session-name testdb \
  --duration-seconds 3600

This returns:

AccessKeyId
SecretAccessKey
SessionToken

Now export these values:

export AWS_ACCESS_KEY_ID=<AccessKeyId>
export AWS_SECRET_ACCESS_KEY=<SecretAccessKey>
export AWS_SESSION_TOKEN=<SessionToken>
export AWS_REGION=<your-region>

Now your shell is operating as the RDSAccessRole, which has rds-db:connect.

Run a temp client pod inside EKS:

kubectl run rds-proxy \
  --image=alpine/socat \
  --restart=Never \
  --command -- \
  socat TCP-LISTEN:5432,fork TCP:<RDS-ENDPOINT>:5432

Port-forward from EKS to your laptop

kubectl port-forward rds-proxy 5432:5432

This is exactly the same as SSM port forwarding, just simpler.

localhost:5432 > EKS > VPC > RDS

November 27, 2025