Sign inSign up

saagie/pre-commit-terraform

By saagie

•Updated 12 months ago

Image
0

2.8K

saagie/pre-commit-terraform repository overview

⁠Collection of git hooks for Terraform to be used with pre-commit framework⁠

Latest Github tag Maintenance status GHA Tests CI/CD Badge Codecov pytest Badge OpenSSF Scorecard Badge OpenSSF Best Practices Badge Codetriage - Help Contribute to Open Source Badge

StandWithUkraine Banner

pre-commit-terraform logo

pre-commit-terraform⁠ provides a collection of Git Hooks⁠ for Terraform and related tools and is driven by the pre-commit framework⁠. It helps ensure that Terraform, OpenTofu, and Terragrunt configurations are kept in good shape by automatically running various checks and formatting code before committing changes to version control system. This helps maintain code quality and consistency across the project.

It can be run:

  • Locally and in CI
  • As standalone Git hooks or as a Docker image
  • For the entire repository or just for change-related files (e.g., local git stash, last commit, or all changes in a Pull Request)

Want to contribute? Check open issues⁠ and contributing notes⁠.

⁠Sponsors

If you want to support the development of pre-commit-terraform and many other open-source projects⁠, please become a GitHub Sponsor⁠!

⁠Table of content

⁠How to install

⁠1. Install dependencies
Docker

Pull docker image with all hooks:

TAG=latest
docker pull ghcr.io/antonbabenko/pre-commit-terraform:$TAG

All available tags here⁠.

Check About Docker image security⁠ section to learn more about possible security issues and why you probably want to build and maintain your own image.

Build from scratch:

IMPORTANT
To build image you need to have docker buildx⁠ enabled as default builder.
Otherwise - provide TARGETOS and TARGETARCH as additional --build-arg's to docker build.

When hooks-related --build-args are not specified, only the latest version of pre-commit and terraform will be installed.

git clone [email protected]:antonbabenko/pre-commit-terraform.git
cd pre-commit-terraform
# Install the latest versions of all the tools
docker build -t pre-commit-terraform --build-arg INSTALL_ALL=true .

To install a specific version of individual tools, define it using --build-arg arguments or set it to latest:

docker build -t pre-commit-terraform \
    --build-arg PRE_COMMIT_VERSION=latest \
    --build-arg OPENTOFU_VERSION=latest \
    --build-arg TERRAFORM_VERSION=1.5.7 \
    --build-arg CHECKOV_VERSION=2.0.405 \
    --build-arg HCLEDIT_VERSION=latest \
    --build-arg INFRACOST_VERSION=latest \
    --build-arg TERRAFORM_DOCS_VERSION=0.15.0 \
    --build-arg TERRAGRUNT_VERSION=latest \
    --build-arg TERRASCAN_VERSION=1.10.0 \
    --build-arg TFLINT_VERSION=0.31.0 \
    --build-arg TFSEC_VERSION=latest \
    --build-arg TFUPDATE_VERSION=latest \
    --build-arg TRIVY_VERSION=latest \
    .

Set -e PRE_COMMIT_COLOR=never to disable the color output in pre-commit.

