How to Set Up Secure Cross-Account AWS DBA Access Using IAM Roles (Step-by-Step)

Managing databases in AWS often requires DBAs to access customer environments securely—without sharing passwords, long-lived keys, or granting excessive permissions. A common and recommended approach is to use AWS IAM roles with cross-account role assumption.

This guide walks through a practical, secure setup for a DBA team to access a client’s AWS environment (for example, to manage Amazon RDS MySQL and a jump host) using:

  • IAM users (or SSO users)
  • A source “DBA access” role in your AWS account
  • A target role in the client AWS account
  • AWS Console role switching and AWS CLI role assumption
  • Least-privilege permissions and troubleshooting tips

Why use AssumeRole for DBA access?

Instead of giving DBAs direct permanent access into a client account, AWS lets you assume a role in another account. This means:

  • Access is temporary (STS tokens)
  • Permissions are limited to the target role
  • The client controls what the DBA role can do
  • All actions are auditable (via CloudTrail)
  • No need to share root or static privileged credentials

This is especially useful for:

  • Amazon RDS administration
  • Jump host access (via SSM or SSH)
  • Performance monitoring
  • Log and metrics investigation

Example Architecture (Generic)

Source account (your organization)

  • AWS Account ID: 111122223333
  • IAM user: dba.engineer
  • Source role: Org-DBA-Access

Target account (client / production)

  • AWS Account ID: 444455556666
  • Target role: client.dba
  • Region: ap-southeast-2

Access flow

  1. DBA signs in as dba.engineer
  2. DBA switches to Org-DBA-Access (same account)
  3. DBA assumes client.dba in client account
  4. DBA accesses RDS / logs / jump host with least privilege

Step 1 — Create or Confirm the DBA IAM User

If using IAM users (instead of AWS Identity Center / SSO), create the DBA user first.

AWS CLI

aws iam create-user --user-name dba.engineer --profile admin

(Optional) Enable console login

aws iam create-login-profile \
--user-name dba.engineer \
--password "Temp#Password!2026" \
--password-reset-required \
--profile admin

Tip: If the login profile already exists, use update-login-profile instead.


Step 2 — Allow the DBA User to Change Their Own Password

A common issue is being forced to reset a password in the console but not having permission to change it.

Attach the AWS-managed policy:

aws iam attach-user-policy \
--user-name dba.engineer \
--policy-arn arn:aws:iam::aws:policy/IAMUserChangePassword \
--profile admin

This avoids “You may not be authorized to perform this action” errors on the password reset screen.


Step 3 — Create the Source Role in Your AWS Account

This is the role your DBAs will switch to before entering the client account.

Role name

Org-DBA-Access

Trust policy (trust the DBA IAM user)

Create a trust policy file (example trust-org-dba-access.json):

{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowDBAUserToAssume",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::111122223333:user/dba.engineer"
},
"Action": "sts:AssumeRole"
}
]
}

Create the role:

aws iam create-role \
--role-name Org-DBA-Access \
--assume-role-policy-document file://trust-org-dba-access.json \
--profile admin

Step 4 — Grant the IAM User Permission to Assume the Source Role

This is the caller-side permission many teams forget.

Create an inline policy (example allow-assume-org-dba-role.json):

{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "sts:AssumeRole",
"Resource": "arn:aws:iam::111122223333:role/Org-DBA-Access"
}
]
}

Attach to the IAM user:

aws iam put-user-policy \
--user-name dba.engineer \
--policy-name AllowAssumeOrgDBARole \
--policy-document file://allow-assume-org-dba-role.json \
--profile admin

Step 5 — Configure the Source Role to Assume the Client Role

Your source role (Org-DBA-Access) needs permission to assume the role in the client account (client.dba).

Create policy file (example allow-assume-client-role.json):

{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AssumeClientDBARole",
"Effect": "Allow",
"Action": "sts:AssumeRole",
"Resource": "arn:aws:iam::444455556666:role/client.dba"
}
]
}

Attach to the source role:

aws iam put-role-policy \
--role-name Org-DBA-Access \
--policy-name AllowAssumeClientDBARole \
--policy-document file://allow-assume-client-role.json \
--profile admin

Step 6 — What the Client Must Configure (Target Role Trust)

The client creates role client.dba in their account and sets a trust policy that trusts your source role.

Client-side trust policy (example)

{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "TrustExternalDBARole",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::111122223333:role/Org-DBA-Access"
},
"Action": "sts:AssumeRole"
}
]
}

Optionally, the client can add conditions later (External ID, session naming rules, IP allowlist). For initial testing, many teams keep it simple.


Step 7 — Test Access in the AWS Console (Role Switching)

A) Sign in as the DBA IAM user

Use the IAM sign-in URL:

  • https://111122223333.signin.aws.amazon.com/console

