4 minutes
CloudFormation all the way down - StackSets for Role Management
Introduction
One of my 100% non-negotiable principals is that all aspects of resource management in the cloud is by Infrastructure-as-Code (IaC). By IaC, I mean ALL infrastructure; from the moment a new AWS account is created through to when production workloads are deployed and run. Nothing is created or managed manually.
This is why CloudFormation StackSets grated on my nerves for so long as they contained steps that were manual. My jaded nerves have now been soothed by the recent announcement of CloudFormation support for StackSets.
The Problem
Step backwards for a moment and consider this scenario; you are a small-scale consumer of AWS who understands that roll-based access control is best for managing who-does-what inside your AWS accounts. You’re fairly time poor and it is really tedious logging into each AWS accounts and handcrafting the same IAM Roles and Policies.
Wouldn’t it be best if you could have a single IaC pipeline to manage all of it for you, but how would that even work?!?
The Solution
StackSets to the rescue! I had this exact problem with my personal AWS accounts. I have a handful of accounts that I’ve collected over the years and each have various layers of automation applied as I grew my AWS experience. After pruning a bunch of unused resources from each of them, I moved them all under a dedicated Organisational Unit (OU) as below:
StackSets give me a single location to deploy two dedicated IAM management roles into all my child accounts. These roles are assumed later by stages in my pipeline to deploy account specific IAM resources. Having all my child accounts under an OU provides the following StackSet benefits:
- The deployed StackSet is configured to deploy to the OU, so existing accounts automatically get the special IAM roles; and
- New accounts which get added will also automatically get the roles deployed (aka I can be lazy and not need to do anything).
The Pipeline
Ensuring my 100% compliance to IaC, I start off by deploying an “Inception Pipeline”.
An “Inception Pipeline” is a CloudFormation template and shell script which creates the following resources:
- An AWS CodeCommit repository.
- An AWS CodePipeline pipeline.
- Two IAM Roles:
- One for assumption by CodePipeline; and
- Another that is assumed to execute CloudFormation actions.
- An S3 Bucket (and Bucket Policy) to host artifacts generated by CodePipeline.
Once the template is successfully deployed, the script initialises the local folder as a git repository, adds in all the files, performs the first commit, and finally pushes everything up to the newly minted CodeCommit repository.
What makes this exceptional, is how CodePipeline is configured. The pipeline contains a CloudFormation action that references the recently executed (and committed to git) template. As I make changes to my pipeline, they are automatically picked up and deployed for me.
I’ll dive deeper into this in future posts as I have a few variations for CodeCommit, GitHub and multi-region pipelines.
This is what a deployed pipeline looks like:
And yes, you can clearly see that I don’t always get things right the first time…. lucky try 16 in this case 😁
The StackSet Template
With a deployment pipeline in place, I created a new CloudFormation template like this (I’ve removed a chunk of unnecessary bits for brevity). Add a CodePipeline Stage to deploy the template, commit, push and ta-daa!
AWSTemplateFormatVersion: 2010-09-09
Parameters:
ParamPipelineName:
Type: String
ParamOrganisationUnitId:
Type: String
ParamMasterAccountId:
Type: String
ParamKmsKeyArn:
Type: String
Resources:
StackSet:
Type: AWS::CloudFormation::StackSet
Properties:
AutoDeployment:
Enabled: true
RetainStacksOnAccountRemoval: false
Capabilities:
- CAPABILITY_NAMED_IAM
Description: 'Deploy an IAM Role to deploy RBAC roles across accounts'
OperationPreferences:
FailureToleranceCount: 1
MaxConcurrentCount: 5
Parameters:
- ParameterKey: ParamMasterAccountId
ParameterValue: !Ref ParamMasterAccountId
- ParameterKey: ParamKmsKeyArn
ParameterValue: !Ref ParamKmsKeyArn
PermissionModel: SERVICE_MANAGED # SERVICE_MANGED | SELF_MANAGED
StackInstancesGroup:
- DeploymentTargets:
OrganizationalUnitIds:
- !Ref ParamOrganisationUnitId
Regions:
- !Ref AWS::Region
StackSetName: !Sub '${ParamPipelineName}RbacStackSet'
TemplateBody: |
AWSTemplateFormatVersion: 2010-09-09
Parameters:
...
Resources:
RbacDeployerPolicy:
Type: AWS::IAM::ManagedPolicy
Properties:
...
RbacDeployerRole:
Type: AWS::IAM::Role
Properties:
...
Outputs:
...
Outputs:
StackSetId:
Value: !Ref StackSet
It’s deployed and I now have a dedicated IAM Role in each of my child accounts that I can assume to deploy my RBAC infrastructure.
Conclusion
In the end it was actually pretty easy to get it all running and deployed (if you ignore the adventures in my previous post 😜).
My next post I’ll dive into how I use StackSets to manage the RBAC infrastructure in all of my accounts.
Stay tuned!