/workshop-cfn-macros

CloudFormation Macros workshop

Primary LanguageMakefile

CloudFormation Macros Workshop - NaclExpander

This workshop is aimed at building your first CloudFormation Macro, and was designed for the Melbourne AWS Programming and Tools Meetup, but can be run independently. The main requirement is that you have an AWS account you can run this in, and have coding experience in a language supported by Lambda. Examples/Answers are provided in both Python (3.7) and Node (10.x).

Last year AWS released CloudFormation Macros and, by doing so, gave us the ability to fully customise our CloudFormation templates. Macros run as Lambda functions that you write yourself and CloudFormation will allow these functions to change your templates in any way you want them to. This can be anything you imagine; duplicating entries, ensuring naming standards, pulling information from S3, up to and including writing your own custom templates that create a complete environment. In this workshop we'll take a first step in this process by building one such Macro and laying the groundwork for you to create your own.

I wrote a more extensive explanation of CloudFormation Macros, including a very simple example, on my site. If you're not already familiar with the concept of Macros, I suggest you read that before you begin as it will likely help you understand how some of this works.

NaclExpander

The Macro we'll be building in this workshop is one I call NaclExpander. This is a Macro that shows how you can easily turn some of the verbose and complicated CloudFormation syntax into something that's a lot easier to work with.

In effect, what it does is expand the existing AWS::EC2::NetworkAcl CloudFormation resource into something that contains the versions of the other required resources. So instead of this:

  NaclPublic:
    Type: AWS::EC2::NetworkAcl
    Properties:
      VpcId: !Ref VPC

  SubnetANaclPublic:
    Type: AWS::EC2::SubnetNetworkAclAssociation
    Properties:
      NetworkAclId: !Ref NaclPublic
      SubnetId: !Ref SubnetA

  NaclPublicInbound100:
    Type: AWS::EC2::NetworkAclEntry
    Properties:
      Egress: false
      NetworkAclId: !Ref 'NaclPublic'
      Protocol: '6'
      RuleAction: allow
      RuleNumber: '100'
      CidrBlock: '0.0.0.0/0'
      PortRange:
        From: '443'
        To: '443'

  NaclPublicOutbound100:
    Type: AWS::EC2::NetworkAclEntry
    Properties:
      Egress: true
      NetworkAclId: !Ref 'NaclPublic'
      Protocol: '6'
      RuleAction: allow
      RuleNumber: '100'
      CidrBlock: '0.0.0.0/0'
      PortRange:
        From: '443'
        To: '443'

you would write this:

Resources:
  NaclPublic:
    Type: AWS::EC2::NetworkAcl
    Properties:
      VpcId: !Ref VPC
      Inbound:
        - "100,6,allow,0.0.0.0/0,443"
      Outbound:
        - "100,6,allow,0.0.0.0/0,443"
      Association:
        - SubnetA

As you can see, this short version is far more readable (whether you agree with the specific syntax or not).

Going through the workshop

The workshop itself is fairly straightforward. When you clone this repo (using the cli you can do so by running git clone https://github.com/ArjenSchwarz/workshop-cfn-macros) out you will be in the master branch. This branch only contains this README file and a Makefile. To get started you can checkout the branch step1. This branch then contains everything you need for this step as well as a file called step1.md. This file will tell you what you need to do and how you can verify that it is working. Afterwards you can then move on to the step2 branch, and continue like that. The last branch is the one called finished, which will contain everything, including a CloudFormation template you can use to test that everything went right.

The included Makefile contains a way to run everything. This includes switching to the different branches (e.g. make goto-step1), running the included unit tests (e.g. make python-test-step1), running a linter over all CloudFormation templates (make cfn-lint), as well as packaging and deploying CloudFormation templates. This is only included to make running commands a bit easier and there is no requirement to use the Makefile.

Now, proceed to step 1.