Skip to content

End-to-end IAM for RDS postgres

0

My goal is to be able to assume a role in an account and using IAM connect to an RDS Proxy backed by a RDS Postgres DB

RDS Info:

  • CA is rds-ca-rsa2048-g1
  • SG allows inbound from the proxy SG on 5432 TCP and 0.0.0.0/0 to allow for direct connections
  • IAM DB authentication is "Enabled

Proxy Info:

  • Proxy is attached to my subnets
  • SG allows outbound to the RDS DB SG on tcp 5432
  • Endpoint status is available
  • Target Groups is available
  • Default authentication scheme is IAM Authentication

My role I assume has a permissiong policy like the following

{
    "Statement": [
        {
            "Action": [
                "rds-db:connect"
            ],
            "Effect": "Allow",
            "Resource": [
                "arn:aws:rds-db:us-west-2:1234:dbuser:*/*"
            ]
        }
    ],
    "Version": "2012-10-17"
}

I originally had it as the following but that did not help.

"arn:aws:rds-db:us-west-2:1234:dbuser:prx-abcd/dbuser",
"arn:aws:rds-db:us-west-2:1234:dbuser:db-abcd/dbuser"]

My Proxies IAM role permission is set to

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "AllowProxyToConnectToDB",
            "Effect": "Allow",
            "Action": "rds-db:connect",
            "Resource": [
                "arn:aws:rds-db:us-west-2:1234:dbuser:db-abcd/dbuser"
            ]
        },
        {
            "Sid": "AllowProxyToReadSecret",
            "Effect": "Allow",
            "Action": [
                "secretsmanager:GetSecretValue"
            ],
            "Resource": [
                "arn:aws:secretsmanager:us-west-2:1234:secret:test_user_db_password-ABCD"
            ]
        }
    ]

The trust relationship is

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "Service": "rds.amazonaws.com"
            },
            "Action": "sts:AssumeRole"
        }
    ]
}

}

I have created the user in the database itself

postgres=> \du
                                                                                        List of roles
    Role name    |                         Attributes                         |                                                  Member of                                                   
-----------------+------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------
 dbuser |                                                            | {pg_read_all_data,pg_write_all_data,rds_iam}

I use a script to assume the role identity and then get the token

import boto3
REGION="us-west-2"
ENDPOINT="proxy-foo.proxy-sawdc21caw.us-west-2.rds.amazonaws.com"
PORT="5432"
USR="dbuser"
sts_client = boto3.client('sts')
assumed_role_object=sts_client.assume_role(
    RoleArn="arn:aws:iam::1234:role/dbuser",
    RoleSessionName="AssumeRoleSession1"
)

credentials=assumed_role_object['Credentials']
client = boto3.client(
    'rds',
    aws_access_key_id=credentials['AccessKeyId'],
    aws_secret_access_key=credentials['SecretAccessKey'],
    aws_session_token=credentials['SessionToken'], 
    region_name=REGION )

token = client.generate_db_auth_token(DBHostname=ENDPOINT, Port=PORT, DBUsername=USR, Region=REGION)
print(f"export PGPASSWORD=\"{token}\"")
print(f"psql \"host={ENDPOINT} port={PORT} dbname=postgres user={USR} sslmode=require\"")

When I try to connect to the proxy I get this error though

psql: error: connection to server at "proxy-foo.proxy-sawdc21caw.us-west-2.rds.amazonaws.com" (10.0.2.174), port 5432 failed: SSL connection has been closed unexpectedly

I am confused on if this is able to be done or not. Documentation exists talking about IAM users with RDS such as https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/UsingWithRDS.IAMDBAuth.DBAccounts.html#UsingWithRDS.IAMDBAuth.DBAccounts.PostgreSQL I also see others talking about this online though with issues with certain libraries https://github.com/MagicStack/asyncpg/issues/952

However in the command help for aws rds modify-db-proxy it states

              IAMAuth -> (string)
                A value that indicates whether to require or disallow Amazon
                Web Services Identity and Access Management (IAM)
                authentication for connections to the proxy. The ENABLED value
                is valid only for proxies with RDS for Microsoft SQL Server.

So the question is how does one actually set this up, what is wrong with my configuration? Is it possible to do this?

asked a year ago595 views

3 Answers
1

Hello.

I tried it with my AWS account and was able to access it successfully.
When creating the RDS Proxy, I enabled IAM authentication as follows:
a

