Dependency-track Jenkins Integration

Dependency-Track is an open-source software tool designed for software supply chain and vulnerability management. It helps organizations identify and reduce risk in their software dependencies and manage component-based development projects effectively.

Key Features of Dependency-Track:

  1. Bill of Materials (BOM):
    • Supports BOM formats like CycloneDX for managing software dependencies.
    • Tracks all third-party and first-party components in your projects.
  2. Vulnerability Management:
    • Integrates with vulnerability databases such as NVD, OSS Index, and others.
    • Identifies vulnerabilities in software dependencies and offers remediation suggestions.
  3. License Compliance:
    • Tracks software licenses associated with dependencies.
    • Helps ensure adherence to legal and compliance requirements.
  4. Risk Analysis:
    • Provides insights into dependency risks, including known vulnerabilities and outdated libraries.
    • Prioritizes remediation based on severity and exploitability.
  5. Automation and CI/CD Integration:
    • Integrates with CI/CD pipelines to automate security checks during builds.
    • Generates SBOMs and evaluates dependencies in real time.
  6. Dashboard and Reporting:
    • Intuitive dashboards for monitoring project risks.
    • Detailed reports on dependency status, vulnerabilities, and trends over time.

Steps for Dependency-track and Jenkins Integration :

  1. Dependency-Track Jenkins Plugin:
  • Install the OWASP Dependency-Track plugin from the Jenkins Plugin Manager. This plugin enables Jenkins to interact with Dependency-Track by uploading CycloneDX BOMs (Bill of Materials) and receiving analysis results.
  • Configure the plugin with your Dependency-Track API URL and an API key. Ensure the API key has the necessary permissions (BOM_UPLOAD, VIEW_PORTFOLIO, and optionally PROJECT_CREATION_UPLOAD for auto-creating projects).
  • Set up a pipeline stage to generate a CycloneDX BOM (e.g., using Maven, Gradle, or NPM tools) and upload it to Dependency-Track via the plugin.
  •  create the API key in dependency track UI and add this in jenkins credentials

generates a BOM file in the target directory as bom.xml. in following command

mvn cyclonedx:makeAggregateBom

2. Upload this BOM.xml file in Dependency track:

  • Dependency-Track relies on CycloneDX BOMs. Use tools like Maven, Gradle, or CycloneDX CLI to generate BOM files for your projects. For non-standard environments, you can use cURL to upload the BOM directly via API.

3. Setting up dependency track in a Jenkins Pipeline :

Add the dependency track stage in your Jenkinsfile.

Jenkinsfile is as Follows:

