Terraform Snippet Pack
Intro: Terraform security lives in both the HCL and the surrounding workflow. This page focuses on reusable snippet patterns for state, provider pinning, role assumption, module discipline, and plan/apply separation.
What this page includes
- remote state and locking examples
- provider version and dependency lock patterns
- IAM-assume-role provider snippets and CI pipeline usage
- policy checks and review-oriented commands
Working assumptions
- infrastructure code should be reproducible, reviewable, and environment-specific without copy-paste sprawl
1. Remote state in S3 with explicit locking options
terraform {
required_version = ">= 1.8.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.80"
}
}
backend "s3" {
bucket = "org-terraform-state-prod"
key = "product-api/prod/terraform.tfstate"
region = "us-east-1"
encrypt = true
use_lockfile = true
# Older setups may still use DynamoDB locking, but HashiCorp documents it as deprecated.
dynamodb_table = "terraform-locks"
}
}
2. Provider configuration with assume role
provider "aws" {
region = var.aws_region
assume_role {
role_arn = "arn:aws:iam::123456789012:role/terraform-prod-apply"
session_name = "terraform-${terraform.workspace}"
}
default_tags {
tags = {
managed_by = "terraform"
owner = "platform"
repo = "product-api-infra"
}
}
}
3. Commit the dependency lock file
Example .terraform.lock.hcl excerpt:
provider "registry.terraform.io/hashicorp/aws" {
version = "5.80.0"
constraints = "~> 5.80"
hashes = [
"h1:examplehash",
"zh:anotherexamplehash"
]
}
Treat lock file changes like dependency changes in application code: review them and commit them intentionally.
4. Separate plan and apply in GitLab
terraform_plan:
stage: build
image: hashicorp/terraform:1.9
script:
- terraform init -input=false
- terraform validate
- terraform plan -out=tfplan
artifacts:
paths: [tfplan, .terraform.lock.hcl]
terraform_apply:
stage: deploy_staging
image: hashicorp/terraform:1.9
needs: [terraform_plan]
when: manual
script:
- terraform init -input=false
- terraform apply -input=false tfplan
Keep apply on protected refs or protected environments only.
5. Module source pinning
module "vpc" {
source = "git::https://gitlab.example.com/platform/tf-modules.git//aws/vpc?ref=v2.4.1"
name = "product-api-prod"
cidr_block = "10.40.0.0/16"
private_subnets = ["10.40.1.0/24", "10.40.2.0/24"]
}
Pin module versions. Avoid floating branches for production infrastructure.
6. Sensitive outputs and state awareness
output "db_password" {
value = aws_secretsmanager_secret_version.db_password.secret_string
sensitive = true
}
Marking an output as sensitive does not mean the value disappears from state. Protect the backend, the access path, and the pipeline role.
7. Workspace guardrail
#!/usr/bin/env bash
set -euo pipefail
expected_workspace="prod"
current_workspace=$(terraform workspace show)
if [ "$current_workspace" != "$expected_workspace" ]; then
echo "Refusing to apply: expected workspace '$expected_workspace', got '$current_workspace'"
exit 1
fi
8. Static checks in CI
terraform_security_checks:
stage: sast
image: aquasec/tfsec:latest
script:
- tfsec . --format json --out tfsec.json
artifacts:
when: always
paths: [tfsec.json]
And with Checkov:
checkov:
stage: sast
image: bridgecrew/checkov:latest
script:
- checkov -d . -o json > checkov.json
artifacts:
when: always
paths: [checkov.json]
9. Provider mirror and plugin policy idea
provider_installation {
filesystem_mirror {
path = "/terraform-providers"
include = ["registry.terraform.io/hashicorp/*"]
}
direct {
exclude = ["registry.terraform.io/hashicorp/*"]
}
}
Use when you need tighter control over how providers are sourced in regulated or offline-adjacent environments.
10. Review checklist
- remote state is encrypted and access-controlled;
- plan and apply are separated;
- provider versions are constrained;
.terraform.lock.hclis reviewed and committed;- module sources are pinned;
- CI role is narrower than human admin role;
- state access is treated as secret access.
Related pages
- AWS IAM Snippet Pack
- AWS IAM and Role Design
- GitLab Mock Interview Pack
- Terraform Mock Interview Pack
Author attribution: Ivan Piskunov, 2026 - Educational and defensive-engineering use.