James Galley

Web application developer

PHP, Yii, MySQL, Node.js - JavaScript, HTML, CSS & SASS - Linux, AWS & serverless

Multiple AWS sub-accounts and cross-account role switching

Using multiple AWS accounts within an organisation is an effective way to isolate your AWS resources, and by setting up cross-account IAM roles you can provide convenient and secure access for users of other AWS accounts.

When creating new cloud-based applications on AWS, I like to use sub-accounts to isolate the account and all the resources within it. As an AWS developer this is very useful to isolate one client from another, even to separate development and production environments and for ease of billing and account management.

Using separate AWS accounts and cross-account roles also means you only need a single IAM user, that of your own IAM user on your primary account - and can use this for accessing all AWS accounts to which you have permission, rather than creating new IAM users within each AWS account. You can also force use of MFA tokens for additional security.

Steps to setup AWS sub-accounts and cross-account role access in the AWS Console

This tutorial assumes you're setting up a new sub-account within your own Organisation, but if you skip to Phase 2 you can allow cross-account Role access into existing AWS accounts too.

Phase 1: Setting up new AWS sub account

If using an Organisation:

  • Create a new account within your Organisation, also within an Organisational Unit if you wish.
  • Use a fresh email address as the root account user (Google email '+' aliases are good for this)
  • Choose a name for the IAM role name, like AccountAccessRole
  • Once the account is created, make a note of the account number.
  • Log out of this account (or open another browser / Incognito window)
  • Try to log in to the new sub account as the root user. You won't be able to because at this stage you haven't chosen a password
  • Follow the reset password process and choose a password

If creating a standalone AWS account:

If using an existing AWS account as your sub-account:

Start from Phase 2 if your sub account already exists

Phase 2: In the AWS sub account

  • Log in to the AWS sub account console as root or an IAM user/Role with sufficient privileges
  • Go to IAM, and into the Roles section. If you created your sub-account using AWS Organisations,find the AccountAccessRole you created earlier. Alternatively, if you're in a new standalone account or existing AWS account, create a new Role called AccountAccessRole or {Source Account Name}AccessRole, something that might help identify the purpose of the Role
  • Open the Role's Trust Relationships tab, then the Edit trust relationship button
  • Stick the following JSON in there, and change {SOURCE ACCOUNT ID} to the 12-digit account ID of the account in which your IAM user is registered. This tells the sub account that it will only trust IAM users from this source account to assume this role. You can enforce MFA whenever an IAM user attempts to assume this role.
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::{SOURCE ACCOUNT ID}:root"
      },
      "Action": "sts:AssumeRole",
      "Condition": {
        "Bool": {
          "aws:MultiFactorAuthPresent": "true"
        }
      }
    }
  ]
}

Phase 3: Back in your parent/source AWS account:

  • Log back into your primary account again.
  • We need to give our IAM user(s) permissions to assume the access role in the sub account. To do this, visit the IAM console and go to Groups.
  • Create a Group with no permissions and save it
  • Find the new group and go to the Permissions tab. Find the Inline Policies section and click Create group policy
  • Paste in this JSON and change the values as appropriate:
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "sts:AssumeRole"
      ],
      "Resource": "arn:aws:iam::{SUB ACCOUNT ID}:role/{SUB ACCOUNT ACCESS ROLE NAME}"
    }
  ]
}
  • Go to the Group Users tab and add the users you wish to have access to the sub account

Now you can use the Switch Role URL that the AWS console provides to assume the new role in the child account. This URL looks something like:

https://signin.aws.amazon.com/switchrole?roleName={SUB ACCOUNT ROLE NAME}&account={SUB ACCOUNT ID}&displayName={ROLE DISPLAY NAME}

This process also applies if you have a separate AWS account that isn't part of your organisation. You can still create a role with a cross-account Trust Relationship, and allow your primary account IAM users to assume the role in the account.

AWS cross-account role CLI access

To use these cross-account roles with the AWS CLI you'll need to add a different style of entry into your .aws/credentials file:

[default]
aws_access_key_id=AKIA123456
aws_secret_access_key=123SECRET567

[profile-label]
role_arn = arn:aws:iam::{SUB ACCOUNT ID}:role/{SUB ACCOUNT ROLE NAME}
source_profile = {.aws/credentials PROFILE LABEL OF PARENT IAM USER CREDS}
mfa_serial = arn:aws:iam::{PARENT ACCOUNT ID}:mfa/{PARENT IAM USERNAME}

As an example:

[sub-account]
role_arn = arn:aws:iam::111122223333:role/AccountAccessRole
source_profile = default
mfa_serial = arn:aws:iam::444455556666:mfa/iam-username

And then to use this sub-account profile in the AWS CLI:

$ aws iam list-users --profile=sub-account