Enabling Teams Using CloudFormation with Centrally Managing StackSet Deployments
The use of CloudFormation StackSets to deploy resources across multiple accounts has proven to be incredibly powerful and convenient. With the introduction of service-managed deployments, the ability to implement account baselines at an OU level has reduced the overhead of creation and management of the resources.
With self-managed deployments of CloudFormation templates as stacksets, I found myself as a bottleneck. This was due to hesitation of granting the level of access required into all accounts — including Organization master/primary billing account. To review, there is a StackSet Administration Role that exists in a central account. This role assumes into a StackSet Execution Role created in each account to deploy resources expressed as code in CloudFormation Templates. In the default configuration, the Execution Role would have administrator access (
Effect: Allow, Action: *, Resource: *) in every account.
Empowering another team to deploy using stacksets does not inherently require that the Organizational master account be used as the central point for deployment. However, considering that many of the other team’s stacksets would need to also be deployed at the time of a new account’s creation, I wanted to be able to integrate them seamlessly into our existing process while also implementing least privilege.
What follows is an explanation of providing a secondary team access to the Organization master account to deploy stacksets in a way that provides very granular controls.
To begin, here are the three roles that will be discussed in more depth:
StackSet Administration Role — exists on Organizations master account; assumes into the execution role in each account
StackSet Execution Roles — deployed to each account; assumed into by the Administration Role; possesses the permissions used to deploy resources from stacksets
Authenticated User Role — this is the role the user logs into AWS with to access the CloudFormation
In the master billing account:
Create a new Administration role that trusts the CloudFormation Service. Attach a policy that allows
AssumeRole into the Execution role in each account.
Create a new entity for the other team to assume into. This role’s policy should allow, among other permissions, the ability to create and modify stacksets with a specific naming convention, but only when the administration role above is used. To accomplish this, the role will also need the ability to pass this role to the CloudFormation service.
In the member accounts:
Create an execution role with a trust policy that allows assumption by both the primary administration role and the newly created one for the secondary team. This is done to allow management as part of new account provisioning by the primary team and future management of the stacks by the secondary team. Keep in mind that permissions like
PutRolePolicy, etc. can allow escalation beyond what the secondary team should have in that account.
To add further controls on the resources being provisioned by the secondary team, this execution role can be equipped with a scoped-down policy that allows the provisioning of allowed resources only.
When the secondary team authenticates to the Organization master account, they will not be able to modify or deploy any stacksets that do not conform to their required naming convention. This prevents modification of existing or prohibited stacksets.
When deploying stacksets, the team will be faced with a permission denied error and unable to proceed if they do not choose the correct administration role, execution role, or name it incorrectly. If they attempt to deploy a resource that the execution role does not have the permission, the stackset will successfully deploy, but the stack instance will fail. If there are specific accounts that need to remain outside the reach of the secondary team — for example, the organization master account itself — simply do not deploy the execution role to said accounts.
Any new account creation process will need to integrate the new solutions developed by the secondary team. This solution allows a secondary team to make organization unit-level or organization-level changes without impacting solutions deployed by other teams. Lastly, make sure that any of these changes follow some sort of internal change process since changes made with this process can have very impactful outcomes.