Sign in as:

  • Username: dba.engineer

B) Switch to the source role

In the AWS Console:

  • Click the account/user menu (top right)
  • Click Switch role
  • Enter:
    • Account ID: 111122223333
    • Role name: Org-DBA-Access

C) Switch to the client role

After switching to Org-DBA-Access, switch role again:

  • Account ID: 444455556666
  • Role name: client.dba

Set the region to:

  • Asia Pacific (Sydney) / ap-southeast-2

If successful, you are now operating in the client’s account using the client-provided DBA permissions.


Step 8 — Test Access with AWS CLI (Recommended)

CLI gives clearer error messages than the console and is excellent for troubleshooting.

1) Verify your base profile

aws sts get-caller-identity --profile admin

2) Assume your source role

aws sts assume-role \
--role-arn arn:aws:iam::111122223333:role/Org-DBA-Access \
--role-session-name DBA-Test \
--profile admin

Export the returned temporary credentials (shell-specific) and verify:

aws sts get-caller-identity

Expected ARN format:

  • arn:aws:sts::111122223333:assumed-role/Org-DBA-Access/DBA-Test

3) Assume the client role

aws sts assume-role \
--role-arn arn:aws:iam::444455556666:role/client.dba \
--role-session-name DBA-Prod-Test

Export the new temporary credentials and verify:

aws sts get-caller-identity

Expected:

  • Account: 444455556666
  • ARN contains assumed-role/client.dba/...

Step 9 — Verify RDS / Logs / Metrics Access

Once inside the client role, test a few read operations:

RDS

aws rds describe-db-instances --region ap-southeast-2

CloudWatch metrics / alarms

aws cloudwatch describe-alarms --region ap-southeast-2

CloudWatch Logs (if RDS logs are exported)

aws logs describe-log-groups --region ap-southeast-2

Performance Insights (if enabled)

Use the AWS Console or PI APIs (permissions required).


Recommended Least-Privilege Policy for External DBA Access (Client Side)

A client-provided role for DBAs should usually include:

RDS (read + limited operations)

  • rds:Describe*
  • rds:ListTagsForResource
  • rds:ModifyDBInstance (if agreed)
  • rds:RebootDBInstance
  • rds:CreateDBSnapshot
  • rds:CopyDBSnapshot
  • rds:RestoreDBInstanceFromDBSnapshot
  • rds:DescribeDBLogFiles
  • rds:DownloadDBLogFilePortion

CloudWatch / Logs (read)

  • cloudwatch:GetMetricData
  • cloudwatch:GetMetricStatistics
  • cloudwatch:ListMetrics
  • cloudwatch:DescribeAlarms
  • logs:DescribeLogGroups
  • logs:DescribeLogStreams
  • logs:GetLogEvents
  • logs:FilterLogEvents

Performance Insights (read)

  • pi:GetResourceMetrics
  • pi:DescribeDimensionKeys
  • pi:GetDimensionKeyDetails

Scope permissions to specific DB instance ARNs, snapshots, and regions whenever possible.


Common Problems and How to Fix Them

1) “Invalid information in one or more fields” when switching roles (Console)

Usually caused by:

  • Missing sts:AssumeRole on the IAM user or source role
  • Trust policy on the target role doesn’t trust your source role
  • MFA condition exists but user is not authenticated with MFA
  • Wrong account ID or role name

2) AccessDenied on sts:AssumeRole

Check both sides:

  • Caller-side policy (does the current identity have sts:AssumeRole?)
  • Role trust policy (does the role trust the caller?)

3) CLI works with --profile myprofile, but not without profile

Your default profile or environment variables are likely invalid. Check:

aws configure list

And clear conflicting environment variables if needed.

4) Password reset fails in console

Often due to:

  • Missing iam:ChangePassword
  • Password policy requirements not met
  • Expired/invalid login profile

Security Best Practices for DBA Access

  • Use roles + STS instead of long-lived access keys wherever possible
  • Enforce MFA for IAM users and/or source role assumption
  • Use per-engineer session names (e.g., DBA-Name-Ticket123)
  • Keep least privilege on the client role
  • Use CloudTrail and session naming for auditability
  • Consider SSM Session Manager instead of direct SSH for jump hosts

Final Thoughts

A role-based cross-account access model is one of the safest and most scalable ways to provide external DBA services in AWS. It gives clients confidence that access is controlled and auditable, while giving DBA teams a clean operational workflow for managing RDS, logs, performance, and infrastructure.

Start simple (trust + assume-role + basic read access), test the path end-to-end, and then tighten with conditions like MFA, session naming, and resource scoping.

If you’re implementing this for Amazon RDS MySQL DBA operations, this pattern works especially well for:

  • Database administration and troubleshooting
  • Log and metric analysis
  • Snapshot/restore workflows
  • Secure jump-host access via SSM