MacOS
brew install pre-commit terraform-docs tflint tfsec trivy checkov terrascan infracost tfupdate minamijoyo/hcledit/hcledit jq
Ubuntu 18.04
sudo apt update
sudo apt install -y unzip software-properties-common
sudo add-apt-repository ppa:deadsnakes/ppa
sudo apt install -y python3.7 python3-pip
python3 -m pip install --upgrade pip
pip3 install --no-cache-dir pre-commit
python3.7 -m pip install -U checkov
curl -L "$(curl -s https://api.github.com/repos/terraform-docs/terraform-docs/releases/latest | grep -o -E -m 1 "https://.+?-linux-amd64.tar.gz")" > terraform-docs.tgz && tar -xzf terraform-docs.tgz && rm terraform-docs.tgz && chmod +x terraform-docs && sudo mv terraform-docs /usr/bin/
curl -L "$(curl -s https://api.github.com/repos/terraform-linters/tflint/releases/latest | grep -o -E -m 1 "https://.+?_linux_amd64.zip")" > tflint.zip && unzip tflint.zip && rm tflint.zip && sudo mv tflint /usr/bin/
curl -L "$(curl -s https://api.github.com/repos/aquasecurity/tfsec/releases/latest | grep -o -E -m 1 "https://.+?tfsec-linux-amd64")" > tfsec && chmod +x tfsec && sudo mv tfsec /usr/bin/
curl -L "$(curl -s https://api.github.com/repos/aquasecurity/trivy/releases/latest | grep -o -E -i -m 1 "https://.+?/trivy_.+?_Linux-64bit.tar.gz")" > trivy.tar.gz && tar -xzf trivy.tar.gz trivy && rm trivy.tar.gz && sudo mv trivy /usr/bin
curl -L "$(curl -s https://api.github.com/repos/tenable/terrascan/releases/latest | grep -o -E -m 1 "https://.+?_Linux_x86_64.tar.gz")" > terrascan.tar.gz && tar -xzf terrascan.tar.gz terrascan && rm terrascan.tar.gz && sudo mv terrascan /usr/bin/ && terrascan init
sudo apt install -y jq && \
curl -L "$(curl -s https://api.github.com/repos/infracost/infracost/releases/latest | grep -o -E -m 1 "https://.+?-linux-amd64.tar.gz")" > infracost.tgz && tar -xzf infracost.tgz && rm infracost.tgz && sudo mv infracost-linux-amd64 /usr/bin/infracost && infracost auth login
curl -L "$(curl -s https://api.github.com/repos/minamijoyo/tfupdate/releases/latest | grep -o -E -m 1 "https://.+?_linux_amd64.tar.gz")" > tfupdate.tar.gz && tar -xzf tfupdate.tar.gz tfupdate && rm tfupdate.tar.gz && sudo mv tfupdate /usr/bin/
curl -L "$(curl -s https://api.github.com/repos/minamijoyo/hcledit/releases/latest | grep -o -E -m 1 "https://.+?_linux_amd64.tar.gz")" > hcledit.tar.gz && tar -xzf hcledit.tar.gz hcledit && rm hcledit.tar.gz && sudo mv hcledit /usr/bin/
Ubuntu 20.04+
sudo apt update
sudo apt install -y unzip software-properties-common python3 python3-pip python-is-python3
python3 -m pip install --upgrade pip
pip3 install --no-cache-dir pre-commit
pip3 install --no-cache-dir checkov
curl -L "$(curl -s https://api.github.com/repos/terraform-docs/terraform-docs/releases/latest | grep -o -E -m 1 "https://.+?-linux-amd64.tar.gz")" > terraform-docs.tgz && tar -xzf terraform-docs.tgz terraform-docs && rm terraform-docs.tgz && chmod +x terraform-docs && sudo mv terraform-docs /usr/bin/
curl -L "$(curl -s https://api.github.com/repos/tenable/terrascan/releases/latest | grep -o -E -m 1 "https://.+?_Linux_x86_64.tar.gz")" > terrascan.tar.gz && tar -xzf terrascan.tar.gz terrascan && rm terrascan.tar.gz && sudo mv terrascan /usr/bin/ && terrascan init
curl -L "$(curl -s https://api.github.com/repos/terraform-linters/tflint/releases/latest | grep -o -E -m 1 "https://.+?_linux_amd64.zip")" > tflint.zip && unzip tflint.zip && rm tflint.zip && sudo mv tflint /usr/bin/
curl -L "$(curl -s https://api.github.com/repos/aquasecurity/tfsec/releases/latest | grep -o -E -m 1 "https://.+?tfsec-linux-amd64")" > tfsec && chmod +x tfsec && sudo mv tfsec /usr/bin/
curl -L "$(curl -s https://api.github.com/repos/aquasecurity/trivy/releases/latest | grep -o -E -i -m 1 "https://.+?/trivy_.+?_Linux-64bit.tar.gz")" > trivy.tar.gz && tar -xzf trivy.tar.gz trivy && rm trivy.tar.gz && sudo mv trivy /usr/bin
sudo apt install -y jq && \
curl -L "$(curl -s https://api.github.com/repos/infracost/infracost/releases/latest | grep -o -E -m 1 "https://.+?-linux-amd64.tar.gz")" > infracost.tgz && tar -xzf infracost.tgz && rm infracost.tgz && sudo mv infracost-linux-amd64 /usr/bin/infracost && infracost auth login
curl -L "$(curl -s https://api.github.com/repos/minamijoyo/tfupdate/releases/latest | grep -o -E -m 1 "https://.+?_linux_amd64.tar.gz")" > tfupdate.tar.gz && tar -xzf tfupdate.tar.gz tfupdate && rm tfupdate.tar.gz && sudo mv tfupdate /usr/bin/
curl -L "$(curl -s https://api.github.com/repos/minamijoyo/hcledit/releases/latest | grep -o -E -m 1 "https://.+?_linux_amd64.tar.gz")" > hcledit.tar.gz && tar -xzf hcledit.tar.gz hcledit && rm hcledit.tar.gz && sudo mv hcledit /usr/bin/
Windows 10/11

