How to delegate access across AWS accounts using IAM roles
Tags: aws, iam
Published: 2022-07-04 13:06:35

## Table of Contents

1. [Prerequisites](#pre-req)
2. [Create a role in the Production Account](#createrole)
3. [Grant access to the role](#grant)
4. [Test access by switching roles (Console)](#switch)
5. [Revoke an assumed role](#revoke)
6. [Clean Up](#cleanup)
7. [Summary](#summary)
8. [Referrals](#referrals)

In this blog we are going to go through the steps to delegate access to resources in two different AWS accounts called Production and Development.
Developers should be able to access an S3 bucket in the Production account, however the testers from the same account should not be able to access the S3 bucket in the Production account.

By setting up cross-account access this way:

- You don't have to create individual IAM users in each account.
- Users don't have to sign out of one account and sign into another in order to access resources in different AWS accounts.
- A user in one account can switch to a role in the same or a different account. While using the role, the user can perform only the actions and access only the resources permitted by the role; their original user permissions are suspended. When the user exits the role, the original user permissions are restored.

![cross-accounts-access](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/c0g3chal3wr86eyznyk8.png)
   > Picture source: AWS

<a name="pre-req"></a>

## Prerequisites

- Two different AWS accounts, one for Production and the other for Development.
- Users and users groups in the Development account.

| User          | User Group    |
| ------------- |:-------------:|
| John          | Developers    |
| Sri           | Testers       |

> We will be using the following substitutions in the following bucket policies:

| Parameter     | Example       |
| ------------- |:-------------:|
| [ProdAccountID] | 99999999999 |
| [DevAccountID]  | 11111111111 |
| [BucketName]  | sriprodbucket`randomnumber` |

-----

<a name="createrole"></a>

## Step 1: Create a role in the Production Account

Before we can create a role, we need the account ID of the Development AWS account. Each AWS account has a unique account ID identifier assigned to it.

1. Obtain the Development AWS account ID by signing in to the console then click on the account name and copy the 12-digit account number (ID).

2. Sign in to the AWS Management Console as an administrator of the Production account, and open the IAM console.

3. We are going to create a custom policy by navigating to **Policies** and then choose **Create policy**

4. Choose the **JSON** tab and copy the text from the following JSON policy document. Paste this text into the JSON text box, replacing the resource ARN (arn:aws:s3:::[BucketName]) with the real one for your Amazon S3 bucket.

    **Policy from the documentation**

    ```json
    {
    "Version": "2012-10-17",
    "Statement": [
        {
        "Effect": "Allow",
        "Action": "s3:ListAllMyBuckets",
        "Resource": "*"
        },
        {
        "Effect": "Allow",
        "Action": [
            "s3:ListBucket",
            "s3:GetBucketLocation"
        ],
        "Resource": "arn:aws:s3:::[BucketName]"
        },
        {
        "Effect": "Allow",
        "Action": [
            "s3:GetObject",
            "s3:PutObject",
            "s3:DeleteObject"
        ],
        "Resource": "arn:aws:s3:::[BucketName]/*"
        }
    ]
    }
    ```
    The ListBucket permission allows users to view objects in the productionapp bucket. The GetObject, PutObject, DeleteObject permissions allows users to view, update, and delete contents in the productionapp bucket.

5. On the Review page, enter `S3ProductionAccessPolicy` for the policy name. Review the policy **Summary** to see the permissions granted by your policy, and then choose **Create policy**.

    The new policy appears in the list of managed policies.

6. In the navigation pane, choose **Roles** and then choose **Create role**.

7. Choose the An AWS account role type.

8. For Account ID, type the `[DevAccountID]`, which we copied earlier at the start of this section.

9. Choose **Next: Permissions** to set the permissions associated with the role.

10. Select the check box next to the policy named `S3ProductionAccessPolicy` and then, click **Next**.

    > Tip: For Filter, choose Customer managed to filter the list to include only the policies that you created. This hides the AWS created policies and makes it much easier to find the one you need.

11. Click on **Create role** and name it as `S3ProductionAccessRole`.

12. Copy the ARN of `S3ProductionAccessRole` role by navigating to **IAM** > **Roles** > Search for `S3ProductionAccessRole` > Click on it > Copy the ARN

At this point, we have established trust between the Production and Development accounts. We did this by creating a role in the Production account that identifies the Development account as a trusted principal. We also defined what the users who switch to the `S3ProductionAccessRole` can do.

![Policy](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zkl1yx2ln1idb3t6ugqp.png)
> Step 1.3

![Create Policy](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/s3fo86z9qnst7rilvwdp.png)
> Step 1.3

![Create Role](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/iza0enhogmdpmc6wamfq.png)
> Step 1.6

![Select Policy](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/uz0tybk5ie7h5fgx9m9t.png)
> Step 1.10

![Review](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rj3khyh8g03lec0ejooh.png)
> Step 1.11

![S3ProductionAccessRole](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/x66dm8y0nwi4rilvqz5n.png)
> Step 1.11

-----

<a name="grant"></a>

## Step 2: Grant access to the role

### To modify the Developers user group to allow them to switch to the S3ProductionAccessRole role

1. Create two users, **John** and **Sri**, and two user groups, **Developers** and **Testers**.

2. Add **John** to **Developers** and **Sri** to **Testers** user groups.

3. Sign in as an administrator in the Development account, and open the IAM console.

4. Choose **User groups**, and then choose **Developers**.

5. Choose the **Permissions** tab, choose **Add permissions**, and then choose **Create inline policy**.

6. Choose the **JSON** tab.

7. Add the following policy statement to allow the **AssumeRole** action on the `S3ProductionAccessRole` in the Production account. Be sure that you change [ProdAccountID] in the Resource element to the actual AWS account ID of the Production account.

    **Policy from the documentation**

    ```json
    {
        "Version": "2012-10-17",
        "Statement": {
            "Effect": "Allow",
            "Action": "sts:AssumeRole",
            "Resource": "arn:aws:iam::[ProdAccountID]:role/S3ProductionAccessRole"
        }
    }
    ```
    
    The Allow effect explicitly allows the Developers group access to the S3ProductionAccessRole role in the Production account. Any developer who tries to access the role succeeds.

8. Choose **Review policy**.
9. Type a Policy name such as `allow-assume-S3-role-in-production`.
10. Choose **Create policy**.

![John-Developer](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/q2jvgnxj0cwuyfcx62hh.png)

### To modify the testers user group to deny permission to assume the S3ProductionAccessRole role

1. Choose **User groups**, and then choose **Developers**.
2. Choose the **Permissions** tab, choose **Add permissions**, and then choose **Create inline policy**.
3. Choose the **JSON** tab.
4. Add the following policy statement to allow the AssumeRole action on the `S3ProductionAccessRole` in the Production account. Be sure that you change [ProdAccountID] in the Resource element to the actual AWS account ID of the Production account.

    **Policy from the documentation**
    ```json
    {
    "Version": "2012-10-17",
    "Statement": {
        "Effect": "Deny",
        "Action": "sts:AssumeRole",
        "Resource": "arn:aws:iam::[ProdAccountID]:role/S3ProductionAccessRole"
    }
    }
    ```
    The Deny effect explicitly denies the Testers group access to the S3ProductionAccessRole role in the Production account. Any tester who tries to access the role receives an access denied message.

5. Choose **Review policy**.
6. Type a Policy name such as `deny-assume-S3-role-in-production`.
7. Choose **Create policy**.

![Sri Tester](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xrbxtlc1v7kca6xa6jtn.png)

-----

<a name="switch"></a>

## Step 3: Test access by switching roles (Console)

We now have a role that grants access to a resource in the Production account. We also have one user group in the Development account with users allowed to use that role. This step discusses how to test switching to that role from the AWS Management Console.

Switching roles using the AWS Management Console only works with accounts that do not require an ExternalId. For example, assume that you grant access to your account to a third party and require an ExternalId in a Condition element in your permissions policy. In that case, the third party can access your account only by using the AWS API or a command line tool. The third party cannot use the console because it cannot supply a value for ExternalId. More informaton at [How to use an external ID when granting access to your AWS resources to a third party,] (https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_create_for-user_externalid.html)

### To assume a role

1. Logon to AWS console as **John** (Developer) in the Development user group.
2. Select **John** on top right corner (the Identity menu) on the navigation bar, and then choose **Switch Role**.
3. Next, in order to access the role, John must type the `ProdAccountID (999999999999)`, the role name (`S3ProductionAccessRole`), Display name as `S3-Production` and then chooses Switch Role.
4. John can now use the Amazon S3 console to work with the Amazon S3 bucket, or any other resource to which the `S3ProductionAccessRole` has permissions.
5. When done, John can return to his original permissions. To do that, he chooses **S3-Production** role display name on the navigation bar and then chooses **Switch Back**.
6. The next time that John wants to switch roles and chooses the Identity menu in the navigation bar, he sees the **S3-Production** entry still there from last time. He can simply choose that entry to switch roles immediately without reentering the account ID and role name.
7. Repeat the above steps with **Sri** (Tester) and he will not be able to assume the role `S3ProductionAccessRole`,

![Switch](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jaywh2g41esafkdiu293.png)

![Switch Roles](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/llceewcldhqj0dxicjd6.png)

![S3-Production](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8f7l1ma4tjpb306xhpk7.png)

![Switch-Back](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/d3v4yc6qzda77nkr7o1m.png)

-----

<a name="revoke"></a>

### Revoke an assumed role

1. Navigate to **S3ProductionAccessRole**  under IAM > Roles in the Production Account.
2. Click on **Revoke Sessions**  > Click on **Revoke active sessions** > Select **I acknowledge that I am revoking all active session for this role** > Click **Revoke active sessions**.
3. This will add an inline policy with a policy name as **AWSRevokeOlderSessions** with a condition of **DateLessThan** the **aws:TokenIssueTime**. All existing sessions will be revoked. 

```json
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Deny",
            "Action": [
                "*"
            ],
            "Resource": [
                "*"
            ],
            "Condition": {
                "DateLessThan": {
                    "aws:TokenIssueTime": "2022-07-04T10:27:56.051Z"
                }
            }
        }
    ]
}
```

![Revoke Sessions](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/naenov2mr7487sti9vy1.png)

![Session Lost](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8tsqlkezsdr5qa18kjch.png)

![AWSRevokeOlderSessions](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pmv14ccrv2nctmysd6cg.png)

<a name="cleanup"></a>

### Clean Up

1. Empty the bucket
2. Delete the bucket
3. Delete **S3ProductionAccessPolicy** and in the Production Account
4. Delete **John** and **Sri** users.
5. Delete **Developers** and **Testers** User groups

---

<a name="summary"></a>

### Summary

- In this demo we have learned how to delegate access across AWS accounts using IAM roles.
- You don't have to create individual IAM users in each account.
- Users don't have to sign out of one account and sign into another in order to access resources in different AWS accounts.
- A user in one account can switch to a role in the same or a different account. While using the role, the user can perform only the actions and access only the resources permitted by the role; their original user permissions are suspended. When the user exits the role, the original user permissions are restored.

---

<a name="referrals"></a>

### Referrals
- [IAM tutorial: Delegate access across AWS accounts using IAM roles)](https://docs.aws.amazon.com/IAM/latest/UserGuide/tutorial_cross-account-with-roles.html#tutorial_cross-account-with-roles-1)

- Cover Image by [@timswaanphotography](https://unsplash.com/@timswaanphotography) from [unsplash](https://unsplash.com/photos/eOpewngf68w).

---