diff --git a/examples/rds-mfa-test/README.md b/examples/rds-mfa-test/README.md index 3bd547d..c7e4a07 100644 --- a/examples/rds-mfa-test/README.md +++ b/examples/rds-mfa-test/README.md @@ -1,91 +1,271 @@ +# IAM DB Authentication for Aurora PostgreSQL / Amazon RDS PostgreSQL -1. **Enable IAM authentication on the Postgres DB instance or Aurora Postgres Cluster** +This guide shows how to enable IAM database authentication and connect using: +- `psql` +- `pgAdmin` +- `DBeaver` -**Terraform:** +It includes CLI commands and sample CLI output you can compare against your environment. -Set iam\_database\_authentication\_enabled = true within the Instance or the Cluster resource and apply. +## References -**Console:** +- AWS Docs (RDS IAM DB Authentication): https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/UsingWithRDS.IAMDBAuth.html +- AWS Docs (Connecting with IAM token): https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/UsingWithRDS.IAMDBAuth.Connecting.html +- AWS Docs (Aurora IAM DB Authentication): https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/UsingWithRDS.IAMDBAuth.html +- AWS Blog: Using IAM authentication to connect with pgAdmin Amazon Aurora PostgreSQL or Amazon RDS for PostgreSQL: https://aws.amazon.com/blogs/database/using-iam-authentication-to-connect-with-pgadmin-amazon-aurora-postgresql-or-amazon-rds-for-postgresql/ -* 1. Enable IAM Authentication on the DB Instance - 1. Go to **RDS Console** → Select your **DB instance or the Cluster**. - 2. Choose **Modify**. - 3. Scroll to **Database Authentication**. - 4. Set **IAM DB authentication** to **Enabled**. - 5. Click **Continue** → **Apply Immediately** or during the next maintenance window. - 6. This allows the DB instance to accept IAM token-based logins +## Prerequisites -**CLI:** +1. PostgreSQL engine on Amazon RDS or Aurora PostgreSQL. +2. TLS/SSL enabled from client to database. +3. AWS CLI v2 installed and authenticated. +4. Identity Center (SSO) login completed with MFA. +5. PostgreSQL user exists for your login name (or mapped username). +Optional but recommended: +- Download the AWS RDS CA bundle for strict certificate validation: + https://truststore.pki.rds.amazonaws.com/global/global-bundle.pem + +## 1. Enable IAM authentication on the database + +Choose one path depending on your deployment type. + +### RDS PostgreSQL instance + +```bash aws rds modify-db-instance \ - --db-instance-identifier \ - --enable-iam-database-authentication \ - --apply-immediately + --db-instance-identifier my-postgres-instance \ + --enable-iam-database-authentication \ + --apply-immediately +``` + +Example output: +```json +{ + "DBInstance": { + "DBInstanceIdentifier": "my-postgres-instance", + "Engine": "postgres", + "IAMDatabaseAuthenticationEnabled": true, + "DBInstanceStatus": "modifying" + } +} +``` + +### Aurora PostgreSQL cluster + +```bash aws rds modify-db-cluster \ - --db-cluster-identifier your-aurora-cluster-identifier \ - --enable-iam-database-authentication \ - --apply-immediately + --db-cluster-identifier my-aurora-pg-cluster \ + --enable-iam-database-authentication \ + --apply-immediately +``` -1. **Create IAM User/Role and assign IAM Policy (Please Confirm with Matt Morgan from SCT - INC000003161057)** +Example output: -Policy: +```json +{ + "DBCluster": { + "DBClusterIdentifier": "my-aurora-pg-cluster", + "Engine": "aurora-postgresql", + "IAMDatabaseAuthenticationEnabled": true, + "Status": "modifying" + } +} +``` -For RDS: +## 2. Create or update IAM policy for connect permission +Grant `rds-db:connect` to the exact DB user ARN. + +### Policy example for RDS PostgreSQL + +```json { - "Version" : "2012-10-17", - "Statement" : - [ + "Version": "2012-10-17", + "Statement": [ { - "Effect" : "Allow", - "Action" : ["rds-db:connect"], - "Resource" : ["arn:aws:rds-db:us-east-1:123456789012:dbuser:db-ABCDEFGHIJKL01234/mydbuser"] + "Effect": "Allow", + "Action": ["rds-db:connect"], + "Resource": ["arn:aws:rds-db:us-east-1:123456789012:dbuser:db-ABCDEFGHIJKL01234/mydbuser"] } - ] + ] } -For Aurora: +``` + +### Policy example for Aurora PostgreSQL +```json { - "Version" : "2012-10-17", - "Statement" : - [ + "Version": "2012-10-17", + "Statement": [ { - "Effect" : "Allow", - "Action" : ["rds-db:connect"], - "Resource" : ["arn:aws:rds-db:us-east-1:123456789012:dbuser:cluster-ABCDEFGHIJKL01234/mydbuser"] + "Effect": "Allow", + "Action": ["rds-db:connect"], + "Resource": ["arn:aws:rds-db:us-east-1:123456789012:dbuser:cluster-ABCDEFGHIJKL01234/mydbuser"] } - ] + ] } +``` + +Attach the policy to the IAM role/user you assume for database access. + +## 3. Grant database user membership to `rds_iam` + +Connect as an admin user and run: + +```sql +CREATE USER mydbuser WITH LOGIN; +GRANT rds_iam TO mydbuser; +``` + +Validation query: + +```sql +\du mydbuser +``` + +Example output: + +```text +Role name | Attributes | Member of +----------+------------+----------------- +mydbuser | | {rds_iam} +``` + +## 4. Authenticate to AWS with MFA (Identity Center / SSO) + +If using AWS CLI SSO profile: + +```bash +aws sso login --profile prod-db +``` + +Example output: + +```text +Attempting to automatically open the SSO authorization page in your default browser. +Successfully logged into Start URL: https://start.us-gov-east-1.us-gov-home.awsapps.com/directory/d-c2672d0b4e#/ +``` + +## 5. Generate an IAM auth token + +Set variables: + +```bash +export AWS_PROFILE=prod-db +export AWS_REGION=us-east-1 +export DBHOST=my-postgres-instance.abcdefghijkl.us-east-1.rds.amazonaws.com +export DBPORT=5432 +export DBUSER=mydbuser +``` + +Generate token: + +```bash +export PGPASSWORD="$(aws rds generate-db-auth-token \ + --hostname "$DBHOST" \ + --port "$DBPORT" \ + --region "$AWS_REGION" \ + --username "$DBUSER")" +``` + +Example output: + +```text +No stdout output. Token stored in PGPASSWORD. +``` + +Token notes: +- Token lifetime is about 15 minutes. +- Generate a new token before each new connection if needed. + +## 6. Connect with psql + +```bash +psql "host=$DBHOST port=$DBPORT dbname=postgres user=$DBUSER sslmode=require" +``` + +Example output: + +```text +psql (16.4, server 15.6) +SSL connection (protocol: TLSv1.2, cipher: ECDHE-RSA-AES256-GCM-SHA384) +Type "help" for help. + +postgres=> select current_user, inet_client_addr(); + current_user | inet_client_addr +--------------+----------------- + mydbuser | 10.100.42.17 +(1 row) +``` + +If you use CA verification, replace `sslmode=require` with: -1. **Enable IAM authentication for the database JBID user** +```bash +sslmode=verify-full sslrootcert=/path/to/global-bundle.pem +``` -Grant rds\_iam to ; +## 7. Connect with pgAdmin -1. Launch the URL from production network to access AWS Console using Identity Center +1. Open pgAdmin and create a new server registration. +2. In Connection tab: + - Host name/address: your RDS or Aurora endpoint + - Port: `5432` + - Maintenance database: `postgres` (or target DB) + - Username: `mydbuser` + - Password: paste the generated IAM token +3. In SSL tab: + - SSL mode: `require` (or `verify-full` with CA cert) + - Root certificate: path to `global-bundle.pem` if using `verify-full` +4. Save and connect before token expiration. - +Expected behavior: +- Connection succeeds. +- If token expires, pgAdmin prompts again; generate a new token and reconnect. -![](images/image_1.png) +## 8. Connect with DBeaver -Once verified via the phone Okta verify app, successfully logged in. +1. Create a new PostgreSQL connection. +2. Main settings: + - Host: your RDS or Aurora endpoint + - Port: `5432` + - Database: `postgres` (or target DB) + - Username: `mydbuser` + - Password: paste generated IAM token +3. SSL settings: + - Enable SSL + - Mode: `require` or `verify-full` + - CA certificate: `global-bundle.pem` when using verification +4. Click Test Connection, then Finish. -![](images/image_2.png) +Expected behavior: +- Test connection succeeds while token is valid. +- Regenerate token when prompted after expiration. -![](images/image_3.png) +## Troubleshooting -Retrieve the Access keys: +### `FATAL: PAM authentication failed` -![](images/image_4.png) +Check: +- IAM auth is enabled on instance/cluster. +- IAM principal has correct `rds-db:connect` ARN. +- Database user exists and has `rds_iam` membership. +- Username in token command exactly matches DB user. -Generate DB token after setting the keys in Power shell or Command prompt. +### `The security token included in the request is invalid` -![](images/image_5.png) +Check: +- AWS profile/session is active. +- `aws sso login --profile ...` was completed. +- Region and endpoint are correct. -![](images/image_6.png) +### SSL or certificate errors -Copy the token and paste in the password box in PGADMIN or DBeaver tools. +Check: +- Client uses SSL. +- Root CA bundle path is valid when using `verify-ca` or `verify-full`. -Token can be obtained only after getting authenticated with MFA. +## Optional screenshots from this example -Login should be successful. +Screenshots in [images/](images/) can be used to supplement the SSO and token workflow in your runbook.