Releases: aws-cloudformation/cloudformation-guard
v3.0.0-alpha
New Features
- Added support for advanced regular expressions
- Improved handling for intrinsic functions in test command
- Added
--structured
flag to validate command to emit JSON/YAML parseable output
What's Changed
- Added OS-specific cargo targets to release workflow by @akshayrane in #310
- [Code Quality]: Rust-fmt action + formatting project by @joshfried-aws in #315
- [Code Quality]: Implementing custom writer, bug fixes, new integration test framework, and adding initial tests for all commands by @joshfried-aws in #325
- Bump tokio from 1.21.2 to 1.24.2 by @dependabot in #327
- +[fancy-regex] Added support for advanced regular expressions by @akshayrane in #326
- improved safety of serde_yaml::Value -> value conversion by @joshfried-aws in #328
- Improve handling of function references for test command by @joshfried-aws in #331
- PR to add Thiserror to cfn-guard by @joshfried-aws in #329
- Redirected verbose output from stdout to custom writer and added unit… by @akshayrane in #332
- Addit cargo-audit to CI + bump up clap to 3.0 by @joshfried-aws in #330
- Implemented custom reader, increasing test coverage for validate command. by @joshfried-aws in #334
- Update CONTRIBUTING.md by @swiercek in #335
- Clap4 by @joshfried-aws in #336
- Added integration tests against aws-guard-rules-registry on Ubuntu by @akshayrane in #337
- Update check-tags-present.guard by @Aishwarya4400 in #313
- Adding structured evaluator by @joshfried-aws in #339
- Added deprecated short flag for print-json in parse-tree by @akshayrane in #345
- bumping up to 3.0.0-alpha by @joshfried-aws in #347
New Contributors
- @swiercek made their first contribution in #335
- @Aishwarya4400 made their first contribution in #313
Full Changelog: 2.1.3...3.0.0-alpha
Details
1. Added support for advanced regular expressions
Supports usage of advanced regular expressions such as lookaround and backreferences.
Rules file (advanced_regex_negative_lookbehind_rule.guard)
NotAwsAccessKey != /(?<![A-Z0-9])[A-Z0-9]{20}(?![A-Z0-9])/
NotSecretAccessKey != /(?<![A-Za-z0-9\\/+=])[A-Za-z0-9\\/+=]{40}(?![A-Za-z0-9\\/+=])/
Data file (advanced_regex_negative_lookbehind_non_compliant.yaml) (click to expand)
NotAwsAccessKey: AKIAIOSFODNN7EXAMPLE
NotSecretAccessKey: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
Command (click to expand)
cfn-guard validate \
-d guard/resources/validate/data-dir/advanced_regex_negative_lookbehind_non_compliant.yaml \
-r guard/resources/validate/rules-dir/advanced_regex_negative_lookbehind_rule.guard \
--show-summary all
Output with non-compliant template (click to expand)
advanced_regex_negative_lookbehind_non_compliant.yaml Status = FAIL
FAILED rules
advanced_regex_negative_lookbehind_rule.guard/default FAIL
---
Evaluation of rules advanced_regex_negative_lookbehind_rule.guard against data advanced_regex_negative_lookbehind_non_compliant.yaml
--
Property [/NotAwsAccessKey] in data [advanced_regex_negative_lookbehind_non_compliant.yaml] is not compliant with [advanced_regex_negative_lookbehind_rule.guard/default] because provided value ["AKIAIOSFODNN7EXAMPLE"] did match expected value ["/(?<![A-Z0-9])[A-Z0-9]{20}(?![A-Z0-9])/"]. Error Message []
Property [/NotSecretAccessKey] in data [advanced_regex_negative_lookbehind_non_compliant.yaml] is not compliant with [advanced_regex_negative_lookbehind_rule.guard/default] because provided value ["wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"] did match expected value ["/(?<![A-Za-z0-9\\/+=])[A-Za-z0-9\\/+=]{40}(?![A-Za-z0-9\\/+=])/"]. Error Message []
2. Improved handling for intrinsic functions in test command
With the test command, the intrinsic functions now get resolved to their equivalent JSON syntax.
Unit test file (intrinsic_fn_tests.yaml) (click to expand)
- name: a redshift cluster with short hand functions
input:
Resources:
myCluster:
Type: "AWS::Redshift::Cluster"
Properties:
DBName: "mydb"
KmsKeyId:
Fn::ImportValue:
!Sub "${pSecretKmsKey}"
expectations:
rules:
REDSHIFT_ENCRYPTED_CMK: PASS
Rule file (intrinsic_fn_rule.guard)
let redshift_clusters = Resources.*[ Type == 'AWS::Redshift::Cluster']
rule REDSHIFT_ENCRYPTED_CMK when %redshift_clusters !empty {
%redshift_clusters.Properties.KmsKeyId exists
%redshift_clusters.Properties.KmsKeyId == {"Fn::ImportValue": {"Fn::Sub":"${pSecretKmsKey}"}}
}
Command (click to expand)
cfn-guard test \
-t intrinsic_fn_tests.yaml \
-r intrinsic_fn_rule.guard
Output (click to expand)
Test Case #1
Name: a redshift cluster with short hand functions
PASS Rules:
REDSHIFT_ENCRYPTED_CMK: Expected = PASS
3. Added --structured
flag to validate command to emit JSON/YAML parseable output
Emits an output that could be directly parsed using native JSON and YAML parsers, in case of multiple files or directories passed as input with the new flag.
Command
cfn-guard validate \
-d guard/resources/validate/data-dir/s3-public-read-prohibited-template-non-compliant.yaml \
-d guard/resources/validate/data-dir/s3-public-read-prohibited-template-compliant.yaml \
-r guard/resources/validate/rules-dir/s3_bucket_public_read_prohibited.guard \
--structured -o json --show-summary none
Output (click to expand)
[
{
"name": "",
"metadata": {},
"status": "FAIL",
"not_compliant": [
{
"Rule": {
"name": "S3_BUCKET_PUBLIC_READ_PROHIBITED",
"metadata": {},
"messages": {
"custom_message": null,
"error_message": null
},
"checks": [
{
"Clause": {
"Unary": {
"context": " %s3_bucket_public_read_prohibited[*].Properties.PublicAccessBlockConfiguration EXISTS ",
"messages": {
"custom_message": "",
"error_message": "Check was not compliant as property [PublicAccessBlockConfiguration] is missing. Value traversed to [Path=/Resources/MyBucket/Properties[L:13,C:6] Value={\"BucketEncryption\":{\"ServerSideEncryptionConfiguration\":[{\"ServerSideEncryptionByDefault\":{\"SSEAlgorithm\":\"AES256\"}}]},\"VersioningConfiguration\":{\"Status\":\"Enabled\"}}]."
},
"check": {
"UnResolved": {
"value": {
"traversed_to": {
"path": "/Resources/MyBucket/Properties",
"value": {
"BucketEncryption": {
"ServerSideEncryptionConfiguration": [
{
"ServerSideEncryptionByDefault": {
"SSEAlgorithm": "AES256"
}
}
]
},
"VersioningConfiguration": {
"Status": "Enabled"
}
}
},
"remaining_query": "PublicAccessBlockConfiguration",
"reason": "Could not find key PublicAccessBlockConfiguration inside struct at path /Resources/MyBucket/Properties[L:13,C:6]"
},
"comparison": [
"Exists",
false
]
}
}
}
}
},
{
"Clause": {
"Binary": {
"context": " %s3_bucket_public_read_prohibited[*].Properties.PublicAccessBlockConfiguration.BlockPublicAcls EQUALS true",
"messages": {
"custom_message": "",
"error_message": "Check was not compliant as property [PublicAccessBlockConfiguration.BlockPublicAcls]...
v2.1.3
AWS CloudFormation Guard 2.1.3 is a patch release that resolves 2 bugs from 2.1.2 release.
Bug fixes
- #306 - Fix for
cfn-guard-lambda
for timestamp offset - #305 - Fix for release workflow to upload artifacts
Full change log: 2.1.2...2.1.3
v2.1.2
AWS CloudFormation Guard 2.1.2 is a patch release that resolves a bug from 2.1.1 release.
Bug fix
- #300 - Resolved issue with failing
test
commands for input templates that had shorthand syntax in YAML, added unit test coverage
Full change log: 2.1.1...2.1.2
v2.1.1
AWS CloudFormation Guard 2.1.1 is a patch release that includes new features, resolves bugs, and addresses feedback from the open source community.
New Features
- Docker image for Guard now available in ECR public gallery
Bug fixes
- Security fix for denial of service attack
- Improved parsing logic and graceful exits in case of parsing failures
- Upgraded Lambda to use new evaluation engine
Issues addressed
- #210 - [BUG] main thread panic
- #160 - cfn-guard test should fail when test file isn't found
- #228 - [BUG] Parsing error when comments used at EOF
- #224 - [BUG] DoS using Crafted Yaml file
- #266 - [BUG] empty Function Broken on Boolean Keys
- #252 - [BUG] Message Formatting
Other changes
- #239 - Updated FFI exports to support Rust-supported types by @tylersouthwick
- #238 - Fixed return Result return types by @tylersouthwick
- #282 - Improved parsing for inner regular expressions by @joshfried-aws
- #287 - Added non-zero exit code for parsing failures by @tylersouthwick
- #278 - Better handling of EOF in Guard rules by @joshfried-aws
- #275 - Handling slashes in Resource names by @joshfried-aws
- #276 - Added error for alias event to prevent panic by @joshfried-aws
- #271 - Decouple from yaml-rust and unblock crates.io (http://crates.io/) release by @joshfried-aws
- #270 - Bump up serde-yaml by @joshfried-aws
- #269 - Added empty check for boolean values by @akshayrane
- #284 - Added is_bool support by @tylersouthwick
- #254 - Fixed formatting for Guard evaluation report by @wkexiang
- #262, #255 - Update Lambda to use new evaluation engine by @GriffinMB & @akshayrane
- #264 - Fix for IN operator with literal LHS by @dchakrav-github
- #243, #246, #263, #247 - Dependabot version bumps
- #292 - Added GitHub action to automatically push a docker image on every commit by @akshayrane
Full change log: 2.1.0...2.1.1
Details
Guard Docker Image launched on ECR public gallery
Prerequisites
- Install docker. Follow this guide.
- Have a directory ready on the host you are downloading the docker image to that contains data templates and Guard rules you are planning to use, we may mount this directory and use the files as input to
cfn-guard
. We'll refer this directory to be calledguard-files
in the rest of this guide
Usage Guide
To use the binary, we should pull the latest docker image, we may do so using the following command:
docker pull public.ecr.aws/aws-cloudformation/cloudformation-guard:latest
Now go ahead and run the docker image, using the files from directory we have our templates and rules file in, using:
docker run \
--mount src=/path/to/guard-files,target=/container/guard-files,type=bind \
-it public.ecr.aws/aws-cloudformation/cloudformation-guard:latest \
./cfn-guard validate -d /container/guard-files/template.yml -r /container/guard-files/rule.guard
We should see the evaluation result emitted out on the console.
Tagging convention
- We use the tag
latest
for the most recent docker image that gets published in sync withmain
branch of thecloudformation-guard
GitHub repository. - We use the convention
<branch_name>.<github_shorthand_commit_hash>
for tags of historical docker images
New contributors
- @joshfried-aws made their first contribution in #270
- @GriffinMB made their first contribution in #255, pushed as part of #262
- @tylersouthwick made their first contribution in #284
- @wkexiang made their first contribution in #254
v2.1.0
AWS CloudFormation Guard 2.1.0 is a major release that includes new features, resolves bugs, and addresses feedback from the open source community.
New Features
- Parameterized Rules
- Directory bundle support for running tests and validations for templates
- Dynamic data lookup for inspection via multiple data files
- Support Code view and pinpoint location of errors
- Backwards compatible with
cfn-guard
2.x.x
Bug Fixes
- Fixed short-circuit on error condition with multiple resources of the same type. All errors are now displayed
- Filter by type attribute and logical name match
Issues Addressed
- #178 - [Enhancement] Add file name convention based test file selection for the test command
- #186 - Filter based on Resource Logical ID
- #202 - [BUG] Error message includes details of unrelated resource
- #203 -
cfn-guard validate —print-json
does not work - #204 - [Enhancement] Add CDKTemplate type to validation command
- #217 - [BUG]
IN
Statement prints out extraneous error info - #219 - [Enhancement] Add line number of analyzed file into the json report
Other Changes
- Create pull_request_template.md by @priyap286 in #181
- Retrieve version number dynamically from environment variable in code by @priyap286 in #179
- Small correction in cfn-guard lambda README.md by @priyap286 in #185
- Fix typos in QUERY_AND_FILTERING.md by @priyap286 in #188
- Created an issue template for a general issue by @priyap286 in #187
- feat: Parameterized rules by @dchakrav-github in #220
- feat: Parameterized rules by @dchakrav-github in #222
- Added
input-parameters
argument for shared context from parameter files against data templates by @akshayrane - Added overloaded behavior for
rules
,data
andinput-parameters
arguments to support multiple mixed-type values of files and directories by @akshayrane - Added unit tests to add coverage for combinations of
rules
,data
andinput-parameters
by @akshayrane
Full Changelog: 2.0.4...2.1.0
Details
Parameterized Rules
A user can leverage parameterized rules to write re-usable checks. User can use these checks to write Guard rules that works across several types of payloads such as AWS CloudFormation Templates, Terraform plans that use AWS CC, and AWS Config for asserting conditions.
Example of re-usable checks:
Sample parameterized guard rule to check network config (click to expand)
#
# Top level doc type checks
#
let cfn_resources = Resources.*
let aws_config = configuration.*
rule is_cfn_doc_type when %cfn_resources !empty {
Resources exists
}
rule is_aws_config_doc_type when %aws_config !empty {
configuration exists
}
#
# ECS Service
#
rule deny_ecs_services_invalid_configuration when is_cfn_doc_type {
check_ecs_services_cfgs(Resources[ Type == 'AWS::ECS::Service' ].Properties)
}
rule deny_ecs_services_invalid_configuration when is_aws_config_doc_type
resourceType == 'AWS::ECS::Service'
{
check_ecs_services_cfgs(configuration)
}
#
# Example of network configuration checks across ECS TaskSets and ECS Service using a common rule:
#
# ECS TaskSet
#
rule deny_ecs_task_set_invalid_configuration when is_cfn_doc_type {
#
# For TaskSet, the property is NetworkConfiguration.Aws[V]pcConfiguration
#
check_ecs_network_config(
Resources[ Type == 'AWS::ECS::TaskSet' ]
.Properties
.NetworkConfiguration
.AwsVpcConfiguration)
}
#
# ECS Service check, common across AWS Config and CloudFormation
#
rule check_ecs_services_cfgs(ecs_service_cfgs) {
%ecs_service_cfgs {
EnableExecuteCommand not exists or
EnableExecuteCommand == false
<<Disallowed command executions for ECS services>>
#
# For ECS Service, the property is NetworkConfiguration.Aws[V]pcConfiguration
#
check_ecs_network_config(NetworkConfiguration.AwsVpcConfiguration)
}
}
#
# Check ECS network configuration common to TaskSet and Service
#
rule check_ecs_network_config(network_cfgs) {
%network_cfgs {
AssignPublicIp == 'DISABLED' or
AssignPublicIp == 'disabled'
<<Prevent assignment of public IP address to ECS services. AssignPublicIp must be DISABLE>>
}
}
Sample infrastructure template for an ECS cluster (click to expand)
Please note that some properties are intentionally omitted for brevity.
Resources:
Cluster:
Type: AWS::ECS::Cluster
TaskDefinition:
Type: AWS::ECS::TaskDefinition
Properties:
Family: test
ContainerDefinitions:
- Name: test
Image: amazon/amazon-ecs-sample
Essential: true
Cpu: 256
Memory: 512
Service:
Type: AWS::ECS::Service
Properties:
Cluster:
Ref: Cluster
DeploymentController:
Type: EXTERNAL
DesiredCount: 0
NetworkConfiguration:
AwsVpcConfiguration:
AssignPublicIp: DISABLED
TaskSet1:
Type: AWS::ECS::TaskSet
Properties:
Service:
Ref: Service
Cluster:
Ref: Cluster
TaskDefinition:
Ref: TaskDefinition
Scale:
Unit: PERCENT
Value: 100
LaunchType: EC2
ExternalId: task-set-001
NetworkConfiguration:
AwsVpcConfiguration:
AssignPublicIp: DISABLED
Directory bundle support for running tests and validations for templates
Users can now evaluate all rules at once for both testing and validating. Users can run all tests for all rules by pointing to the top-level directory. Testing follows a simple naming convention to run the appropriate tests against the rules.
Testing Setup
- Let's begin with a sample directory, by name
guard-test-root
. Create a Guard rule and name itrule_01.guard
. - Create a sub-directory within
guard-test-root
calledtests
directory (name has to be verbatimtests
for this to work). Createrule_01_*.yaml
for success and failures. This names will very as per different rule names.
Directory structure
guard-test-root/
├── rule_01.guard
└── tests/
├── rule_01_cfn_fail.yaml
├── rule_01_cfn_success.yaml
├── rule_01_config_fail.yaml
└── rule_01_config_success.yaml
Command
Run the following command in the parent directory ofguard-test-root
.
cfn-guard test -d guard-test-root
Validate Setup
For validate, we have overloaded all 3 arguments to support directory as input --data
, --rules
as well as --input-parameters
. Let us demonstrate an example with using a directory to pass rules, but know that it works the same way with others.
- Starting with a root directory called
guard-validate-root
. Create a sub-directory calledrules
. - Add different Guard rule files in here.
rule_01.guard
,rule_02.guard
,rule_03.guard
. Please note we should use one of the supported extensions here. As of now,.guard
and.ruleset
are good for rules. - Go back to
guard-validate-root
. Create an infrastructure as code template to be validated astemplate.yaml
.
Directory structure
guard-validate-root/
├── template.yaml
└── rules/
├── rule_01.guard
├── rule_02.guard
└── rule_03.guard
Command
Navigate to guard-validate-root
and run the following command.
cfn-guard validate -r rules/ -d template.yaml
The validate
command will pick all rule file names with the following extensions and execute the checks:
*.guard
*.ruleset
More scenarios for validate
In a similar scenario, where we have multiple template data files in a directory named data
to be validated against all files in a rules
directory, we can run the following command.
cfn-guard validate -r rules/ -d data/
Where directory structure looks like the following:
guard-validate-root/
├── data/
| ├── template_01.yaml
| ├── template_02.yaml
| └── template_03.yaml
└── rules/
├── rule_01.guard
├── rule_02.guard
└── rule_03.guard
For a data directory passed as input, the validate
command will pick all rule file names with the following extensions and execute the checks:
*.yaml
*.yml
*.json
*.jsn
*.template
Thus, we have extended support for validating...
- a single data template against a single guard rule
- a single data template against multiple guard rules
- multiple data templates against a single guard rule
- multiple data templates against multiple guard rules
Apart from support for directory we also support multiple usages of the arguments with values of mixed nature (directory/file). For example, the following command is a valid command.
cfn-g...
Release v2.1.0-pre-rc1
AWS CloudFormation Guard 2.1.0 is a major release that includes new features, resolves bugs, and addresses feedback from the open source community.
New Features
- Parameterized Rules
- Directory bundle support for running tests and validations for templates
- Dynamic data lookup for inspection via multiple data files
- Support Code view and pinpoint location of errors
- Backwards compatible with
cfn-guard
2.x.x
Bug Fixes
- Fixed short-circuit on error condition with multiple resources of the same type. All errors are now displayed
- Filter by type attribute and logical name match
Issues Addressed
- #178 - [Enhancement] Add file name convention based test file selection for the test command
- #186 - Filter based on Resource Logical ID
- #202 - [BUG] Error message includes details of unrelated resource
- #203 -
cfn-guard validate —print-json
does not work - #204 - [Enhancement] Add CDKTemplate type to validation command
- #217 - [BUG]
IN
Statement prints out extraneous error info - #219 - [Enhancement] Add line number of analyzed file into the json report
Other Changes
- Create pull_request_template.md by @priyap286 in #181
- Retrieve version number dynamically from environment variable in code by @priyap286 in #179
- Small correction in cfn-guard lambda README.md by @priyap286 in #185
- Fix typos in QUERY_AND_FILTERING.md by @priyap286 in #188
- Created an issue template for a general issue by @priyap286 in #187
- feat: Parameterized rules by @dchakrav-github in #220
- feat: Parameterized rules by @dchakrav-github in #222
Full Changelog: 2.0.3...v2.1.0-pre-rc1
Details
Parameterized Rules
A user can leverage parameterized rules to write re-usable checks. User can use these checks to write Guard rules that works across several types of payloads such as AWS CloudFormation Templates, Terraform plans that use AWS CC, and AWS Config for asserting conditions.
Example of re-usable checks:
Sample parameterized guard rule to check network config (click to expand)
#
# Top level doc type checks
#
let cfn_resources = Resources.*
let aws_config = configuration.*
rule is_cfn_doc_type when %cfn_resources !empty {
Resources exists
}
rule is_aws_config_doc_type when %aws_config !empty {
configuration exists
}
#
# ECS Service
#
rule deny_ecs_services_invalid_configuration when is_cfn_doc_type {
check_ecs_services_cfgs(Resources[ Type == 'AWS::ECS::Service' ].Properties)
}
rule deny_ecs_services_invalid_configuration when is_aws_config_doc_type
resourceType == 'AWS::ECS::Service'
{
check_ecs_services_cfgs(configuration)
}
#
# Example of network configuration checks across ECS TaskSets and ECS Service using a common rule:
#
# ECS TaskSet
#
rule deny_ecs_task_set_invalid_configuration when is_cfn_doc_type {
#
# For TaskSet, the property is NetworkConfiguration.Aws[V]pcConfiguration
#
check_ecs_network_config(
Resources[ Type == 'AWS::ECS::TaskSet' ]
.Properties
.NetworkConfiguration
.AwsVpcConfiguration)
}
#
# ECS Service check, common across AWS Config and CloudFormation
#
rule check_ecs_services_cfgs(ecs_service_cfgs) {
%ecs_service_cfgs {
EnableExecuteCommand not exists or
EnableExecuteCommand == false
<<Disallowed command executions for ECS services>>
#
# For ECS Service, the property is NetworkConfiguration.Aws[V]pcConfiguration
#
check_ecs_network_config(NetworkConfiguration.AwsVpcConfiguration)
}
}
#
# Check ECS network configuration common to TaskSet and Service
#
rule check_ecs_network_config(network_cfgs) {
%network_cfgs {
AssignPublicIp == 'DISABLED' or
AssignPublicIp == 'disabled'
<<Prevent assignment of public IP address to ECS services. AssignPublicIp must be DISABLE>>
}
}
Sample infrastructure template for an ECS cluster (click to expand)
Please note that some properties are intentionally omitted for brevity.
Resources:
Cluster:
Type: AWS::ECS::Cluster
TaskDefinition:
Type: AWS::ECS::TaskDefinition
Properties:
Family: test
ContainerDefinitions:
- Name: test
Image: amazon/amazon-ecs-sample
Essential: true
Cpu: 256
Memory: 512
Service:
Type: AWS::ECS::Service
Properties:
Cluster:
Ref: Cluster
DeploymentController:
Type: EXTERNAL
DesiredCount: 0
NetworkConfiguration:
AwsVpcConfiguration:
AssignPublicIp: DISABLED
TaskSet1:
Type: AWS::ECS::TaskSet
Properties:
Service:
Ref: Service
Cluster:
Ref: Cluster
TaskDefinition:
Ref: TaskDefinition
Scale:
Unit: PERCENT
Value: 100
LaunchType: EC2
ExternalId: task-set-001
NetworkConfiguration:
AwsVpcConfiguration:
AssignPublicIp: DISABLED
Directory bundle support for running tests and validations for templates
Users can now evaluate all rules at once for both testing and validating. Users can run all tests for all rules by pointing to the top-level directory. Testing follows a simple naming convention to run the appropriate tests against the rules.
Testing Setup
- Let's begin with a sample directory, by name
guard-test-root
. Create a Guard rule and name itrule_01.guard
. - Create a sub-directory within
guard-test-root
calledtests
directory (name has to be verbatimtests
for this to work). Createrule_01_*.yaml
for success and failures. This names will very as per different rule names.
Directory structure
guard-test-root/
├── rule_01.guard
└── tests/
├── rule_01_cfn_fail.yaml
├── rule_01_cfn_success.yaml
├── rule_01_config_fail.yaml
└── rule_01_config_success.yaml
Command
Run the following command in the parent directory ofguard-test-root
.
cfn-guard test -d guard-test-root
Validate Setup
For validate, we have overloaded all 3 arguments to support directory as input --data
, --rules
as well as --input-parameters
. Let us demonstrate an example with using a directory to pass rules, but know that it works the same way with others.
- Starting with a root directory called
guard-validate-root
. Create a sub-directory calledrules
. - Add different Guard rule files in here.
rule_01.guard
,rule_02.guard
,rule_03.guard
. Please note we should use one of the supported extensions here. As of now,.guard
and.ruleset
are good for rules. - Go back to
guard-validate-root
. Create an infrastructure as code template to be validated astemplate.yaml
.
Directory structure
guard-validate-root/
├── template.yaml
└── rules/
├── rule_01.guard
├── rule_02.guard
└── rule_03.guard
Command
Navigate to guard-validate-root
and run the following command.
cfn-guard validate -r rules/ -d template.yaml
The validate
command will pick all rule file names with the following extensions and execute the checks:
*.guard
*.ruleset
More scenarios for validate
In a similar scenario, where we have multiple template data files in a directory named data
to be validated against all files in a rules
directory, we can run the following command.
cfn-guard validate -r rules/ -d data/
Where directory structure looks like the following:
guard-validate-root/
├── data/
| ├── template_01.yaml
| ├── template_02.yaml
| └── template_03.yaml
└── rules/
├── rule_01.guard
├── rule_02.guard
└── rule_03.guard
For a data directory passed as input, the validate
command will pick all rule file names with the following extensions and execute the checks:
*.yaml
*.yml
*.json
*.jsn
*.template
Thus, we have extended support for validating...
- a single data template against a single guard rule
- a single data template against multiple guard rules
- multiple data templates against a single guard rule
- multiple data templates against multiple guard rules
Apart from support for directory we also support multiple usages of the arguments with values of mixed nature (directory/file). For example, the following command is a valid command.
cfn-guard validate -r rules/ -r foo/rule_99.guard -d data/ -d bar/template_99.yaml
Dynamic data lookup for inspection via multiple data files
Users can now specify multiple data files for dynamic look ups using --input-parameters
argument, along with the independent context of a data file passed as --data
for actual validation inspection (e.g., the template tha...
Release v2.0.4
Description of improvements released in version v2.0.4:
#201
You can now use a payload
flag that will allow to pass a JSON with data and rules as strings to validate
command.
{"data": [<data1 as string>, <data2 as string>,....], "rules" : [ <rule1 as string>, <rule2 as string>,....]}
eg.
{"data": ["{\"Resources\":{\"NewVolume\":{\"Type\":\"AWS::EC2::Volume\",\"Properties\":{\"Size\":500,\"Encrypted\":false,\"AvailabilityZone\":\"us-west-2b\"}},\"NewVolume2\":{\"Type\":\"AWS::EC2::Volume\",\"Properties\":{\"Size\":50,\"Encrypted\":false,\"AvailabilityZone\":\"us-west-2c\"}}},\"Parameters\":{\"InstanceName\":\"TestInstance\"}}","{\"Resources\":{\"NewVolume\":{\"Type\":\"AWS::EC2::Volume\",\"Properties\":{\"Size\":500,\"Encrypted\":false,\"AvailabilityZone\":\"us-west-2b\"}},\"NewVolume2\":{\"Type\":\"AWS::EC2::Volume\",\"Properties\":{\"Size\":50,\"Encrypted\":false,\"AvailabilityZone\":\"us-west-2c\"}}},\"Parameters\":{\"InstanceName\":\"TestInstance\"}}"], "rules" : [ "Parameters.InstanceName == \"TestInstance\"","Parameters.InstanceName == \"TestInstance\"" ]}
Sample run:
$ cfn-guard validate --payload
{"data": ["{\"Resources\":{\"NewVolume\":{\"Type\":\"AWS::EC2::Volume\",\"Properties\":{\"Size\":500,\"Encrypted\":false,\"AvailabilityZone\":\"us-west-2b\"}},\"NewVolume2\":{\"Type\":\"AWS::EC2::Volume\",\"Properties\":{\"Size\":50,\"Encrypted\":false,\"AvailabilityZone\":\"us-west-2c\"}}},\"Parameters\":{\"InstanceName\":\"TestInstance\"}}","{\"Resources\":{\"NewVolume\":{\"Type\":\"AWS::EC2::Volume\",\"Properties\":{\"Size\":500,\"Encrypted\":false,\"AvailabilityZone\":\"us-west-2b\"}},\"NewVolume2\":{\"Type\":\"AWS::EC2::Volume\",\"Properties\":{\"Size\":50,\"Encrypted\":false,\"AvailabilityZone\":\"us-west-2c\"}}},\"Parameters\":{\"InstanceName\":\"TestInstance\"}}"], "rules" : [ "Parameters.InstanceName == \"TestInstance\"","Parameters.InstanceName == \"TestInstance\"" ]}
DATA_STDIN[1] Status = PASS
PASS rules
RULES_STDIN[1]/default PASS
---
Evaluation of rules RULES_STDIN[1] against data DATA_STDIN[1]
--
Rule [RULES_STDIN[1]/default] is compliant for template [DATA_STDIN[1]]
--
DATA_STDIN[2] Status = PASS
PASS rules
RULES_STDIN[1]/default PASS
---
Evaluation of rules RULES_STDIN[1] against data DATA_STDIN[2]
--
Rule [RULES_STDIN[1]/default] is compliant for template [DATA_STDIN[2]]
--
DATA_STDIN[1] Status = PASS
PASS rules
RULES_STDIN[2]/default PASS
---
Evaluation of rules RULES_STDIN[2] against data DATA_STDIN[1]
--
Rule [RULES_STDIN[2]/default] is compliant for template [DATA_STDIN[1]]
--
DATA_STDIN[2] Status = PASS
PASS rules
RULES_STDIN[2]/default PASS
---
Evaluation of rules RULES_STDIN[2] against data DATA_STDIN[2]
--
Rule [RULES_STDIN[2]/default] is compliant for template [DATA_STDIN[2]]
#179
Retrieve version number dynamically from environment variable in code
Release v2.0.3
Description of improvements released in version 2.0.3.
#158
You can now provide test names to each unit test in your test file. The test names will be displayed in the test execution report together with the unit test execution status. This enhances the readability of test file execution reports.
#159
Guard will now continue evaluation of a clause for all values produced by its query even after encountering a failed evaluation. You will be able to see details of failed values by using the --show-clause-failures
flag with the validate
command.
- The
validate
command now supports JSON, YAML and single-line output formats; you can now use thejson
,yaml
andsingle-line-summary
values, respectively, for the-o
or--output-format
options of thevalidate
command. Example:
cfn-guard validate -r rules/ -d data/ --show-summary none --type CFNTemplate —output-format yaml
Output:
---
data_from: sample-template.yaml
rules_from: cluster.guard
not_compliant: {}
not_applicable:
- test
compliant: []
---
data_from: sample-template.yaml
rules_from: migrated-3.guard
not_compliant:
vol2:
- rule: aws_ec2_volume_checks
path: Properties.Encrypted
provided: false
expected: true
comparison:
operator: Eq
not_operator_exists: false
message: ""
not_applicable:
- aws_apigateway_deployment_checks
- aws_apigateway_stage_checks
- aws_dynamodb_table_checks
compliant:
- aws_events_rule_checks
- aws_iam_role_checks
- You can now use the
-t
or--type
option for thevalidate
command to specify the type of the data file against which you are evaluating your rules.CFNTemplate
is the only value supported today. When you now specify, for example,--type CFNTemplate
as an option to thevalidate
command, Guard will output logical name of resources and relevant properties (e.g.,Resource [vol2] property [Properties.Encrypted] in template [sample-template.yaml]
), as opposed to property paths and values (e.g.,Property [/Resources/vol2/Properties/Encrypted] in data [sample-template.yaml]
). Example:
cfn-guard validate -r /tmp/rules/ -d /tmp/data/ --show-summary none —type CFNTemplate
Output:
Evaluation of rules cluster.guard for template sample-template.yaml, number of resource failures = 0
--
Rule [cluster.guard/test] is not applicable for template [sample-template.yaml]
--
Evaluation of rules migrated-3.guard for template sample-template.yaml, number of resource failures = 1
--
Resource [vol2] property [Properties.Encrypted] in template [sample-template.yaml] is not compliant with [migrated-3.guard/aws_ec2_volume_checks] because provided value [false] did not match with expected value [true]. Error message []
Resource [vol2] traversed until [Properties] for template [sample-template.yaml] wasn't compliant with [migrated-3.guard/aws_ec2_volume_checks] due to retrieval error. Error Message [Attempting to retrieve array index or key from map at path = /Resources/vol2/Properties , Type was not an array/object map, Remaining Query = Size]
Resource [vol2] property [Properties.Encrypted] in template [sample-template.yaml] is not compliant with [migrated-3.guard/mixed_types_checks] because provided value [false] did not match with expected value [true]. Error message []
--
Rule [migrated-3.guard/aws_iam_role_checks] is compliant for template [sample-template.yaml]
Rule [migrated-3.guard/aws_events_rule_checks] is compliant for template [sample-template.yaml]
--
Rule [migrated-3.guard/aws_apigateway_deployment_checks] is not applicable for template [sample-template.yaml]
Rule [migrated-3.guard/aws_apigateway_stage_checks] is not applicable for template [sample-template.yaml]
Rule [migrated-3.guard/aws_dynamodb_table_checks] is not applicable for template
- The command now supports suppressing summary information. You can choose whether or not you want to display the summary table when you run the
validate
command; by default, summary is displayed (--show-summary all
); alternatively, you can specify--show-summary pass,fail
to only summarize rules that did pass/fail), and with--show-summary none
you turn off the visualization of the summary.
Release v2.0.2
Release v2.0.1
Documentation update over v2.0.0.