Terraform Code Quality
Tags: Terraform, Azure, DevOps, Infrastructure As Code, AWS

Terraform code quality: checking for compliance

So far, we talked about the initial steps, with a very static analysis and we got a bit further with TFLint by asking the API for real IDs, checks for reality, etc…

So if you’re familiar with Terraform after this analysis step, you have the planning phase. The planning phase basically just creates all your code, a diff, and checks against the cloud provider’s API for what you are supposed to create. If you want to create a new S3 bucket , and you don’t have it, then it is going to make a plan to create it. Your next steps will be to review the plan and then to apply it to create that resource.

At this stage, you might want to enforce some compliance with a tool creatively named Terraform compliance.

Quickly making a digression here, if you’re not familiar with the cucumber BDD (behavior-driven development) structure: it implies features name, a scenario and conditions :

Given “blah blah blah” you are expected to have “this result

This is executed in the background by some code, and will then provide you with some results. The BDD system is very useful to code, but in this case, it is used for compliance using natural language.

In our case, if we take the previous example, we could have written something like that and it would have been perfectly supported by Terraform compliance against the plan.

Given I have AWS S3 Bucket defined

Then it must contain server_side_encryption_configuration

Let’s be more specific :

resource "aws_s3_bucket" "example_from_reddit" {

bucket = "my-secret-bucket"

acl = "private"

In this case, we created this bucket but we didn’t create a tag. We might have a process where it is very important that all our resources have tags. So we can write something very easy like this scenario :

Feature: All Resources Scenario: Ensure all resources have tags

Given I have resource that supports tags defined

Then it must contain tags

And its value must not be null

Why is that?

You can create a tag with a variable, and it might work all the way through the previous steps but not just this one, because the variable went wrong. Maybe it was supposed to be a number and it ended up being null?

During the planning phase, there is some computation, and this computation can go wrong. This is why compliance checks are very important now that things are computed and not just statically analyzed.

Integrating those checks and their feedback in your CI/CD system (in a pull request) will give you a much better view of what your code is really doing compliance-wise.

Terraform compliance is a provider agnostic tool, including your own custom providers. There are a lot of ready to use examples and you really can get started in minutes just by using the examples they serve directly on the documentation. It is obviously security-oriented by all the usual suspects, like KMS etc….

This tool also has cool features like allowing you to enforce naming conventions. Probably you want to enforce naming for various items like your country, your continent, resources… and here prefixes can be self-documented and forbidden resources as well.

In the case you need to be PCI DSS compliant, you might just be forbidden to use a list of resources at AWS that are not PCI compliant. This can be done at the compliance level way before asking the IAM user on AWS for your rights to use resources.

You can find Terraform compliance at terraform.compliance.com