pipeline {
agent any

environment {
DOCKERHUB_CREDENTIALS = credentials('dockerhubpwd')
SLACK_CREDENTIALS = credentials('b3ee302b-e782-4d8e-ba83-7fa591d43205')
DEP_TRACK_API_KEY = credentials('d_track_id')
BOM_FILE_PATH = 'Desktop/testhello/target'
DEP_TRACK_SERVER_URL = 'http://localhost:8025'
DEP_TRACK_PROJECT_ID = '33d794ea-e8d3-49fd-b8f8-0c6cbce382cf'
MAVEN_HOME = 'Maven 3.8.4'
SONARQUBE_CREDENTIALS = credentials('sonar_d_token') // Add your SonarQube credentials here
SONARQUBE_SERVER = 'http://localhost:9000' // Set your SonarQube server URL here
}

parameters {
string(name: 'JAVA_REPO', defaultValue: 'Your project repo name', description: 'Java Application Repository')
string(name: 'DOCKERHUB_USERNAME', defaultValue: 'your Dockerhub Username', description: 'DockerHub Username')
string(name: 'JAVA_IMAGE_NAME', defaultValue: 'testhello', description: 'Java Docker Image Name')
string(name: 'JAVA_NAMESPACE', defaultValue: 'test', description: 'Kubernetes Namespace for Java Application')
}

stages {
stage('Clone Repository') {
steps {
git url: params.JAVA_REPO, branch: 'main'
}
}

stage('SonarQube Analysis') {
steps {
dir('testhello') {
withSonarQubeEnv('SonarQube') {
sh '''
mvn sonar:sonar \
-Dsonar.projectKey=testhello \
-Dsonar.host.url=${SONARQUBE_SERVER} \
-Dsonar.login=${SONARQUBE_CREDENTIALS}
'''
}
}
}
}

stage('Build and Push Docker Image') {
steps {
dir('testhello') {
sh 'mvn clean install'
script {
def image = docker.build("${params.DOCKERHUB_USERNAME}/${params.JAVA_IMAGE_NAME}:${currentBuild.number}")
docker.withRegistry('', 'dockerhubpwd') {
image.push()
}
}
}
}
}

stage('Generate BOM') {
steps {
dir('testhello') {
// Generate BOM file using CycloneDX Maven plugin
sh 'mvn org.cyclonedx:cyclonedx-maven-plugin:makeAggregateBom'
}
}
}

stage('Download Dependency-Track CLI') {
steps {
sh 'curl -L -o dependency-track-cli.jar https://example.com/path/to/dependency-track-cli.jar'
}
}

stage('Upload BOM to Dependency-Track') {
steps {
sh ''' curl -X POST "${DEP_TRACK_SERVER_URL}/api/v1/bom" \
-H "X-Api-Key: ${DEP_TRACK_API_KEY}" \
-H "Content-Type: multipart/form-data" \
-F "project=${DEP_TRACK_PROJECT_ID}" \
-F "bom=@/home/ubuntu/Desktop/testhello/target/bom.xml"
'''
}
}

stage('Get Approval') {
steps {
script {
input message: 'Do you approve this deployment?', ok: 'Yes, deploy'
}
}
}

stage('Install yq') {
steps {
sh """
wget https://github.com/mikefarah/yq/releases/download/v4.6.1/yq_linux_amd64 -O "${WORKSPACE}/yq"
chmod +x "${WORKSPACE}/yq"
export PATH="${WORKSPACE}:$PATH"
"""
}
}

stage('Build and Package Java Helm Chart') {
steps {
dir('testhello') {
sh """
"${WORKSPACE}/yq" e -i '.image.tag = "latest"' ./myspringbootchart/values.yaml
helm template ./myspringbootchart
helm lint ./myspringbootchart
helm package ./myspringbootchart --version "1.0.0"
"""
}
}
}

stage('Deploy Java Application to Kubernetes') {
steps {
script {
kubernetesDeploy(
configs: 'Build and Deploy Java and Python Applications',
kubeconfigId: 'kubeconfig1pwd'
)
}
}
}
}

post {
always {
echo 'Pipeline completed.'
emailext(
to: 'your mail address',
subject: "Jenkins Build ${env.JOB_NAME} #${env.BUILD_NUMBER} ${currentBuild.currentResult}",
body: """<p>Build ${env.JOB_NAME} #${env.BUILD_NUMBER} finished with status: ${currentBuild.currentResult}</p>
<p>Check console output at ${env.BUILD_URL}</p>""",
mimeType: 'text/html'
)
}

failure {
emailext(
to: 'your mail address',
subject: "Jenkins Build ${env.JOB_NAME} #${env.BUILD_NUMBER} Failed",
body: """<p>Build ${env.JOB_NAME} #${env.BUILD_NUMBER} failed.</p>
<p>Check console output at ${env.BUILD_URL}</p>""",
mimeType: 'text/html'
)
}

success {
emailext(
to: 'your mail address',
subject: "Jenkins Build ${env.JOB_NAME} #${env.BUILD_NUMBER} Succeeded",
body: """<p>Build ${env.JOB_NAME} #${env.BUILD_NUMBER} succeeded.</p>
<p>Check console output at ${env.BUILD_URL}</p>""",
mimeType: 'text/html'
)
}
}
}


Mahesh Wabale
Latest posts by Mahesh Wabale (see all)

Leave a Comment