Collection of git hooks for Terraform to be used with pre-commit framework
- How to install
- Available Hooks
- Hooks usage notes and examples
- Notes for contributors
- Authors
- License
pre-commit,terraform,git, POSIX compatible shell, Internet connection (on first run), x86_64 compatible operation system, Some hardware where this OS will run, Electricity for hardware and internet connection, Some basic physical laws, Hope that it all will works.checkovrequired forcheckovhook.terraform-docsrequired forterraform_docshooks.terragruntrequired forterragrunt_validatehook.terrascanrequired forterrascanhook.TFLintrequired forterraform_tflinthook.TFSecrequired forterraform_tfsechook.
Docker
If no --build-arg is specified, then the latest versions of pre-commit and terraform will be installed.
git clone git@github.com:antonbabenko/pre-commit-terraform.git
cd pre-commit-terraform
# Install all tools with latest versions:
docker build -t pre-commit --build-arg INSTALL_ALL=true .You can specify needed tool versions by providing --build-arg's.
If you'd like you can use the latest versions:
docker build -t pre-commit \
--build-arg PRE_COMMIT_VERSION=latest \
--build-arg TERRAFORM_VERSION=latest \
--build-arg CHECKOV_VERSION=2.0.405 \
--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 \
.To disable pre-commit color output set -e PRE_COMMIT_COLOR=never.
MacOS
coreutils required for terraform_validate hook on macOS (due to use of realpath).
brew install pre-commit terraform-docs tflint tfsec coreutils checkov terrascan
terrascan initUbuntu 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/accurics/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 initUbuntu 20.04
sudo apt update
sudo apt install -y unzip software-properties-common python3 python3-pip
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/accurics/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/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}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: git://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
EOFAfter pre-commit hook has been installed you can run it manually on all files in the repository.
Local installation:
pre-commit run -aDocker:
docker run -v $(pwd):/lint -w /lint pre-commit run -aYou be able list tools versions when needed
TAG=latest && docker run --entrypoint cat pre-commit:$TAG /usr/bin/tools_versions_info
There are several pre-commit hooks to keep Terraform configurations (both *.tf and *.tfvars) and Terragrunt configurations (*.hcl) in a good shape:
| Hook name | Description |
|---|---|
checkov |
checkov static analysis of terraform templates to spot potential security issues. Hook notes |
terraform_docs_replace |
Runs terraform-docs and pipes the output directly to README.md |
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 |
Inserts input and output documentation into README.md. Recommended. Hook notes |
terraform_fmt |
Rewrites all Terraform configuration files to a canonical format. Hook notes |
terraform_tflint |
Validates all Terraform configuration files with TFLint. Available TFLint rules. Hook notes. |
terraform_tfsec |
TFSec static analysis of terraform templates to spot potential security issues. Hook notes |
terraform_validate |
Validates all Terraform configuration files. Hook notes |
terragrunt_fmt |
Rewrites all Terragrunt configuration files (*.hcl) to a canonical format. |
terragrunt_validate |
Validates all Terragrunt configuration files (*.hcl) |
terrascan |
terrascan Detect compliance and security violations. |
Check the source file to know arguments used for each hook.
For checkov you need to specify each argument separately:
- id: checkov
args: [
"-d", ".",
"--skip-check", "CKV2_AWS_8",
]-
terraform_docsandterraform_docs_without_aggregate_type_defaultswill insert/update documentation generated by terraform-docs framed by markers:<!-- BEGINNING OF PRE-COMMIT-TERRAFORM DOCS HOOK --> <!-- END OF PRE-COMMIT-TERRAFORM DOCS HOOK -->
if they are present in
README.md. -
It is possible to pass additional arguments to shell scripts when using
terraform_docsandterraform_docs_without_aggregate_type_defaults. Send pull-request with the new hook if there is something missing.
For these hooks you need to specify all arguments as one:
- id: terraform_docs
args:
- tfvars hcl --output-file terraform.tfvars.model .terraform_docs_replace replaces the entire README.md rather than doing string replacement between markers. Put your additional documentation at the top of your main.tf for it to be pulled in. The optional --dest argument lets you change the name of the file that gets created/modified.
Example:
- id: terraform_docs_replace
args:
- --sort-by-required
- --dest=TEST.md-
terraform_tflintsupports custom arguments so you can enable module inspection, deep check mode etc.Example:
- id: terraform_tflint args: - --args=--deep - --args=--enable-rule=terraform_documented_variables
-
When you have multiple directories and want to run
tflintin all of them and share single config file it is impractical to hard-code the path to.tflint.hclfile. The solution is to use__GIT_WORKING_DIR__placeholder which will be replaced byterraform_tflinthooks with Git working directory (repo root) at run time. For example:- id: terraform_tflint args: - --args=--config=__GIT_WORKING_DIR__/.tflint.hcl
-
terraform_tfsecwill consume modified files that pre-commit passes to it, so you can perform whitelisting of directories or files to run against via files pre-commit flagExample:
- id: terraform_tfsec files: ^prd-infra/
The above will tell pre-commit to pass down files from the
prd-infra/folder only such that the underlyingtfsectool can run against changed files in this directory, ignoring any other folders at the root level -
To ignore specific warnings, follow the convention from the documentation.
Example:
resource "aws_security_group_rule" "my-rule" { type = "ingress" cidr_blocks = ["0.0.0.0/0"] #tfsec:ignore:AWS006 }
-
terraform_validatesupports custom arguments so you can pass supported no-color or json flags:- id: terraform_validate args: - --args=-json - --args=-no-color
-
terraform_validatealso supports custom environment variables passed to the pre-commit runtime:- id: terraform_validate args: - --envs=AWS_DEFAULT_REGION="us-west-2" - --envs=AWS_ACCESS_KEY_ID="anaccesskey" - --envs=AWS_SECRET_ACCESS_KEY="asecretkey"
-
It may happen that Terraform working directory (
.terraform) already exists but not in the best condition (eg, not initialized modules, wrong version of Terraform, etc). To solve this problem you can find and delete all.terraformdirectories in your repository:echo " function rm_terraform { find . -name ".terraform*" -print0 | xargs -0 rm -r } " >>~/.bashrc # Reload shell and use `rm_terraform` command in repo root
terraform_validatehook will try to reinitialize them before runningterraform validatecommand.Warning: If you use Terraform workspaces, DO NOT use this workaround (details). Wait to
force-initoption implementation
- Python hooks are supported now too. All you have to do is:
- add a line to the
console_scriptsarray inentry_pointsinsetup.py - Put your python script in the
pre_commit_hooksfolder
- add a line to the
Enjoy the clean, valid, and documented code!
pre-commit try-repo {-a} /path/to/local/pre-commit-terraform/repo {hook_name}I.e.
pre-commit try-repo /mnt/c/Users/tf/pre-commit-terraform terraform_fmt # Run only `terraform_fmt` check
pre-commit try-repo -a ~/pre-commit-terraform # run all existing checks from repoRunning pre-commit with try-repo ignores all arguments specified in .pre-commit-config.yaml.
This repository is managed by Anton Babenko with help from these awesome contributors.
MIT licensed. See LICENSE for full details.