How Do Use AWS Cross Account Resource Access
In my previous post, I explored how to use IAM roles to authenticate with Amazon RDS. But what if you need to access resources in a different AWS account? This is where cross-account access comes in - it enables resources in one account to securely access resources in another.
According to the official doc, there are many benefits of using multiple AWS accounts:
- Account Isolation: Multiple accounts help isolate different environments (e.g., dev, staging, prod) and projects, reducing the risk of accidental changes or data breaches.
- Cost Allocation and Tracking: Separating costs by account allows for better tracking and allocation of expenses, making it easier to manage budgets and optimize spend.
- Security and Compliance: Using separate accounts for different purposes (e.g., dev vs. prod) helps ensure compliance with security policies and regulations, reducing the risk of unauthorized access or data breaches.
- Operational Efficiency: Multiple accounts enable more efficient operations by allowing teams to work independently without affecting other projects or environments.
- Governance and Management: Having separate accounts for different purposes helps establish clear governance and management structures, making it easier to manage a large number of AWS resources.
In this post, I’ll explain how cross-account access works and use terraform to demonstrate how to set up IAM roles in different accounts.
Let’s get started.
Concept
Here is a simple diagram demonstrate how this works.
In this example, we have two AWS accounts:
- Account 1 (Trusted): This account contains the users or roles that need to access resources in another account.
- Account 2 (Trustee): This account owns the resources that need to be accessed from Account 1.
Here’s how it works:
In Account 1, IAM assigns a role (let’s call it Role 1) to an EC2 instance. This EC2 instance can then use Role 1 to assume a role in Account 2 (Role 2). Once the assumption is successful, the EC2 instance can use the temporary credentials from the returned response to access resources in Account 2.
In the next section, I will show you how to access secrets in Account 2.
Terraform
We will use a terraform to set up IAM roles in both accounts.
IAM role in account 1
Below Terraform code defines an IAM role and policies that enable EC2 instances in your trusted account (Account 1) to assume roles in trustee account (Account 2).
Specifically, it:
- Creates IAM role ec2-read-secrets and allows EC2 instances in Account 1 to assume this role.
- Creates IAM policy assume-account-two that permits the assumption of the “secret-readonly“ role in Account 2.
- Attaches assume-account-two to the “ec2-read-secrets“ role.
1 | resource "aws_iam_role" "ec2_cross_account" { |
IAM role in account 2
Now let’s go to account 2 and see what we need to do.
- Creates IAM role secret-readonly.
- Create IAM role policy ec2_cross_account to allow role ec2-read-secrets in Account 1 to assume.
- Creates IAM policy that allow read only access to a specific secrets. (Example taken from official doc)
- Attaches both IAM role policy and IAM policy to the role.
1 | data "aws_iam_policy_document" "ec2_cross_account" { |
1 | output "role_arn" { |
Demo
Now that with the roles set up, let’s see how it works. For simplicity, I am using aws cli for the demo.
Validation
To verify our set up, follow these steps
- SSH to EC2 in Account 1.
The EC2 instance should have Role 1 assigned to its instance rofile. - Assume Role 2
1
2
3
4aws sts assume-role \
--role-arn arn:aws:iam::<ACCOUNT_TWO_NUMBER>:role/secret-readonly \
--role-session-name demo \
--output json
If your setup is correct, this command should execute successfully and return credentials in JSON format.
Access secret
Now let’s access the secret.
Store the sts API call response.
1
2
3
4SESSION=$(aws sts assume-role \
--role-arn arn:aws:iam::<ACCOUNT_TWO_NUMBER>:role/secret-readonly \
--role-session-name demo \
--output json)Save credentials to environment variables.
1
2
3export AWS_ACCESS_KEY_ID=$(echo $SESSION | jq -r .Credentials.AccessKeyId)
export AWS_SECRET_ACCESS_KEY=$(echo $SESSION | jq -r .Credentials.SecretAccessKey)
export AWS_SESSION_TOKEN=$(echo $SESSION | jq -r .Credentials.SessionToken)Access secrect in Account 2.
1
2aws secretsmanager get-secret-value \
--secret-id <SECRET_NAME>
That’s all I want to share with you today. See you next time.