Integrate Deepfactor scanner in your CI/CD pipelines

Deepfactor provides a command line utility dfctl which can be used to scan container images and file systems to generate software bill of materials (SBOM) and find SCA vulnerabilities associated with the SBOM. Deepfactor also packages this CLI in a container image which can be used in CI/CD pipelines to run scans against your images or file sytems.

The following document will describe the generic steps one needs to follow to integrate Deepfactor scanner in CI/CD pipelines. These steps should work for most CI/CD tools with some tool specific changes. The latter sections of this document provide example pipeline scripts for a few common scan scenarios in Jenkins and GitLab.

Deepfactor scanner image

Deepfactor scanner image can be found at the following path:

public.ecr.aws/deepfactor/df/runtime:latest

We will be using this image in the later sections of this document where we explain how to launch a scan against your container image / file system.

Dfctl scan arguments

The dfctl scan verb takes multiple arguments to help you customize the scan. The following table describes the various options. We will be using a combination of these options in the subsequent sections where we describe a few common scan use cases.

 

Argument

Title

Description

Required

-s

Scan Artifact Type

Specify the scan artifact type. Allowed values are image, fs

No. Defaults to image

-a

Application Name

Specify the name of your application. This is required in the case of a file system scan. The artifact name will be applicationName:componentName on the portal UI

Required for filesystem scan only

-c

Component Name

Specify the name of your component. This is required in the case of a file system scan. The artifact name will be applicationName:componentName on the portal UI

Required for filesystem scan only

-V

Component Version

Specify the version of the component you are currently scanning. For container images, the image SHA is automatically considered as the version and you need not specify this argument. This argument is required only for filesystem scans. We recommend using a build number/identifier/version from your pipeline for this argument

Required for filesystem scan only

-u

Scan Timeout

You can optionally specify a timeout in minutes and the scan will be stopped when the timeout occurs.

No

-h

Agent Name

You can optionally provide a name for the scan agent. We recommend setting this to the name of the tool. Example: jenkins

No

-g

Agent Type

You can optionally provide scan agent type. We recommend setting this to something like ‘CI/CD’.

No

-p

Alert Policy

Specify the name of the scan alert policy for this scan. You can create custom policies from the Deepfactor portal UI to customize the alerts you receive.

No. Policy marked as default on the portal will be used for the scan if this argument is not specified

-f

Output Format

Specify the output format you want. Allowed values are json, table, cyclonedx, spdx, spdx-json

No

-O

Output Filename

Specify output file path. If specified, the results of the scan will be stored in a file on the disk with this filename.

No

 

Scan Artifact

Specify Image name/path or filesystem path to scan.

Yes

 

Prerequisites

  1. Ensure you have docker installed on the CI/CD agent where you intend to scan your artifact.

  2. Mount docker.sock to Deepfactor scan container so that the scanner can scan local images using the following option

    -v /var/run/docker.sock:/var/run/docker.sock

Scanning artifacts

Scanning artifacts using Deepfactor scanner involves two steps

1. Store Deepfactor run token as a secret in your CI/CD tool

Once you setup the Deepfactor portal, you can get the Deepfactor run token from the portal UI (by clicking the start button). We recommend storing this token as a secret in your CI/CD tool and then passing it to the Deepfactor scan pipeline step.

2. Execute the Deepfactor scan command in your pipeline

Sample command to scan a container image:

docker run --rm -e DF_RUN_TOKEN=$DF_RUN_TOKEN --network host \
-v /var/run/docker.sock:/var/run/docker.sock \
-v $WORKSPACE/$OUTPUT_FOLDER:/$OUTPUT_FOLDER \
public.ecr.aws/deepfactor/df/runtime:latest \
dfctl scan -f $REPORT_FORMAT -O /$OUTPUT_FOLDER/$OUTPUT_FILE_NAME $IMAGE_NAME

Sample command to scan source code:

docker run --rm -e DF_RUN_TOKEN=$DF_RUN_TOKEN --network host \
-v /var/run/docker.sock:/var/run/docker.sock \
-v $WORKSPACE/$OUTPUT_FOLDER:/$OUTPUT_FOLDER \
-v $WORKSPACE/$SCAN_PATH:$SCAN_PATH \
public.ecr.aws/deepfactor/df/runtime:latest \
dfctl scan -s fs -a $APPLICATION_NAME -c $COMPONENT_NAME -V $ARTIFACT_VERSION \
-f $REPORT_FORMAT -O /$OUTPUT_FOLDER/$OUTPUT_FILE_NAME $SCAN_PATH

where:

DF_RUN_TOKEN is the Deepfactor run token, preferably stored as a secret in your CI/CD tool

OUTPUT_FOLDER is the folder in which you would like to store the scan output reports. This directory has to be mounted to the scan container.

REPORT_FORMAT is the report format which can be one of table, json, cyclonedx, spdx or spdx-json

OUTPUT_FILE_NAME is the name of the scan output report file name

IMAGE_NAME is the image you want to scan in the pipeline

APPLICATION_NAME is the name of the application for filesystem scan (you can provide application name of your choice)

COMPONENT_NAME is the name of the component for filesystem scan (you can provide component name of your choice)

ARTIFACT_VERSION is the version of the artifact in the case of filesystem scan

SCAN_PATH is the directory path you would like to scan. This directory has to be mounted to the scan container so it can access and scan the file system directory.

Jenkins

The following section outlines sample scripts for common scan scenarios in Jenkins.

Store Deepfactor run token as a secret in Jenkins

As mentioned earlier, we recommend storing the Deepfactor run token as a secret. You can achieve that in Jenkins using the following steps

  • Navigate to Mange Jenkins > Manage Credentials

jenkins_secret_1.png
  • Navigate to System > Global credentials and click on Add Credentials

jenkins_secret_2.png
  • Select Kind “Secret text” and Scope as preferred

  • Enter ID as DF_RUN_TOKEN

jenkins_secret_3.png
  • The Secret (DF_RUN_TOKEN) can be obtained from Deepfactor portal UI

jenkins_secret_4.png
  • Click on create. Now we will be able to reference the DF_RUN_TOKEN secret in our pipeline

Scan Examples

Scan a container image

pipeline {
    // agent any
    // or an agent node
    agent any
    environment {
        // fetch run token from credentials
        DF_RUN_TOKEN=credentials('DF_RUN_TOKEN')
    }
    stages {
        stage('Deepfactor static scan') {
            steps {
                sh('docker run --rm -e DF_RUN_TOKEN=$DF_RUN_TOKEN --network host -v /var/run/docker.sock:/var/run/docker.sock public.ecr.aws/deepfactor/df/runtime:latest dfctl scan node:alpine')
            }
        }
    }
}

Scan a locally built container image

In this pipeline example, we will perform the following steps

  1. Check out source code from git. Build container image.

  2. Scan the built container image using Deepfactor.

pipeline {
    // agent any
    // or an agent node
    agent any
    environment {
        DF_RUN_TOKEN=credentials('DF_RUN_TOKEN')
    }
    stages {
        stage('Pull source code and build image') {
            steps {
                git 'https://github.com/dockersamples/linux_tweet_app.git'
                sh 'docker build . -t tweet'
            }
        }
        stage('Deepfactor static scan') {
            steps {
                sh('docker run --rm -e DF_RUN_TOKEN=$DF_RUN_TOKEN --network host -v /var/run/docker.sock:/var/run/docker.sock public.ecr.aws/deepfactor/df/runtime:latest dfctl scan tweet')
            }
        }
    }
}

Scan a container image and generate CycloneDX SBOM

In this pipeline example, we will perform the following steps

  1. Check out source code from git. Build container image.

  2. Scan the built container image using Deepfactor and generate CycloneDX SBOM.

  3. Store the CycloneDX SBOM file as a pipeline artifact.

Note: As mentioned in the earlier section, since we want the store the scan output, CycloneDX SBOM file as a pipeline artifact, we have to mount a volume where the Deepfactor scan container can store the requested output files.

pipeline {
    // agent any
    // or an agent node
    agent any
    environment {
        DF_RUN_TOKEN=credentials('DF_RUN_TOKEN')
        OUTPUT_FOLDER='archive'
        OUTPUT_FILE_NAME= 'report.cdx.json'
    }
    stages {
        stage('Pull source code and build image') {
            steps {
                git 'https://github.com/dockersamples/linux_tweet_app.git'
                sh 'docker build . -t tweet'
            }
        }
        stage('Deepfactor static scan') {
            steps {
                sh('docker run --rm -e DF_RUN_TOKEN=$DF_RUN_TOKEN --network host -v /var/run/docker.sock:/var/run/docker.sock -v "$WORKSPACE/$OUTPUT_FOLDER:/$OUTPUT_FOLDER" public.ecr.aws/deepfactor/df/runtime:latest dfctl scan tweet -f cyclonedx -O "/$OUTPUT_FOLDER/$OUTPUT_FILE_NAME"')
            }
        }
        stage('Archive output') {
            steps {
                archiveArtifacts artifacts: OUTPUT_FOLDER + '/*'
            }
        }
    }
}

Scan source code

In this pipeline example, we will perform the following steps

  1. Check out source code from git.

  2. Scan the source code using Deepfactor and generate CycloneDX SBOM.

  3. Store the CycloneDX SBOM file as a pipeline artifact.