The following IAM policy is set for the RDS Proxy IAM role:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "rds-db:connect"
            ],
            "Resource": [
                "arn:aws:rds-db:ap-northeast-1:123456789012:dbuser:db-123456789012/postgres"
            ]
        }
    ]
}

The database user has IAM authentication enabled with the following command.

CREATE USER dbuser;
GRANT rds_iam TO dbuser;
GRANT CONNECT ON DATABASE postgres TO dbuser;

Finally, I connected to the VPC from CloudShell using the following command.

export PGPASSWORD=$(aws rds generate-db-auth-token --hostname hogerdsproxy.proxy-1234567890.ap-northeast-1.rds.amazonaws.com --port 5432 --username dbuser)
psql "host=hogerdsproxy.proxy-1234567890.ap-northeast-1.rds.amazonaws.com port=5432 dbname=postgres user=dbuser password=$PGPASSWORD sslmode=require"

The security group is configured as follows:

RDS Proxy SG (Inbound)

TypeProtocolPort rangeSource
PostgreSQLTCP5432Client SG

RDS SG (Inbound)

TypeProtocolPort rangeSource
PostgreSQLTCP5432RDS Proxy SG

By the way, I confirmed that I can connect even if I create a token etc. using the script you created.
The following IAM policy is set for "arn:aws:iam::1234:role/dbuser".

{
    "Statement": [
        {
            "Action": [
                "rds-db:connect"
            ],
            "Effect": "Allow",
            "Resource": [
                "arn:aws:rds-db:ap-northeast-1:123456789012:dbuser:prx-12345678/dbuser"
            ]
        }
    ],
    "Version": "2012-10-17"
}
EXPERT

