Streamlining Container Security: Integrating Jenkins, Trivy, and DefectDojo

In modern DevOps workflows, automating security checks is critical. Jenkins can orchestrate your CI/CD pipeline, Trivy scans containers for vulnerabilities, and DefectDojo centralizes and manages all discovered findings. By combining these three tools, you can quickly identify, track, and remediate vulnerabilities throughout the development lifecycle.


 

Lab Setup Overview

  • Operating System: Ubuntu (or any Linux distribution) with Docker installed.
  • Jenkins: Installed on the same machine or a separate VM/container.
  • DefectDojo: Deployed via Docker or Kubernetes (see DefectDojo docs for detailed instructions).
  • Trivy: Installed on the Jenkins server/agent (so Jenkins can invoke Trivy scans).
  • OWASP Juice Shop: An intentionally insecure web application that we will containerize and scan.

Why OWASP Juice Shop?
OWASP Juice Shop is a popular application for security testing and demonstrations because it’s deliberately vulnerable and actively maintained. It’s also open-source and easy to containerize.

1. Installing Trivy

1. Install Trivy on your Jenkins server or in your build agent:

# Example for Linux (using a script from Trivy's docs):
curl -sfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh | sudo sh -s -- -b /usr/local/bin


2. Verify installation:

trivy --version 

2. Installing and Setting Up DefectDojo

1. Deploy DefectDojo (official docs here). You can use a Docker-based setup or a Kubernetes Helm chart.

2. Obtain API Key for DefectDojo:

  • Log in as an admin user.
  • Go to API v2 Key page.
  • Generate and copy your key.


3. Create a New Product:

  • Navigate to ProductsNew Product in DefectDojo.
  • Provide a name and description.
  • Note the Product ID.


4. Create a New Engagement:

  • Under Engagements, create a New Engagement linked to the product.
  • Note the Engagement ID.

3. Jenkins Pipeline Script

