Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JSON/YAML discrepancy when parsing functions #27

Closed
f0o opened this issue Jun 25, 2020 · 8 comments
Closed

JSON/YAML discrepancy when parsing functions #27

f0o opened this issue Jun 25, 2020 · 8 comments

Comments

@f0o
Copy link

f0o commented Jun 25, 2020

Hi,

I have a policy to check for specific tags like:

AWS::ElasticLoadBalancingV2::LoadBalancer Tags.0 == {"Key":"EnvironmentType","Value":"EnvironmentType"}
AWS::ElasticLoadBalancingV2::LoadBalancer Tags.1 == {"Key":"OwnerContact","Value":"OwnerContact"}

They work fine on YAMLs in format:

        - Key: EnvironmentType
          Value: !Ref EnvironmentType
        - Key: OwnerContact
          Value: !Ref OwnerContact

However they fail on JSON:

          { "Key" : "EnvironmentType", "Value" : { "Ref" : "EnvironmentType" } },
          { "Key" : "OwnerContact", "Value" : { "Ref" : "OwnerContact" } },

with the error:

"[Sg] failed because [Tags.0] is [{\"Key\":\"EnvironmentType\",\"Value\":{\"Ref\":\"EnvironmentType\"}}] and the permitted value is [{\"Key\":\"EnvironmentType\",\"Value\":\"EnvironmentType\"}]"
"[Sg] failed because [Tags.1] is [{\"Key\":\"OwnerContact\",\"Value\":{\"Ref\":\"OwnerContact\"}}] and the permitted value is [{\"Key\":\"OwnerContact\",\"Value\":\"OwnerContact\"}]"

What would be the proper way of matching both formats?

//Edit

Using IN [{"Key":"OwnerContact","Value":"OwnerContact"},{"Key":"OwnerContact","Value":{"Ref":"OwnerContact"}}] doesnt work either with the error:

"[Alb] failed because [{\"Key\":\"OwnerContact\",\"Value\":\"OwnerContact\"}] is not in [{\"Key\":\"OwnerContact\",\"Value\":\"OwnerContact\"},{\"Key\":\"OwnerContact\",\"Value\":{\"Ref\":\"OwnerContact\"}}] for [Tags.1]"

However I believe this should be working as the matching object is in the list. (I tried with [[{...}],[{...}]] same result)

//Edit2:

== /^\{"Key":"OwnerContact","Value":"OwnerContact"\}$|^\{"Key":"OwnerContact","Value":\{"Ref":"OwnerContact"\}\}$/
This seems to work, but I highly doubt this is how it's intended to work

@nathanataws
Copy link
Contributor

You are correct. The behaviors are different because of the different way CFn intrinsic functions are represented within the two formats. We're working through a number of possible ways to address it.

Check out this part of the README for more info: https://github.com/aws-cloudformation/cloudformation-guard/blob/master/cfn-guard/README.md#working-with-cloudformation-intrinsic-functions

For your second approach, try changing the Tags reference to a wildcard (Tags.*) and the "==" will match if any part of the Tags list passes.

@f0o
Copy link
Author

f0o commented Jun 26, 2020

The wildcard solution is sadly not applicable because it will fail on any additional tags that aren't defined in the ruleset (#23 (comment))

@nathanataws
Copy link
Contributor

nathanataws commented Jun 26, 2020

I added some comments to #23.

[EDIT: Removed my repeat of the intrinsics details above]

That said, I'm not happy about how it works right now. We're kicking around different approaches to come up with a behavior that reconciles the different representations without being lossy or confusing. Hopefully, we'll get an elegant, supportable solution out soon. In the mean time, you need to use the |OR| with a checking for the intrinsic in JSON on one side and YAML on the other.

@nathanataws
Copy link
Contributor

For example:

AWS::EC2::Volume AvailabilityZone == ["EC2Instance","AvailabilityZone"] |OR| AWS::EC2::Volume AvailabilityZone == {"Fn::GetAtt":["EC2Instance","AvailabilityZone"]}

@f0o
Copy link
Author

f0o commented Jun 29, 2020

Yeah I'm using regex match now instead. It's really ugly tho 😅

@nathanataws
Copy link
Contributor

Check out the latest release-0.5.2 branch. I added JSON list literals to make the task of matching against intrinsics in both YAML and JSON templates a bit easier.

For example:

let tag_vals = [{"Key":"OwnerContact","Value":"OwnerContact"},{"Key":"OwnerContact","Value":{"Ref":"OwnerContact"}}]
AWS::EC2::SecurityGroup Tags.* IN %tag_vals

Should now work correctly for both the YAML and JSON versions you're trying to check.

@f0o
Copy link
Author

f0o commented Jul 2, 2020

Works and also 0.5.2 is quite a lot faster too!

Thanks :)

@f0o f0o closed this as completed Jul 2, 2020
@nathanataws
Copy link
Contributor

Awesome! 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants