Description
Describe the issue
There are a few Guard Rules examples in this repo that are not handling Resource Policies Condition keys correctly. As a result, the rule enforcement can easily be bypassed by defining condition keys mixing it with upper/lower case.
Any examples
Please supply:
https://github.com/aws-cloudformation/cloudformation-guard/blob/main/guard-examples/cross-account/sns-cross-account.guard
let source_accounts = %expected_conditions[ keys == /(aws|AWS):[sS]ource(Account|Owner|Arn|ARN)/ ]
The above regex will handle a few key combinations. I will list some of them for SourceAccount as an example:
- aws:SourceAccount
- aws:sourceAccount
- AWS:SourceAccount
- AWS:sourceAccount
The problem here is that Condition key name is not case sensitive as documented here: https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_elements_condition.html
With the above rule, if the user specifies in their resource policy the condition key as aws:SOURCEACCOUNT, allowing an account not specified in the allowed_accounts variable, the rule result will be SKIP instead of FAIL.
The Regex could be rewritten from:
let source_accounts = %expected_conditions[ keys == /(aws|AWS):[sS]ource(Account|Owner|Arn|ARN)/ ]
to the following which addresses the case sensitive problem:
let source_accounts = %expected_conditions[ keys == /(?i)aws:Source(Account|Owner|Arn)/ ]
It could be further enhanced to prevent invalid prefix/suffix in the condition key as follows:
let source_accounts = %expected_conditions[ keys == /^(?i)aws:Source(Account|Owner|Arn)$/ ]
Operating System:
Amazon Linux 2
OS Version
Amazon Linux 2
Guard Version 2.1.3