Below is an example Jenkins pipeline (Jenkinsfile) that:

  • Checks out the code from GitHub.
  • Builds a Docker image of OWASP Juice Shop.
  • Runs the container.
  • Scans it with Trivy for HIGH and CRITICAL severity vulnerabilities.
  • Uploads the JSON scan results to DefectDojo.
  •  

    pipeline {
        agent any
        environment {
            DOCKER_IMAGE = "owasp/juice-shop"
            CONTAINER_NAME = "juice-shop-container"
            DOCKER_HOST = 'unix:///var/run/docker.sock'
            DEFECTDOJO_URL = "https://defectdojo.example.com" // Replace with your DefectDojo URL
            DEFECTDOJO_API_KEY = "your_api_key"              // Replace with your DefectDojo API key
            PRODUCT_ID = "123"                              // Replace with your DefectDojo Product ID
            ENGAGEMENT_ID = "456"                           // Replace with your DefectDojo Engagement ID
            TRIVY_JSON_FILE = "trivy_results.json"
        }
        stages {
            stage('Checkout Code') {
                steps {
                    git branch: 'main', url: 'https://github.com/amykr777/juice-shop'
                }
            }
            stage('Build Docker Image') {
                steps {
                    script {
                        try {
                            echo "Building Docker image: ${DOCKER_IMAGE}"
                            sh "docker build --no-cache -t ${DOCKER_IMAGE} ."
                        } catch (Exception e) {
                            error "Failed to build Docker image: ${e.getMessage()}"
                        }
                    }
                }
            }
            stage('Run Docker Container') {
                steps {
                    script {
                        try {
                            echo "Running Docker container: ${CONTAINER_NAME}"
                            sh """
                            docker run -d --name ${CONTAINER_NAME} \
                            -p 3000:3000 ${DOCKER_IMAGE}
                            """
                        } catch (Exception e) {
                            error "Failed to run Docker container: ${e.getMessage()}"
                        }
                    }
                }
            }
            stage('Trivy Container Scan') {
                steps {
                    script {
                        try {
                            echo "Running Trivy scan on Docker image: ${DOCKER_IMAGE}"
                            sh """
                            trivy image --severity HIGH,CRITICAL --no-progress \
                            --format json --output ${TRIVY_JSON_FILE} ${DOCKER_IMAGE}
                            """
                        } catch (Exception e) {
                            error "Trivy scan failed: ${e.getMessage()}"
                        }
                    }
                }
            }
            stage('Upload Scan Results to DefectDojo') {
                steps {
                    script {
                        try {
                            echo "Uploading Trivy results to DefectDojo"
                            sh """
                            python3 upload_to_defectdojo.py \
                                --url ${DEFECTDOJO_URL} \
                                --api_key ${DEFECTDOJO_API_KEY} \
                                --product_id ${PRODUCT_ID} \
                                --engagement_id ${ENGAGEMENT_ID} \
                                --file ${TRIVY_JSON_FILE} \
                                --scan_type "Trivy Scan"
                            """
                        } catch (Exception e) {
                            error "Failed to upload scan results to DefectDojo: ${e.getMessage()}"
                        }
                    }
                }
            }
        }
        post {
            always {
                script {
                    try {
                        echo "Stopping and removing container: ${CONTAINER_NAME}"
                        sh """
                        docker stop ${CONTAINER_NAME} || true
                        docker rm ${CONTAINER_NAME} || true
                        """
                    } catch (Exception e) {
                        echo "Cleanup failed: ${e.getMessage()}"
                    }
                }
            }
            failure {
                echo "Pipeline failed. Check the logs for more details."
            }
            success {
                echo "Pipeline completed successfully!"
            }
        }
    }


    Stage-by-Stage Explanation

    • Environment Block

      • Defines environment variables used throughout the pipeline.
      • DOCKER_IMAGE: Name/tag of the Docker image to build (OWASP Juice Shop).
      • CONTAINER_NAME: Name of the running container.
      • DEFECTDOJO_URL, DEFECTDOJO_API_KEY: Connection details for DefectDojo.
      • PRODUCT_ID, ENGAGEMENT_ID: References to the Product and Engagement in DefectDojo.
      • TRIVY_JSON_FILE: File name for the Trivy scan output.
    • stage('Checkout Code')

      • Clones the OWASP Juice Shop repository from GitHub into the Jenkins workspace.
    • stage('Build Docker Image')

      • Uses docker build to create a Docker image from the local Dockerfile.
      • The --no-cache flag ensures a fresh build each time.
    • stage('Run Docker Container')

      • Runs the newly built Docker image as a container.
      • Exposes port 3000 for the Juice Shop web app.
    • stage('Trivy Container Scan')

      • Invokes Trivy to scan the Docker image for HIGH and CRITICAL vulnerabilities.
      • The results are saved to trivy_results.json in JSON format.
    • stage('Upload Scan Results to DefectDojo')

      • Runs a Python script (upload_to_defectdojo.py) to upload the JSON scan results to DefectDojo.
      • Requires the DefectDojo URL, API key, product/engagement IDs, and scan file.
      • Scan Type is set to “Trivy Scan,” so DefectDojo correctly interprets the results.
    • post { ... }

      • always: Cleans up the Docker container by stopping and removing it.
      • failure: Prints a message if the pipeline fails.
      • success: Prints a success message when the pipeline completes without errors.

    4. Viewing Findings in DefectDojo

    After the pipeline finishes, go to your DefectDojo Engagement. You will see a new test entry titled “Trivy Scan”, and under Findings, a list of identified vulnerabilities.


    Conclusion:
    By following these steps, you can seamlessly integrate Trivy scans within a Jenkins pipeline and centralize vulnerability management in DefectDojo. This setup ensures that any critical or high vulnerabilities in your containerized applications are quickly detected and tracked for remediation.

     

    No comments:

    Post a Comment