AWS with Terraform Tutorial: Terraform Tools (20)
Essential Terraform and OpenTofu tools #
Format, validate, lint, scan, document and estimate the cost of your Terraform and OpenTofu code before it reaches AWS.
Welcome to our tutorial series about Terraform or OpenTofu on AWS. Infrastructure code deserves the same care as application code: it should be formatted consistently, checked automatically and reviewed. The tools in this section find most problems in seconds, before tofu apply creates (and bills) anything. They work the same with Terraform and OpenTofu; the examples use tofu.
Prerequisites #
Read the previous sections of the tutorial, listed in the series index at the end of this page. The examples use the project with modules from Terraform Modules.
The built-in commands #
OpenTofu and Terraform already include the first line of defense.
| Command | What it does |
|---|---|
tofu fmt -recursive |
Rewrites the files with the canonical style. Use -check -diff in CI to fail when a file is not formatted |
tofu validate |
Checks the syntax and the consistency of the configuration (types, references, required arguments). It does not call AWS |
tofu plan |
Shows what would change. Save it with -out=tfplan and read it with tofu show tfplan |
tofu console |
An interactive prompt to try expressions and functions against the real state |
tofu graph |
Prints the dependency graph in DOT format |
tofu state list, tofu state show <address> |
Inspect what is in the state |
$ tofu fmt -recursive -check -diff
$ tofu init -backend=false
$ tofu validate
Success! The configuration is valid.
tofu init -backend=false downloads providers and modules without touching the remote state, which is what a validation job needs.
Try an expression with tofu console:
$ tofu console
> cidrsubnet("172.21.0.0/19", 4, 1)
"172.21.2.0/23"
> module.network.subnet_ids["ditwl-sn-za-pro-pub-00"]
"subnet-09da811e23c212363"
To see the dependencies as an image (needs Graphviz):
$ tofu graph | dot -Tsvg > graph.svg
TFLint: finds mistakes that validate cannot see #
TFLint is a linter. With the AWS ruleset it detects invalid instance types, deprecated arguments, unused variables or missing required versions.
plugin "terraform" {
enabled = true
preset = "recommended"
}
plugin "aws" {
enabled = true
version = "0.40.0" # replace with the latest release of tflint-ruleset-aws
source = "github.com/terraform-linters/tflint-ruleset-aws"
}$ tflint --init
$ tflint --recursive
Security scanners: Trivy and Checkov #
Misconfigurations are the most common cause of cloud incidents: an open security group, a public bucket, an unencrypted volume. Static scanners read the code and report them before deployment.
- Trivy scans Terraform and OpenTofu code (it includes the rules of the former tfsec) and also container images and dependencies.
- Checkov has thousands of policies for AWS, Azure and GCP and supports custom policies.
$ trivy config .
$ checkov -d .
For example, both report the rule that the tutorial broke on purpose in AWS Security Groups: SSH (port 22) open to 0.0.0.0/0. When a finding is accepted, document the exception in the code, for example #trivy:ignore:<rule-id> or #checkov:skip=<id>:reason, so it is visible in the review.
terraform-docs: documentation that does not get old #
terraform-docs generates the inputs, outputs and requirements of a module from the code. Put these markers in the README of the module:
<!-- BEGIN_TF_DOCS -->
<!-- END_TF_DOCS -->
and run:
$ terraform-docs markdown table --output-file README.md --output-mode inject modules/network
The tables between the markers are replaced and the rest of the file is kept.
Infracost: the price before the apply #
Infracost estimates the monthly cost of the infrastructure from the code and, in a pull request, shows how much each change adds or saves.
$ infracost breakdown --path .
$ infracost diff --path . --compare-to infracost-base.json
It would have shown, for example, the difference between two and three NAT Gateways or the cost of the load balancer from AWS Load Balancers.
Pre-commit: run everything before every commit #
The pre-commit framework runs the tools automatically when you commit. The pre-commit-terraform collection has a hook for each tool above. By default it looks for the terraform binary: the --tf-path argument selects OpenTofu.
repos:
- repo: https://github.com/antonbabenko/pre-commit-terraform
rev: v1.99.0 # replace with the latest release
hooks:
- id: terraform_fmt
args: [--hook-config=--tf-path=tofu]
- id: terraform_validate
args: [--hook-config=--tf-path=tofu]
- id: terraform_tflint
- id: terraform_trivy
- id: terraform_docs$ pip install pre-commit
$ pre-commit install
$ pre-commit run --all-files
The same checks run again in the pipeline of the next section, because a local hook can always be skipped.
Other useful tools #
-
Version managers: tenv installs and switches between OpenTofu, Terraform and Terragrunt versions, using the version in the
.opentofu-versionor.terraform-versionfile of the project. -
Import existing resources: an
importblock adopts a resource created by hand into the state, andtofu planshows the result before anything is saved:import { to = aws_s3_bucket.logs id = "ditwl-logs-bucket" } -
State surgery:
tofu state mv,tofu state rmandmoved/removedblocks, to reorganize the code without destroying resources (see Terraform Modules). -
Debugging:
TF_LOG=debug tofu planprints the API calls and the internal decisions. -
Terragrunt: a wrapper to keep configurations DRY when there are many environments and states.
-
Editor support: the OpenTofu and Terraform language servers give completion, hover documentation and diagnostics in VS Code, IntelliJ and Neovim.
A recommended order #
tofu fmtandtofu validate: seconds, always.- TFLint: seconds, catches provider-specific mistakes.
- Trivy or Checkov: seconds to a minute, security.
tofu plan: needs credentials, shows the real change.- Infracost: cost, in the pull request.
Common Questions About Terraform Tools #
Do these tools work with OpenTofu? #
Yes. They read the same HCL language. Where a tool expects the terraform binary, there is an option to use tofu (as in the --tf-path argument above).
Which security scanner should I choose: Trivy or Checkov? #
Either one. Trivy is one tool for code, containers and dependencies; Checkov has more cloud-specific policies and custom rules in Python or YAML. Many teams run one of them and review the report of the other from time to time.
Should the checks fail the build? #
Formatting, validation and linting should. For security findings start with warnings, fix the existing ones and then make new high-severity findings fail the build.
Next Steps #
The code is formatted, checked and documented on every commit. The last section runs these checks, the plan and the apply automatically in a pipeline: Terraform CI/CD.