AWS IAM Role Use Cases

Maxat AkbanovMaxat Akbanov
7 min read

Cross Account Access

You need to enable cross account access for a user from Account B to access the S3 bucket in Account A. You own both AWS accounts A and B.

Overview

To enable cross-account access to an Amazon S3 bucket in Account A for a user from Account B, you need to configure IAM policies in both accounts and potentially update the bucket policy in Account A.


1. IAM Role in Account A (Resource Account)

  • Create an IAM Role in Account A that grants access to the S3 bucket.

  • Trust Policy: Configure the IAM role with a trust relationship to allow Account B users to assume the role.

Example Trust Policy for the role in Account A:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::<AccountB-ID>:root"
      },
      "Action": "sts:AssumeRole"
    }
  ]
}
  • Permissions Policy: Attach a policy to the role to allow specific S3 actions on the bucket.

Example Permissions Policy:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "s3:GetObject",
        "s3:ListBucket"
      ],
      "Resource": [
        "arn:aws:s3:::example-bucket",
        "arn:aws:s3:::example-bucket/*"
      ]
    }
  ]
}

2. User or IAM Role in Account B (Requesting Account)

  • Allow AssumeRole Action: Grant the user or IAM role in Account B permission to assume the role in Account A.

Example Policy for User/Role in Account B:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "sts:AssumeRole",
      "Resource": "arn:aws:iam::<AccountA-ID>:role/RoleName"
    }
  ]
}
  • Add a bucket policy to explicitly grant access to the bucket for the IAM Role in Account A. This ensures the role can access the bucket as per the principle of least privilege.

Example Bucket Policy:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::<AccountA-ID>:role/RoleName"
      },
      "Action": [
        "s3:GetObject",
        "s3:ListBucket"
      ],
      "Resource": [
        "arn:aws:s3:::example-bucket",
        "arn:aws:s3:::example-bucket/*"
      ]
    }
  ]
}

Workflow of Cross-Account Access

  1. User in Account B:

    • Authenticates with their IAM credentials.

    • Assumes the IAM role in Account A using the sts:AssumeRole API call.

  2. STS Role Session:

    • The user gets temporary credentials from STS to perform actions permitted by the IAM role.
  3. Accessing S3:

    • The temporary credentials are used to access the S3 bucket in Account A.

Summary of IAM Policy Placement

EntityPolicy TypePurpose
IAM Role (Account A)Trust PolicyAllows users/roles from Account B to assume the role.
IAM Role (Account A)Permissions PolicyGrants access to S3 resources.
IAM User/Role (Account B)Permissions PolicyAllows the user/role to assume the role in Account A.
S3 Bucket (Account A)Bucket PolicyOptionally enforces access for the IAM role in Account A.

This configuration ensures secure and auditable access to the S3 bucket from Account B to Account A.

Cross Account Access with 3rd party AWS Account

When granting a third-party AWS Account B access to an S3 bucket in your Account A, the process involves securely sharing an IAM role ARN and using an ExternalID for enhanced security to prevent unauthorized access.


Key Components

  1. Role in Account A: You create an IAM role in your account (Account A) that the third party can assume.

  2. ExternalID: This is a unique identifier provided to the third party (Account B) to include in the sts:AssumeRole request. It ensures that only the intended third party can assume the role.


Step-by-Step Setup

1. Create an IAM Role in Account A

  • Trust Policy: Configure the role to allow sts:AssumeRole action from Account B using an ExternalID.

Example Trust Policy:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::<AccountB-ID>:root"
      },
      "Action": "sts:AssumeRole",
      "Condition": {
        "StringEquals": {
          "sts:ExternalId": "unique-external-id-value"
        }
      }
    }
  ]
}
  • Permissions Policy: Attach a policy to the role to grant access to specific S3 actions and resources.

Example Permissions Policy:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "s3:ListBucket",
        "s3:GetObject"
      ],
      "Resource": [
        "arn:aws:s3:::example-bucket",
        "arn:aws:s3:::example-bucket/*"
      ]
    }
  ]
}

2. Share the Role ARN and ExternalID with Account B

  • Provide the third party with:

    • The Role ARN: arn:aws:iam::<AccountA-ID>:role/RoleName

    • The ExternalID: A unique string (e.g., third-party-access-1234).

3. Account B Assumes the Role

  • The third party configures their system to assume the role using the Role ARN and the provided ExternalID.

Example CLI Command:

aws sts assume-role \
  --role-arn "arn:aws:iam::<AccountA-ID>:role/RoleName" \
  --role-session-name "ThirdPartySession" \
  --external-id "unique-external-id-value"

The response includes temporary credentials (AccessKeyId, SecretAccessKey, and SessionToken) that Account B uses to access the bucket.