We highly recommend using WSL/WSL2⁠ with Ubuntu and following the Ubuntu installation guide. Or use Docker.

IMPORTANT
We won't be able to help with issues that can't be reproduced in Linux/Mac.
So, try to find a working solution and send PR before open an issue.

Otherwise, you can follow this gist⁠:

  1. Install git⁠ and gitbash⁠
  2. Install Python 3⁠
  3. Install all prerequisites needed (see above)

Ensure your PATH environment variable looks for bash.exe in C:\Program Files\Git\bin (the one present in C:\Windows\System32\bash.exe does not work with pre-commit.exe)

For checkov, you may need to also set your PYTHONPATH environment variable with the path to your Python modules.
E.g. C:\Users\USERNAME\AppData\Local\Programs\Python\Python39\Lib\site-packages

Full list of dependencies and where they are used:

  • pre-commit⁠, terraform⁠ or opentofu⁠, git⁠, BASH 3.2.57 or newer⁠, Internet connection (on first run), x86_64 or arm64 compatible operating system, Some hardware where this OS will run, Electricity for hardware and internet connection, Some basic physical laws, Hope that it all will work.

  • [checkov][checkov repo] required for terraform_checkov hook
  • [terraform-docs][terraform-docs repo] 0.12.0+ required for terraform_docs hook
  • [terragrunt][terragrunt repo] required for terragrunt_validate and terragrunt_valid_inputs hooks
  • [terrascan][terrascan repo] required for terrascan hook
  • [TFLint][tflint repo] required for terraform_tflint hook
  • [TFSec][tfsec repo] required for terraform_tfsec hook
  • [Trivy][trivy repo] required for terraform_trivy hook
  • [infracost][infracost repo] required for infracost_breakdown hook
  • [jq][jq repo] required for terraform_validate with --retry-once-with-cleanup flag, and for infracost_breakdown hook
  • [tfupdate][tfupdate repo] required for tfupdate hook
  • [hcledit][hcledit repo] required for terraform_wrapper_module_for_each hook
⁠1.1 Custom Terraform binaries and OpenTofu support

It is possible to set custom path to terraform binary.
This makes it possible to use OpenTofu⁠ binary (tofu) instead of terraform.

How binary discovery works and how you can redefine it (first matched takes precedence):

  1. Check if per hook configuration --hook-config=--tf-path=<path_to_binary_or_binary_name> is set
  2. Check if PCT_TFPATH=<path_to_binary_or_binary_name> environment variable is set
  3. Check if TERRAGRUNT_TFPATH=<path_to_binary_or_binary_name> environment variable is set
  4. Check if terraform binary can be found in the user's $PATH
  5. Check if tofu binary can be found in the user's $PATH
⁠2. Install the pre-commit hook globally

Note

Not needed if you use the Docker image
DIR=~/.git-template
git config --global init.templateDir ${DIR}
pre-commit init-templatedir -t pre-commit ${DIR}
⁠3. Add configs and hooks