Note: As mentioned in the earlier section, since we want the scan the source code directory, we have to mount a volume to the scan container so Deepfactor scanner can access and scan the source code.

pipeline {
    // agent any
    // or an agent node
    agent any
    environment {
        DF_RUN_TOKEN=credentials('DF_RUN_TOKEN')
        OUTPUT_FOLDER='archive'
        OUTPUT_FILE_NAME= 'report.cdx.json'
    }
    stages {
        stage('Pull source code') {
            steps {
                git 'https://github.com/django-ve/django-helloworld.git'
            }
        }
        stage('Deepfactor static scan') {
            steps {
                // scanning the entire workspace
                sh('docker run --rm -e DF_RUN_TOKEN=$DF_RUN_TOKEN --network host -v /var/run/docker.sock:/var/run/docker.sock -v "$WORKSPACE/$OUTPUT_FOLDER:/$OUTPUT_FOLDER" -v "$WORKSPACE:$WORKSPACE" public.ecr.aws/deepfactor/df/runtime:latest dfctl scan -s fs -a django -c hello -V 1 -f cyclonedx -O "/$OUTPUT_FOLDER/$OUTPUT_FILE_NAME" "$WORKSPACE"')
            }
        }
        stage('Archive output') {
            steps {
                archiveArtifacts artifacts: OUTPUT_FOLDER + '/*'
            }
        }
    }
}

GitLab

Prerequisite

Store Deepfactor run token as a variable in GitLab

As mentioned earlier, we recommend storing the Deepfactor run token as a secret. You can achieve that in GitLab using the following steps

  • Navigate in your project to Settings > CI/CD > Variables and click Add variable

gitlab_secret_1.png
  • Add key DF_RUN_TOKEN, and make sure to check Mask variable

  • The value (DF_RUN_TOKEN) can be obtained from Deepfactor portal

gitlab_secret_2.png
  • Once added DF_RUN_TOKEN can be referenced in pipeline script

Scan examples

Scan a container image and generate CycloneDX SBOM

In this pipeline example, we will perform the following steps

  1. Build a container image.

  2. Scan the built container image using Deepfactor and generate CycloneDX SBOM.

  3. Store the CycloneDX SBOM file as a pipeline artifact.

Note: As mentioned in the earlier section, since we want the store the scan output, CycloneDX SBOM file as a pipeline artifact, we have to mount a volume where the Deepfactor scan container can store the requested output files.

variables:
  OUTPUT_FORMAT: cyclonedx
  OUTPUT_FILENAME: "report.cdx.json"
  ARTIFACTS_FOLDER_NAME: "artifacts"

build_image:
  script:
    - docker build . -t helloworld
scan_image:
  script:
    - docker run --rm -e DF_RUN_TOKEN=$DF_RUN_TOKEN --network host -v /var/run/docker.sock:/var/run/docker.sock -v $CI_PROJECT_DIR/$ARTIFACTS_FOLDER_NAME:/$ARTIFACTS_FOLDER_NAME public.ecr.aws/deepfactor/df/runtime:latest dfctl scan -f $OUTPUT_FORMAT -O /$ARTIFACTS_FOLDER_NAME/$OUTPUT_FILENAME helloworld

  artifacts:
    paths:
      - $ARTIFACTS_FOLDER_NAME/*

Scan source code

In this pipeline example, we will perform the following steps

  1. Scan the source code using Deepfactor and generate CycloneDX SBOM.

  2. Store the CycloneDX SBOM file as a pipeline artifact.

variables:
  OUTPUT_FORMAT: cyclonedx
  OUTPUT_FILENAME: "report.cdx.json"
  ARTIFACTS_FOLDER_NAME: "artifacts"
scan_files:
  script:
    - docker run --rm -e DF_RUN_TOKEN=$DF_RUN_TOKEN --network host -v /var/run/docker.sock:/var/run/docker.sock -v $CI_PROJECT_DIR/$ARTIFACTS_FOLDER_NAME:/$ARTIFACTS_FOLDER_NAME -v $CI_PROJECT_DIR:$CI_PROJECT_DIR public.ecr.aws/deepfactor/df/runtime:latest dfctl scan -s fs -a django -c helloworld -V 1 -f $OUTPUT_FORMAT -O /$ARTIFACTS_FOLDER_NAME/$OUTPUT_FILENAME $CI_PROJECT_DIR

  artifacts:
    paths:
      - $ARTIFACTS_FOLDER_NAME/*
Was this article helpful?
0 out of 0 found this helpful

Comments

0 comments

Please sign in to leave a comment.