Conftest in Terraform in Action

Introduction

In today’s rapidly evolving technological landscape, ensuring the security and compliance of infrastructure has become paramount. Open Policy Agent (OPA) is a CNCF-graduated open-source project that utilizes rego policies for enforcement. With its ability to expand to multiple resources and its relatively easy-to-pick-up syntax, OPA has gained significant popularity. In this blog post, we will explore the capabilities of OPA and how it can serve as a guardrail and validation tool for infrastructure as code, preventing misconfigurations and exposed credentials. We will also touch upon Kyverno, a Policy-as-Code solution that leverages the Open Policy Agent library, and Conftest, a versatile tool that assists with various technologies such as Dockerfiles, Terraform, and Kubernetes.

Infrastructure as Code and Policy Enforcement

Organizations are adopting infrastructure as code (IaC) practices, this does increase the use of re-usable code but can also have configurations that can be problematic and deployed quickly without guardrails. If you are using terraform in your pipelines with use of infrastructure as code scanning notably (SAST) its also a good idea to understand guard rails you place on the code. Such as, is network policies enabled that don’t expose ports that aren’t intended? These are areas you can author policies that can deny operations prior to release. In the background I’ve been quietly testing open policy agent on some code repositories I’ve worked with in terraform to test functionality for this demo.

Conftest: Expanding Open Policy Agents Influence

Conftest is a powerful tool a part of the open policy agent ecosystem for terraform and has numerous examples to get up and running if you are following along let’s start with the installation of conftest.

Depending on your architecture this can differ but notably if we are running on linux.

From the docs on Linux and MacOS you can run the following

LATEST_VERSION=$(wget -O - "https://api.github.com/repos/open-policy-agent/conftest/releases/latest" | grep '"tag_name":' | sed -E 's/.*"([^"]+)".*/\1/' | cut -c 2-)
wget "https://github.com/open-policy-agent/conftest/releases/download/v${LATEST_VERSION}/conftest_${LATEST_VERSION}_Linux_x86_64.tar.gz"
tar xzf conftest_${LATEST_VERSION}_Linux_x86_64.tar.gz
sudo mv conftest /usr/local/bin

If all goes well in installation and you type in conftest you’ll be greeted with the options associated with it.

For our demo we are going to use the github repository

git clone https://github.com/sn0rlaxlife/terraform-aks-azure.git
cd terraform-aks-azure

So I’ll have to explain a few files we are primarily going to use aks.rego

Before we jump ahead lets get started with actually getting the tfplan.json file you see listed the way to do this in the configuration if you’d like to overwrite this is the following

terraform init
terraform plan -out=tfplan
terraform show -json ./tfplan > tfplan.json

We can use the tool jq to parse the tfplan.json and assist with crafting our policies this is essentially seeing how the structured json is crafted.

cat tfplan.json | jq .resource_changes

The output is really long so for being brief this will be a screenshot of the targeted area we are interested in.

This will play into what we need for our policies.

So if we run a grep command we can see the format is used such as “network_policy”: “calico”, we are going to check for this and show the results.

Notably the more we parse as you can see we can narrow down exactly what we are searching to create a policy for, navigate to the aks.rego in the root folder.

So this is the primary crux of the denial policy to break this down we are leveraging resource and ‘r’ parameter which stores our json configuration and using similar parsing to find the same area. If finding that the value is listed as calico we are going to result in a denial.

I’ve replicated some of the docs use of the walk function to gather the data and still testing other policies so I’ve commented out the private cluster portion.

Running Conftest

conftest test -o table -p aks.rego tfplan.json

So we can see our plan failed which is the policies we crafted along with the finding having context of where in our code to have the value – Azure as CNI and network policy with the value for Azure. So let’s change value real quick in our json document and show what the output changes to in one value to have a test pass (ideally you’d rerun init as earlier once we change the configuration file for demo purposes I’m changing the .json to demonstrate this)

Summary

Open Policy Agent, with its rego policies and versatile enforcement capabilities, has emerged as a popular choice for organizations seeking to enhance the security and compliance of their infrastructure. Tools that are part of the ecosystem using open policy agent in the background such as Conftest bring you capabilities to leverage. Check out conftest documentation its pretty thorough and covers other use cases such as docker files which I’ll demonstrate in a separate post.

References

Open Policy Agent – https://www.openpolicyagent.org/

Conftest – https://www.conftest.dev/

Github Repo – https://github.com/sn0rlaxlife/terraform-aks-azure