Deploying AWS resources with GitHub Actions can help save you a lot of time and ensure you are deploying quality templates. Beyond quality, you can be sure you are keeping your Infrastructure-as-Code (IaC) in line with what is ACTUALLY deployed in your environments.
There is a time and a place to not use CICD to deploy AWS Resources, but most of the time you can run your pipelines or workflows to deliver your resources directly into your AWS Account knowing that what is deployed is exactly what is represented in your Master branch.
Don’t need the 30,000ft. view? Jump right to the code here:
https://github.com/rosswickman/aws-automation-workflows
The Setup
You will need:
-
A Clone or Fork of the repo linked above
-
S3 Bucket to store CFN and TF templates. Possibly your TF state. (recommended but not required)
-
IAM User with permissions to deliver templates to S3
-
IAM User with permissions to deploy resources
NOTE: You could do this with a single IAM User but I recommend minimizing blast radius with least-privilege wherever possible. In the ideal production situation, you should configure a GitHub Actions Runner in your environment with the permissions required.
The Configuration
Deploy the three stacks in the requirements/
directory of the shared repo. The workflows are configured for region us-west-2, so deploy there.
Configure your repository secrets by getting the IAM Access Keys from AWS Secrets Manager in your account.
If you cloned/forked the project to start, you will see there is a cloudformation
and a terraform
directory in the project. Each directory has a respective template that deploys a security group in your configured AWS Account. We used a security group because they don’t cost anything. You will need to update the VPC ID (from us-west-2) in each template for the resource to properly deploy in your account, but that is all you should need to do.
The Process
Before deploying anything to (specifically) production, the templates should be reviewed for security issues and quality. For this, we use tools like SuperLinter, CFN-NAG, CFN-Lint, and Checkov.
Each tool is represented by a workflow that completes a respective process. These workflows can be organized to your liking. However, as they are configured in this project, this process will run after you push any changes to your feature branch.
Once our templates check out and pass those basic checks, we can deliver the templates to an S3 bucket. This allows the templates to be referenced within the AWS Console or stored for backup but is not required.
To prepare the resources for delivery and deployment, you will need to create a Pull Request. The pull request will run the Terraform Plan and show you what will happen if the Terraform template is deployed.
Delivery happens upon Merge to the Master Branch. You can configure the deployment of resources to be automatic or by a manual trigger. In some cases, manual deployment makes a lot of sense. I’ll let you be the judge of what should be a manual trigger.
The Outcome
Once your Pull Request was merged into the Master Branch, the templates were Delivered to the S3 bucket you configured using the instructions in the Git Project. If you left the Workflows alone, the CloudFormation Deploy and Terraform Deploy required manual action to trigger.
Once triggered and completed successfully, you should see two new Security Groups attached to your VPC. One was deployed via the CloudFormation template and the other with Terraform.
There you have it. You have just configured a CICD/D workflow to deliver source-controlled AWS Resource Templates directly to your Account.
In future posts, I will show how to deploy AWS Organization StackSets as well as deploying StackSets to a Multi-Org Configuration sourced from a single repo.
I know there are many different ways to configure this process, this demo uses a single repository for both CFN and TF templates. That may not always be the desired solution. If you are similarly deploying resources, I’d love to know what you are doing differently or if you have any recommendations on what I should do differently.