What's Changed
- Populated filename in the output by @akshayrane in #358
- Support for some function expressions / stateful rules by @joshfried-aws in #361
- Combined structured output and updated default rule clause name to include file name by @akshayrane in #360
- Clap Autocompletions by @joshfried-aws in #340
- Adding documentation for functions by @joshfried-aws in #362
- Deprecated migrate and previous engine by @akshayrane in #364
- Removing unnecessary print statement for failure in parse-tree command by @joshfried-aws in #368
- Improve error message for templates that cause an error by @joshfried-aws in #370
- Clippy lints + ci by @joshfried-aws in #371
- [Bugfix]: Fixed bug where cfn template fails validate rule check and when failing node isnt a child of resources by @joshfried-aws in #372
- Updating reporters to all use serde for both json and yaml + misc improvements by @joshfried-aws in #373
- [Bugfix] Fixing improper console output when using single line summary by @joshfried-aws in #378
- [Enhancement] Creating a new error code for rule failures by @joshfried-aws in #379
- Refined documentation for functions, join path bugfix & version bump by @akshayrane in #381
- Changes to CI actions by @akshayrane & @joshfried-aws in #366 & #383
- Updates to
README.md
for3.0.0
- Added latest configuration for aws-guard-rules-registry integration tests
- Added new deployment method for
cfn-guard-lambda
through AWS SAM-CLI - Deprecated
-j
as short flag forprint-json
- Updated names for artifacts to have
v3
in them - Added
rogue_one
branch to docker workflow, this will publish an ECR image for all updates to this remote branch as well
- Updates to
- 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
- Improved documentation for new Guard version and keeping version up to date for GitHub runner OS by @razcloud in #365
- +[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
Breaking changes in 3.0.0
- Error codes - We emit a different exit code (19) now for validation failure if the data template(s) passed are non-compliant against the rules. This will make it easy to distinguish between the two. Previously, we emitted the same code as for parse errors (5). (PR #379)
- Intrinsic function resolution with test command. We now handle the intrinsic functions like
Fn::ImportValue
,Fn::Sub
, etc in unit tests in an improved way. Read more about this change here. - Standardized the output format for generic JSON/YAML templates to be inline with CFN-specific one. (PR #373)
Table of Contents
- Built-in Functions and Stateful Rules
- Added alternative deployment method using SAM-CLI for
cfn-guard-lambda
- Updated the output to contain filename
- Updated combined structured output & default anonymous rule name
- Command auto-completions
- 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
Details
1. Built-in Functions and Stateful Rules
As of version 3.0.0 guard now supplies some builtin functions, allowing for stateful rules.
Built-in functions are supported only through assignment to a variable at the moment, and not inline.
NOTE: all examples are operating off the following YAML template
Data
(click to expand)
Resources:
newServer:
Type: AWS::New::Service
Properties:
Policy: |
{
"Principal": "*",
"Actions": ["s3*", "ec2*"]
}
Arn: arn:aws:newservice:us-west-2:123456789012:Table/extracted
Encoded: This%20string%20will%20be%20URL%20encoded
Collection:
- a
- b
- c
BucketPolicy:
PolicyText: '{"Version":"2012-10-17","Statement":[{"Sid":"DenyReducedReliabilityStorage","Effect":"Deny","Principal":"*","Action":"s3:*","Resource":"arn:aws:s3:::s3-test-123/*","Condition":{"StringEquals":{"s3:x-amz-storage-class-123":["ONEZONE_IA","REDUCED_REDUNDANCY"]}}}]}'
s3:
Type: AWS::S3::Bucket
Properties:
PublicAccessBlockConfiguration:
BlockPublicAcls: true
BlockPublicPolicy: true
IgnorePublicAcls: true
RestrictPublicBuckets: true
bucket:
Type: AWS::S3::Bucket
Properties:
PublicAccessBlockConfiguration:
BlockPublicAcls: false
BlockPublicPolicy: true
IgnorePublicAcls: true
RestrictPublicBuckets: true
String Manipulation Functions
The following functions all operate on queries that resolve to string values
1. json_parse()
The json_parse
function adds support for parsing inline JSON strings from a given template. After parsing the string into an object,
you can now evaluate certain properties of this struct just like with a normal JSON/YAML object
Rule
(click to expand)
let template = Resources.*[ Type == 'AWS::New::Service']
let expected = {
"Principal": "*",
"Actions": ["s3*", "ec2*"]
}
rule TEST_JSON_PARSE when %template !empty {
let policy = %template.Properties.Policy
let res = json_parse(%policy)
%res !empty
%res == %expected
<<
Violation: the IAM policy does not match with the recommended policy
>>
}
2. regex_replace()
The regex_replace
function adds support for replacing one regular expression with another
In this simple example, we will re-format an ARN by moving around some sections in it.
We will start with a normal ARN that has the following pattern: arn:<Partition>:<Service>:<Region>:<AccountID>:<ResourceType>/<ResourceID>
and we will try to convert it to: <Partition>/<AccountID>/<Region>/<Service>-<ResourceType>/<ResourceID>
Rule
(click to expand)
let template = Resources.*[ Type == 'AWS::New::Service']
rule TEST_REGEX_REPLACE when %template !empty {
%template.Properties.Arn exists
let arn = %template.Properties.Arn
let arn_partition_regex = "^arn:(\w+):(\w+):([\w0-9-]+):(\d+):(.+)$"
let capture_group_reordering = "${1}/${4}/${3}/${2}-${5}"
let res = regex_replace(%arn, %arn_partition_regex, %capture_group_reordering)
%res == "aws/123456789012/us-west-2/newservice-Table/extracted"
<< Violation: Resulting reformatted ARN does not match the expected format >>
}
3. join()
The join
function adds support to collect a query, and then join their values using the provided delimiter.
Rule
(click to expand)
let template = Resources.*[ Type == 'AWS::New::Service']
rule TEST_COLLECTION when %template !empty {
let collection = %template.Collection.*
let res = join(%collection, ",")
%res == "a,b,c"
<< Violation: The joined value does not match the expected result >>
}
4. to_lower()
This function can be used to change the casing of the all characters in the string passed to all lowercase.
Rule
(click to expand)
let type = Resources.newServer.Type
rule STRING_MANIPULATION when %type !empty {
let lower = to_lower(%type)
%lower == /aws::new::service/
<< Violation: expected a value to be all lowercase >>
}
4. to_upper()
This function can be used to change the casing of the all characters in the string passed to all uppercase.
Rule
(click to expand)
let type = Resources.newServer.Type
rule STRING_MANIPULATION when %type !empty {
let upper = to_upper(%type)
%upper == "AWS::NEW::SERVICE"
<< Violation: expected a value to be all uppercase >>
}
6. substring()
The substring
function allows to extract a part of string(s) resolved from a query
Rule
(click to expand)
let template = Resources.*[ Type == 'AWS::New::Service']
rule TEST_SUBSTRING when %template !empty {
%template.Properties.Arn exists
let arn = %template.Properties.Arn
let res = substring(%arn, 0, 3)
%res == "arn"
<< Violation: Substring extracted does not match with the expected outcome >>
}
7. url_decode()
This function can be used to transform URL encoded strings into their decoded versions
Rule
(click to expand)
let template = Resources.*[ Type == 'AWS::New::Service']
rule SOME_RULE when %template !empty {
%template.Properties.Encoded exists
let encoded = %template.Properties.Encoded
let res = url_decode(%encoded)
%res == "This string will be URL encoded"
<<
Violation: The result of URL decoding does not
match with the expected outcome
>>
}
Collection functions
8. count()
This function can be used to count the number of items that a query resolves to
Rule
(click to expand)
let template = Resources.*[ Type == 'AWS::New::Service' ]
rule SOME_RULE when %template !empty {
let collection = %template.Collection.*
let res2 = count(%collection)
%res2 >= 3
<< Violation: Collection should contain at least 3 items >>
}
2. Added alternative deployment method using SAM-CLI for cfn-guard-lambda
cfn-guard-lambda
can now also be deployed using this new method, through AWS SAM CLI.
Dependencies
- SAM CLI installed
- AWS CLI installed and configured with permissions to deploy via CloudFormation. SAM CLI will internally use the credentials you setup AWS CLI with. You may use the following IAM policy as a reference for least privileged access.
IAM Policy for SAM CLI User
{
"Version": "2012-10-17",
"Statement":
[
{
"Effect": "Allow",
"Action":
[
"cloudformation:CreateChangeSet",
"cloudformation:CreateStack",
"cloudformation:DeleteChangeSet",
"cloudformation:DeleteStack",
"cloudformation:DescribeChangeSet",
"cloudformation:DescribeStackEvents",
"cloudformation:DescribeStackResource",
"cloudformation:DescribeStackResources",
"cloudformation:DescribeStacks",
"cloudformation:ExecuteChangeSet",
"cloudformation:GetTemplate",
"cloudformation:GetTemplateSummary",
"cloudformation:ListStackResources",
"cloudformation:SetStackPolicy",
"cloudformation:UpdateStack",
"cloudformation:UpdateTerminationProtection",
"iam:AttachRolePolicy",
"iam:CreateRole",
"iam:DeleteRole",
"iam:DetachRolePolicy",
"iam:GetRole",
"iam:PassRole",
"lambda:CreateFunction",
"lambda:DeleteFunction",
"lambda:GetFunction",
"lambda:TagResource",
"s3:GetObject",
"s3:PutObject"
],
"Resource": "*"
}
]
}
- Docker installed
Building and deploying
- Make sure docker is running
- Navigate to
guard-lambda
directory and runsam build --use-container
to build the code for the Lambda function - Run
sam deploy --guided
and complete the interactive workflow. This workflow will create a CloudFormation changeset and deploy it - Once it succeeds, the name of the function will be shown in the
CloudFormationGuardLambdaFunctionName
output - For subsequent updates, build the code again (step 2) and run
sam deploy
(without--guided
)
3. Updated the output to contain filename
Output now shows the data template filename field populated under the field name
.
Example:
Rule
(click to expand)
s3_bucket_server_side_encryption_enabled.guard
let s3_buckets_server_side_encryption = Resources.*[ Type == 'AWS::S3::Bucket']
rule S3_BUCKET_SERVER_SIDE_ENCRYPTION_ENABLED when %s3_buckets_server_side_encryption !empty {
%s3_buckets_server_side_encryption.Properties.BucketEncryption exists
%s3_buckets_server_side_encryption.Properties.BucketEncryption.ServerSideEncryptionConfiguration[*].ServerSideEncryptionByDefault.SSEAlgorithm in ["aws:kms","AES256"]
<<
Violation: S3 Bucket must enable server-side encryption.
Fix: Set the S3 Bucket property BucketEncryption.ServerSideEncryptionConfiguration.ServerSideEncryptionByDefault.SSEAlgorithm to either "aws:kms" or "AES256"
>>
}
Data
(click to expand)
s3-server-side-encryption-template.yaml
Resources:
MyBucket1:
Type: AWS::S3::Bucket
Properties:
BucketEncryption:
ServerSideEncryptionConfiguration:
- ServerSideEncryptionByDefault:
SSEAlgorithm: aws:kms
Command:
cfn-guard validate \
-d s3-server-side-encryption-template.yaml \
-r s3_bucket_server_side_encryption_enabled.guard \
--show-summary none -o json
Output
{
"name": "s3-server-side-encryption-template.yaml",
"metadata": {},
"status": "PASS",
"not_compliant": [],
"not_applicable": [],
"compliant": [
"S3_BUCKET_SERVER_SIDE_ENCRYPTION_ENABLED"
]
}
4. Updated combined structured output & default anonymous rule name
The output using the --structured
flag with R
rule files against D
data files now gives a merged array of size D
, all the related rules show up as R
children of a single parent object per data template passed as the input. (see example 1 below). An anonymous rule will be fully-qualified and will contain the filename as well. (see example 2 below)
Example 1
Command
cfn-guard validate --structured --show-summary none --output-format json --payload
Payload input
(click to expand)
Note the rules only have conditions and no name.
{
"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\""]
}
Press <Ctrl+D> to register input
Output
[
{
"name": "DATA_STDIN[1]",
"metadata": {},
"status": "PASS",
"not_compliant": [],
"not_applicable": [],
"compliant": [
"RULES_STDIN[1]/default",
"RULES_STDIN[2]/default"
]
},
{
"name": "DATA_STDIN[2]",
"metadata": {},
"status": "PASS",
"not_compliant": [],
"not_applicable": [],
"compliant": [
"RULES_STDIN[1]/default",
"RULES_STDIN[2]/default"
]
}
]
Example 2
Command
cfn-guard validate \
--show-summary all \
--rules guard/resources/validate/rules-dir/advanced_regex_negative_lookbehind_rule.guard \
--data guard/resources/validate/data-dir/advanced_regex_negative_lookbehind_non_compliant.yaml
Rule
(click to expand)
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
(click to expand)
advanced_regex_negative_lookbehind_non_compliant.yaml
NotAwsAccessKey: AKIAIOSFODNN7EXAMPLE
NotSecretAccessKey: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
Output
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 []
--
5. Command auto-completions
We now have auto-completions for all our commands in shell.
Setup
To setup auto-completions you will need to follow instructions for the specific shell your are running.
Currently guard only supports auto-completions for zsh, bash, and fish shells. If you would like autocompletions for a specific shell feel free to open up a new github issue.
Auto-completions are only something available for version >= 3.0
zsh
cfn-guard completions --shell='zsh' > /usr/local/share/zsh/site-functions/_cfn-guard && compinit
bash
cfn-guard completions --shell='bash' > ~/cfn-guard.bash && source ~/cfn-guard.bash
fish
cfn-guard completions --shell='fish' > ~/cfn-guard.fish
cd ~
./ ./cfn-guard.fish
NOTE: for both bash and fish shells you are able to output the completions script to any file in any location you would like, just make sure the file you output it to and the file you source are the same.
For bash shells if you dont want to do this everytime you open up a new terminal, once you have the script you can add source ~/cfn-guard.bash to your .bashrc
6. 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 []
7. 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
8. 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"
]
}
]
Full Changelog: 2.1.4...3.0.0