Step into the repository you want to have the pre-commit hooks installed and run:

git init
cat <<EOF > .pre-commit-config.yaml
repos:
- repo: https://github.com/antonbabenko/pre-commit-terraform
  rev: <VERSION> # Get the latest from: https://github.com/antonbabenko/pre-commit-terraform/releases
  hooks:
    - id: terraform_fmt
    - id: terraform_docs
EOF

If this repository was initialized locally via git init or git clone before you installed the pre-commit hook globally (step 2⁠), you will need to run:

pre-commit install
⁠4. Run

Execute this command to run pre-commit on all files in the repository (not only changed files):

pre-commit run -a

Or, using Docker (available tags⁠):

Tip

This command uses your user id and group id for the docker container to use to access the local files. If the files are owned by another user, update the `USERID` environment variable. See [File Permissions section](#file-permissions) for more information.
TAG=latest
docker run -e "USERID=$(id -u):$(id -g)" -v "$(pwd):/lint" -w "/lint" "ghcr.io/antonbabenko/pre-commit-terraform:$TAG" run -a

Execute this command to list the versions of the tools in Docker:

TAG=latest
docker run --rm --entrypoint cat ghcr.io/antonbabenko/pre-commit-terraform:$TAG /usr/bin/tools_versions_info

⁠Available Hooks

There are several pre-commit⁠ hooks to keep Terraform configurations (both *.tf and *.tfvars) and Terragrunt configurations (*.hcl) in a good shape:

Hook nameDescriptionDependencies
Install instructions here⁠
checkov and terraform_checkov[checkov][checkov repo] static analysis of terraform templates to spot potential security issues. Hook notes⁠checkov
Ubuntu deps: python3, python3-pip
infracost_breakdownCheck how much your infra costs with [infracost][infracost repo]. Hook notes⁠infracost, jq, Infracost API key⁠
terraform_docsInserts input and output documentation into README.md. Hook notes⁠terraform-docs
terraform_docs_replaceRuns terraform-docs and pipes the output directly to README.md. DEPRECATED, see #248⁠. Hook notes⁠python3, terraform-docs
terraform_docs_without_
aggregate_type_defaults
Inserts input and output documentation into README.md without aggregate type defaults. Hook notes same as for terraform_docs⁠terraform-docs
terraform_fmtReformat all Terraform configuration files to a canonical format. Hook notes⁠-
terraform_providers_lockUpdates provider signatures in dependency lock files⁠. Hook notes⁠-
terraform_tflintValidates all Terraform configuration files with [TFLint][tflint repo]. Available TFLint rules⁠. Hook notes⁠.tflint
terraform_tfsec[TFSec][tfsec repo] static analysis of terraform templates to spot potential security issues. DEPRECATED, use terraform_trivy. Hook notes⁠tfsec
terraform_trivy[Trivy][trivy repo] static analysis of terraform templates to spot potential security issues. Hook notes⁠trivy
terraform_validateValidates all Terraform configuration files. Hook notes⁠jq, only for --retry-once-with-cleanup flag
terragrunt_fmtReformat all [Terragrunt][terragrunt repo] configuration files (*.hcl) to a canonical format.terragrunt
terragrunt_validateValidates all [Terragrunt][terragrunt repo] configuration files (*.hcl)terragrunt
terragrunt_validate_inputsValidates [Terragrunt][terragrunt repo] unused and undefined inputs (*.hcl)
terragrunt_providers_lockGenerates .terraform.lock.hcl files using [Terragrunt][terragrunt repo].terragrunt
terraform_wrapper_module_for_eachGenerates Terraform wrappers with for_each in module. Hook notes⁠hcledit
terrascan[terrascan][terrascan repo] Detect compliance and security violations. Hook notes⁠terrascan
tfupdate[tfupdate][tfupdate repo] Update version constraints of Terraform core, providers, and modules. Hook notes⁠tfupdate

Tag summary

Content type

Image

Digest

sha256:955162978…

Size

225.4 MB

Last updated

12 months ago

docker pull saagie/pre-commit-terraform:v0.88.1-v1.10.6