Comments (20)
Awesome. I'll close this for now. Please do re-open it if you're still jammed-up.
from cloudformation-guard.
Okay. If you're cool with how it works, that's a good thing. :-)
On my end, things are working as expected and I have lots of tests around both the list types and the wildcards, so hopefully, I have all of them nailed down. If not, please do reopen and we'll keep unpacking this.
from cloudformation-guard.
Do you have an example template to run against this rule?
As written, it would look at the Tags property of the AWS::EC2::EIP type and expect it to exactly match that list of maps on the right-side of the rule. If there were an additional value inside that right-side list, it would fail to exactly match and the check should fail.
Here's what I got from a test that sounds similar to your question:
"[CheckRequirements] failed because [HttpFloodProtectionLogParserActivated] is [[\"HttpFloodProtectionLogParserActivated\",\"yes\",\"no\",\"maybe\"]] and the permitted value is [[\"HttpFloodProtectionLogParserActivated\",\"yes\",\"no\"]]"
Number of failures: 1
from cloudformation-guard.
Generally we want that all tagable resources have 2 specific tags, one that denotes the owner and one that denotes the environment type.
However the resources may also have any number of additional tags that we do not track or care about and it should not fail cfn-guard if those additional tags are defined.
The only hard requirement is the existence the Owner and Environment tags.
from cloudformation-guard.
That sounds like a good candidate for wildcards. Try something like:
AWS::EC2::EIP Tags.* == {"Key":"Foo","Value":"abc"}
AWS::EC2::EIP Tags.* == {"Key":"Bar","Value":"def"}
What these rules say is "At least item in the list under Tags must contain this value". Taken together they guarantee that each instance of EIP Tags needs to have these somewhere in its list.
Note the lack of whitespace, though. Because the parsers eliminate them when they deserialize, your right-side value needs to be {"Key":"Foo","Value":"abc"}
instead of {"Key": "Foo", "Value": "abc"}
. When in doubt, run a template through cfn-guard-rulegen and you'll get a view of how the parsers view the values. And you can always increase the verbosity logging level to make the processing more clear. In particular, -vvv
will give you everything that happens from start to finish.
from cloudformation-guard.
Hi,
That didnt work as expected, now it complains twice for every other tag that's not specifically listed like:
"[Alb] failed because [Tags.0] is [{\"Key\":\"Name\",\"Value\":\"${EnvironmentType}-${ClusterName}-ecs-alb\"}] and the permitted value is [{\"Key\":\"EnvironmentType\",\"Value\":\"EnvironmentType\"}]"
"[Alb] failed because [Tags.0] is [{\"Key\":\"Name\",\"Value\":\"${EnvironmentType}-${ClusterName}-ecs-alb\"}] and the permitted value is [{\"Key\":\"OwnerContact\",\"Value\":\"OwnerContact\"}]"
"[Alb] failed because [Tags.1] is [{\"Key\":\"EnvironmentType\",\"Value\":\"EnvironmentType\"}] and the permitted value is [{\"Key\":\"OwnerContact\",\"Value\":\"OwnerContact\"}]"
"[Alb] failed because [Tags.2] is [{\"Key\":\"ClusterName\",\"Value\":\"ClusterName\"}] and the permitted value is [{\"Key\":\"EnvironmentType\",\"Value\":\"EnvironmentType\"}]"
"[Alb] failed because [Tags.2] is [{\"Key\":\"ClusterName\",\"Value\":\"ClusterName\"}] and the permitted value is [{\"Key\":\"OwnerContact\",\"Value\":\"OwnerContact\"}]"
"[Alb] failed because [Tags.3] is [{\"Key\":\"Scope\",\"Value\":\"ecs\"}] and the permitted value is [{\"Key\":\"EnvironmentType\",\"Value\":\"EnvironmentType\"}]"
"[Alb] failed because [Tags.3] is [{\"Key\":\"Scope\",\"Value\":\"ecs\"}] and the permitted value is [{\"Key\":\"OwnerContact\",\"Value\":\"OwnerContact\"}]"
The ruleset is:
AWS::ElasticLoadBalancingV2::LoadBalancer Tags.* == {"Key":"EnvironmentType","Value":"EnvironmentType"}
AWS::ElasticLoadBalancingV2::LoadBalancer Tags.* == {"Key":"OwnerContact","Value":"OwnerContact"}
The template is missing OwnerContact Tag
//Edit:
It seems that I can only enforce it using positional Tags such as Tags.0 == {"Key":"EnvironmentType","Value":"EnvironmentType"}
and Tags.1 == {"Key":"OwnerContact","Value":"OwnerContact"}
from cloudformation-guard.
Hmm. Sorry to hear that's not working. The extra messages are a result of wildcard ==
being treated as a set of |OR|
's. So if it doesn't hit any of allowed values in the Tags field, the result from both failed sides of the |OR|
are output.
I think I can write a simple rule to address this use case but before I do, can I get an example template (nothing sensitive in it) to try it on my side?
from cloudformation-guard.
This would be an example:
ClusterSg:
Type: AWS::EC2::SecurityGroup
Properties:
VpcId:
Fn::ImportValue: !Sub ${EnvironmentType}-net-vpc-VpcId
GroupDescription: !Sub ${EnvironmentType}-sg-${ClusterName}
SecurityGroupEgress:
- CidrIp: "0.0.0.0/0"
IpProtocol : "-1"
Description: "Allow all outgoing traffic"
SecurityGroupIngress:
- SourceSecurityGroupId: !Ref AlbSg
IpProtocol : "-1"
Description: !Sub "Allow incoming traffic from ${ClusterName} ALB"
Tags:
- Key: EnvironmentType
Value: !Ref EnvironmentType
- Key: OwnerContact
Value: !Ref OwnerContact
- Key: Name
Value: !Sub ${EnvironmentType}-${ClusterName}-sg
- Key: ClusterName
Value: !Ref ECSCluster
- Key: Scope
Value: ecs
The only tags we want to enforce setting is EnvironmentType
, OwnerContact
and Name
- Order doesnt matter, right now since I do regex matching to solve it the order is fixed like this in all templates but ideally the devs should be allowed to put them in any order.
I appreciate the help :)
from cloudformation-guard.
You caught a bug! Good eye. The issue was that the regex was too restrictive and mandated a value after the *
(which is incorrect behavior). I added tests for correct pass & fail behavior for stuff like Tags.*
and merged a fix into the branch release-0.5.2
in PR #34.
Can you build from the release-0.5.2
branch and see if this particular issue is resolved with a ruleset like:
AWS::EC2::SecurityGroup Tags.* == {"Key":"EnvironmentType","Value":"EnvironmentType"}
AWS::EC2::SecurityGroup Tags.* == {"Key":"OwnerContact","Value":"OwnerContact"}
It should mandate that each of those tags must be present at least once.
You'll still get the multiple errors when they're not present because the * ==
wildcard operation is an OR
across all the possible matches. But that is an accurate outcome. In other words, with the rules above and the tags that match commented out in your template:
Resources:
ClusterSg:
Type: AWS::EC2::SecurityGroup
Properties:
VpcId:
Fn::ImportValue: !Sub ${EnvironmentType}-net-vpc-VpcId
GroupDescription: !Sub ${EnvironmentType}-sg-${ClusterName}
SecurityGroupEgress:
- CidrIp: "0.0.0.0/0"
IpProtocol : "-1"
Description: "Allow all outgoing traffic"
SecurityGroupIngress:
- SourceSecurityGroupId: !Ref AlbSg
IpProtocol : "-1"
Description: !Sub "Allow incoming traffic from ${ClusterName} ALB"
Tags:
#- Key: EnvironmentType
# Value: !Ref EnvironmentType
#- Key: OwnerContact
# Value: !Ref OwnerContact
- Key: Name
Value: !Sub ${EnvironmentType}-${ClusterName}-sg
- Key: ClusterName
Value: !Ref ECSCluster
- Key: Scope
Value: ecs
You should get the following result:
⋊> ~/p/c/cfn-guard on release-0.5.2 ◦ cargo run -- -t ~/scratch_template.yaml -r ~/scratch.ruleset 10:46:42
Finished dev [unoptimized + debuginfo] target(s) in 0.03s
Running `target/debug/cfn-guard -t /Users/nathanmc/scratch_template.yaml -r /Users/nathanmc/scratch.ruleset`
[ClusterSg] failed because [Tags.0] is [{"Key":"Name","Value":"${EnvironmentType}-${ClusterName}-sg"}] and the permitted value is [{"Key":"EnvironmentType","Value":"EnvironmentType"}]
[ClusterSg] failed because [Tags.0] is [{"Key":"Name","Value":"${EnvironmentType}-${ClusterName}-sg"}] and the permitted value is [{"Key":"OwnerContact","Value":"OwnerContact"}]
[ClusterSg] failed because [Tags.1] is [{"Key":"ClusterName","Value":"ECSCluster"}] and the permitted value is [{"Key":"EnvironmentType","Value":"EnvironmentType"}]
[ClusterSg] failed because [Tags.1] is [{"Key":"ClusterName","Value":"ECSCluster"}] and the permitted value is [{"Key":"OwnerContact","Value":"OwnerContact"}]
[ClusterSg] failed because [Tags.2] is [{"Key":"Scope","Value":"ecs"}] and the permitted value is [{"Key":"EnvironmentType","Value":"EnvironmentType"}]
[ClusterSg] failed because [Tags.2] is [{"Key":"Scope","Value":"ecs"}] and the permitted value is [{"Key":"OwnerContact","Value":"OwnerContact"}]
Number of failures: 6
But with the tags in the template uncommented, it should pass.
from cloudformation-guard.
Haha nice, this will slim down my rules a lot. I'll build 0.5.2 and test it :)
from cloudformation-guard.
Seems like we need to reopen this because some recent commit of release-0.5.2 caused regression and broke it again :/
//EDIT:
#35 This worked
#36 Broke it again
Did a format change happen?
from cloudformation-guard.
👀 Taking a look. This should be covered by test cases. If not, that's a bug in and of itself.
from cloudformation-guard.
I just tested from the head of release-0.5.2
using the template:
Resources:
ClusterSg:
Type: AWS::EC2::SecurityGroup
Properties:
VpcId:
Fn::ImportValue: !Sub ${EnvironmentType}-net-vpc-VpcId
GroupDescription: !Sub ${EnvironmentType}-sg-${ClusterName}
SecurityGroupEgress:
- CidrIp: "0.0.0.0/0"
IpProtocol : "-1"
Description: "Allow all outgoing traffic"
SecurityGroupIngress:
- SourceSecurityGroupId: !Ref AlbSg
IpProtocol : "-1"
Description: !Sub "Allow incoming traffic from ${ClusterName} ALB"
Tags:
- Key: EnvironmentType
Value: !Ref EnvironmentType
- Key: OwnerContact
Value: !Ref OwnerContact
- Key: Name
Value: !Sub ${EnvironmentType}-${ClusterName}-sg
- Key: ClusterName
Value: !Ref ECSCluster
- Key: Scope
Value: ecs
And the ruleset:
AWS::EC2::SecurityGroup Tags.* == {"Key":"EnvironmentType","Value":"EnvironmentType"}
AWS::EC2::SecurityGroup Tags.* == {"Key":"OwnerContact","Value":"OwnerContact"}
It failed with the tags commented out:
⋊> ~/p/cloudformation-guard on release-0.5.2 ◦ cfn-guard -t ~/scratch-template.yaml -r ~/scratch.ruleset 12:58:19
[ClusterSg] failed because [Tags.0] is [{"Key":"Name","Value":"${EnvironmentType}-${ClusterName}-sg"}] and the permitted value is [{"Key":"EnvironmentType","Value":"EnvironmentType"}]
[ClusterSg] failed because [Tags.0] is [{"Key":"Name","Value":"${EnvironmentType}-${ClusterName}-sg"}] and the permitted value is [{"Key":"OwnerContact","Value":"OwnerContact"}]
[ClusterSg] failed because [Tags.1] is [{"Key":"ClusterName","Value":"ECSCluster"}] and the permitted value is [{"Key":"EnvironmentType","Value":"EnvironmentType"}]
[ClusterSg] failed because [Tags.1] is [{"Key":"ClusterName","Value":"ECSCluster"}] and the permitted value is [{"Key":"OwnerContact","Value":"OwnerContact"}]
[ClusterSg] failed because [Tags.2] is [{"Key":"Scope","Value":"ecs"}] and the permitted value is [{"Key":"EnvironmentType","Value":"EnvironmentType"}]
[ClusterSg] failed because [Tags.2] is [{"Key":"Scope","Value":"ecs"}] and the permitted value is [{"Key":"OwnerContact","Value":"OwnerContact"}]
Number of failures: 6
And passed when the tags were uncommented:
⋊> ~/p/cloudformation-guard on release-0.5.2 ◦ cfn-guard -t ~/scratch-template.yaml -r ~/scratch.ruleset 12:58:38
⋊> ~/p/cloudformation-guard on release-0.5.2 ◦
What's the error you got?
from cloudformation-guard.
Actually looking at the results again it seems to be matching different Tags objects that it just didnt match before...
Something like:
Type: "AWS::MediaLive::Channel"
Properties:
Tags:
OwnerContact: !Ref OwnerContact
EnvironmentType: !Ref EnvironmentType
Had to heavily redact this one sadly.
But this will be matched against:
[MediaLiveChannel] failed because [EnvironmentType] is not in [{"Key":"EnvironmentType","Value":"EnvironmentType"},{"Key":"EnvironmentType","Value":{"Ref":"EnvironmentType"}},{"Key":"EnvironmentType","PropagateAtLaunch":true,"Value":"EnvironmentType"},{"Key":"EnvironmentType","PropagateAtLaunch":true,"Value":{"Ref":"EnvironmentType"}}] for [Tags.EnvironmentType]
So I just added 'EnvironmentType' as literal into the array and it started matching again.
from cloudformation-guard.
Interesting! Can you give me the rule? I think some of the unexpected behavior might be tied to the new JSON list vs regular list.
from cloudformation-guard.
I'll just assume it's a list type rule and test with that, but I'd love to have the exact rule to make sure I'm not making bad assumptions.
from cloudformation-guard.
Based on what you were saying about adding the literal making it work, I think I might know what you're running into:
let tag_list = [{"Key":"EnvironmentType","Value":"EnvironmentType"},{"Key":"EnvironmentType","Value":{"Ref":"EnvironmentType"}},{"Key":"EnvironmentType","PropagateAtLaunch":true,"Value":"EnvironmentType"},{"Key":"EnvironmentType","PropagateAtLaunch":true,"Value":{"Ref":"EnvironmentType"}}]
AWS::EC2::SecurityGroup Tags.* IN %tag_list
Works because when it's looking at tags, each item in the tag list represented by the * themselves resolve to the full item (eg, Key: "key", Value: "value"
).
However if the rule is written like:
AWS::EC2::SecurityGroup Tags.*.Key IN %tag_list
It'll fail because "Key" would resolve to "key", not Key: "key"
:
⋊> ~/p/cloudformation-guard on release-0.5.2 ◦ cfn-guard -t ~/scratch-template.yaml -r ~/scratch.ruleset 13:39:54
[ClusterSg] failed because [ClusterName] is not in [{"Key":"EnvironmentType","Value":"EnvironmentType"},{"Key":"EnvironmentType","Value":{"Ref":"EnvironmentType"}},{"Key":"EnvironmentType","PropagateAtLaunch":true,"Value":"EnvironmentType"},{"Key":"EnvironmentType","PropagateAtLaunch":true,"Value":{"Ref":"EnvironmentType"}}] for [Tags.3.Key]
[ClusterSg] failed because [EnvironmentType] is not in [{"Key":"EnvironmentType","Value":"EnvironmentType"},{"Key":"EnvironmentType","Value":{"Ref":"EnvironmentType"}},{"Key":"EnvironmentType","PropagateAtLaunch":true,"Value":"EnvironmentType"},{"Key":"EnvironmentType","PropagateAtLaunch":true,"Value":{"Ref":"EnvironmentType"}}] for [Tags.0.Key]
[ClusterSg] failed because [Name] is not in [{"Key":"EnvironmentType","Value":"EnvironmentType"},{"Key":"EnvironmentType","Value":{"Ref":"EnvironmentType"}},{"Key":"EnvironmentType","PropagateAtLaunch":true,"Value":"EnvironmentType"},{"Key":"EnvironmentType","PropagateAtLaunch":true,"Value":{"Ref":"EnvironmentType"}}] for [Tags.2.Key]
[ClusterSg] failed because [OwnerContact] is not in [{"Key":"EnvironmentType","Value":"EnvironmentType"},{"Key":"EnvironmentType","Value":{"Ref":"EnvironmentType"}},{"Key":"EnvironmentType","PropagateAtLaunch":true,"Value":"EnvironmentType"},{"Key":"EnvironmentType","PropagateAtLaunch":true,"Value":{"Ref":"EnvironmentType"}}] for [Tags.1.Key]
[ClusterSg] failed because [Scope] is not in [{"Key":"EnvironmentType","Value":"EnvironmentType"},{"Key":"EnvironmentType","Value":{"Ref":"EnvironmentType"}},{"Key":"EnvironmentType","PropagateAtLaunch":true,"Value":"EnvironmentType"},{"Key":"EnvironmentType","PropagateAtLaunch":true,"Value":{"Ref":"EnvironmentType"}}] for [Tags.4.Key]
Number of failures: 5
If you added a literal item to the list that would match to "key", eg:
let tag_list = ["EnvironmentType", {"Key":"EnvironmentType","Value":"EnvironmentType"}]
It'll pass because a "Key"'s actual value will match to EnvironmentType
.
from cloudformation-guard.
The ruleset hasn't changed, I still just use .. Tags.* IN %var
- I just had to add the EnvironmentType
as string into the %var array and it fixed itself :)
I assume it wasnt matching the Tags of that resource previously so all in all it got better :D
from cloudformation-guard.
Hi @f0o
were you able to accomplish what you wanted (check for mandatory tags on your resources in addition to other tags it may have) ? If so can you please share the cfn-guard rule snippet please ? I have been struggling to get this working and came across your post.. Will be really helpful if you can please share the working rule.
from cloudformation-guard.
@KarthikVenkatraman have a look at #152 for v1 rulesets - otherwise the ruleset of v0 as posted above in this thread still work fine
from cloudformation-guard.
Related Issues (20)
- CFN Guard validate does not work correctly when entire rule file is comments HOT 2
- [BUG] `empty` `exists` `!= null` don't work as documented HOT 2
- Check on specific Key Value pair[GENERAL ISSUE] HOT 2
- [BUG] install-guard.sh will fail with exit code 0 if GitHub raises a 403 HOT 2
- [GENERAL ISSUE] sam build fails due to certificate problem HOT 5
- [BUG] cfn-guard validate doesn't produce a parseable json/yaml output in 'custom_message' field HOT 2
- [BUG] Incorrect download URL for pre-built binary HOT 2
- [Enhancement] Show full path to file HOT 3
- [Enhancement] Add support for windows
- Add support for SARIF [Enhancement] HOT 2
- [GENERAL ISSUE] Documentation HOT 4
- [BUG] cfn-guard error via GitHub Actions HOT 2
- [Enhancement] Only show errors/failures in output HOT 5
- [BUG] Failed rule does not print details of the failure HOT 6
- [Enhancement] Add cspell action to check for spelling errors
- [Documentation] Update docs for all public facing functions, and structs
- [BUG] SAM CLI deployed lambda returns InvalidEntryPoint error HOT 3
- [Enhancement] Add support to retrieve the key of a given node HOT 1
- [BUG] '!=' does not work as expected even for same type while using 2 literals. HOT 2
- [Enhancement] Make variables mutable HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from cloudformation-guard.