Skip to content

v3.0.0-alpha

Pre-release
Pre-release
Compare
Choose a tag to compare
@akshayrane akshayrane released this 23 Mar 18:26
· 20 commits to rogue_one since this release
38b5c2d

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

New Contributors

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] to compare from 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.BlockPublicAcls",
                        "reason": "Could not find key PublicAccessBlockConfiguration inside struct at path /Resources/MyBucket/Properties[L:13,C:6]"
                      },
                      "comparison": [
                        "Eq",
                        false
                      ]
                    }
                  }
                }
              }
            },
            {
              "Clause": {
                "Binary": {
                  "context": " %s3_bucket_public_read_prohibited[*].Properties.PublicAccessBlockConfiguration.BlockPublicPolicy EQUALS  true",
                  "messages": {
                    "custom_message": "",
                    "error_message": "Check was not compliant as property [PublicAccessBlockConfiguration.BlockPublicPolicy] to compare from 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.BlockPublicPolicy",
                        "reason": "Could not find key PublicAccessBlockConfiguration inside struct at path /Resources/MyBucket/Properties[L:13,C:6]"
                      },
                      "comparison": [
                        "Eq",
                        false
                      ]
                    }
                  }
                }
              }
            },
            {
              "Clause": {
                "Binary": {
                  "context": " %s3_bucket_public_read_prohibited[*].Properties.PublicAccessBlockConfiguration.IgnorePublicAcls EQUALS  true",
                  "messages": {
                    "custom_message": "",
                    "error_message": "Check was not compliant as property [PublicAccessBlockConfiguration.IgnorePublicAcls] to compare from 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.IgnorePublicAcls",
                        "reason": "Could not find key PublicAccessBlockConfiguration inside struct at path /Resources/MyBucket/Properties[L:13,C:6]"
                      },
                      "comparison": [
                        "Eq",
                        false
                      ]
                    }
                  }
                }
              }
            },
            {
              "Clause": {
                "Binary": {
                  "context": " %s3_bucket_public_read_prohibited[*].Properties.PublicAccessBlockConfiguration.RestrictPublicBuckets EQUALS  true",
                  "messages": {
                    "custom_message": ";    Violation: S3 Bucket Public Write Access controls need to be restricted.;    Fix: Set S3 Bucket PublicAccessBlockConfiguration properties for BlockPublicAcls, BlockPublicPolicy, IgnorePublicAcls, RestrictPublicBuckets parameters to true.;  ",
                    "error_message": "Check was not compliant as property [PublicAccessBlockConfiguration.RestrictPublicBuckets] to compare from 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.RestrictPublicBuckets",
                        "reason": "Could not find key PublicAccessBlockConfiguration inside struct at path /Resources/MyBucket/Properties[L:13,C:6]"
                      },
                      "comparison": [
                        "Eq",
                        false
                      ]
                    }
                  }
                }
              }
            }
          ]
        }
      }
    ],
    "not_applicable": [],
    "compliant": []
  },
  {
    "name": "",
    "metadata": {},
    "status": "PASS",
    "not_compliant": [],
    "not_applicable": [],
    "compliant": [
      "S3_BUCKET_PUBLIC_READ_PROHIBITED"
    ]
  }
]