Cloudformation Guard

Cloudformation Guard

Policy as Code automates enforcement and implementation via the policy to find out logical inconsistencies , syntax error, missing dependencies before they go into Infrastructure Provisioning process through the IAC. They act as guardrails and are proven to be valuable in Infra code testability. Policy as code ensures consistency and accountability with version control and transparency improving development efficiency. They reduce implementation error and deployment time along with prevention of drifts early in the development

Some Examples of Policy as Code are

  • Hashicorp Sentinel

  • Pulmi Crossguard

  • Open Policy Agent

  • Cloudformation Guard

In this blog we will be talking about CloudFormation Guard which is an opensource policy as code evaluation tool

The AWS’s Guard command line interface (CLI) provides a simple-to-use, yet powerful and expressive, declarative domain-specific language (DSL) that you can use to express policy as code. Also you can use CLI commands to validate structured hierarchical JSON or YAML data against those rules. Guard also provides a built-in unit testing framework to verify that your rules work as intended.

Cfn-lint is like typescript for js. It does thorough inspection of the template instruction. The linter shows error on wrong formats.

Cfn guard is opensource cli. For example Creating rules to ensure the cryptographic keys for ec2 is always set or The volume of ec2 is always less than 20 GB and is encrypted.

Installing the Cloudformation Guard CLI

curl --proto '=https' --tlsv1.2 -sSf | sh

Set the path (optionally in ~/.bashconfig)

export PATH=~/.guard/bin:$PATH

Check if cfn-guard is installed

Cfn-guard --version

Rules are made of clauses based upon the Guard domain-specific language (DSL) that an be validated for json or yaml structures. Rules can be on plaintext and doesnot require an extension.

Guide to Migrating if youre already using cfn-guard 1.0 to 2.0 or later

cfn-guard migrate --output migrated_rules.guard --rules rules.guard

Unit Testing Syntax

- name: <TEST NAME>

Validating multiple rules against a template.

cfn-guard validate --data /path/to/dataDirectory --rules /path/to/ruleDirectory

Lets get started with ec2 volume size

We are saving this sample template to create a ec2 volume of type gp2 with size 10 gb

AWSTemplateFormatVersion: '2010-09-09'
Description: Sample template
    Type: AWS::EC2::Volume
        Encrypted: true
        Size: 10
        VolumeType: gp2

Creating a Rule

Now let’s create a rule that says the size should be less than or equal to 30 gb and type should be gp2

AWS::EC2::Volume {
    Properties {
        Encrypted == true
        Size <= 30
        VolumeType == 'gp2'

Now lets validate with the cfn-guard cli

cfn-guard validate -d your-test.template -r your-test.rules

The Result for failed test because our yaml contains g[2 and the rule contains gp2

cfn-guard validate -d your-test.template -r your-test.rules your-test.template Status = FAIL FAILED rules your-test.rules/default FAIL --- Evaluating data your-test.template against rules your-test.rules Number of non-compliant resources 1 Resource = SampleVolume { Type = AWS::EC2::Volume Rule = your-test.rules/default { ALL { Check = VolumeType EQUALS "gp3" { ComparisonError { Error = Check was not compliant as property value [Path=/Resources/SampleVolume/Properties/VolumeType[L:8,C:18] Value="gp2"] not equal to value [Path=[L:0,C:0] Value="gp3"]. PropertyPath = /Resources/SampleVolume/Properties/VolumeType[L:8,C:18] Operator = EQUAL Value = "gp2" ComparedWith = "gp3" Code: 6. Properties: 7. Encrypted: true 8. Size: 10 9. VolumeType: gp2 } } } } } 

The guard test failed because gp2 was compared with gp3. The test passes when the value is gp2

Now let’s also modify the volume size to <= 40

It gives another error

Note the two errors for size

Value is 10 and compared with greater than or equal to 40 gb

The next error is as of previous for the type of the volume gp3

Now we can enforce rules for our Infrastructure as code