Hamburger Cross Icon
Terraform Guardrails - Lunar Policy for Deployment And Infrastructure

Terraform Guardrails

Enforce Terraform-specific best practices including provider version pinning, minimum provider versions, module version pinning, and remote backend configuration.

Add terraform to your lunar-config.yml:
uses: github://earthly/lunar-lib/policies/terraform@v1.0.0

Included Guardrails

This policy includes 4 guardrails that enforce standards for your deployment and infrastructure.

Guardrail

provider-versions-pinned

Requires Terraform providers to specify version constraints in required_providers. Unpinned providers can introduce breaking changes unexpectedly.

terraform providers version pinning reproducibility required_providers
View Guardrail
Guardrail

module-versions-pinned

Requires Terraform modules to use pinned versions or commit SHAs. Unpinned modules make infrastructure deployments non-reproducible.

terraform modules version pinning reproducibility
View Guardrail
Guardrail

remote-backend

Requires Terraform to use a remote backend for state management. Local state files are fragile and cannot be shared across teams.

terraform backend state management s3 gcs terraform cloud
View Guardrail
Guardrail

min-provider-versions

Enforces minimum version requirements for Terraform providers. Ensures providers meet security and compatibility baselines.

terraform providers minimum version security semver
View Guardrail

How Guardrails Fit into Lunar

Lunar guardrails define your engineering standards as code. They evaluate data collected by integrations and produce pass/fail checks with actionable feedback.

Policies support gradual enforcement—from silent scoring to blocking PRs or deployments—letting you roll out standards at your own pace without disrupting existing workflows.

Learn How Lunar Works
1
Integrations Gather Data
Collectors extract metadata from code, CI pipelines, tool outputs, and scans
2
{ } Centralized as JSON
All data merged into each component's unified metadata document
3
Guardrails Enforce Standards This Policy
Real-time feedback in PRs and AI workflows

Required Integrations

This policy evaluates data gathered by one or more of the following integration(s). Make sure to enable them in your lunar-config.yml.

Configuration

Configure this policy in your lunar-config.yml.

Inputs

Input Required Default Description
required_backend_types Required Comma-separated list of approved backend types (empty = any remote backend)
min_provider_versions Optional {} JSON object mapping provider names to minimum versions (e.g., {"aws": "5.0", "random": "3.0"})

Documentation

View on GitHub

Terraform Guardrails

Enforces Terraform-specific configuration best practices.

Overview

This policy enforces Terraform-specific standards that don't transfer to other IaC frameworks: provider version pinning, module version pinning, and remote backend usage. It reads from .iac.native.terraform.files[] and analyzes the parsed HCL to extract required_providers, module, and backend blocks. For generic IaC checks (validity, WAF, datastores), see the iac policy.

Policies

This policy provides the following guardrails (use include to select a subset):

Policy Description Failure Meaning
provider-versions-pinned Providers specify version constraints Provider in required_providers has no version field
module-versions-pinned Modules use pinned versions Module missing version or ?ref= in source
remote-backend Remote backend configured No terraform { backend {} } block found
min-provider-versions Providers meet minimum version requirements Provider version constraint below required minimum

Required Data

This policy reads from the following Component JSON paths:

Path Type Provided By
.iac.native.terraform.files[] array terraform collector

Note: Ensure the terraform collector is configured before enabling this policy.

Installation

Add to your lunar-config.yml:

collectors:
  - uses: github://earthly/lunar-lib/collectors/terraform@main
    on: [infra]

policies:
  - uses: github://earthly/lunar-lib/policies/terraform@main
    on: [infra]
    enforcement: report-pr
    # include: [provider-versions-pinned, remote-backend]  # Only run specific checks
    # with:
    #   required_backend_types: "s3,gcs,remote"  # Restrict allowed backend types
    #   min_provider_versions: '{"aws": "5.0", "random": "3.0"}'  # Enforce minimum versions

Examples

Passing Example

A component with pinned providers, versioned modules, and a remote backend:

{
  "iac": {
    "native": {
      "terraform": {
        "files": [
          {
            "path": "main.tf",
            "hcl": {
              "terraform": [
                {
                  "required_providers": [
                    {
                      "aws": {"source": "hashicorp/aws", "version": "~> 5.0"},
                      "random": {"source": "hashicorp/random", "version": ">= 3.0"}
                    }
                  ],
                  "backend": [
                    {"s3": {"bucket": "my-state", "key": "state.tfstate"}}
                  ]
                }
              ],
              "module": {
                "vpc": [{"source": "terraform-aws-modules/vpc/aws", "version": "5.1.0"}]
              }
            }
          }
        ]
      }
    }
  }
}

Failing Example

A component with unpinned providers, unversioned modules, and no backend:

{
  "iac": {
    "native": {
      "terraform": {
        "files": [
          {
            "path": "main.tf",
            "hcl": {
              "terraform": [
                {
                  "required_providers": [
                    {
                      "aws": {"source": "hashicorp/aws"},
                      "random": {"source": "hashicorp/random"}
                    }
                  ]
                }
              ],
              "module": {
                "vpc": [{"source": "terraform-aws-modules/vpc/aws"}],
                "rds": [{"source": "git::https://github.com/org/tf-module.git"}]
              }
            }
          }
        ]
      }
    }
  }
}

Failure messages:

  • Providers without version constraints: aws, random. Add version constraints in required_providers to ensure reproducible deployments.
  • Modules without pinned versions: vpc, rds. Add version constraints or use ?ref= to pin module sources.
  • No backend configured. Terraform state is stored locally, which is fragile and cannot be shared across teams.

Remediation

When this policy fails, resolve it by:

  1. For provider-versions-pinned failures: Add version constraints to each provider in required_providers:
    terraform {
      required_providers {
        aws = {
          source  = "hashicorp/aws"
          version = "~> 5.0"
        }
      }
    }
    
  2. For module-versions-pinned failures: Add version to registry modules or ?ref= to git sources:
    module "vpc" {
      source  = "terraform-aws-modules/vpc/aws"
      version = "5.1.0"
    }
    
  3. For remote-backend failures: Configure a remote backend for shared state:
    terraform {
      backend "s3" {
        bucket = "my-terraform-state"
        key    = "state.tfstate"
        region = "us-east-1"
      }
    }
    

Open Source

This policy is open source and available on GitHub. Contribute improvements, report issues, or fork it for your own use.

View Repository

Ready to Automate Your Standards?

See how Lunar can turn your engineering wiki, compliance docs, or postmortem action items into automated guardrails with our 100+ built-in guardrails.

Works with any process
check Infrastructure conventions
check Post-mortem action items
check Security & compliance policies
check Testing & quality requirements
Automate Now
Turn any process doc into guardrails
Book a Demo