b997bd63b1
---ci--- project: atelier phase: 1 milestone: v0.2 status: complete requirements: covered: [ATELIER-36, ATELIER-37, ATELIER-38, ATELIER-39, ATELIER-40] partial: [] ---/ci---
3.6 KiB
3.6 KiB
Terraform — Derived Rules
Derives from
domains/infrastructure-as-code/first-principles.md. Applies P1–P10 to Terraform specifically. See alsoopentofu.md(the open-source fork),state.md, andmodules.md.
HCL Structure (P1 Declarative Intent)
- Resources are declared, not scripted. A resource block states what should exist; Terraform reconciles it.
resource "aws_s3_bucket" "logs" { ... }— the type and name are the identity; the body is the desired state.- Data sources read existing state without claiming ownership:
data "aws_caller_identity" "current" {}. - Variables are the input contract; outputs are the interface to consumers. Both are typed.
Providers (P5 Version Everything, P7 Least Privilege)
- Pin the provider version:
required_providers { aws = { source = "hashicorp/aws", version = "~> 5.0" } }. - A provider block configures credentials and region. Credentials come from environment, files, or a secrets manager — never inline.
- One credential set per environment. Do not reuse a prod credential in a dev workspace.
The Core Workflow (P4 Plan Before Apply)
terraform init— resolve providers and modules. Reproducible from the lock file (.terraform.lock.hcl), which is committed.terraform plan— preview the diff. Read it. Every line. The plan is the contract review.terraform apply— execute the plan. Requires a reviewed plan in CI; in interactive use, requires typingyes.terraform destroy— tear down. Treatdestroyas a first-class operation with its own plan review; prod destroys are a change event, not a keystroke.
Workspaces (P4 Locality of Environments)
- Workspaces separate state for the same configuration across environments (dev, staging, prod).
- Do not use workspaces to separate unrelated stacks — use separate configurations. A workspace is an environment axis, not a project axis.
- State is isolated per workspace (see
state.md).
State Backends (P3 State is Truth, P8 Remote State with Locking)
- Remote state is mandatory for any shared or production environment. See
state.mdfor backend selection and locking. - Never commit
terraform.tfstateto the repo. It is a secret-bearing artifact and a source of drift. terraform statesubcommands inspect and manipulate state directly — use sparingly, only for recovery.
Registry and Modules (P6 Modules Compose)
- The Terraform Registry hosts versioned, signed modules. Reference modules by version:
source = "terraform-aws-modules/vpc/aws",version = "5.x". - Compose modules rather than copy-pasting blocks. A module is reviewed once and reused many times.
- See
modules.mdfor module structure, versioning, and the module-vs-copy boundary.
Secrets (P10 Secrets Never in Code)
- Secrets via provider data sources (
aws_secretsmanager_secret_version), environment variables, or a dedicated secrets provider. Never a literal string in a resource block. - State may contain plaintext secrets if a resource attribute is sensitive. Mark attributes
sensitive = trueto keep them out of plan output; use a backend that encrypts state at rest (seestate.md).
What Violates Terraform Discipline
| Violation | Principle |
|---|---|
Unpinned provider (source without version) |
P5 Version Everything |
terraform apply without a read plan |
P4 Plan Before Apply |
| Local state in a shared environment | P8 Remote State with Locking |
| Hardcoded secret in HCL | P10 Secrets Never in Code |
| Copy-pasted resource blocks instead of a module | P6 Modules Compose |
| Manual change to a managed resource | P9 Drift is Recoverable |
| Admin credentials in CI | P7 Least Privilege Providers |