azure-pipelines.yaml to break the infrastructure deployment into multiple stages. These are stage: validate where I ran terraform validate against all the workspaces to check for code correctness, followed by stage: Dev, Test, and Prod, where I deployed the infrastructure changes. Per the documentation, Checkov can be used to scan the .tf source files and the terraform plan file to identify anomalies and highlight them. Hence, I planned to run a scan against the terraform source code in the validate stage and scan the plan file in each Dev, Test, and Prod stage since the plan files are separate for these three environments.
With that objective at hand and a little bit of research, I identified three steps to add to azure-pipelines.yaml that had to be followed for each of these four stages.
Step 1: Install Checkov.
I used a bash task to install Checkov following the installation guide at Checkov-quick-start.
Step 2: Scan terraform configuration files.
I used a bash task to run the scan command where the output was formatted in JUnit. The command is self-explanatory. I selected the source folder with terraform configuration files to be the working directory. And ran the checkov -d . command to run that on the current directory. The output would be available on the build logs if I did not provide the -o junitxml flag. By routing the output to an XML file, I published them in the next step.
Note: I added a continueOnError: true so that, if the build failed (due to code scan identifying vulnerabilities), I could get the next step (publish report) to run and review the code scan failures.
Step 3: Publish the result.
Finally, I published the scan result in the last step, which Checkov produced via the familiar PublishTestResults task.
I applied these three steps to the validate stage.
However, as mentioned in the docs, Checkov can scan the Terraform plan file, too, and I followed a tweaked version of the above three steps for all the three stages, Dev, Test, and Prod. I wrote “tweaked version” since I scanned the plan file, not the terraform configuration files. The below three steps provide a little more detail.
Step 1: Install Checkov.
This step is identical to the previous one, where I installed Checkov on the local build agent.
Step 2: Scan plan file.
For the following three stages(Dev, Test, and Prod), I scanned the plan file using the command shown below. This task is started after Terraform created a tfplan file.
This is a two-step process where the tfplan file is converted to JSON, and then a Checkov scan is run on that to produce an XML file in JUnit format. Here is a little more information on terraform show and an example from checkov-terraform-scanning.
Step 3: Publish scan report.
This step was identical to step 3 of the validate stage, where the scan report was published to be available for review.
These reports were available on the build page next to the Summary tab, titled Tests.
Here is an image of the scan result.
Based on the report’s title, I drilled down and identified the vulnerabilities in my code.
I titled the code scan report as testRuntitle: Terraform source code scan in the PublishTestResults task and was able to view the information as shown below.
I followed a similar approach for the plan file scan in Stage: Dev and Test and Prod. If you are interested in knowing more, I have a link to the azure-pipelines build log. Click on the Test tab to review the vulnerabilities. The link to my GitHub repository is Working-with-Terraform-workspace-and-AWS.
Overall, I found it reasonably easy to integrate Checkov into azure-pipelines.yaml to scan the Terraform configuration and plan files. The Checkov error log notifies which resource configuration has a security vulnerability (points to the line number in the terraform source file) and how to remediate it. E.g., the CKV_AWS_130/Ensure VPC subnets do not assign public IP by default provides a link to the guideline where Checkov provides a fix to the vulnerability. In this case, it is to set the map_public_ip_on_launch to false.
There are multiple options from here on. I could either decide to review and fix the errors identified in the scan or introduce Checkov policy suppression blocks in the terraform code to suppress these errors. Here is an example of how to suppress policies.
Either way, it is an excellent mechanism to identify vulnerabilities in the Terraform configuration files. If you are interested, please give Checkov a try and share your findings. As I have shown, it is pretty easy to integrate that with the existing azure-pipelines.yaml file to build the Terraform configuration files. If I can be of help, please don’t hesitate to reach out.
Note: I learned this concept from Ned’s video and Adin’s blog.