It is a good practice to organise AWS workloads in multiple accounts, be it for security, accounting, or just to maintain our sanity. Here is how I work with multiple accounts in my AWS Organization from the command line.
account(s)
Why does AWS encourage multiple accounts setups (apart from getting customers further entrenched on the platform)? This video(3:20-7:00) gives a good explanation.
As for me, I’m organising my demos and PoCs in a separate Demo
account. This way, I can share admin access to my demos with my colleagues without exposing my main account. In addition, I’m also centralising all IAM users in my main account, and access my Demo
(and other accounts) by switching (assuming) roles. For readers new to this setup, I suggest this tutorial.
In my Demo
account, I create DemoAdminRole
role, with the following trust policy to allow users from my main account to assume this roles:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::<MAIN_ACCOUNT_NUM>:root"
},
"Action": "sts:AssumeRole"
}
]
}
In my main account, I created proxy roles that do not have any permission, other then to assume roles in my Demo
account, with policy that looks like this:
{
"Version": "2012-10-17",
"Statement": {
"Effect": "Allow",
"Action": "sts:AssumeRole",
"Resource": "arn:aws:iam::<DEMO_ACCOUNT_NUM>:role/<DEMO_ROLE_NAME>"
}
}
I can then attach this role to users that I want to grant access to my Demo
account.
Finally, to prevent creation of users and access keys in the Demo
account, I attached a service control policy like so to my Demo
account:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Statement1",
"Effect": "Deny",
"Action": [
"iam:CreateUser",
"iam:CreateAccessKey"
],
"Resource": [
"*"
]
}
]
}
profiles, profiles
AWS CLI and SDKs make use of ~/.aws/config
and ~/.aws/credentials
to manage AWS profiles and credentials. My ~/.aws/config
file looks like this:
[profile demo]
region=ap-southeast-1
role_arn=arn:aws:iam::<DEMO_ACCT_NUM>:role/<DEMO_ROLE_NAME>
source_profile=demo
[profile main]
region=us-west-2
output=json
and ~/.aws/credentials
looks like this:
[demo]
aws_access_key_id = <DEMO_PROXY_USER_ACCESS_KEY>
aws_secret_access_key = <DEMO_PROXY_USER_SECRET_KEY>
[main]
aws_access_key_id = <MAIN_ACCESS_KEY>
aws_secret_access_key = <MAIN_SECRET_KEY>
switching between profiles
I deliberately not have a default profile to reduce the chance of targeting my scripts and ansible playbooks at the wrong profile. Instead, I added the following.[1] to my .zshrc
(and .bashrc
) to allow me to quickly switch between profiles:
# working with AWS profiles
function _aws_list_all {
credentialFileLocation=${AWS_SHARED_CREDENTIALS_FILE};
if [ -z $credentialFileLocation ]; then
credentialFileLocation=~/.aws/credentials
fi
while read line; do
if [[ $line == "["* ]]; then echo "$line"; fi;
done < $credentialFileLocation;
};
function _aws_switch_profile() {
if [ -z $1 ]; then echo "Usage: aws-profile profilename"; return; fi
exists="$(aws configure get aws_access_key_id --profile $1)"
if [[ -n $exists ]]; then
export AWS_DEFAULT_PROFILE=$1;
export AWS_PROFILE=$1;
export AWS_REGION=$(aws configure get region --profile $1);
echo "Switched to AWS Profile: $1";
aws configure list
fi
};
alias aws-all="_aws_list_all"
alias aws-profile="_aws_switch_profile"
alias aws-whoami="aws configure list"
I can then switch profiles using the 3 aliases like so: