# 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

  

<table><tbody><tr><td colspan="1" rowspan="1"><p>curl --proto '=https' --tlsv1.2 -sSf <a target="_blank" rel="noopener noreferrer nofollow" href="https://raw.githubusercontent.com/aws-cloudformation/cloudformation-guard/main/install-guard.sh" style="pointer-events: none">https://raw.githubusercontent.com/aws-cloudformation/cloudformation-guard/main/install-guard.sh</a> | sh</p></td></tr></tbody></table>

  
  

Set the path (optionally in ~/.bashconfig)

  

<table><tbody><tr><td colspan="1" rowspan="1"><p>export PATH=~/.guard/bin:$PATH</p></td></tr></tbody></table>

  

Check if cfn-guard is installed

<table><tbody><tr><td colspan="1" rowspan="1"><p>Cfn-guard --version</p></td></tr></tbody></table>

  

![](https://lh5.googleusercontent.com/98OfAP0qaFY_6Q5KTP42vZceMWB55k0q5EVbHKCScWEJpFs421O0sH5OyINAyPLP2W4sdZeUL4LFxAD0COr8MiF0j0cVYlNsMa0NVD-yfSvoyX4bOUzqKpDGHf_aMR3ENgwd7PPStUsGMNuRvjN9HBk align="left")

  

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

  

<table><tbody><tr><td colspan="1" rowspan="1"><p>cfn-guard migrate --output migrated_rules.guard --rules rules.guard</p></td></tr></tbody></table>

  
  
  

Unit Testing Syntax

  

<table><tbody><tr><td colspan="1" rowspan="1"><p>---<br>- name: &lt;TEST NAME&gt;<br>&nbsp; input:<br>&nbsp; &nbsp; &lt;SAMPLE INPUT&gt;<br>&nbsp; expectations:<br>&nbsp; &nbsp; rules:<br>&nbsp; &nbsp; &nbsp; &lt;RULE NAME&gt;: [PASS|FAIL|SKIP]</p></td></tr></tbody></table>

  
  

Validating multiple rules against a template.

  

<table><tbody><tr><td colspan="1" rowspan="1"><p>cfn-guard validate --data /path/to/dataDirectory --rules /path/to/ruleDirectory</p></td></tr></tbody></table>

  

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

  

<table><tbody><tr><td colspan="1" rowspan="1"><p>---<br>AWSTemplateFormatVersion: '2010-09-09'<br>Description: Sample template<br>Resources:<br>&nbsp; &nbsp; SampleVolume:<br>&nbsp; &nbsp; Type: AWS::EC2::Volume<br>&nbsp; &nbsp; Properties:<br>&nbsp; &nbsp; &nbsp; &nbsp; Encrypted: true<br>&nbsp; &nbsp; &nbsp; &nbsp; Size: 10<br>&nbsp; &nbsp; &nbsp; &nbsp; VolumeType: gp2</p></td></tr><tr><td colspan="1" rowspan="1"><p></p></td></tr></tbody></table>

  
  

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

  

<table><tbody><tr><td colspan="1" rowspan="1"><p>AWS::EC2::Volume {<br>&nbsp; &nbsp; Properties {<br>&nbsp; &nbsp; &nbsp; &nbsp; Encrypted == true<br>&nbsp; &nbsp; &nbsp; &nbsp; Size &lt;= 30<br>&nbsp; &nbsp; &nbsp; &nbsp; VolumeType == 'gp2'<br>&nbsp; &nbsp; }<br>}</p></td></tr></tbody></table>

  

Now lets validate with the cfn-guard cli

  

<table><tbody><tr><td colspan="1" rowspan="1"><p>cfn-guard validate -d your-test.template -r your-test.rules</p></td></tr></tbody></table>

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

<table><tbody><tr><td colspan="1" rowspan="1"><p>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 } } } } }&nbsp;</p></td></tr></tbody></table>

![](https://lh6.googleusercontent.com/78xlPlfRBIh8JQsCvzYrg_YWg2XvSN8zjQQAhlJvkkrcVMWX2AYWWC4_q0SCM0XeSEj5wvcILPDdwtGCsJHTnf1oKKy3YhyrMR6tv02_T8Oovrpz2wchkJe5udd4oAbd8A1r8LeAyzn1VRzBR9O8JDg align="left")

  

![](https://lh3.googleusercontent.com/Cj0ShzJSLPupaws3RTZ38rDqmJaZPd-PPDJDlCh7swa5tGRUJfxguMcTqPWxeSPHmLC9eDJuGUQyy1dxxJ2YzEc08cf89iFn06Yt3QTIr9Z8tjx437r2Bimj36VNwUT_Kx0GwwendrB89BATDYWIv7U align="left")

  

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 &lt;= 40 

  

It gives another error

  

![](https://lh6.googleusercontent.com/nxal1yHnfAHeSyiUf2f1_RjkeM9lKjks8cT453XlBoC-ed91dho0XHDkRRqoKx1EZk8tAUPAy1zJDd0liRSJUQuUWQOBYNRpA3c9I4BV9hMrmPEqJ8GWDgY4UnKpF60PMyozOqAg31pvuIqlz8Kf2iQ align="left")

  

Note the two errors for size

  

![](https://lh6.googleusercontent.com/pDSaRD4kbPF7hRrQHLibiXJB-x5hqUHXjdx3N5hJvG38pHOKdEUQ_5cqomb8V7b2CCXph2wvKiBBVk_Bey71vue7bzGCNxRaV3r_dXxZXD5925yHij88z2JY9nHqlNW_OhNzgJNX4NIuorEK4x1oChs align="left")

  

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
