Skip to content

Policy Testing

Terrateam Configuration Terrateam behavior can be configured via a config.yml. This file is located in a directory named .terrateam at the root of your Terraform repository: .terrateam/config.yml.

See Configuration documentation for details.

Policy testing against Plan operations with OPA and Conftest can be configured with a custom Workflow.

Conftest

When a Plan operation runs, the exit status of conftest against the generated Terraform plan file can be used to determine the success or failure of the entire operation. This grants users the ability to enforce custom policies against any Terraform-related change in a pull request.

In the screenshots below, the terraform plan step succeeds but the conftest step fails causing the entire Terrateam Plan operation to fail.

Steps

Conftest Plan Failure

Plan

Conftest Plan Failure

Configuration

The Terrateam configuration file can be configured to execute conftest with a custom workflow. Tags and Tag Queries can be used to target specific Dirspaces.

.terrateam/config.yml

workflows:
- tag_query: ""
plan:
- type: init
- type: plan
- type: run
cmd: ['conftest-wrapper']
capture_output: true

Directory structure

If a pull request contains a change for the file foo/bar/main.tf in the root of your repository, then conftest will look for rego policy files in the foo/bar/policy/ directory.

Terminal window
josh@ringo:~/terraform$ tree foo
foo
└── bar
├── main.tf
└── policy
└── main.rego
2 directories, 2 files
josh@ringo:~/terraform$

Rego policy

Conftest policies are written using the Rego query language.

Example main.rego policy denying any resources created using the null_resource provider:

Terminal window
package main
resource_types = {"null_resource"}
resources[resource_type] = all {
some resource_type
resource_types[resource_type]
all := [name |
name:= input.resource_changes[_]
name.type == resource_type
]
}
num_creates[resource_type] = num {
some resource_type
resource_types[resource_type]
all := resources[resource_type]
creates := [res | res:= all[_]; res.change.actions[_] == "create"]
num := count(creates)
}
deny[msg] {
num_resources := num_creates["null_resource"]
num_resources > 0
msg := "Resource 'null_resource' detected in Terraform plan file. Denied."
}

Policy directory

By default, conftest will look for policies in the policy directory where Terrateam is operating against.

Example with custom options

All available conftest configuration options can be passed using environment variables.

For example, to specify a different policy directory, the CONFTEST_POLICY environment variable can be set using a custom Terrateam workflow.

.terrateam/config.yml

workflows:
- tag_query: "dir:aws/us-east-1/production/iam"
plan:
- type: init
- type: plan
- type: env
name: CONFTEST_POLICY
cmd: ["echo", "$TERRATEAM_ROOT/aws/policies/iam/"]
- type: run
cmd: ['conftest-wrapper']
capture_output: true

The above configuration would instruct conftest to look for rego policy files in the aws/policies/iam directory when creating a Terraform pull request against the aws/us-east-1/production/iam directory.

aws/us-east-1/production/iam/main.tf

Terminal window
josh@elmer:~/terraform $ cat aws/us-east-1/production/iam/main.tf
resource "null_resource" "foo" {
provisioner "local-exec" {
command = "echo foo"
}
}
josh@elmer:~/terraform $

aws/policies/iam/main.rego

Terminal window
josh@elmer:~/terraform $ cat aws/policies/iam/main.rego
package main
resource_types = {"null_resource"}
resources[resource_type] = all {
some resource_type
resource_types[resource_type]
all := [name |
name:= input.resource_changes[_]
name.type == resource_type
]
}
num_creates[resource_type] = num {
some resource_type
resource_types[resource_type]
all := resources[resource_type]
creates := [res | res:= all[_]; res.change.actions[_] == "create"]
num := count(creates)
}
deny[msg] {
num_resources := num_creates["null_resource"]
num_resources > 0
msg := "Resource 'null_resource' detected in Terraform plan file. Denied."
}
josh@elmer:~/terraform $

If a user were to initiate a pull request against the aws/us-east-1/production/iam/main.tf file then the Terrateam Plan operation would execute conftest using the main.rego policy file in the aws/policies/iam directory. The entire Plan operation would fail because the main.rego policy file does not allow the creation of a null_resource.

We use cookies and similar technologies to provide certain features, enhance the user experience and deliver content that is relevant to your interests. Depending on their purpose, analysis and marketing cookies may be used in addition to technically necessary cookies. By clicking on "Agree and continue", you declare your consent to the use of the aforementioned cookies. Here you can make detailed settings or revoke your consent (in part if necessary) with effect for the future. For further information, please refer to our Privacy Policy .