Maintaining multiple accounts in AWS is an utter pain. If you have effectively separated your accounts for things like Dev/Test, Production that’s not too bad, 2 IAM users, with 2FA shouldn’t be too difficult. However, if you throw into that, separating operations infrastructure (build and deployment services, Monitoring, alerting, etc), then think about customer separation, or business stream separation, it’s another story.
A good separation methodology in AWS is:
- Users Account
Used only for storing IAM users, the users here have no ability to do anything other than assuming roles from other accounts. This is also the only account that has IAM users with console access. - Operations Account
This is for shared services like Logging Servers, telemetry systems, build services, monitoring services - Vault/Secure Account
For storing readonly things, like AWS CloudTrail logs, or backups. Extremely restricted access for writing data - Live Account
This is the only place that is allowed to store Customer data, strict security control, limited administrator access. - Dev/Test Account
You can be more liberal with access here, allowing users to see all the data in the account, make manual changes rather than CF/TF, run direct queries against DynamoDb etc. This could also be separated further, but as they’re generally costed together, and have similar access and data security requirements, it just adds a complexity that isn’t required to split them - R&D account
This should allow people full access to all features of AWS, allowing people to test things out, spike things without worrying about affecting other environments.
The live and dev/test accounts are then replicated when you have different business streams, or teams with distinct separation.
Some of the advantages to this approach are:
- Research and development costs are easily identifiable
- Dev/Test can be identified and controlled easily
- Operational costs and access and reliably separated
- Audit teams are happy as the vault can be controlled by them
- Single place to remove access
As you can see, maintain 2FA across all those accounts, and user credentials, can be a nightmare. So, enter role delegation.
What is role delegation
AWS provides the ability for an IAM User or Role in an account to “Assume” a role that is defined in either the same account or, more importantly for this usecase, another account.
This functionality exists at both the Console level, and CLI. What’s even more cool about this is that you can allow access to this functionality for InstanceProfiles too.
The Setup
Step 1. Define Access
The first step is to define the access you need in each account. By default, I normally create at least one role that provides full administrator access to users from the users account. This allows a few capabilities that are pretty cool. If you keep the naming consistent, the policies that need to be created will be easier.
Note: You’ll need to take note of the AccountId from the users account, I normally retrieve this from the “Support” section in the AWS console.
So in the Operations Account (or any account other than Vault or Users) navigate to IAM => Roles => Create Role.
Choose “Another AWS account”.
From here, you’ll need to input the AccountId from the “Users” account, and check the “Require MFA” checkbox. This will ensure that only users who have logged into the users account with MFA can use this role.
Next, you’ll setup the permissions:
As this is going to be the default role, that will grant all access, we’ll check the “AdministratorAccess” policy, however, if you repeat this for things like read only access, or you want to be more granular, this is where you can add your own IAM policy to the role.
For the role name, this is where consistency is your friend. As this is an admin role, something like “useraccount-fulladmin”. If all your accounts have this role name, you’ll see that the policy we’ll need to create is a lot easier.
Step 2. Grant Access
Allowing someone (an IAM User) to Assume the role in the delegated account, is done using IAM Policies. This is also why it’s important that people in the Users account don’t have the “AdministratorAccess” policy applied.
My recommendation is that all IAM Users are given a policy, by default, that only allows login and managing their password. This even applies to administrators. A second IAM user should be created for administrators along the lines of “{username}-admin” that allows managing more IAM permissions.
Create a Policy in the Users account with the following Policy document:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"Version": "2012-10-17", | |
"Statement": [ | |
{ | |
"Effect": "Allow", | |
"Action": "sts:AssumeRole", | |
"Resource": "arn:aws:iam::*:role/useraccount-fulladmin" | |
} | |
] | |
} |
The cool thing here is the * in the Resource definition. This means that it will allow the user with this policy to switch to ANY account that has:
a) The “useraccount-fulladmin” role exists in the account
b) Has granted the “Users” account access to that role.
Simply apply this policy to a user, and they’ll have the “ability” to switch to that role.
The Usage
The main usecase I’ve had for this is using the UI. As we use CloudFormation, and Instance Profiles, etc. Role Delegation has become mostly used for UI interaction when it comes to users.
All we need to do for UI Role delegation is to provide links to our users.
A switch role link looks like this:
https://signin.aws.amazon.com/switchrole?account={AccountId}&roleName={rolename}&displayName={Name to Show}
The user will then be shown a switch role page, where they can choose a colour identifier.
When you’re logged in, and you’re acting as the other role, you’ll see it identified in the UI like this:
Conclusion:
This approach to Account separation provides, amongst other things, better cost separation. However, it does come with it’s own challenges. Here’s a few issues we’ve had to work around:
- Multiple VPCs
As we’re using multiple accounts, there’s lots of peering happening, which means manual steps required. - Access Issues
Sorting out the right roles, and policies, becomes vitally important. - Limited to 5 previous Roles in the UI history
This means you end up having to maintain a separate site with all the role delegation links, would be great if you could host this inside the users account securely. - Single Browser Session
Constantly switching can be a pain, comparing things that exist in different accounts can be hard. Firefox Container Tabs helps.
This is a methodology that’s working well for us, our financial visibility has increased, forecasting, and budget alignment is much better. We are more than happy with the trade-offs. It’s an opinionated approach, granted, however, it’s worth considering.
Leave a Reply