Terraform Compliance


In my post about resource tagging I wrote about the importance of tags. Of course tags are not the only important (meta-) information that each resource must contain. Also names of resources should have a consistent schema.

I am a lazy person and if I can avoid things I try to. Also, I am forgetful. So there is only one way to guarantee that tagging and naming happens in consistent way: enforcement or governance.

The tool of (my) choice is terraform-compliance.

To enforce that every resource that supports tags has all mandatory tags you can specify a BDD feature like this:

Feature: Tags identify each resource and allow to collate them to specific projects.

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

    Examples:
      | tags        | value                        |
      | namespace   | .+                           |
      | environment | ^(test\|prod)$               |
      | stage       | .+                           |
      | name        | .+                           |

This feature forces the tags namespace, environment, stage and name to be set. For the tag environment only the values test and prod are allowed.

It is easy to set up (docker or pip) and can also be integrated in a CI/CD environment, for example in .gitlab-ci.yml. Here is an excerpt from a pipeline I use:

before_script:
  - alias convert_report="jq -r '([.resource_changes[]?.change.actions?]|flatten)|{\"create\":(map(select(.==\"create\"))|length),\"update\":(map(select(.==\"update\"))|length),\"delete\":(map(select(.==\"delete\"))|length)}'"
  - cd terraform
  - terraform --version
  - terraform init

stages:
  - validate
  - build
  - test
  - deploy

validate:
  stage: validate
  script:
    - pwd
    - terraform validate

plan:
  stage: build
  script:
    - terraform plan -out=$PLAN
    - "terraform show --json $PLAN | convert_report > $JSON_PLAN_FILE"
    - terraform-compliance -f features -p $PLAN

In the build stage a terraform plan is generated. The json output is now verified by terraform-compliance. If any of the features is not met the build will stop at this point and no changes at the infrastructure will be applied.

The terraform-compliance page has a lot more examples where and how to enforce consistent names or even security aspects (for example deny access from /0 for ssh).

Happy enforcing!