Static code analysis for terraform
Static code analysis is a crucial component of quality assurance for software projects. It allows errors to be detected early in a short feedback loop and addressed promptly. Source code is examined against defined rules to identify errors and potential vulnerabilities, and depending on the tool used, possible solutions are often suggested.
With the emergence of “Infrastructure as Code” approaches, infrastructure descriptions are increasingly being stored in the form of code or at least structured text files. This enables the advantages of static code analysis to be applied to infrastructure definitions as well.
Analysis of Terraform Files
For analyzing Terraform definition files, there is the CLI tool tfsec. It is available under the MIT license as an executable file for Windows, Linux, and macOS, or as a Docker image for download.
tfsec
comes with an extensive set of rules for major hyperscalers like AWS, Azure, and Google Cloud. However, there are fewer rules available for a self-hosted Kubernetes environment or an OpenStack cluster. While you can define custom rules using Custom Checks, using tfsec
in a managed environment is probably the most practical approach.
tfsec
In the simplest case, you can run tfsec
in the folder containing your Terraform files or pass the path as the first command-line argument. tfsec
recursively scans all files with the extensions .tf
and .tfvars
and displays the results in the console.
./tfsec ./terraform
If no rule violations are detected, tfsec
will output some statistics and provide an “no problems” message.
timings
──────────────────────────────────────────
disk i/o 5.3983ms
parsing 0s
adaptation 610.2µs
checks 3.2634ms
total 9.2719ms
counts
──────────────────────────────────────────
modules downloaded 0
modules processed 1
blocks processed 11
files read 1
results
──────────────────────────────────────────
passed 6
ignored 0
critical 0
high 0
medium 0
low 0
No problems detected!
When issues are detected, tfsec
provides details about the problematic file, the exact location of the issue, as well as hints and links to further information. Using the --concise-output
parameter reduces the output to the most essential information.
> ./tfsec ./terraform --concise-output
Result #1 CRITICAL Storage account uses an insecure TLS version.
────────────────────────────────────────────────────────────────────────────────
./Terraform/main.tf:55
────────────────────────────────────────────────────────────────────────────────
ID azure-storage-use-secure-tls-policy
Impact The TLS version being outdated and has known vulnerabilities
Resolution Use a more recent TLS/SSL policy for the load balancer
More Information
- https://aquasecurity.github.io/tfsec/v1.28.1/checks/azure/storage/use-secure-tls-policy/
- https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/storage_account#min_tls_version
────────────────────────────────────────────────────────────────────────────────
5 passed, 1 potential problem(s) detected.
In the example, tfsec
is flagging an outdated TLS version for an Azure Storage Account.
If you want to exclude specific rules from being applied, you can use the --exclude [RULE-ID]
parameter to exclude them from the analysis. You can also ignore issues related to individual resources or options within your Terraform definitions by using comments in your code.
resource "azurerm_storage_account" "storage_account" {
account_kind = "StorageV2"
account_tier = "Standard"
min_tls_version = "TLS1_1" #tfsec:ignore:azure-storage-use-secure-tls-policy
...
}
CI Pipeline
A useful feature of tfsec
is its ability to output the results of an analysis in various formats. Using the --format
parameter, you can select the desired formats, including options like Markdown, HTML, and JUnit. By using the --out
parameter, you specify the directory (which must exist) and the filename prefix for the output files. The first format specified will also be displayed on the console.
The following command generates the files results.lovely
, results.junit
, and results.markdown
in the directory ./terraform/tfsec-results
.
./tfsec ./terraform --concise-output \
--format lovely,junit,markdown \
--out ./terraform/tfsec-results/results
The results can now be further processed in a CI pipeline, and the build can fail in case of rule violations.
Azure DevOps Pipeline
If you are using Azure DevOps Pipelines, you can publish the JUnit file as test results. This way, you can easily integrate tfsec
into existing test and build workflows and visualize errors directly within the pipeline.
For simpler adaptation to other CI systems, I will demonstrate how to use tfsec
as a shell command. Additionally, there is a pipeline extension available in the Visual Studio Marketplace and a GitHub Action.
First, download the appropriate binary for your system, set the execute bit if necessary, and create the output folder. Then, run tfsec
. If you want to see the result in Markdown format as part of the pipeline run in the web interface, you can upload it using a logging command like echo "##vso[task.uploadsummary]...
.
In a second task, you can then publish the JUnit file as test results.
- task: CmdLine@2
displayName: "Run tfsec"
inputs:
workingDirectory: "$(System.DefaultWorkingDirectory)/Infrastructure/Terraform"
script: |
echo "Download tfsec v1.28.1 ..."
wget -q https://github.com/aquasecurity/tfsec/releases/download/v1.28.1/tfsec-linux-amd64 -O tfsec
chmod +x tfsec
mkdir ./tfsec-results
./tfsec . --concise-output \
--format lovely,junit,markdown \
--out ./tfsec-results/results
echo "##vso[task.uploadsummary]$(System.DefaultWorkingDirectory)/Infrastructure/Terraform/tfsec-results/results.markdown"
- task: PublishTestResults@2
displayName: "Publish tfsec results"
condition: succeededOrFailed()
inputs:
testResultsFormat: JUnit
searchFolder: $(System.DefaultWorkingDirectory)/Infrastructure/Terraform/tfsec-results
testResultsFiles: "results.junit"
failTaskOnFailedTests: true
testRunTitle: tfsec
The tfsec
results are included in the test statistics.
The result of the Markdown file is displayed in the Extensions
tab.
With this, you have integrated automatic and continuous validation of Terraform files into your CI pipeline.