aws-cloudformation / aws-cloudformation/cloudformation-guard
[BUG]
- Dominant language
- Rust
- Stars
- 1.4k
- Forks
- 196
- Avg merge
- 3d 6h
- Merged PRs (30d)
- 5
Description
Describe the bug
A clear and concise description of what the bug is.
The rule I wrote checking for S3 permissions on wildcard Resource is running and failing on IAM roles without any S3 permissions.
To Reproduce
Please supply:
Example rules and template that results in the error
Template:
```
rImmutaRdsLambdaRole:
Type: "AWS::IAM::Role"
Properties:
RoleName: immunment
PermissionsBoundary: !Sub "arn:aws:iam::${AWS::AccountId}:policy/L-Boundary"
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: "Allow"
Principal:
Service: "rds.amazonaws.com"
Action: "sts:AssumeRole"
Policies:
- PolicyName: "RdsInvokeLambdaPolicy"
PolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: "Allow"
Action: "lambda:InvokeFunction"
Resource: !GetAtt rIImmuta.Arn
```
CloudFormation Guard Rule:
### _**I KNOW THIS SEEMS TOTALLY UNRELATED TO THE CODE ABOVE BUT THIS IS THE CHECK THAT KEEPS FAILING**_
```
# R5.0 Automatically inspect the code for * in S3 folder (prefix) access and present a warning statement to the developer if found
let aws_iam_policies_no_full_access_for_s3 = Resources.*[
Type in [/AWS::IAM::Policy/, /AWS::IAM::ManagedPolicy/]
Metadata.guard.SuppressedRules not exists or
Metadata.guard.SuppressedRules.* != "IAM_POLICY_NO_FULL_ACCESS_FOR_S3"
]
let aws_iam_roles_no_full_access_for_s3 = Resources.*[
Type in [/AWS::IAM::Role/]
Metadata.guard.SuppressedRules not exists or
Metadata.guard.SuppressedRules.* != "IAM_ROLE_NO_FULL_ACCESS_FOR_S3"
]
# Checks there is no wildcard in the bucket name in an IAM Role
rule IAM_ROLE_FULL_BUCKET_NAME_USED when %aws_iam_roles_no_full_access_for_s3 !empty {
let violationsString = Resources.*[
Type in [/AWS::IAM::Role/]
some Properties.Policies[*].PolicyDocument.Statement[*] {
some Resource[*] in [/^arn:aws:s3:::(.*?)(.*?)(\*)(.*?)\/$/]
}
]
let violationsSub = Resources.*[
Type in [/AWS::IAM::Role/]
some Properties.Policies[*].PolicyDocument.Statement[*] {
some Resource[*][keys == "Fn::Sub"] in [/^arn:aws:s3:::(.*?)(.*?)(\*)(.*?)\/$/]
}
]
%violationsString empty
<<
Violation: * in S3 folder (prefix) access.
Fix: Avoid wildcard matching * in S3 folder (prefix) access
>>
%violationsSub empty
<<
Violation: * in S3 folder (prefix) access.
Fix: Avoid wildcard matching * in S3 folder (prefix) access
>>
}
# Checks the full folder path is used with no wildcards before the second "/" in an IAM Role
rule IAM_ROLE_FULL_FOLDER_PATH_USED when %aws_iam_roles_no_full_access_for_s3 !empty {
let violationsString = Resources.*[
Type in [/AWS::IAM::Role/]
some Properties.Policies[*].PolicyDocument.Statement[*] {
some Resource[*] in [/^arn:aws:s3:::llp(.*?)(\*)(.*?)\/(.*?)\/(.*?)/, /^arn:aws:s3:::llp(.*?)\/(.*?)(\*)(.*?)\/(.*)/]
}
]
let violationsSub = Resources.*[
Type in [/AWS::IAM::Role/]
some Properties.Policies[*].PolicyDocument.Statement[*] {
some Resource[*][keys == "Fn::Sub"] in [/^arn:aws:s3:::llp(.*?)(\*)(.*?)\/(.*?)\/(.*?)/, /^arn:aws:s3:::llp(.*?)\/(.*?)(\*)(.*?)\/(.*)/]
}
]
%violationsString empty
<<
Violation: * in S3 folder (prefix) access.
Fix: Avoid wildcard matching * in S3 folder (prefix) access
>>
%violationsSub empty
<<
Violation: * in S3 folder (prefix) access.
Fix: Avoid wildcard matching * in S3 folder (prefix) access
>>
}
# Checks there is no wildcard in the bucket name in an IAM Policy
rule IAM_POLICY_FULL_BUCKET_NAME_USED when %aws_iam_policies_no_full_access_for_s3 !empty {
let violationsString = Resources.*[
Type in [/AWS::IAM::Policy/, /AWS::IAM::ManagedPolicy/]
some Properties.PolicyDocument.Statement[*] {
some Resource[*] in [/^arn:aws:s3:::(.*?)(.*?)(\*)(.*?)\/$/]
}
]
let violationsSub = Resources.*[
Type in [/AWS::IAM::Policy/, /AWS::IAM::ManagedPolicy/]
some Properties.PolicyDocument.Statement[*] {
some Resource[*][keys == "Fn::Sub"] in [/^arn:aws:s3:::(.*?)(.*?)(\*)(.*?)\/$/]
}
]
%violationsString empty
<<
Violation: * in S3 folder (prefix) access.
Fix: Avoid wildcard matching * in S3 folder (prefix) access
>>
%violationsSub empty
<<
Violation: * in S3 folder (prefix) access.
Fix: Avoid wildcard matching * in S3 folder (prefix) access
>>
}
# Checks the full folder path is used with no wildcards before the second "/" in an IAM Policy
rule IAM_POLICY_FULL_FOLDER_PATH_USED when %aws_iam_policies_no_full_access_for_s3 !empty {
let violationsString = Resources.*[
Type in [/AWS::IAM::Policy/, /AWS::IAM::ManagedPolicy/]
some Properties.PolicyDocument.Statement[*] {
some Resource[*] in [/^arn:aws:s3:::llp(.*?)(\*)(.*?)\/(.*?)\/(.*?)/, /^arn:aws:s3:::llp(.*?)\/(.*?)(\*)(.*?)\/(.*)/]
}
]
let violationsSub = Resources.*[
Type in [/AWS::IAM::Policy/, /AWS::IAM::ManagedPolicy/]
some Properties.PolicyDocument.Statement[*] {
some Resource[*][keys == "Fn::Sub"] in [/^arn:aws:s3:::llp(.*?)(\*)(.*?)\/(.*?)\/(.*?)/, /^arn:aws:s3:::llp(.*?)\/(.*?)(\*)(.*?)\/(.*)/]
}
]
%violationsString empty
<<
Violation: * in S3 folder (prefix) access.
Fix: Avoid wildcard matching * in S3 folder (prefix) access
>>
%violationsSub empty
<<
Violation: * in S3 folder (prefix) access.
Fix: Avoid wildcard matching * in S3 folder (prefix) access
>>
}
let s3_no_full_permission = Resources.*[ Type == 'AWS::S3::BucketPolicy'
Metadata.guard.SuppressedRules not exists or
Metadata.guard.SuppressedRules.* != "S3_NO_FULL_PERMISSION"
]
# Checks there is no wildcard in the bucket name in an IAM Policy
rule BUCKET_POLICY_FULL_BUCKET_NAME_USED when %s3_no_full_permission !empty {
let violationsString = Resources.*[
Type == 'AWS::S3::BucketPolicy'
some Properties.PolicyDocument.Statement[*] {
some Resource[*] in [/^arn:aws:s3:::(.*?)(.*?)(\*)(.*?)\/$/]
}
]
let violationsSub = Resources.*[
Type == 'AWS::S3::BucketPolicy'
some Properties.PolicyDocument.Statement[*] {
some Resource[*][keys == "Fn::Sub"] in [/^arn:aws:s3:::(.*?)(.*?)(\*)(.*?)\/$/]
}
]
%violationsString empty
<<
Violation: * in S3 folder (prefix) access.
Fix: Avoid wildcard matching * in S3 folder (prefix) access
>>
%violationsSub empty
<<
Violation: * in S3 folder (prefix) access.
Fix: Avoid wildcard matching * in S3 folder (prefix) access
>>
}
# Checks the full folder path is used with no wildcards before the second "/" in an IAM Policy
rule BUCKET_POLICY_FULL_FOLDER_PATH_USED when %s3_no_full_permission !empty {
let violationsString = Resources.*[
Type == 'AWS::S3::BucketPolicy'
some Properties.PolicyDocument.Statement[*] {
some Resource[*] in [/^arn:aws:s3:::llp(.*?)(\*)(.*?)\/(.*?)\/(.*?)/, /^arn:aws:s3:::llp(.*?)\/(.*?)(\*)(.*?)\/(.*)/]
}
]
let violationsSub = Resources.*[
Type == 'AWS::S3::BucketPolicy'
some Properties.PolicyDocument.Statement[*] {
some Resource[*][keys == "Fn::Sub"] in [/^arn:aws:s3:::llp(.*?)(\*)(.*?)\/(.*?)\/(.*?)/, /^arn:aws:s3:::llp(.*?)\/(.*?)(\*)(.*?)\/(.*)/]
}
]
%violationsString empty
<<
Violation: * in S3 folder (prefix) access.
Fix: Avoid wildcard matching * in S3 folder (prefix) access
>>
%violationsSub empty
<<
Violation: * in S3 folder (prefix) access.
Fix: Avoid wildcard matching * in S3 folder (prefix) access
>>
}
The commands you used to invoke the tool
OUTPUT=RUST_BACKTRACE=1 ./cfn-guard-v3-ubuntu-latest/cfn-guard validate --show-summary pass,fail --data "$TEMPLATE_FILE" --rules .github/folderlib/cfn-guard/rules/ 2>&1
The output of a -v log level if it's not related to cfn-guard-lambda, or the relevant CloudWatch log messages if it is related to the cfn-guard-lambda
s3_no_full_access.guard/IAM_ROLE_NO_FULL_ACCESS_FOR_S3 FAIL
---
Evaluating data template.yml against rules s3_no_full_access.guard
Number of non-compliant resources 1
Resource = rImmutaRdsLambdaRole {
Type = AWS::IAM::Role
Rule = IAM_ROLE_NO_FULL_ACCESS_FOR_S3 {
ALL {
Check = %violationsSub EMPTY {
ComparisonError {
Message {
Violation: * in S3 folder (prefix) access.
Fix: Avoid wildcard matching * in S3 folder (prefix) access
}
Error = Check was not compliant as property [/Resources/rImmutaRdsLambdaRole[L:1549,C:4]] was not empty.
PropertyPath = /Resources/rImmutaRdsLambdaRole[L:1549,C:4]
Operator = EMPTY
Code:
1547. Principal: secretsmanager.amazonaws.com
1548.
1549. rImmutaRdsLambdaRole:
1550. Type: "AWS::IAM::Role"
1551. Properties:
1552. RoleName: !Sub immuta-rds-invoke-lambda-role-
}
}
}
}
}
```
Expected behavior
A clear and concise description of what you expected to happen.
The test should skip
Operating System:
[eg, MacOS, Windows, Ubuntu, etc]
Linux
OS Version
[eg Catalina, 10, 18.04, etc]
Ubuntu latest
Contributor guide
Research direction
Start with the rules under .github/folderlib/cfn-guard/rules/ and reproduce the report using the shown cfn-guard validate command against the supplied template. Trace why IAM_ROLE_NO_FULL_ACCESS_FOR_S3 evaluates the role's violationsSub check when it has no S3 permissions. Done means the validation skips that role and no longer reports the S3 wildcard violation.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- aws, rust
- Domain
- cloud, security, tooling
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100