# Rule Identifier:
# CFN_NO_EXPLICIT_RESOURCE_NAMES
# NOTE: Reduced for test-case sake to prove inconsistent failure
let applicable_types = [
"AWS::EC2::SecurityGroup",
"AWS::IAM::Role"
]
# Select applicable resources less suppressed resources
let cloudformation_no_static_name_resources = Resources.*[Type in %applicable_types
Metadata.guard.SuppressedRules not exists or
Metadata.guard.SuppressedRules.* != "CFN_NO_EXPLICIT_RESOURCE_NAMES"
]
rule CFN_NO_EXPLICIT_RESOURCE_NAMES
when %cloudformation_no_static_name_resources !empty {
AWS::EC2::SecurityGroup {
Properties{
GroupName empty
}
}
AWS::IAM::Role {
Properties{
RoleName empty
}
}
%cloudformation_no_static_name_resources not empty
<<
Violation: Resource found with an explicit name, this disallows updates that require replacement of this resource.
Fix: Remove static name from the resource
>>
}
Test Case #1
Name: CFN_NO_EXPLICIT_RESOURCE_NAMES Single Resource IAM Role, CONFORM/Expect Pass
PASS Rules:
CFN_NO_EXPLICIT_RESOURCE_NAMES: Expected = PASS
Test Case #2
Name: CFN_NO_EXPLICIT_RESOURCE_NAMES Single Resource IAM Role, FLOUT/Expect Fail
PASS Rules:
CFN_NO_EXPLICIT_RESOURCE_NAMES: Expected = FAIL
Test Case #3
Name: CFN_NO_EXPLICIT_RESOURCE_NAMES Single Resource IAM Role, FLOUT+SUPPRESS/Expect Skip
PASS Rules:
CFN_NO_EXPLICIT_RESOURCE_NAMES: Expected = SKIP
Test Case #4
Name: CFN_NO_EXPLICIT_RESOURCE_NAMES Multiple Resource, Suppression in Both (SecurityGroup suppression not needed)/Expect Skip
PASS Rules:
CFN_NO_EXPLICIT_RESOURCE_NAMES: Expected = SKIP
Test Case #5
Name: CFN_NO_EXPLICIT_RESOURCE_NAMES Multiple Resource, Suppression in Role Only (SecurityGroup suppression Removed)/Expect Skip
FAIL Rules:
CFN_NO_EXPLICIT_RESOURCE_NAMES: Expected = SKIP, Evaluated = [FAIL]
Test Case #1
Name: CFN_NO_EXPLICIT_RESOURCE_NAMES Single Resource IAM Role, CONFORM/Expect Pass
`- File(, Status=PASS)[Context=File(rules=1)]
`- Rule(CFN_NO_EXPLICIT_RESOURCE_NAMES, Status=PASS)[Context=CFN_NO_EXPLICIT_RESOURCE_NAMES]
|- Rule/When(Status=PASS)[Context=Rule#CFN_NO_EXPLICIT_RESOURCE_NAMES/When]
| `- GuardClauseBlock(Status = PASS)[Context=GuardAccessClause#block %cloudformation_no_static_name_resources not EMPTY ]
| |- Filter/ConjunctionsBlock(Status=PASS)[Context=Filter/Map#2]
| | |- GuardClauseBlock(Status = PASS)[Context=GuardAccessClause#block Type IN %applicable_types]
| | | `- GuardClauseValueCheck(Status=PASS)[Context= Type IN %applicable_types]
| | `- Disjunction(Status = PASS)[Context=cfn_guard::rules::exprs::GuardClause#disjunction]
| | `- GuardClauseBlock(Status = PASS)[Context=GuardAccessClause#block Metadata.guard.SuppressedRules not EXISTS ]
| | `- GuardClauseValueCheck(Status=PASS)[Context= Metadata.guard.SuppressedRules not EXISTS ]
| `- GuardClauseValueCheck(Status=PASS)[Context= %cloudformation_no_static_name_resources not EMPTY ]
|- Type(AWS::EC2::SecurityGroup, Status=SKIP)[Context=TypeBlock#AWS::EC2::SecurityGroup]
| `- Filter/ConjunctionsBlock(Status=FAIL)[Context=Filter/Map#1]
| `- GuardClauseBlock(Status = FAIL)[Context=GuardAccessClause#block Type EQUALS "AWS::EC2::SecurityGroup"]
| `- GuardClauseBinaryCheck(Status=FAIL, Comparison= EQUALS, from=(resolved, Path=/Resources/ElasticContainerTaskExecutionRole/Type[L:0,C:0] Value="AWS::IAM::Role"), to=(resolved, Path=[L:0,C:0] Value="AWS::EC2::SecurityGroup"))[Context= Type EQUALS "AWS::EC2::SecurityGroup"]
|- Type(AWS::IAM::Role, Status=PASS)[Context=TypeBlock#AWS::IAM::Role]
| |- Filter/ConjunctionsBlock(Status=PASS)[Context=Filter/Map#1]
| | `- GuardClauseBlock(Status = PASS)[Context=GuardAccessClause#block Type EQUALS "AWS::IAM::Role"]
| | `- GuardClauseValueCheck(Status=PASS)[Context= Type EQUALS "AWS::IAM::Role"]
| `- TypeBlock/Block Status=PASS)[Context=TypeBlock#AWS::IAM::Role/0]
| `- GuardValueBlockCheck(Status = PASS)[Context=BlockGuardClause#Location[file:cfn_no_explicit_resource_names-modified.guard, line:24, column:7]]
| `- GuardClauseBlock(Status = PASS)[Context=GuardAccessClause#block RoleName EMPTY ]
| `- GuardClauseValueCheck(Status=PASS)[Context= RoleName EMPTY ]
`- GuardClauseBlock(Status = PASS)[Context=GuardAccessClause#block %cloudformation_no_static_name_resources not EMPTY ]
`- GuardClauseValueCheck(Status=PASS)[Context= %cloudformation_no_static_name_resources not EMPTY ]
PASS Rules:
CFN_NO_EXPLICIT_RESOURCE_NAMES: Expected = PASS
Test Case #2
Name: CFN_NO_EXPLICIT_RESOURCE_NAMES Single Resource IAM Role, FLOUT/Expect Fail
`- File(, Status=FAIL)[Context=File(rules=1)]
`- Rule(CFN_NO_EXPLICIT_RESOURCE_NAMES, Status=FAIL)[Context=CFN_NO_EXPLICIT_RESOURCE_NAMES]
|- Rule/When(Status=PASS)[Context=Rule#CFN_NO_EXPLICIT_RESOURCE_NAMES/When]
| `- GuardClauseBlock(Status = PASS)[Context=GuardAccessClause#block %cloudformation_no_static_name_resources not EMPTY ]
| |- Filter/ConjunctionsBlock(Status=PASS)[Context=Filter/Map#2]
| | |- GuardClauseBlock(Status = PASS)[Context=GuardAccessClause#block Type IN %applicable_types]
| | | `- GuardClauseValueCheck(Status=PASS)[Context= Type IN %applicable_types]
| | `- Disjunction(Status = PASS)[Context=cfn_guard::rules::exprs::GuardClause#disjunction]
| | `- GuardClauseBlock(Status = PASS)[Context=GuardAccessClause#block Metadata.guard.SuppressedRules not EXISTS ]
| | `- GuardClauseValueCheck(Status=PASS)[Context= Metadata.guard.SuppressedRules not EXISTS ]
| `- GuardClauseValueCheck(Status=PASS)[Context= %cloudformation_no_static_name_resources not EMPTY ]
|- Type(AWS::EC2::SecurityGroup, Status=SKIP)[Context=TypeBlock#AWS::EC2::SecurityGroup]
| `- Filter/ConjunctionsBlock(Status=FAIL)[Context=Filter/Map#1]
| `- GuardClauseBlock(Status = FAIL)[Context=GuardAccessClause#block Type EQUALS "AWS::EC2::SecurityGroup"]
| `- GuardClauseBinaryCheck(Status=FAIL, Comparison= EQUALS, from=(resolved, Path=/Resources/ElasticContainerTaskExecutionRole/Type[L:0,C:0] Value="AWS::IAM::Role"), to=(resolved, Path=[L:0,C:0] Value="AWS::EC2::SecurityGroup"))[Context= Type EQUALS "AWS::EC2::SecurityGroup"]
|- Type(AWS::IAM::Role, Status=FAIL)[Context=TypeBlock#AWS::IAM::Role]
| |- Filter/ConjunctionsBlock(Status=PASS)[Context=Filter/Map#1]
| | `- GuardClauseBlock(Status = PASS)[Context=GuardAccessClause#block Type EQUALS "AWS::IAM::Role"]
| | `- GuardClauseValueCheck(Status=PASS)[Context= Type EQUALS "AWS::IAM::Role"]
| `- TypeBlock/Block Status=FAIL)[Context=TypeBlock#AWS::IAM::Role/0]
| `- GuardValueBlockCheck(Status = FAIL)[Context=BlockGuardClause#Location[file:cfn_no_explicit_resource_names-modified.guard, line:24, column:7]]
| `- GuardClauseBlock(Status = FAIL)[Context=GuardAccessClause#block RoleName EMPTY ]
| `- GuardClauseUnaryCheck(Status=FAIL, Comparison= EMPTY, Value-At=(resolved, Path=/Resources/ElasticContainerTaskExecutionRole/Properties/RoleName[L:0,C:0] Value="task-execution-role"))[Context= RoleName EMPTY ]
`- GuardClauseBlock(Status = PASS)[Context=GuardAccessClause#block %cloudformation_no_static_name_resources not EMPTY ]
`- GuardClauseValueCheck(Status=PASS)[Context= %cloudformation_no_static_name_resources not EMPTY ]
PASS Rules:
CFN_NO_EXPLICIT_RESOURCE_NAMES: Expected = FAIL
Test Case #3
Name: CFN_NO_EXPLICIT_RESOURCE_NAMES Single Resource IAM Role, FLOUT+SUPPRESS/Expect Skip
`- File(, Status=SKIP)[Context=File(rules=1)]
`- Rule(CFN_NO_EXPLICIT_RESOURCE_NAMES, Status=SKIP)[Context=CFN_NO_EXPLICIT_RESOURCE_NAMES]
`- Rule/When(Status=FAIL)[Context=Rule#CFN_NO_EXPLICIT_RESOURCE_NAMES/When]
`- GuardClauseBlock(Status = FAIL)[Context=GuardAccessClause#block %cloudformation_no_static_name_resources not EMPTY ]
|- Filter/ConjunctionsBlock(Status=FAIL)[Context=Filter/Map#2]
| |- GuardClauseBlock(Status = PASS)[Context=GuardAccessClause#block Type IN %applicable_types]
| | `- GuardClauseValueCheck(Status=PASS)[Context= Type IN %applicable_types]
| `- Disjunction(Status = FAIL)[Context=cfn_guard::rules::exprs::GuardClause#disjunction]
| |- GuardClauseBlock(Status = FAIL)[Context=GuardAccessClause#block Metadata.guard.SuppressedRules not EXISTS ]
| | `- GuardClauseUnaryCheck(Status=FAIL, Comparison=not EXISTS, Value-At=(resolved, Path=/Resources/ElasticContainerTaskExecutionRole/Metadata/guard/SuppressedRules[L:0,C:0] Value=["CFN_NO_EXPLICIT_RESOURCE_NAMES"]))[Context= Metadata.guard.SuppressedRules not EXISTS ]
| `- GuardClauseBlock(Status = FAIL)[Context=GuardAccessClause#block Metadata.guard.SuppressedRules.* not EQUALS "CFN_NO_EXPLICIT_RESOURCE_NAMES"]
| `- GuardClauseBinaryCheck(Status=FAIL, Comparison=not EQUALS, from=(resolved, Path=/Resources/ElasticContainerTaskExecutionRole/Metadata/guard/SuppressedRules/0[L:0,C:0] Value="CFN_NO_EXPLICIT_RESOURCE_NAMES"), to=(resolved, Path=[L:0,C:0] Value="CFN_NO_EXPLICIT_RESOURCE_NAMES"))[Context= Metadata.guard.SuppressedRules.* not EQUALS "CFN_NO_EXPLICIT_RESOURCE_NAMES"]
`- GuardClause(Status=FAIL, Empty, )[Context= %cloudformation_no_static_name_resources not EMPTY ]
PASS Rules:
CFN_NO_EXPLICIT_RESOURCE_NAMES: Expected = SKIP
Test Case #4
Name: CFN_NO_EXPLICIT_RESOURCE_NAMES Multiple Resource, Suppression in Both (SecurityGroup suppression not needed)/Expect Skip
`- File(, Status=SKIP)[Context=File(rules=1)]
`- Rule(CFN_NO_EXPLICIT_RESOURCE_NAMES, Status=SKIP)[Context=CFN_NO_EXPLICIT_RESOURCE_NAMES]
`- Rule/When(Status=FAIL)[Context=Rule#CFN_NO_EXPLICIT_RESOURCE_NAMES/When]
`- GuardClauseBlock(Status = FAIL)[Context=GuardAccessClause#block %cloudformation_no_static_name_resources not EMPTY ]
|- Filter/ConjunctionsBlock(Status=FAIL)[Context=Filter/Map#2]
| |- GuardClauseBlock(Status = PASS)[Context=GuardAccessClause#block Type IN %applicable_types]
| | `- GuardClauseValueCheck(Status=PASS)[Context= Type IN %applicable_types]
| `- Disjunction(Status = FAIL)[Context=cfn_guard::rules::exprs::GuardClause#disjunction]
| |- GuardClauseBlock(Status = FAIL)[Context=GuardAccessClause#block Metadata.guard.SuppressedRules not EXISTS ]
| | `- GuardClauseUnaryCheck(Status=FAIL, Comparison=not EXISTS, Value-At=(resolved, Path=/Resources/ElasticContainerSecurityGroup/Metadata/guard/SuppressedRules[L:0,C:0] Value=["EC2_SECURITY_GROUP_EGRESS_OPEN_TO_WORLD_RULE","SECURITY_GROUP_EGRESS_PORT_RANGE_RULE","CFN_NO_EXPLICIT_RESOURCE_NAMES"]))[Context= Metadata.guard.SuppressedRules not EXISTS ]
| `- GuardClauseBlock(Status = FAIL)[Context=GuardAccessClause#block Metadata.guard.SuppressedRules.* not EQUALS "CFN_NO_EXPLICIT_RESOURCE_NAMES"]
| |- GuardClauseValueCheck(Status=PASS)[Context= Metadata.guard.SuppressedRules.* not EQUALS "CFN_NO_EXPLICIT_RESOURCE_NAMES"]
| |- GuardClauseValueCheck(Status=PASS)[Context= Metadata.guard.SuppressedRules.* not EQUALS "CFN_NO_EXPLICIT_RESOURCE_NAMES"]
| `- GuardClauseBinaryCheck(Status=FAIL, Comparison=not EQUALS, from=(resolved, Path=/Resources/ElasticContainerSecurityGroup/Metadata/guard/SuppressedRules/2[L:0,C:0] Value="CFN_NO_EXPLICIT_RESOURCE_NAMES"), to=(resolved, Path=[L:0,C:0] Value="CFN_NO_EXPLICIT_RESOURCE_NAMES"))[Context= Metadata.guard.SuppressedRules.* not EQUALS "CFN_NO_EXPLICIT_RESOURCE_NAMES"]
|- Filter/ConjunctionsBlock(Status=FAIL)[Context=Filter/Map#2]
| |- GuardClauseBlock(Status = PASS)[Context=GuardAccessClause#block Type IN %applicable_types]
| | `- GuardClauseValueCheck(Status=PASS)[Context= Type IN %applicable_types]
| `- Disjunction(Status = FAIL)[Context=cfn_guard::rules::exprs::GuardClause#disjunction]
| |- GuardClauseBlock(Status = FAIL)[Context=GuardAccessClause#block Metadata.guard.SuppressedRules not EXISTS ]
| | `- GuardClauseUnaryCheck(Status=FAIL, Comparison=not EXISTS, Value-At=(resolved, Path=/Resources/ElasticContainerTaskExecutionRole/Metadata/guard/SuppressedRules[L:0,C:0] Value=["CFN_NO_EXPLICIT_RESOURCE_NAMES"]))[Context= Metadata.guard.SuppressedRules not EXISTS ]
| `- GuardClauseBlock(Status = FAIL)[Context=GuardAccessClause#block Metadata.guard.SuppressedRules.* not EQUALS "CFN_NO_EXPLICIT_RESOURCE_NAMES"]
| `- GuardClauseBinaryCheck(Status=FAIL, Comparison=not EQUALS, from=(resolved, Path=/Resources/ElasticContainerTaskExecutionRole/Metadata/guard/SuppressedRules/0[L:0,C:0] Value="CFN_NO_EXPLICIT_RESOURCE_NAMES"), to=(resolved, Path=[L:0,C:0] Value="CFN_NO_EXPLICIT_RESOURCE_NAMES"))[Context= Metadata.guard.SuppressedRules.* not EQUALS "CFN_NO_EXPLICIT_RESOURCE_NAMES"]
`- GuardClause(Status=FAIL, Empty, )[Context= %cloudformation_no_static_name_resources not EMPTY ]
PASS Rules:
CFN_NO_EXPLICIT_RESOURCE_NAMES: Expected = SKIP
Test Case #5
Name: CFN_NO_EXPLICIT_RESOURCE_NAMES Multiple Resource, Suppression in Role Only (SecurityGroup suppression Removed)/Expect Skip
`- File(, Status=FAIL)[Context=File(rules=1)]
`- Rule(CFN_NO_EXPLICIT_RESOURCE_NAMES, Status=FAIL)[Context=CFN_NO_EXPLICIT_RESOURCE_NAMES]
|- Rule/When(Status=PASS)[Context=Rule#CFN_NO_EXPLICIT_RESOURCE_NAMES/When]
| `- GuardClauseBlock(Status = PASS)[Context=GuardAccessClause#block %cloudformation_no_static_name_resources not EMPTY ]
| |- Filter/ConjunctionsBlock(Status=PASS)[Context=Filter/Map#2]
| | |- GuardClauseBlock(Status = PASS)[Context=GuardAccessClause#block Type IN %applicable_types]
| | | `- GuardClauseValueCheck(Status=PASS)[Context= Type IN %applicable_types]
| | `- Disjunction(Status = PASS)[Context=cfn_guard::rules::exprs::GuardClause#disjunction]
| | |- GuardClauseBlock(Status = FAIL)[Context=GuardAccessClause#block Metadata.guard.SuppressedRules not EXISTS ]
| | | `- GuardClauseUnaryCheck(Status=FAIL, Comparison=not EXISTS, Value-At=(resolved, Path=/Resources/ElasticContainerSecurityGroup/Metadata/guard/SuppressedRules[L:0,C:0] Value=["EC2_SECURITY_GROUP_EGRESS_OPEN_TO_WORLD_RULE","SECURITY_GROUP_EGRESS_PORT_RANGE_RULE"]))[Context= Metadata.guard.SuppressedRules not EXISTS ]
| | `- GuardClauseBlock(Status = PASS)[Context=GuardAccessClause#block Metadata.guard.SuppressedRules.* not EQUALS "CFN_NO_EXPLICIT_RESOURCE_NAMES"]
| | |- GuardClauseValueCheck(Status=PASS)[Context= Metadata.guard.SuppressedRules.* not EQUALS "CFN_NO_EXPLICIT_RESOURCE_NAMES"]
| | `- GuardClauseValueCheck(Status=PASS)[Context= Metadata.guard.SuppressedRules.* not EQUALS "CFN_NO_EXPLICIT_RESOURCE_NAMES"]
| |- Filter/ConjunctionsBlock(Status=FAIL)[Context=Filter/Map#2]
| | |- GuardClauseBlock(Status = PASS)[Context=GuardAccessClause#block Type IN %applicable_types]
| | | `- GuardClauseValueCheck(Status=PASS)[Context= Type IN %applicable_types]
| | `- Disjunction(Status = FAIL)[Context=cfn_guard::rules::exprs::GuardClause#disjunction]
| | |- GuardClauseBlock(Status = FAIL)[Context=GuardAccessClause#block Metadata.guard.SuppressedRules not EXISTS ]
| | | `- GuardClauseUnaryCheck(Status=FAIL, Comparison=not EXISTS, Value-At=(resolved, Path=/Resources/ElasticContainerTaskExecutionRole/Metadata/guard/SuppressedRules[L:0,C:0] Value=["CFN_NO_EXPLICIT_RESOURCE_NAMES"]))[Context= Metadata.guard.SuppressedRules not EXISTS ]
| | `- GuardClauseBlock(Status = FAIL)[Context=GuardAccessClause#block Metadata.guard.SuppressedRules.* not EQUALS "CFN_NO_EXPLICIT_RESOURCE_NAMES"]
| | `- GuardClauseBinaryCheck(Status=FAIL, Comparison=not EQUALS, from=(resolved, Path=/Resources/ElasticContainerTaskExecutionRole/Metadata/guard/SuppressedRules/0[L:0,C:0] Value="CFN_NO_EXPLICIT_RESOURCE_NAMES"), to=(resolved, Path=[L:0,C:0] Value="CFN_NO_EXPLICIT_RESOURCE_NAMES"))[Context= Metadata.guard.SuppressedRules.* not EQUALS "CFN_NO_EXPLICIT_RESOURCE_NAMES"]
| `- GuardClauseValueCheck(Status=PASS)[Context= %cloudformation_no_static_name_resources not EMPTY ]
|- Type(AWS::EC2::SecurityGroup, Status=PASS)[Context=TypeBlock#AWS::EC2::SecurityGroup]
| |- Filter/ConjunctionsBlock(Status=PASS)[Context=Filter/Map#1]
| | `- GuardClauseBlock(Status = PASS)[Context=GuardAccessClause#block Type EQUALS "AWS::EC2::SecurityGroup"]
| | `- GuardClauseValueCheck(Status=PASS)[Context= Type EQUALS "AWS::EC2::SecurityGroup"]
| |- Filter/ConjunctionsBlock(Status=FAIL)[Context=Filter/Map#1]
| | `- GuardClauseBlock(Status = FAIL)[Context=GuardAccessClause#block Type EQUALS "AWS::EC2::SecurityGroup"]
| | `- GuardClauseBinaryCheck(Status=FAIL, Comparison= EQUALS, from=(resolved, Path=/Resources/ElasticContainerTaskExecutionRole/Type[L:0,C:0] Value="AWS::IAM::Role"), to=(resolved, Path=[L:0,C:0] Value="AWS::EC2::SecurityGroup"))[Context= Type EQUALS "AWS::EC2::SecurityGroup"]
| `- TypeBlock/Block Status=PASS)[Context=TypeBlock#AWS::EC2::SecurityGroup/0]
| `- GuardValueBlockCheck(Status = PASS)[Context=BlockGuardClause#Location[file:cfn_no_explicit_resource_names-modified.guard, line:19, column:7]]
| `- GuardClauseBlock(Status = PASS)[Context=GuardAccessClause#block GroupName EMPTY ]
| `- GuardClauseValueCheck(Status=PASS)[Context= GroupName EMPTY ]
|- Type(AWS::IAM::Role, Status=FAIL)[Context=TypeBlock#AWS::IAM::Role]
| |- Filter/ConjunctionsBlock(Status=FAIL)[Context=Filter/Map#1]
| | `- GuardClauseBlock(Status = FAIL)[Context=GuardAccessClause#block Type EQUALS "AWS::IAM::Role"]
| | `- GuardClauseBinaryCheck(Status=FAIL, Comparison= EQUALS, from=(resolved, Path=/Resources/ElasticContainerSecurityGroup/Type[L:0,C:0] Value="AWS::EC2::SecurityGroup"), to=(resolved, Path=[L:0,C:0] Value="AWS::IAM::Role"))[Context= Type EQUALS "AWS::IAM::Role"]
| |- Filter/ConjunctionsBlock(Status=PASS)[Context=Filter/Map#1]
| | `- GuardClauseBlock(Status = PASS)[Context=GuardAccessClause#block Type EQUALS "AWS::IAM::Role"]
| | `- GuardClauseValueCheck(Status=PASS)[Context= Type EQUALS "AWS::IAM::Role"]
| `- TypeBlock/Block Status=FAIL)[Context=TypeBlock#AWS::IAM::Role/0]
| `- GuardValueBlockCheck(Status = FAIL)[Context=BlockGuardClause#Location[file:cfn_no_explicit_resource_names-modified.guard, line:24, column:7]]
| `- GuardClauseBlock(Status = FAIL)[Context=GuardAccessClause#block RoleName EMPTY ]
| `- GuardClauseUnaryCheck(Status=FAIL, Comparison= EMPTY, Value-At=(resolved, Path=/Resources/ElasticContainerTaskExecutionRole/Properties/RoleName[L:0,C:0] Value="explicit-name"))[Context= RoleName EMPTY ]
`- GuardClauseBlock(Status = PASS)[Context=GuardAccessClause#block %cloudformation_no_static_name_resources not EMPTY ]
`- GuardClauseValueCheck(Status=PASS)[Context= %cloudformation_no_static_name_resources not EMPTY ]
FAIL Rules:
CFN_NO_EXPLICIT_RESOURCE_NAMES: Expected = SKIP, Evaluated = [FAIL]
Describe the bug
I have a simple CloudFormation template that has more than one resource. For some resources, I would like to adhere to the aws-guard-rules-registry/CFN_NO_EXPLICIT_RESOURCE_NAMES rule, and for others I want to use explicit names with good reason. The problem is that when I apply suppression via
Metadata.guard.SuppressedRulesto a resource that does not conform to the rule, aFAILwould be reported when I do not also include the metadata for Resources that do NOT need it.I do apologise for submitting a new issue as this relates to #636 but this is a sanitised submission stripped down to the least amount of data to reproduce the issue using
cfn-guard test.To Reproduce
Please supply:
Resources:
Resource 1: Guard data:
file: cfn_no_explicit_resource_names-modified.guardNotes:
AWS::EC2::SecurityGroupandAWS::IAM::Rolein bothapplicable_typesand Rule/When evaluationMetadata.cfn_nagportions have been removedResource 2: Test data:
file: test.yamlNotes:
cfn-guard test -r cfn_no_explicit_resource_names-modified.guard -t test.yamlOutput:
With
-voutput:NOTE: Please be sure that the templates, rules and logs you provide as part of your bug report do not contain any sensitive information.
Expected behaviour
Having a template with multiple resources that is eligible to be evaluated against the aws-guard-rules-registry/CFN_NO_EXPLICIT_RESOURCE_NAMES rule should not affect the rule evaluation result of a different resource to the one which has its
Metadataaltered.Operating System:
Windows, running WSL2
OS Version
Ubuntu 24.04.2 LTS /
Linux HOSTNAME_REDACTED 5.15.167.4-microsoft-standard-WSL2 #1 SMP Tue Nov 5 00:21:55 UTC 2024 x86_64 x86_64 x86_64 GNU/LinuxAdditional context
At this stage of the journey I don't know whether the problem is with the Guard DSL or within
cfn-guardand the Rust code. I am down the rabbit hole learning Rust in an attempt to troubleshoot this problem and I don't see light at the end of the tunnel yet.