Handling multiple AWS accounts with aws-vault

July 10, 2018

When using AWS in larger organizations, it’s a best practice to use multiple AWS accounts for different teams, applications or environments. AWS provides AWS organizations to support creating multiple AWS accounts for one organization.

When using AWS organizations you usually create IAM users in the master account and provide different IAM roles in the member accounts, which the users in the master accont can assume. As a security best practice it is also recommended to require MFA to assume roles in the member accounts.

When having a setup like this it can often be tricky to handle access to the various AWS accounts via CLI. To handle this aws-vault comes in handy.

aws-vault

aws-vault is tool for securely storing and accessing AWS credentials. On a Mac you can easily install it with Homebrew:

$ brew cask install aws-vault

Let’s make sure to have some decent default settings configured. aws-vault can be configured with environment variables. I have the following settings in my ~/.bashrc:

1
2
3
4
export AWS_VAULT_FILE_PASSPHRASE="randompassphrase" # Avoid entering a passphrase when using aws-vault
export AWS_VAULT_BACKEND="file" # Use the file backend of aws-vault
export AWS_SESSION_TTL="12h" # Set the session ttl to 12 hours to avoid reentering MFA multiple times a day 
export AWS_ASSUME_ROLE_TTL="15m"

In my example setup I have a master account named and two member accounts which will be configured later.

AWS console access is configured in a config file ~/.aws/config. My master account is named fstehle-master which leads to the following configuration:

1
2
[profile fstehle-master]
region = eu-west-1 # Use region eu-west-1 by default

Let’s store the access token of our AWS IAM user from the master account in aws-vault:

$ aws-vault add fstehle-master

Enter Access Key ID: ...
Enter Secret Access Key: ...
Added credentials to profile "fstehle-master" in vault

We want to make sure the token is setup correctly by verifying the identity with GetCallerIdentity API call in the Security Token Service (STS). To do this AWS CLI needs to be installed, on a Mac this can be done with:

$ brew install awscli

Finally we can verify our identity by calling aws sts get-caller-identity inside the AWS acocunt fstehle-master:

$ aws-vault exec fstehle-master aws sts get-caller-identity
{
    "UserId": "AIDAIMS2AF3S7ZAYUAVQO",
    "Account": "123456789010",
    "Arn": "arn:aws:iam::123456789010:user/fstehle"
}

Make sure that the returned Account is the correct AWS account id of you master account.

Using aws-vault for accessing multiple accounts

Now that we setup access to our master account we can use aws-vault to get access to member accounts as well. Let’s create some member accounts in the AWS Organizations console.

In my example I created to member accounts fstehle-memberaccount1 (account 123456789011) and fstehle-memberaccount2 (account 123456789012). I use the automatically generated role OrganizationAccountAccess of the member accounts, however you are free to create your own roles. If you want to require MFA to assume the roles make sure you set it up according to the documentation. Use the correct MFA serial of you IAM user in the configuration (arn:aws:iam::123456789010:mfa/fstehle in my case).

This leads to a configuration in ~/.aws/config as follows:

 4
 5
 6
 7
 8
 9
10
11
12
13
14
[profile fstehle-memberaccount1]
region = eu-west-1 # Use region eu-west-1 by default
role_arn = arn:aws:iam::123456789011:role/OrganizationAccountAccess
mfa_serial = arn:aws:iam::123456789010:mfa/fstehle # Use MFA when assuming the role
source_profile = fstehle-master

[profile fstehle-memberaccount2]
region = eu-west-1 # Use region eu-west-1 by default
role_arn = arn:aws:iam::123456789012:role/OrganizationAccountAccess
mfa_serial = arn:aws:iam::123456789010:mfa/fstehle # Use MFA when assuming the role
source_profile = fstehle-master

We can now invoke AWS CLI commands in the member accounts.

Let’s get our caller identity in fstehle-memberaccount1:

$ aws-vault exec fstehle-memberaccount1 aws sts get-caller-identity
Enter token for arn:aws:iam::123456789010:mfa/fstehle: 381200
{
    "UserId": "AIDAIMS2AF3S7ZAYUAVQO:1273433422334232327",
    "Account": "123456789011",
    "Arn": "arn:aws:sts::123456789011:assumed-role/OrganizationAccountAccess/1273433422334232327"
}

Let’s list some EC2 instances in fstehle-memberaccount2

$ aws-vault exec fstehle-memberaccount2 aws ec2 describe-instances
Enter token for arn:aws:iam::123456789010:mfa/fstehle: 321670
{
    "Reservations": [
        {
            "Groups": [],
            "Instances": [
                {
                    "AmiLaunchIndex": 0,
                    "ImageId": "ami-466768ac",
                    "InstanceId": "i-04cd3c48db295f773",
                    "InstanceType": "t2.micro",
                    "LaunchTime": "2018-07-22T11:34:41.000Z",
                    "Monitoring": {
                        "State": "disabled"
                    },
                    "Placement": {
                        "AvailabilityZone": "eu-west-1c",
                        "GroupName": "",
                        "Tenancy": "default"
                    },
                    "PrivateDnsName": "ip-172-31-2-112.eu-west-1.compute.internal",
                    "PrivateIpAddress": "172.31.2.112",
                    "ProductCodes": [],
                    "PublicDnsName": "ec2-34-241-133-228.eu-west-1.compute.amazonaws.com",
                    "PublicIpAddress": "34.241.133.228",
                    "State": {
                        "Code": 16,
                        "Name": "running"
                    },
                    ...
                }
            ],
            "OwnerId": "123456789012",
            "ReservationId": "r-0815a1d5729255f20"
        }
    ]
}

The MFA token for a specific AWS account is saved for the time of the configured session TTL (environment variable AWS_SESSION_TTL), which is 12 hours in my case. That way I only have to enter it once a day.

Recap

aws-vault is a great tool to access multiple accounts from the command line, especially in combination with the AWS CLI. Have a look in the excellent README of aws-vault for further details.

Do you use some other tool to handle access to multiple AWS accounts. Let me know in the comments how you handle this!


comments powered by Disqus