Multi-account AWS setup with Pulumi
A year or so ago we had 2 AWS accounts, one for dev and one for prod, but we had a number of services products hosted in the one account. This made billing more difficult because a number of things cannot be tagged. It also increases the blast radius for security related incidents.
We also use S3 for our state management, but this approach would work for any Pulumi state store.
To get started you need a root account which Pulumi will login to, the console access will be the same.
my-org-management, will be our root account for this post. We will always log into this account, then switch role into the various other accounts we have.
We will also use Pulumi to setup our account structure. These projects will just store the state in our git repo.
Management account setup
First we need roles which users log into the management account using. I will not be covering user setup in this post. When users (iam or federated) login they need to end up with one of these ‘management’ roles assumed.
We then need to create mappings from our management role to the IAM role in each sub account, below Management-Admin can assume the Admin and Billing roles in all accounts. Management-Billing can only assume the Billing role.
You could also have prodSubaccounts and devSubaccounts lists allowing a management developer role to assume admin in a dev account.
Finally, we need to allow our management roles to access our pulumi state bucket and KMS key. This policy should be very minimal, because if you forget to add a provider to any Pulumi resources your program won’t accidentally create it in your management account.
Then lets export a few things for the sub account program
Now we have our management account setup, we can setup our sub-accounts.
You should have a Pulumi program and then you can create a stack per sub-account. This is because you need to login as an IAM account for each account to run the program as we don’t yet have a multi account setup.
The sub-account setup is much easier than the management account. We just have to create the Roles which we configured in the management account, then attach some managed policies to those roles.
To run this stack, ensure AWS_PROFILE is setup for that account, then run the up command for that account
pulumi up -s bootstrap-subaccount.<ACCOUNT> --cwd bootstrap-subaccount
AWS Console usage
Once you have logged into the management account, to use any sub account choose Switch Role from the user dropdown, then enter the account alias and role you want to jump into.
Pulumi Program Setup
The nice thing about this setup is the way you use the AWS console and write your Pulumi program is the same.
To run this program our AWS_PROFILE needs to be logged in as the Management-Admin role in our management account. This role has permissions to write to our Pulumi state bucket in the management account and also use our KMS key which encrypts our secrets.
This requires us to set the
provider on all our resources, if we forget then the
up will fail because the management role doesn’t have permissions to create resources in the management account.
By creating a management account which contains our KMS key to encrypt our Pulumi secrets and also our Pulumi state bucket, we can run all our Pulumi programs as a single role, then configuration of the stack will get Pulumi to assume a role into the target account to create the infrastructure there.
We have also put our AWS account setup into Pulumi programs, ensuring all our sub-accounts have a consistent setup. It’s a good idea to also put your admins of last resort IAM users, setup cloudtrail and perform whatever standard setup you need to perform.