AWS IAM - Roles between two AWS Accounts
Problem:
Your company has two AWS accounts:
DevAccountandProdAccount. Developers inDevAccountneed to access an S3 bucket inProdAccountwithout using long-term credentials. How do you configure access securely?Solution:
- Create an IAM Role in
ProdAccount
Define a trust policy allowing
DevAccountto assume the role.Attach an S3 bucket policy granting required permissions.
2. Grant Permissions in
DevAccount
Create an IAM policy allowing developers to assume the cross-account role.
Attach the policy to a developer IAM group.
✅ Solution
1️⃣ Create an IAM Role in ProdAccount
Create an IAM role in the Prod account.
Define a trust policy that allows the DevAccount to assume the role using
sts:AssumeRole.Attach an S3 permission policy (or bucket policy) that grants only the required access (read / write as needed).
🏗 Architecture
DevAccount (111111111111)
└── IAM Group: Developers
└── Users assume role
↓
ProdAccount (222222222222)
└── IAM Role: ProdS3RWRole
└── Access S3 bucket
Steps
1️⃣ ProdAccount (222222222222)
1.1 Create S3 Bucket
aws s3api create-bucket \
--bucket prod-data-bucket \
--region ap-southeast-1 \
--create-bucket-configuration LocationConstraint=ap-southeast-1
1.2 Create Trust Policy (Allow DevAccount)
prod-trust-policy.json
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::111111111111:root"
},
"Action": "sts:AssumeRole"
}
]
}
1.3 Create IAM Role in ProdAccount
aws iam create-role \
--role-name ProdS3RWRole \
--assume-role-policy-document file://prod-trust-policy.json
1.4 Attach S3 Permission Policy (Least Privilege)
prod-s3-rw-policy.json
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "ListBucket",
"Effect": "Allow",
"Action": "s3:ListBucket",
"Resource": "arn:aws:s3:::prod-data-bucket"
},
{
"Sid": "ReadWriteObjects",
"Effect": "Allow",
"Action": [
"s3:GetObject",
"s3:PutObject",
"s3:DeleteObject"
],
"Resource": "arn:aws:s3:::prod-data-bucket/*"
}
]
}
Attach it:
aws iam put-role-policy \
--role-name ProdS3RWRole \
--policy-name ProdS3RWPolicy \
--policy-document file://prod-s3-rw-policy.json
1.5 (Optional but Recommended) Bucket Policy
This forces access via the role only.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowProdRoleAccessOnly",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::222222222222:role/ProdS3RWRole"
},
"Action": "s3:*",
"Resource": [
"arn:aws:s3:::prod-data-bucket",
"arn:aws:s3:::prod-data-bucket/*"
]
}
]
}
2️⃣ DevAccount (111111111111)
2.1 Create Assume-Role Policy
dev-assume-prod-role.json
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "sts:AssumeRole",
"Resource": "arn:aws:iam::222222222222:role/ProdS3RWRole"
}
]
}
2.2 Create IAM Policy
aws iam create-policy \
--policy-name AssumeProdS3Role \
--policy-document file://dev-assume-prod-role.json
2.3 Create Developer Group
aws iam create-group --group-name Developers
Attach policy:
aws iam attach-group-policy \
--group-name Developers \
--policy-arn arn:aws:iam::111111111111:policy/AssumeProdS3Role
2.4 Create Developer User (Example)
aws iam create-user --user-name dev-user
aws iam add-user-to-group \
--user-name dev-user \
--group-name Developers
3️⃣ Developer Usage (DevAccount)
3.1 Assume Role
aws sts assume-role \
--role-arn arn:aws:iam::222222222222:role/ProdS3RWRole \
--role-session-name dev-session
3.2 Export Temporary Credentials
export AWS_ACCESS_KEY_ID=...
export AWS_SECRET_ACCESS_KEY=...
export AWS_SESSION_TOKEN=...
3.3 Access Prod S3
aws s3 ls s3://prod-data-bucket
aws s3 cp file.txt s3://prod-data-bucket/
🔐 Security Best Practices (Strongly Recommended)
✅ Use MFA in trust policy
✅ Limit session duration
✅ Enable CloudTrail in both accounts
✅ Use permission boundaries
✅ Avoid s3:* if not required
🔑 Key Takeaways
Trust policy controls who can assume the role
Permission policy controls what the role can do
Cross-account access uses STS temporary credentials
No static credentials in ProdAccount
Clean separation of Dev and Prod