AWS Database Blog
Resilient IAM database authentication with Amazon Aurora Global Database writer endpoint
When you run Amazon Aurora Global Database across multiple AWS Regions for resilience, a cross-Region switchover or failover promotes a secondary Region to primary. If your application uses IAM database authentication for passwordless, token-based access, that promotion creates two problems for a connection:
Problem 1: The signing Region changes. Your Signature Version 4 (SigV4) token must be signed for a specific Region. After a failover, the primary is in a different Region, so a token signed for the old Region no longer works.
Problem 2: The primary or writer cluster resource ID changes. Your rds-db:connect permission authorizes a specific cluster resource ID. The newly promoted primary is a different cluster with a different resource ID, so the old authorization no longer applies.
Routing, notably, is not on that list. The Amazon Aurora Global Database writer endpoint is a single, stable DNS name for the whole Global cluster. Aurora automatically re-points it to the current writer, so your connection string never changes across a failover.
In this post, I show how to compose the Aurora Global Database writer endpoint with IAM authentication so that passwordless access survives a cross-Region switchover or failover with no configuration changes. I sign the token for the primary Region discovered dynamically at connection time, which solves Problem 1. I scope the rds-db:connect permission to every Regional cluster resource ID up front, which solves Problem 2. And I connect through the Global Database writer endpoint so that routing is handled automatically. I then run a planned switchover or failover to prove the pattern holds using the same endpoint, policy, and commands.
Overview
The key insight is that the Global writer endpoint handles routing, and AWS Identity and Access Management (IAM) handles authentication. These two concerns operate independently. You make three design choices so that they work together across a failover:
- Connect through the Global writer endpoint. The DNS name stays the same. Aurora automatically points it to the newly promoted primary, so your connection string never has to change.
- Sign the token for the current primary Region, discovered dynamically. The
generate-db-auth-tokencommand builds the token from four inputs: hostname, port, Region, and username. You keep the hostname pointed at the Global Database writer endpoint but set Region to whichever Region is currently the primary. Your application discovers that Region at connection time by runningdescribe-global-clusters. The writer’s ARN tells you which Region it’s in. - Scope the rds-db:connect permission to every cluster that can become primary. IAM database authentication doesn’t currently support policy condition keys. The least-privilege approach is to list the
DbClusterResourceIdof each Regional cluster in the IAM policy Resource list. Then authorization succeeds through the same endpoint no matter which cluster is the writer, with no policy edits on failover.
The rest of this post puts these three choices into practice with an AWS Command Line Interface (AWS CLI) walkthrough you can follow along with. It includes a switchover or failover test that confirms everything works without any configuration changes. The walkthrough uses an Amazon Aurora Global Database with a single secondary Region. Where relevant, I’ve included the equivalent commands for both the Amazon Aurora PostgreSQL and Aurora MySQL engines.
Prerequisites
- The AWS CLI installed and configured.
- An IAM principal (an IAM user or an assumed role) with the permissions needed to run the commands in this post — specifically
rds:DescribeDBClusters,rds:ModifyDBCluster,rds:DescribeGlobalClusters,rds:SwitchoverGlobalCluster,iam:CreatePolicy,rds:FailoverGlobalCluster,iam:AttachRolePolicy,iam:DetachRolePolicy, andiam:DeletePolicy. - An Aurora Global Database with two Regions. If you don’t already have one, follow Getting started with Amazon Aurora global databases to either create a new Global Database or add a secondary Region to an existing Aurora cluster.
- Basic understanding of IAM authentication with Aurora.
- A psql client (PostgreSQL) or mysql client (MySQL) to connect to the Aurora cluster.
- Cross-Region network connectivity from your client to both Regional clusters so you can connect after the writer moves.
- A test/staging environment where you can perform the steps described in this post.
Step 1: Configure the variables
In this step, you define the shell variables that the rest of the walkthrough reuses, such as the primary and secondary Region names and your account ID. Run every AWS CLI command and set shell variables in this post from a Bash shell (Linux, macOS Terminal, or Git Bash on Windows) with the AWS CLI configured. You can run these commands as any IAM principal that has the permissions listed in Prerequisites.
1.1 Get the Global Database identifier
Run the following command to capture the Global Database identifier (also called the global cluster identifier):
If the command returns a single identifier, capture it directly into a variable named GDI (Global Database identifier):
If you have multiple Aurora Global Database setups, the describe-global-clusters command returns multiple identifiers. Set GDI to the one you want to use:
1.2 Capture cluster, Region, and AWS account ID details
Here, you dynamically derive the DB cluster IDs, the Regions of both the primary and secondary clusters, and the AWS account ID. You store each in its own variable for reuse later in the post. This walkthrough assumes you already have an Aurora Global Database spanning two Regions. If you have multiple secondary Regions, adjust the commands as needed or set these variables manually.
1.3 Confirm (or enable) IAM authentication on both clusters
This walkthrough focuses on the IAM authentication configuration that makes the deployment failover-resilient. IAM database authentication is managed per DB cluster and must be enabled on every Regional cluster, so a connection authenticates no matter which Region is primary.
If it returns false, enable IAM authentication on the cluster in the primary Region:
Repeat the preceding step for the secondary cluster with its identifier and Region:
1.4 Record both cluster resource IDs and endpoints
You need the DbClusterResourceId and endpoint of each Regional cluster in the following steps. Capture them for both Regions using the following commands:
With --output as text and a multi-field query like [DbClusterResourceId, Endpoint], the two values come back tab-separated on one line, and read splits them into the two variables.
Step 2: Create the IAM policy scoped to both clusters
In this step, define the database user and create the IAM policy with the required permission.
2.1 Set the database user variable
First, store the database user name, app_user, in a shell variable named db_user. You create this user inside the database of the primary cluster later in Step 3.
2.2 Create the policy
The following command writes the policy document to a JSON file:
The policy contains two statements:
- The first statement grants
rds-db:connect, the minimum permission required to authenticate to the database with IAM authentication. Its Resource list includes one ARN for each Regional cluster, built from that cluster’s resource ID (from Step 1.4) and the database user (app_user). Because the policy covers both Regions, IAM authentication keeps working after a switchover or failover, and you don’t need to change the policy. - The second statement grants
rds:DescribeGlobalClusters, scoped to your global cluster. Your application needs this permission to discover the current primary Region at connection time, as shown in Step 4 and Step 5. Without it, the discovery call fails with anAccessDeniederror.
The following command uses this JSON file to create a new IAM policy and returns the policy ARN. For more information, see Creating and using an IAM policy for IAM database access.
2.3 Attach the policy
Attach the returned policy ARN to the IAM role your application uses to connect to Aurora, such as its Amazon Elastic Compute Cloud (Amazon EC2) instance role or AWS Lambda execution role. Replace <IAM_ROLE> with that role’s name.
Step 3: Create the database user mapped to IAM
In this step, create a database user called app_user that matches the IAM policy created in Step 2.2.
Aurora PostgreSQL
First, connect to the primary cluster as the master user using the following command, and enter the master password when prompted:
Modify the following parameters as needed:
sslrootcert=global-bundle.pem: AWS enforces SSL/TLS connections for IAM-based logins to make sure that these sensitive authentication tokens are safely encrypted while crossing the network. Download this file from Download certificate bundles for Amazon RDS.
dbname=demodb: I use a demodb database. If you already have an Aurora cluster, use your existing database name. There’s no need to create a new one for IAM authentication. If you’re setting this up on a brand-new cluster and don’t have an application database yet, you can create one first.
user=masteruser: Replace masteruser with the master user of your Aurora cluster.
After you connect to demodb on the primary cluster, create the IAM-mapped user and grant the necessary permissions. The user replicates automatically to the secondary cluster.
(Optional) Verify that the user replicated to the secondary cluster (connect as the master user, read-only):
Aurora MySQL
If you are using the MariaDB client, use the following command:
If you are using the Oracle MySQL client, use the following command:
Enter the master password when prompted, then run:
(Optional) Verify that the user replicated to the secondary cluster:
If you are using the MariaDB client:
If you are using the Oracle MySQL client:
Step 4: Connect through the Global Database writer endpoint
First, get the Aurora Global Database writer endpoint by running the following command:
Generate an IAM authentication token using the Global writer endpoint as the hostname and the current primary as the signing Region, then connect over TLS.
Aurora PostgreSQL:
The output looks similar to the following:
This query returns three columns that together prove who you connected as and which instance/role you landed on:
- current_user: The database user you’re authenticated as. It confirms you connected as
app_user(through the IAM token, not a password). - instance_name: The name of the specific Aurora DB instance you’re connected to. This tells you exactly which instance in which Region served your connection. In the preceding example, it’s
apg-primary-instance-1. - region_role (the CASE expression): Uses
pg_is_in_recovery()to determine whether this instance is a writer or a reader.pg_is_in_recovery()returns true on a reader/standby, since it’s still applying replication, so the instance is labeled Secondary (Reader). On the writer/primary it returns false, so the instance is labeled Primary (Writer).
Aurora MySQL:
This query returns the following three columns:
- current_user(): The database user you’re authenticated as.
- server_id (
@@aurora_server_id): The name of the specific Aurora DB instance you’re connected to. This tells you exactly which instance in which Region served your connection. - region_role (the IF expression): Uses
@@innodb_read_onlyto determine whether this instance is a writer or a reader.@@innodb_read_onlyis 1 on a reader/standby, since it only accepts read traffic, so the instance is labeled Secondary (Reader). On the writer/primary it is 0, so the instance is labeled Primary (Writer).
Step 5: Test database resilience
Promoting a secondary DB cluster to be primary can happen in two ways: a switchover or a failover. In this step, you test whichever option you choose, using the same Global writer endpoint, IAM policy, and connection commands from Step 4. Run only one of the following options during your test:
Option 1: Switchover
Use a switchover for planned operational procedures, such as maintenance or disaster recovery drills, when all Aurora clusters and the services they interact with are healthy. Trigger a planned switchover to the secondary Region:
Option 2: Managed failover
Use a failover to recover from an unplanned event, such as a Regional impairment. Unlike a switchover, a failover doesn’t wait for replication to catch up. Because Aurora replicates asynchronously, it can lose writes that hadn’t reached the secondary. Managed failover requires compatible engine versions on the primary and secondary clusters. If your database versions are incompatible, see Performing manual failovers for Aurora global databases.
Run this step only in a test environment, because it can result in data loss:
Wait for the switchover or failover to complete and for the global cluster status to return to Available.
Rediscovery of the Region
Run the same discovery as before, using the same Global writer endpoint, IAM policy, and commands. The only difference is that discovery now returns the promoted primary, so the token is signed for that Region automatically. During a Regional impairment, the discovery call must reach a healthy Region, so pass --region with any healthy member Region to the describe-global-clusters command. Without --region, the command uses the client’s default Region. If that Region is the impaired former primary, discovery fails and the application can’t sign a token, even though the writer endpoint has already moved.
From the preceding command you will see that the primary Region is now the Region that was previously the secondary.
Generate a new IAM authentication token with the same command as before.
Aurora PostgreSQL:
The output looks like the following:
After the switchover or failover, running the same query against the same endpoint returns a different instance name (in my example, it’s test-global-instance-1-us-east-2c), one in the other Region. The role still shows as Primary (Writer). This demonstrates that the endpoint re-pointed to the current primary Region on its own, and IAM authentication kept working, with no changes on your side.
Aurora MySQL:
This proves the pattern works. With a stable endpoint, a dynamically discovered signing Region, and a policy that already covers both clusters, you change nothing. Passwordless authentication survives the switchover or failover.
With and without the Amazon Aurora Global Database writer endpoint
Without the Aurora Global writer endpoint, you connect to a Regional cluster endpoint (for example, my-cluster.cluster-xxxx.us-east-1.rds.amazonaws.com). After a switchover or failover, that endpoint becomes read-only. Your application must then detect the promotion and re-point to the new primary Region’s cluster endpoint, typically through custom discovery, an Amazon Route 53 CNAME you update, or a redeploy. IAM authentication still needs the correct signing Region either way. The Global Database writer endpoint removes the routing half of the problem by giving you one stable name, managed by Aurora, for both routing and your SigV4 hostname.
Best practices
- Enforce TLS: Always connect with
sslmode=verify-fulland the RDS global bundle (--ssl-cafor MySQL). Non-TLS connections are rejected. - Enumerate every cluster ARN: IAM database authentication doesn’t support policy condition keys, so list the
rds-db:connectresource ARN for each Regional cluster’sDbClusterResourceId. Add the new cluster’s ARN whenever you attach a secondary Region to the Global Database. - Discover the signing Region dynamically, and cache it: Don’t hardcode
--region. Read the current primary Region fromdescribe-global-clusters, cache it in memory, and refresh it only when authentication fails or the connection drops. This control plane call is subject to throttling, so calling it for every connection can throttle your application, especially during a connection storm after a failover. - Handle token lifetime and DNS caching: Authentication tokens are valid for 15 minutes, so generate a fresh one per connection attempt. For details, see IAM database authentication. Also, respect the writer endpoint’s DNS TTL instead of caching resolved IPs indefinitely, so clients pick up the re-pointing promptly.
- Keep the Regions symmetric: Use non-overlapping virtual private cloud (VPC) CIDRs for cross-Region connectivity and keep cluster parameter groups at parity so behavior is identical after a switchover or failover.
- Use the AWS Advanced Drivers where available: Most production applications connect through a database driver, not the AWS CLI. The AWS Advanced JDBC Wrapper and the AWS Advanced Python Wrapper wrap the standard PostgreSQL and MySQL drivers and add an IAM authentication plugin. The plugin generates and refreshes authentication tokens for you. The JDBC wrapper also includes Aurora Global Database support with a Global Database failover plugin that reconnects your application when the primary Region changes. If a wrapper is available for your language and driver, use it rather than building this logic yourself. For Java applications, see Unlock Amazon Aurora’s Advanced Features with Standard JDBC Driver using AWS Advanced JDBC Wrapper.
Clean up
This walkthrough added an IAM policy and an IAM-mapped database user. If you no longer need them, remove them after you finish the walkthrough.
Remove the IAM policy (detach from any roles/users first):
For Aurora PostgreSQL, connect to the primary cluster, revoke the database privilege, and drop the IAM-mapped user:
For Aurora MySQL, run the following command on the primary cluster:
If you created an Aurora Global Database to follow this post, delete it using the steps in Deleting an Amazon Aurora global database.
Conclusion
In this post, I showed how the Amazon Aurora Global Database writer endpoint and IAM database authentication compose into a passwordless, failover-resilient access pattern. The Global Database writer endpoint handles routing through a stable DNS name that Aurora re-points automatically. IAM handles authentication independently. By connecting through the Global Database writer endpoint, signing the token for the dynamically discovered primary Region, and scoping the rds-db:connect policy to every Regional cluster resource ID, your application keeps authenticating across a cross-Region switchover or failover. It requires no configuration changes. To get started, work through the walkthrough in a test account, then run the switchover to see the pattern hold. For more details, see Amazon Aurora Global Database, IAM database authentication, Diving deep into the new Amazon Aurora Global Database writer endpoint, and Using switchover or failover in Amazon Aurora Global Database.