Production and development services are typically separated into separate AWS accounts. You might have a scenario where you need to access an AWS service(s) (e.g. S3 or DynamoDB) in production from development. In order to do so, you need to setup cross account access via IAM roles.
Below are steps to create the IAM roles in development and production to access S3 and DynamoDB.
In your development AWS account:
- Create an IAM role – dev-role.
- Configure the trusted relationships to allow EC2 instances to assume this role as such:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "ec2.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
- Create an inline policy for your role as such:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "sts:AssumeRole",
"Resource": "arn:aws:iam::{prod-account-id}:role/prod-assume-role"
},
{
"Effect": "Allow",
"Action": "iam:PassRole",
"Resource": "arn:aws:iam::{prod-account-id}:role/prod-assume-role"
},
{
"Effect": "Allow",
"Action": "s3:*",
"Resource": "arn:aws:s3:::prod-bucket"
},
{
"Effect": "Allow",
"Action": "s3:*",
"Resource": "arn:aws:s3:::prod-bucket/*"
},
{
"Effect": "Allow",
"Action": "dynamodb:*",
"Resource": "arn:aws:dynamodb:eu-west-1:{prod-account-id}:table/prod-table"
}
]
}
You might have not have created the IAM role arn:aws:iam::{prod-account-id}:role/prod-assume-role yet, but you can put it in the policy as a placeholder (until you create it below).
- Once it is created, take note of the IAM role ARN (e.g. arn:aws:iam::{dev-account-id}:role/dev-role).
In you production account:
- Create an IAM role – prod-assume-role.
- Configure the trusted relationships to include the IAM role you created above as such:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::{dev-account-id}:root"
},
"Action": "sts:AssumeRole",
"Condition": {}
},
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::{dev-account-id}:role/dev-role"
},
"Action": "sts:AssumeRole",
"Condition": {}
}
]
}
- Create an inline policy for your role as such:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "sts:AssumeRole",
"Resource": "*"
},
{
"Effect": "Allow",
"Action": "s3:*",
"Resource": "arn:aws:s3:::prod-bucket"
},
{
"Effect": "Allow",
"Action": "s3:*",
"Resource": "arn:aws:s3:::prod-bucket/*"
},
{
"Effect": "Allow",
"Action": "dynamodb:*",
"Resource": "arn:aws:dynamodb:eu-west-1:{prod-account-id}:table/prod-table"
}
]
}
- Once it is created, take note of the IAM role ARN (e.g. arn:aws:iam::{prod-account-id}:role/prod-assume-role), since it will be used below to verify the cross account access.
- Update the S3 bucket policy to allow access for arn:aws:iam::{dev-account-id}:role/dev-role as such:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": [
"arn:aws:iam::{prod-account-id}:root",
"arn:aws:iam::{dev-account-id}:role/dev-role"
]
},
"Action": "s3:*",
"Resource": [
"arn:aws:s3:::prod-bucket",
"arn:aws:s3:::prod-bucket/*"
]
}
]
}
Assuming you have an EC2 instance with the arn:aws:iam::{dev-account-id}:role/dev-role role attached, lets verify the cross account access works. From within the EC2 instance, do the following:
$ pip install awscli --upgrade --user && export PATH=~/.local/bin:$PATH
$ aws sts assume-role --role-arn arn:aws:iam::{prod-account-id}:role/pipeline-assume-role --role-session-name cross-account
$ export AWS_DEFAULT_REGION=eu-west-1
$ export AWS_ACCESS_KEY_ID={AccessKeyId}
$ export AWS_SECRET_ACCESS_KEY={SecretAccessKey}
$ export AWS_SESSION_TOKEN={SessionToken}
$ aws sts get-caller-identity
$ aws dynamodb describe-table --table-name prod-table --region eu-west-1
$ aws s3 ls s3://prod-bucket
Replace {AccessKeyId}, {SecretAccessKey}, and {SessionToken} with the correct
values from the output of aws sts assume-role.