When working with DevOps (either Azure DevOps or GitHub), and using multi-stage YAML pipelines, it is a best practice to include some type of quality check (ie. Unit Test, Linting, etc.).
This makes sense when evaluating application code, but how does it work/relate to Infrastructure-as-Code (IaC)?
Quality Controls for Terraform
While working with Infrastructure-as-Code (IaC), and in particular, HashiCorp Terraform, I set out to find a few tools that could be used for the same type of quality checks for IaC code. One of the tools that I came across was TFSec. TFSec uses static analysis of your terraform templates to spot potential security issues.
At the time of this writing, TFSec has:
- 51 x AWS checks
- 19 x Azure checks
- 12 x GCP checks
- 3 x General checks
When you look at the documentation for TFSec, you will see that, aside from installing it locally, you can also run TFSec in a Docker container. Here is the command you can use to do so:
docker run –rm -it -v “$(pwd):/src“ liamg/tfsec /src
To run this in an Azure DevOps pipeline, this is what the Job looks like…
When you run this in the Azure pipeline, this is the type of output you would see. Notice that the execution exits with a non-zero exit code if a potential problem is detected. This enables us to be able to use it in a CI/CD pipeline and exit/error-out, as we would expect to.
That’s all great, but let’s take it a step further.
Publish the Results
In Azure Pipelines, there is a Publish Test Results task that publishes test results when tests are executed to provide a comprehensive test reporting and analytics experience. But how do we get the results out of the container, and into one of the supported results formats?
Here’s what worked for me…
docker run –rm -t -v $(System.DefaultWorkingDirectory):/src liamg/tfsec ./src –format JUnit > $(System.DefaultWorkingDirectory)/TFSecReport/junit.xml
Notice a few things in this revised docker run command. Firstly, you’ll notice the –format JUnit parameter. According to the TFSec Output Options, we can output the TFSecc results as JSON, CSV, Checkstyle, Sarif, or JUnit. If you read the documentation for the Publish Test Results task, you will see that one of the supported results formats is JUnit.
Next, you’ll notice that, in order to retrieve the output from the docker container into pipeline, we are piping the StdOut to a file within the working directory of the pipeline (the ‘>‘ part).
After we get the output from the docker container, we can now use the Publish Test Results task, and publish the results to the pipeline.
Conclusion
The end result that we get is the following.
We can now see all of the TFSec test results that failed, and the individual tests as well. The only thing that would make this better, is if the output also included which tests passed.
We have now successfully published our Terraform quality controls results to the Pipeline, just like we do for application Unit Tests, etc.