Source Control your AWS CloudFormation templates with GitHub

In this blog post I show you how to source control your AWS CloudFormation templates using the source control tool, GitHub.

Source Control your AWS CloudFormation templates with GitHub
Source Control your AWS CloudFormation templates with GitHub

Source Control is the practice of tracking and managing changes to your code. This could be software code or infrastructure as code (IaC).

Source Control in the Development side of IT has been common practice for a long time. But it is something that is still new or uncommon within the Operations teams in IT.

I can hold my hand up and say a lot of the scripts or deployment templates I wrote use to live in folders marked version 1, old version, new version, etc. Or even in draft emails in my email account. What a crazy way to work, right?

Files, computer screen and cup
Illustration by Icons 8 from Ouch!

Thanks to the invention and my discovery of GitHub I have been become better at storing scripts and become a better write of scripts (hopefully!) now everything is publicly on display.

What is GitHub?

What is GitHub video

Use GitHub for your AWS CloudFormation source control

I've recently been learning and creating AWS CloudFormation templates and have created a GitHub repository to help store my templates, so I can work on them and also share with others.

You can find my workings here:

When I have been creating the templates on my local machine I have been using certain tools to validate and check my templates for best practices and any security vulnerabilities.

This has led me to see if I can build these checks into my GitHub repository with GitHub Actions and I can!

Validate your AWS CloudFormation template

When writing a template it can be easily to get in to bad habits, or maybe use the wrong phrasing or syntax. Especially if you are switching between languages or even multi-tasking.

In order to test your AWS CloudFormation templates you can deploy them, it will help to validate your template but there are other ways, better ways. Lint testing your code is the way forward.

Lint testing your code can help to pick up any errors or best practice violations. You can lint test your code as you write it, there are often tools you can install or plugs within your favourite code editor. But best practice is also perform lint testing when you check code into your source control environment.

To help validate your AWS CloudFormation templates you can use a tool called cfn-lint.

The cfn-lint tool can validate both YAML and JSON templates against the AWS CloudFormation Resource Specification.

The cfn-lint tool will return a zero exit code if there are no issues found in your template. Any other value suggests there is something wrong with the template.

  • 0 is no issue was found
  • 2 is an error
  • 4 is a warning
  • 6 is an error and a warning
  • 8 is an informational
  • 10 is an error and informational
  • 12 is an warning and informational
  • 14 is an error and a warning and an informational

Use cfn_nag to check for security vulnerabilities

There is another tool called cfn_nag that can check your code for potentially any insecure infrastructure. When you read the documentation around this tool, the author says it can check for things such as:

  • IAM rules that are too permissive (wildcards)
  • Security group rules that are too permissive (wildcards)
  • Access logs that aren't enabled
  • Encryption that isn't enabled
  • Password literals

Checking your infrastructure templates early in the process for any potential security issues is important. No one wants to be responsible for security holes within their infrastructure that could cause reputational or finance issues for them or their customers.

AWS CloudFormation workflow with GitHub Actions

With our AWS CloudFormation templates being stored within GitHub as a central repository we want to ensure that only templates that conform to the correct standards are stored there.

In order to this we can build a GitHub actions workflow that will run the cfn-lint and cfn_nag tools.

Below is the GitHub Actions workflow that I have created.

# This is a basic workflow to help you get started with Actions
name: Lint Test CFN templates

# Controls when the workflow will run

# Triggers the workflow on push or pull request events but only for the main branch
    branches: [main]
    branches: [main]

# Allows you to run this workflow manually from the Actions tab

# This workflow runs all the templates through cfn-lint and cfn_nag
    name: Check linting and securtity concerns
    runs-on: ubuntu-latest
      - name: Checkout
        uses: actions/checkout@v2
      - name: cfn-lint-action
        uses: ScottBrenner/cfn-lint-action@v2.2.3
          args: "*.yaml"
      - name: Stelligent cfn_nag
        uses: stelligent/cfn_nag@v0.8.6

The workflow I have created will trigger for a number of reasons:

  • When something is pushed into the main branch of the repository.
  • When a pull request is created to push something into the main branch of the repository.
  • When manually triggered.

The GitHub Action runs on a Ubuntu runner. It runs three steps:

  • Checkout - This step checkouts the code so that the workflow can work with it and have access to it.
  • cfn-lint-action - This second step runs all my YAML template files against the cfn-lint tool.
  • stelligent cfn_nag - This third steps runs the cfn_nag tool against all the templates.

I recently created a pull request trying to merge a new template into the main repository and when the checks ran there were errors:

GitHub Action Pull Request failure
GitHub Action Pull Request failure

When I drilled into the details I can see I have some warnings and errors within my template according to the cfn_nag tool.

cfn-nag tool warnings and errors
cfn_nag tool warnings and errors

This helps to alert me and the owner or maintainer of the repository that the template has some issues and should be looked at before being merged into the main branch.

Let me know what how you are using GitHub Actions to help store and write better Infrastructure as Code templates!