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

Require a specific tag if another specific tag is present #243

Closed
M1ke opened this issue Mar 30, 2020 · 16 comments
Closed

Require a specific tag if another specific tag is present #243

M1ke opened this issue Mar 30, 2020 · 16 comments
Labels
question waiting for confirmation Workaround/Fix applied, waiting for confirmation

Comments

@M1ke
Copy link
Contributor

M1ke commented Mar 30, 2020

This is a general usage question

I am using this tool to enforce tag compliance for Cost Explorer. We have a rule where every resource must contain an environment tag, which is easy to apply.

We have a secondary role which is that for the "live" environment every resource must also have a non-empty tag called "service". I am finding that hard to express in the BDD syntax provided.

I have attempted

Scenario Outline: Ensure that service tags are added to live resources
  Given I have resource that supports tags defined
  When its tags includes "environment"
  And its value is "live"
  Then it must contain <tags>
  And its value must match the "<value>" regex

  Examples:
    | tags        | value              |
    | service | .+ |

However this reports that:

Can not find live value in

And then a list of every resource. So I presume the pivot from the environment tag being present to work out what it contains doesn't work. Is this mechanism supported, and if not is there a path for me to go about adding it?

@eerkunt
Copy link
Member

eerkunt commented Mar 30, 2020

Hi @M1ke,

For the Scenario you posted above, don't forget that is will SKIP the test if environment tag is not found or the value of the tag is not live. If you have another Scenario checking this already, then no problem.

I think you can do what you want like this ;

For HCL something like below ;

resource "aws_s3_bucket" "success" {
  bucket = "succeeded-bucket"

  tags = {
    environment = "live"
    service = "some service"
  }
}

resource "aws_s3_bucket" "skip" {
  bucket = "skipped-bucket"

  tags = {
    something = "something else"
  }
}

resource "aws_s3_bucket" "another_skip" {
  bucket = "skipped-bucket-2"

  tags = {
    environment = "dead"
    something = "something else"
  }
}

resource "aws_s3_bucket" "failure" {
  bucket = "failed-bucket"

  tags = {
    environment = "live"
    some_other_tag = "something"
  }
}

resource "aws_s3_bucket" "aonther_failure" {
  bucket = "failed-bucket"

  tags = {
    environment = "live"
    service = ""
  }
}

The scenario can be ;

Feature: test

  Scenario: Ensure we have service tag for live environments
    Given I have resource that supports tags defined
    When it contains tags
    And its environment is live
    Then it must contain service
    And its value must not be null

Of course you can convert this to Scenario Outline and use a parameter instead of service

@eerkunt
Copy link
Member

eerkunt commented Mar 30, 2020

The result that I have is ;

    Scenario: Ensure we have service tag for live environments
        Given I have resource that supports tags defined
        When it contains tags
        And its environment is live
		Failure: aws_s3_bucket.aonther_failure (resource that supports tags) does not have service property.
		Failure: aws_s3_bucket.failure (resource that supports tags) does not have service property.
        Then it must contain service
       
        And its value must not be null

@eerkunt eerkunt added question waiting for confirmation Workaround/Fix applied, waiting for confirmation labels Mar 30, 2020
@M1ke
Copy link
Contributor Author

M1ke commented Mar 30, 2020

That sounds sensible; unfortunately upon trying it I actually get:

        Given I have resource that supports tags defined
        When it contains tags
        And its environment is live
          AttributeError: 'NoneType' object has no attribute 'get'

My guess here would be that it looks for a parameter called "environment" (rather than tag of that key) which it doesn't find, yet your implementation seems to work.

@eerkunt
Copy link
Member

eerkunt commented Mar 30, 2020

Can you have a try with 1.1.13 please ? Just released :) I must have tested with that.

@M1ke
Copy link
Contributor Author

M1ke commented Mar 30, 2020

Have updated and I get the same AttributeError

@eerkunt
Copy link
Member