answered a year ago

  • Thanks for the reply. I am confused about your use of the IAM policy; the GUI gives this as a template

    arn:aws:rds-db:{Region}:{Account}:dbuser:{DbiResourceId}/{DbUserName}

    Your ARN would assume that the DB username is postgres "arn:aws:rds-db:ap-northeast-1:123456789012:dbuser:db-123456789012/postgres"

    Your SQL commands to create a user, however, imply that dbuser is the user.

    Can you clarify?

  • When creating the RDS Proxy, I set "postgres" as the database user in the "Database accounts for IAM authentication" item. As a result, "postgres" was used to connect from the RDS Proxy to the RDS instance. In other words, I think that "postgres" is used between RDS Proxy and RDS. If you change "Database accounts for IAM authentication", "dbuser" will be used. a

    By changing "Database accounts for IAM authentication" to "dbuser", the database user name in the IAM policy ARN will change to "arn:aws:rds-db:ap-northeast-1:123456789012:dbuser:db-123456789012/dbuser".

  • Thanks for the follow-up. I did the same now and the new role created has the resource "arn:aws:rds-db:us-west-2:123:dbuser:db-123/dbuser" It however still does not allow me to connect, if I go back to modify the IAM authentication was changed to "Not Allowed" I set it to "Required" when I created the proxy and have recreated it twice now and both times it has changed.

    aws rds --profile AdministratorAccess-123 describe-db-proxies --db-proxy-name proxy-three { "DBProxies": [ { "DBProxyName": "proxy-three", "DBProxyArn": "arn:aws:rds:us-west-2:123:db-proxy:prx-123", "Status": "available", "EngineFamily": "POSTGRESQL", "VpcId": "vpc-123", "VpcSecurityGroupIds": [ "sg-123" ], "VpcSubnetIds": [ "subnet-123", "subnet-123", "subnet-123" ], "Auth": [], "RoleArn": "arn:aws:iam::123:role/service-role/rds-proxy-role-1761715570966", "Endpoint": "proxy-three.proxy-123.us-west-2.rds.amazonaws.com", "RequireTLS": true, "IdleClientTimeout": 1800, "DebugLogging": true, "CreatedDate": "2025-10-29T05:26:12.091000+00:00", "UpdatedDate": "2025-10-29T05:33:15.407000+00:00" }

  • In my environment, the error "port 5432 failed: SSL connection has been closed unexpectedly" does not occur. Try connecting from CloudShell once connected to the VPC.

  • So I did more troubleshooting. It seems that I can connect from ec2 but the issue seems to be EKS. I have a cluster in a separate account that is attached to a second accounts VPC. The RDS Proxy and DB are in that second account VPC also. If I try to psql from EC2 with the iam token it works, if I do the exact same command with the same role in EKS it fails.

    Strangely though if I use psycopg2 it works. I have an open case with AWS to look dive deeper but the fact psycopg2 works means I can likely progress with my work. It is really strange though

    I have checked psql version, ldd and both are the same. Networking should be working or else psycopg2 would not work.

0
  1. It seems like the web portal requires you to add in secrets no matter what, does this affect the usage of end-to-end IAM? If I remove Secrets Manager Secrets in the proxy configuration page the IAM authentication field falls back to "Not Allowed" which would seem to be a step backwards.

  2. I am aware of the broad policies, I am trying to get this working and am trying a lot of things to get a connection to work. As mentioned before I did have them set to more specific values and will work on tightening them up once I find out the root cause here.

  3. I added the connect privilege though I think it was allowed before postgres=> GRANT CONNECT ON DATABASE postgres TO dbuser; GRANT

  4. I have tried now to connect now with verify-full and using multiple different Root CA PEMs found at https://www.amazontrust.com/repository/ and none have worked. I have also tried the globa-bundle.pem located at https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/UsingWithRDS.SSL.html

  5. Token generation is using the proxy and one of the first things in the token is the url of the proxy endpoint. I went ahead and changed the iam resources as requested to the prx arn with my correct account/proxy id/user name

For the proxy what exactly should I have for each field under Authentication? I currently have Default authentication scheme: IAM Authentication Identity and access management (IAM) role: my proxy's role which is separate from my dbuser Secrets Manager Secrets: test_user_db_password (this is just some BS password that I used to get past the web UIs gating) Client authentication type: SCRAM SHA 256 IAM authentication: Required

Connectivity has "Require Transport Layer Security" enabled

For the security groups, it should be enough to have Proxy SG

  • Outbound to the RDS SG on 5432 RDS SG
  • Inbound from the Proxy SG on 5432

Correct?

answered a year ago

-1

Based on the information provided, you're trying to set up end-to-end IAM authentication with RDS Proxy for PostgreSQL. This is a feature that was announced in September 2025 and is now available for MySQL and PostgreSQL database engines.

Here are some issues with your current setup and how to fix them:

  1. IAM Authentication Configuration: End-to-end IAM authentication eliminates the need for Secrets Manager credentials. However, your proxy IAM role still includes permissions to read secrets from Secrets Manager, which suggests you might be mixing the standard IAM authentication approach with end-to-end IAM authentication.

  2. IAM Policy Resource Scope: Your role's permission policy uses a wildcard (arn:aws:rds-db:us-west-2:1234:dbuser:*/*) which is very broad. For better security, you should specify the exact proxy and database user ARN.

  3. Database User Setup: While you've created the database user and added it to the rds_iam group, ensure that this user has been granted the CONNECT privilege on the database you're trying to connect to.

  4. SSL/TLS Configuration: The error message indicates an SSL connection issue. When using IAM authentication with RDS Proxy, you must use TLS/SSL. Make sure you're using the correct SSL certificate (you mentioned rds-ca-rsa2048-g1) and that your sslmode is set to verify-full rather than just require.

  5. Token Generation: Ensure you're generating the token correctly. The token should be generated for the proxy endpoint, not the direct database endpoint.

Here's what you should do:

  1. Update your IAM policy to specifically target the proxy and user:
"Resource": "arn:aws:rds-db:us-west-2:1234:dbuser:prx-abcd/dbuser"
  1. If you're using end-to-end IAM authentication, you don't need the Secrets Manager permissions in your proxy role.

  2. Make sure your PostgreSQL user has the proper permissions:

GRANT CONNECT ON DATABASE postgres TO dbuser;
  1. Update your connection string to use verify-full for SSL mode and specify the correct certificate:
psql "host={ENDPOINT} port={PORT} dbname=postgres user={USR} sslmode=verify-full sslrootcert=/path/to/rds-ca-rsa2048-g1.pem"
  1. Ensure your security groups allow traffic between your client and the proxy.

The error message about SSL connection being closed unexpectedly often indicates either a certificate issue or a security group configuration problem. Double-check both of these aspects.

Regarding the aws rds modify-db-proxy help text you mentioned, that specific limitation about ENABLED being valid only for SQL Server applies to a different context and doesn't mean end-to-end IAM authentication isn't available for PostgreSQL.
Sources
What's New at AWS - Cloud Innovation & News
Connecting to a database through RDS Proxy - Amazon Relational Database Service
Setting up AWS IAM Authentication with Amazon RDS Proxy for Aurora PostgreSQL | AWS re:Post
Connecting to a database through RDS Proxy - Amazon Aurora

answered a year ago

You are not logged in. Log in to post an answer.

A good answer clearly answers the question and provides constructive feedback and encourages professional growth in the question asker.