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