Working with postcondition checks in Terraform

Updated: February 3, 2024 By: Guest Contributor Post a comment

Overview

Terraform is a powerful tool for building, changing, and versioning infrastructure safely and efficiently. However, even with careful planning and execution, infrastructure deployments can sometimes result in configurations that don’t align with expectations or policy requirements. This is where postcondition checks come into play, offering a method to ensure that your Terraform-managed resources comply with predefined conditions after deployment.

In this tutorial, we’ll explore how to implement and leverage postcondition checks in Terraform. We’ll start with basic concepts and gradually move to more advanced techniques, providing code examples and outputs along the way.

What are Postcondition Checks?

Postcondition checks are assertions made after a Terraform apply operation, ensuring that the state of the infrastructure matches certain criteria. These checks can be used to verify compliance with security policies, operational best practices, or cost controls, among other things.

Implementing Basic Postcondition Checks

Let’s begin with a simple postcondition check. Imagine you have deployed an AWS S3 bucket using Terraform and you want to verify that it’s been encrypted.

resource "aws_s3_bucket" "example" {
  bucket = "my-tf-test-bucket"
  server_side_encryption_configuration {
    rule {
      apply_server_side_encryption_by_default {
        sse_algorithm = "AES256"
      }
    }
  }
}

Now for the postcondition check, we could use the Terraform `external` data source to call a script that checks the encryption status of the bucket:

data "external" "check_encryption" {
  program = ["python", "./check_encryption.py", "my-tf-test-bucket"]
}

The `check_encryption.py` script would use the AWS SDK to verify the encryption status and output the result in a format Terraform can understand.

Intermediate Postcondition Checks

As a next step, let’s consider a scenario where you need to verify that a deployed instance is not exposed to the public internet. For instance, you may want to ensure that no security groups allow traffic from 0.0.0.0/0 to sensitive ports.

resource "aws_security_group" "example" {
  // Configuration omitted for brevity
}

data "external" "check_security_group" {
  program = ["python", "./check_security_group.py", "${aws_security_group.example.id}"]
}

The `check_security_group.py` script would inspect the security group rules and output whether the instance is exposed or not.

Advanced Postcondition Checks

For more complex environments, you may want to implement checks that span multiple resources or even cross-cloud checks. In such cases, a comprehensive audit script or tool can be invoked to assess the environment against a broader set of criteria.

Terraform Compliance Frameworks

Apart from scripting postcondition checks, it’s worthwhile to consider frameworks designed for carrying out compliance checks against Terraform plans, states, or live environments. Tools like “tfsec” and “checkov” scan your Terraform code for common security and compliance issues, offering an added layer of validation.

Conclusion

Implementing postcondition checks in Terraform goes a long way towards ensuring that your infrastructure not only deploys successfully but also adheres to essential compliance and security standards. While the early examples showcased basic checks, evolving your practice to include comprehensive reviews either through scripting or leveraging existing frameworks will further bolster your infrastructure’s integrity and resilience.