# 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

```hcl
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

```hcl
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:

```hcl
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

```yaml
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

```hcl
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

```hcl
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

```bash
#!/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

```yaml
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:

```yaml
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

```hcl
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.hcl` is 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](/cloud-kubernetes-and-infrastructure-security/index/aws-iam-snippet-pack.md)
* [AWS IAM and Role Design](/cloud-kubernetes-and-infrastructure-security/index/aws-iam-and-role-design.md)
* [GitLab Mock Interview Pack](/learning-labs-interview-and-templates/index-1/gitlab-mock-interview.md)
* [Terraform Mock Interview Pack](/learning-labs-interview-and-templates/index-1/terraform-mock-interview.md)

***

*Author attribution: Ivan Piskunov, 2026 - Educational and defensive-engineering use.*


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.product-security.expert/cloud-kubernetes-and-infrastructure-security/index/terraform-snippet-pack.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