eerkunt commented Mar 30, 2020

Oh ? Now this is interesting.

May I know your terraform and python version please ?

@M1ke
Copy link
Contributor Author

M1ke commented Mar 30, 2020

> terraform -v
Terraform v0.12.24
> python3 --version
Python 3.5.2

Although interestingly

> cat $(which terraform-compliance)             
#!/usr/bin/python3.6

It was installed with pip3 install --user terraform-compliance

@eerkunt
Copy link
Member

eerkunt commented Mar 30, 2020

Very interesting. Tried with 1.1.12. 1.1.13 and 1.1.14 couldn't reproduce your problem. Same terraform version.

Quite weird really. Did you try the docker image ?

@M1ke
Copy link
Contributor Author

M1ke commented Mar 30, 2020

May you send me the plan.out that you're using? I am running this on my state so I wonder if there's some resource in my actual state that's behaving differently to the S3 resources you're using to demo?

(Jumping off for today but will check this tomorrow to help work it out if I can)

@eerkunt
Copy link
Member

eerkunt commented Mar 30, 2020

Sure,

plan.out.json.txt

Now I am more curious about your state and really want to fix the problem :)

@M1ke
Copy link
Contributor Author

M1ke commented Mar 31, 2020

@eerkunt found the issue.

It's the same issue that causes this problem. I have another statement:

    Scenario Outline: Ensure that specific tags are defined
        Given I have resource that supports tags defined
        When it contains tags
        Then it must contain <tags>
        And its value must match the "<value>" regex

It fails on all my aws_autoscaling_group resources. Why? Because their tags are not declared like:

tags {
  Key = "value"
}

But instead as:

tag {
  key = "Key"
  value = "Value"
  propagate_at_launch = true
}
// repeat for more tags

If I remove the ASGs from my state then your feature definition works to identify other issues. So I presume the quick fix is to catch that AttributeError and skip the resource. Then the proper fix is for aws_autoscaling_group to either be handled differently, or more helpfully maybe exclude them from resource that supports tags and write a custom interpreter for them.

@M1ke
Copy link
Contributor Author

M1ke commented Mar 31, 2020

(a quick fix my side would be if the WHEN could filter our specific resource types but I am unsure if it can)

@eerkunt
Copy link
Member

eerkunt commented Mar 31, 2020

Aha! Great find @M1ke! 🎉

I will introduce a fix for this for a permanent solution, though first I need to have a dig deeper a bit on this. AttributeError is something that it shouldn't threw.

Anyway, focusing on your quickfix, yes we can filter out specific resource types. E.g. ;

Scenario: Ensure we have service tag for live environments
        Given I have resource that supports tags defined
        When its type is not aws_autoscaling_group
        And it contains tags
        And its environment is live
		Failure: aws_s3_bucket.aonther_failure (resource that supports tags) does not have service property.
		Failure: aws_s3_bucket.failure (resource that supports tags) does not have service property.
        Then it must contain service
        And its value must not be null

Let me know if this works for you, while I will debug the problem. :)

@M1ke
Copy link
Contributor Author

M1ke commented Mar 31, 2020

This works for my use case; highlighting the type filter is also useful for my other rule to work correctly. I was not aware of that from the docs, so as you have seen I've opened a PR to update the docs to reference this: #246

@eerkunt
Copy link
Member

eerkunt commented Mar 31, 2020

Just released 1.1.15, should be in PyPi in few minutes. Could you please have a try with Auto-Scaling Groups also. Now it supports it.

@eerkunt eerkunt closed this as completed May 9, 2020
@ghost
Copy link

ghost commented May 9, 2020

This issue's conversation is now locked. If you want to continue this discussion please open a new issue.

@ghost ghost locked and limited conversation to collaborators May 9, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
question waiting for confirmation Workaround/Fix applied, waiting for confirmation
Projects
None yet
Development

No branches or pull requests

2 participants