I'm using iam_policy_no_statements_with_full_access.guard to validate my CloudFormation template. I'm trying to suppress the rule for one of my managed policies, but it seems to get ignored and still fails the test.
Reproduction Steps
The following is a reproducible snippet of my CloudFormation template (named repro.yaml):
I ran cfn-guard validate --show-summary fail --output-format single-line-summary --data repro.yaml --rules iam_policy_no_statements_with_full_access.guard to validate this template.
What did you expect to happen?
Since I added the Metadata block to suppress IAM_POLICY_NO_STATEMENTS_WITH_FULL_ACCESS, the cfn-guard validate command shouldn't show any failures.
What actually happened?
The validate command failed with the following output:
repro.yaml Status = FAIL
FAILED rules
iam_policy_no_statements_with_full_access.guard/IAM_POLICY_NO_STATEMENTS_WITH_FULL_ACCESS FAIL
---
Evaluating data repro.yaml against rules iam_policy_no_statements_with_full_access.guard
Number of non-compliant resources 1
Resource = GitHubRemainingPolicy {
Type = AWS::IAM::ManagedPolicy
Rule = IAM_POLICY_NO_STATEMENTS_WITH_FULL_ACCESS {
ALL {
Check = %violations EMPTY {
ComparisonError {
Message {
Violation: One or more IAM Managed Policies allow full access to at least 1 AWS service
Fix: Remove policy statements that match {"Effect": "Allow", "Action": "<service-name>:*" ... } or {"Effect": "Allow", "Action": "*" ... }
}
Error = Check was not compliant as property [/Resources/GitHubRemainingPolicy[L:3,C:4]] was not empty.
PropertyPath = /Resources/GitHubRemainingPolicy[L:3,C:4]
Operator = EMPTY
Code:
1.AWSTemplateFormatVersion: "2010-09-09"
2.Resources:
3. GitHubRemainingPolicy:
4. Type: AWS::IAM::ManagedPolicy
5. Metadata:
6. guard:
}
}
}
}
}
CloudFormation Guard Version
cfn-guard 3.0.0
OS
Ubuntu (running Windows Subsystem for Linux on Windows 11)
OS Version
Ubuntu 20.04.6 LTS
Other information
After debugging for hours, I realized the issue may be due to the guard rule when multiple managed policies are defined in the CloudFormation template. Looking at iam_policy_no_statements_with_full_access.guard:
let aws_iam_managed_policies_no_statements_with_full_access = Resources.*[ Type == 'AWS::IAM::ManagedPolicy'
Metadata.guard.SuppressedRules not exists or
Metadata.guard.SuppressedRules.* != "IAM_POLICY_NO_STATEMENTS_WITH_FULL_ACCESS"
]
rule IAM_POLICY_NO_STATEMENTS_WITH_FULL_ACCESS when %aws_iam_managed_policies_no_statements_with_full_access !empty {
let violations = Resources.*[
Type == 'AWS::IAM::ManagedPolicy'
some Properties.PolicyDocument.Statement[*] {
some Action[*] in ["*", /^[a-zA-Z0-9]*:\*$/]
Effect == "Allow"
some Resource in ["*"]
}
]
%violations empty
<<
Violation: One or more IAM Managed Policies allow full access to at least 1 AWS service
Fix: Remove policy statements that match {"Effect": "Allow", "Action": "<service-name>:*" ... } or {"Effect": "Allow", "Action": "*" ... }
>>
}
From my understanding:
aws_iam_managed_policies_no_statements_with_full_access is looking at all the managed policies without any suppression metadata. This will get the CodeBuildPolicy since it's a managed policy and no rules are suppressed there.
The IAM_POLICY_NO_STATEMENTS_WITH_FULL_ACCESS rule will kick in since aws_iam_managed_policies_no_statements_with_full_access is not empty, based on step 1.
violations will check the Action, Effect, and Resource values in all the managed policy documents.
Since GitHubRemainingPolicy contains policies allowing all actions for all resources (such as "cloudformation:*"), violations is non-empty, causing the rule to fail.
I think the bug is due to step 3. Even though the rule was originally executed for CodeBuildPolicy, it's checking GitHubRemainingPolicy as well, effectively ignoring the suppression earlier. I've noticed most of the other guard rules, such as IAM_NO_INLINE_POLICY_CHECK, reference the let variable inside the rule block:
let aws_iam_entities_no_inline_policy = Resources.*[
Type in [ /AWS::IAM::User/,
/AWS::IAM::Role/,
/AWS::IAM::Group/ ]
Metadata.guard.SuppressedRules not exists or
Metadata.guard.SuppressedRules.* != "IAM_NO_INLINE_POLICY_CHECK"
]
rule IAM_NO_INLINE_POLICY_CHECK when %aws_iam_entities_no_inline_policy !empty {
%aws_iam_entities_no_inline_policy.Properties.Policies empty
<<
Violation: Inline policies are not allowed on IAM Users, Roles, or Groups.
Fix: Remove the Policies list property from any IAM Users, Roles, or Groups.
>>
}
which only applies the check to all the resources that satisfy the filters defined in the let variable.
Workaround: If I remove CodeBuildPolicy or add the suppression metadata in that policy as well, the cfn-guard validate command succeeds, because aws_iam_managed_policies_no_statements_with_full_access is now empty, causing the rule to be skipped. However, I would have to apply this fix to any other managed policies I add to the CloudFormation template, so it's not an ideal solution.
What is the problem?
I'm using iam_policy_no_statements_with_full_access.guard to validate my CloudFormation template. I'm trying to suppress the rule for one of my managed policies, but it seems to get ignored and still fails the test.
Reproduction Steps
The following is a reproducible snippet of my CloudFormation template (named repro.yaml):
I ran
cfn-guard validate --show-summary fail --output-format single-line-summary --data repro.yaml --rules iam_policy_no_statements_with_full_access.guard
to validate this template.What did you expect to happen?
Since I added the Metadata block to suppress
IAM_POLICY_NO_STATEMENTS_WITH_FULL_ACCESS
, thecfn-guard validate
command shouldn't show any failures.What actually happened?
The validate command failed with the following output:
CloudFormation Guard Version
cfn-guard 3.0.0
OS
Ubuntu (running Windows Subsystem for Linux on Windows 11)
OS Version
Ubuntu 20.04.6 LTS
Other information
After debugging for hours, I realized the issue may be due to the guard rule when multiple managed policies are defined in the CloudFormation template. Looking at
iam_policy_no_statements_with_full_access.guard
:From my understanding:
aws_iam_managed_policies_no_statements_with_full_access
is looking at all the managed policies without any suppression metadata. This will get theCodeBuildPolicy
since it's a managed policy and no rules are suppressed there.IAM_POLICY_NO_STATEMENTS_WITH_FULL_ACCESS
rule will kick in sinceaws_iam_managed_policies_no_statements_with_full_access
is not empty, based on step 1.violations
will check the Action, Effect, and Resource values in all the managed policy documents.GitHubRemainingPolicy
contains policies allowing all actions for all resources (such as "cloudformation:*"),violations
is non-empty, causing the rule to fail.I think the bug is due to step 3. Even though the rule was originally executed for
CodeBuildPolicy
, it's checkingGitHubRemainingPolicy
as well, effectively ignoring the suppression earlier. I've noticed most of the other guard rules, such as IAM_NO_INLINE_POLICY_CHECK, reference the let variable inside the rule block:which only applies the check to all the resources that satisfy the filters defined in the let variable.
Workaround: If I remove
CodeBuildPolicy
or add the suppression metadata in that policy as well, thecfn-guard validate
command succeeds, becauseaws_iam_managed_policies_no_statements_with_full_access
is now empty, causing the rule to be skipped. However, I would have to apply this fix to any other managed policies I add to the CloudFormation template, so it's not an ideal solution.I've also noticed that IAM_POLICY_NO_STATEMENTS_WITH_ADMIN_ACCESS and RESTRICTED_INCOMING_TRAFFIC follow a similar
violations
pattern without referencing the let variable, so this bug might extend to those rules as well.