Enhance Security in GitLab CI: Integrate Trivy for Terraform Code Scanning

Discover how Groundfog transitioned from tfsec to Trivy for enhanced security scanning in GitLab pipelines. This move ensures comprehensive vulnerability insights and long-term support, securing Terraform resources more effectively. Explore our custom Trivy integration and streamline your CI/CD process for robust security.

Felix Pafel - June 20, 2024

Utilizing GitLab pipelines for deploying Terraform resources is a key aspect of our daily workflow. Given the significance of these resources to our customers' infrastructure, ensuring their security is a top priority at Groundfog. As part of our security measures, we conduct static code analysis scans during each pipeline execution. While GitLab offers a template for this purpose, it lacks visibility and requires manual artifact retrieval. Hence, we initially adopted tfsec, which served its purpose effectively.

Transition to Trivy

As Aqua Security, the company behind tfsec, consolidated its security scanning tools into Trivy, we decided to transition our pipelines accordingly. Trivy not only retains the functionalities of tfsec but also introduces several additional features, making it an attractive choice for our security needs.

One crucial factor in our decision-making process was the realization that any issues or updates required for tfsec would only be addressed in Trivy going forward. This forward-looking approach ensures that our security scanning tool remains supported and updated, mitigating potential vulnerabilities and ensuring the long-term reliability of our CI/CD pipelines.

Integration into GitLab Pipelines

To ensure all necessary information is readily available within the GitLab pipeline dashboard, we developed a custom template for Trivy. This template, built upon Trivy's default template with added fields, provides comprehensive insights. To avoid reliance on external services like AWS S3, we opted to create our Docker container based on the current Trivy container. Alternatively, the template can be stored externally and fetched using a simple curl command.

<?xml version="1.0" ?>

<testsuites name="trivy">

{{- range $resultIndex, $resultItem := . -}}

{{- $failures := len .Vulnerabilities }}

   <testsuite tests="{{ $failures }}" failures="{{ $failures }}" name="{{  .Target }}" errors="0" skipped="0" time="">

   {{- if not (eq .Type "") }}

       <properties>

           <property name="type" value="{{ .Type }}"></property>

       </properties>

       {{- end -}}

       {{ range .Vulnerabilities }}

       <testcase classname="{{ .PkgName }}-{{ .InstalledVersion }}" name="[{{ .Vulnerability.Severity }}] {{ .VulnerabilityID }}" time="">

           <failure message="{{ escapeXML .Title }}" type="description">{{ escapeXML .Description }}</failure>

       </testcase>

   {{- end }}

   </testsuite>

{{- if .MisconfSummary }}

   <testsuite tests="{{ add .MisconfSummary.Successes .MisconfSummary.Failures }}" failures="{{ .MisconfSummary.Failures }}" name="{{  .Target }}" errors="0" skipped="{{ .MisconfSummary.Exceptions }}" time="">

{{- else }}

   <testsuite tests="0" failures="0" name="{{  .Target }}" errors="0" skipped="0" time="">

{{- end }}

   {{- if not (eq .Type "") }}

       <properties>

           <property name="type" value="{{ .Type }}"></property>

       </properties>

       {{- end -}}

    {{ range .Misconfigurations }}

   <testcase classname="{{ .Type }}" name="[{{ .Severity }}] {{ .ID }}" time="" file="{{ $resultItem.Target }}">

   {{- if eq .Status "FAIL" }}

       <failure message="{{ escapeXML .Title }}" type="cause">

&#xD;{{ escapeXML .Description }}&#xD;&#xA;

       {{- with .CauseMetadata }}

{{ $resultItem.Target }}: Lines {{ .StartLine }} - {{ .EndLine }}

&#xD;&#xA;

{{- range .Code.Lines }}

{{ escapeXML .Content }}

           {{- end }}

       {{- end }}

       </failure>

   {{- end }}

   </testcase>

{{- end }}

   </testsuite>

{{- end }}
</testsuites>

Dockerfile for Custom Container

FROM aquasec/trivy:0.49.0

COPY ./junit-template.tpl /opt/junit-template.tpl

WORKDIR /opt

Pipeline Configuration

For the actual scan execution in our pipelines, we streamlined the process with a dedicated configuration file within our Git repository. This file orchestrates the Trivy scan, specifies the necessary directories, and handles artifact management.

stages:

 - test

trivy:

 stage: test

 image:

   name: "${CI_REGISTRY}/gitlab-builder-images/trivy:2"

   entrypoint: [""]

 variables:

   REPORT_DIR: "${CI_PROJECT_DIR}/.report"

   TERRAFORM_DIR: "${CI_PROJECT_DIR}/terraform"

 allow_failure: true

 script:

   - mkdir -p ${REPORT_DIR}

   - trivy --version

   - trivy config --exit-code 1 --format template --template "@/opt/junit-template.tpl" -o "${REPORT_DIR}/trivy-junit.xml" ${TERRAFORM_DIR}

 artifacts:

   expire_in: 1 week

   when: always

   reports:

     junit: "${REPORT_DIR}/trivy-junit.xml"

 rules:

   - if: $SAST_DISABLED

     when: never

   - changes:

     - '**/*.tf'

This file is being included by each project that needs to run the terraform scan.

include:

- project: 'gitlab-job-templates'

  ref: '3'

  file: Trivy.gitlab-ci.yml

GitHub Integration

For those interested in integrating Trivy into GitHub pipelines, the trivy-action GitHub Action provides a seamless solution. By incorporating trivy-action into your GitHub workflow, you can scan for vulnerabilities directly within your CI/CD process.

Here's an example of how the integration can be configured:

name: build

on:

 push:

   branches:

   - main

 pull_request:

jobs:

 build:

   name: Build

   runs-on: ubuntu-20.04

   steps:

   - name: Checkout code

     uses: actions/checkout@v3

   - name: Run Trivy vulnerability scanner in fs mode

     uses: aquasecurity/trivy-action@master

     with:

       scan-type: 'fs'

       scan-ref: '.'

       trivy-config: trivy.yaml

For more information and detailed usage instructions, you can explore the trivy-action repository on GitHub.

Conclusion

Transitioning from tfsec to Trivy in our GitLab pipelines has significantly enhanced our security scanning capabilities. The seamless integration and comprehensive insights provided by Trivy ensure that our Terraform resources are deployed securely, safeguarding our customers' infrastructure.

Considering the importance of security in CI/CD pipelines, we encourage others to explore Trivy for their security scanning needs. Its robust features and ease of integration make it a valuable asset in maintaining a secure development environment.


Let's explore the full potential of the cloud together

Contact us today to discover how our tailored solutions can drive growth, scalability, and financial efficiency for your business.

REACH OUT TODAY