AWS released version 2 of CloudFormation Guard, their open source tool for validating CloudFormation templates. This release introduces a number of new features including type blocks, support for Conjunctive Normal Form, filters, and named rules.
Guard enables writing policy-as-code that can then be used to validate any well-formed JSON or YAML file. These rules can be used to validate any number of infrastructure-as-code files including CloudFormation ChangeSets, Terraform JSON configuration files, or Kubernetes configurations. As an example, Guard could be wired into a CI pipeline to validate ChangeSets are safe before moving into deployment.
With this release it is now possible to write rules using type blocks. This enables writing more succinct rules with implicit AND
s between clauses. For example, to validate if all EC2 volumes are encrypted, with a volume type of GP2 and a size of less than 10GB you can now write:
AWS::EC2::Volume {
Properties {
Encrypted == true
Size <= 10
VolumeType == 'gp2'
}
}
With the added support for Conjunctive Normal Form (CNF), it is now possible to include OR
clauses within the type blocks. The above example can be adjusted to permit either GP2 or GP3 volume types:
AWS::EC2::Volume {
Properties {
Encrypted == true
Size <= 10
VolumeType == 'gp2' OR
VolumeType == 'gp3'
}
}
The above example could also be written using the new IN
operator. The IN
operator allows for specifying a list of valid options to be checked against:
AWS::EC2::Volume {
Properties {
Encrypted == true
Size <= 10
VolumeType in ['gp2', 'gp3']
}
}
There is now support for filtering and named rule sets. The type block is a short-hand filter that matches only by type of resource. Naming rules allows for reusing rule blocks throughout the file. As Matteo Rinaudo, senior developer advocate with AWS, notes:
Filters and named rules are the prescribed way to express clauses in Guard 2.0. Use both features to enhance readability, support refactoring and allow for complete flexibility in recombining rules for higher order clauses.
For example, to validate that resources have any tags on them the following named rule could be defined:
rule assert_all_resources_have_non_empty_tags {
Resources.*.Properties.Tags !empty
}
This rule can then be used within a larger rule that validates that DynamoDB tables have at least one tag and are also encrypted:
let ddb = Resources.*[ Type == 'AWS::DynamoDB::Table' ]
rule dynamo_db_sse_on when %ddb !empty {
assert_all_resources_have_non_empty_tags
%ddb.Properties.SSESpecification.SSEEnabled == true
}
Validation can be done on any section within the template now, including Description and Parameters. Unit tests can be written against the rules to validate they work as desired. The test data file is a JSON or YAML file that mocks the necessary resources and includes an expected outcome for the rule assessment.
CloudFormation Guard is open-source and available via GitHub.