4. (Optional) Add a Bucket Policy in Account A

  • Explicitly grant access to the role in the bucket policy for extra security.

Example Bucket Policy:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::<AccountA-ID>:role/RoleName"
      },
      "Action": [
        "s3:GetObject",
        "s3:ListBucket"
      ],
      "Resource": [
        "arn:aws:s3:::example-bucket",
        "arn:aws:s3:::example-bucket/*"
      ]
    }
  ]
}

How ExternalID Adds Security

  • The ExternalID prevents the risk of the third party accidentally or maliciously assuming a role meant for another entity.

  • It ensures that the third party includes a unique identifier in their sts:AssumeRole request, verifying their identity.


Summary Workflow

  1. Account A creates an IAM role and specifies Account B as the trusted entity with a required ExternalID.

  2. Account A shares the Role ARN and ExternalID with the third party.

  3. Account B assumes the role using the provided ARN and ExternalID to obtain temporary credentials.

  4. The temporary credentials are used to access the S3 bucket in Account A.

This approach ensures secure, auditable, and controlled access to your resources.

Role Delegation to AWS Services

Consider common situation when you need to provide access for your application running on EC2 instance access to the S3 bucket.

In this case, to enable an application running on an EC2 instance to access an S3 bucket in the same AWS account, you can leverage EC2 instance profiles, IAM roles, STS, and IAM policies. This approach securely provides temporary credentials to the EC2 instance, allowing it to access the S3 bucket without hardcoding credentials.


Key Components

  1. EC2 Instance Profile: Links an IAM role to an EC2 instance.

  2. IAM Role: Grants permissions to access the S3 bucket.

  3. STS: Issues temporary credentials for the IAM role when assumed by the EC2 instance.

  4. IAM Policies: Define the permissions for accessing the S3 bucket.


Step-by-Step Setup

1. Create an IAM Role

  • Service Principal: Specify that the role is for EC2 instances to assume.

Example Trust Policy for the IAM role:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Service": "ec2.amazonaws.com"
      },
      "Action": "sts:AssumeRole"
    }
  ]
}
  • Permissions Policy: Attach an inline or managed policy to the role that grants the required S3 permissions.

Example Permissions Policy:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "s3:ListBucket",
        "s3:GetObject",
        "s3:PutObject"
      ],
      "Resource": [
        "arn:aws:s3:::example-bucket",
        "arn:aws:s3:::example-bucket/*"
      ]
    }
  ]
}

2. Create an Instance Profile

  • An Instance Profile is a container for the IAM role. It allows EC2 instances to assume the role.

AWS CLI Command:

aws iam create-instance-profile --instance-profile-name MyInstanceProfile
aws iam add-role-to-instance-profile --instance-profile-name MyInstanceProfile --role-name MyRole

3. Attach the Instance Profile to the EC2 Instance

  • When launching the EC2 instance, associate it with the instance profile.

Via Console:

  1. Go to the EC2 instance settings.

  2. Under "Modify IAM Role," attach the instance profile.

Via CLI:

aws ec2 associate-iam-instance-profile --instance-id i-xxxxxxxx --iam-instance-profile Name=MyInstanceProfile

4. Application Uses Temporary Credentials from STS

  • When the EC2 instance assumes the IAM role, STS (AWS Security Token Service) automatically provides temporary credentials.

  • The application can retrieve these credentials via the Instance Metadata Service (IMDS).

The response includes:

  • AccessKeyId

  • SecretAccessKey

  • SessionToken

  • Expiration


Key Points

  1. Security: Temporary credentials provided by STS are short-lived and automatically rotated, reducing the risk of compromise.

  2. No Hardcoding: No need to hardcode or manually manage long-term credentials in the application or instance.

  3. Least Privilege: The IAM role's permissions policy should only grant the minimal permissions required for the application.


Summary Workflow

  1. IAM Role: Defines permissions and allows EC2 to assume the role.

  2. Instance Profile: Links the IAM role to the EC2 instance.

  3. STS: Provides temporary credentials when the instance assumes the role.

  4. Application: Uses AWS SDK to interact with S3 using temporary credentials.

This configuration ensures secure, scalable, and efficient access to S3 for applications running on EC2 instances.

References

0
Subscribe to my newsletter

Read articles from Maxat Akbanov directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Maxat Akbanov
Maxat Akbanov

Hey, I'm a postgraduate in Cyber Security with practical experience in Software Engineering and DevOps Operations. The top player on TryHackMe platform, multilingual speaker (Kazakh, Russian, English, Spanish, and Turkish), curios person, bookworm, geek, sports lover, and just a good guy to speak with!