Skip to content

MLE-22024: Add BlackDuck scan for latest images #359

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 7 commits into
base: develop
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 53 additions & 4 deletions Jenkinsfile
Original file line number Diff line number Diff line change
Expand Up @@ -368,9 +368,38 @@ void publishToInternalRegistry() {
/**
* Triggers a BlackDuck scan job for the published image.
* Runs asynchronously (wait: false).
*
* @param scanType Type of scan to perform:
* - 'current' (default): Scans only the currently built image
* - 'latest': Scans all latest standard MarkLogic Docker images from DockerHub
*/
void scanWithBlackDuck() {
build job: 'securityscans/Blackduck/KubeNinjas/docker', wait: false, parameters: [ string(name: 'branch', value: "${env.BRANCH_NAME}"), string(name: 'CONTAINER_IMAGES', value: "${dockerRegistry}/${publishImage}") ]
void scanWithBlackDuck(String scanType = 'current') {
if (scanType == 'latest') {
// Fetch all latest MarkLogic Docker images from DockerHub
def dockerHubImages = sh(script: '''
curl -s "https://hub.docker.com/v2/repositories/marklogic/marklogic-server/tags?page_size=100" | \
jq -r '.results[] | select(.name | startswith("latest-")) | "marklogic/marklogic-server:" + .name'
Comment on lines +380 to +381
Copy link
Preview

Copilot AI Jun 25, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Limiting 'page_size=100' may miss tags if the repository grows beyond 100; consider implementing pagination to ensure all 'latest-*' tags are retrieved.

Suggested change
curl -s "https://hub.docker.com/v2/repositories/marklogic/marklogic-server/tags?page_size=100" | \
jq -r '.results[] | select(.name | startswith("latest-")) | "marklogic/marklogic-server:" + .name'
page=1
all_tags=""
while true; do
response=$(curl -s "https://hub.docker.com/v2/repositories/marklogic/marklogic-server/tags?page_size=100&page=$page")
tags=$(echo "$response" | jq -r '.results[] | select(.name | startswith("latest-")) | "marklogic/marklogic-server:" + .name')
if [ -z "$tags" ]; then
break
fi
all_tags="$all_tags\n$tags"
page=$((page + 1))
done
echo -e "$all_tags" | sed '/^$/d'

Copilot uses AI. Check for mistakes.

''', returnStdout: true).trim()

// Use only the standard MarkLogic Docker images
def allImages = dockerHubImages

// Filter out empty lines and create comma-separated list
def imageList = allImages.split('\n').findAll { it.trim() != '' }.join(',')
Comment on lines +384 to +388
Copy link
Preview

Copilot AI Jun 25, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The variable 'allImages' simply aliases 'dockerHubImages'; consider removing this redundant assignment and using 'dockerHubImages' directly to reduce indirection.

Suggested change
// Use only the standard MarkLogic Docker images
def allImages = dockerHubImages
// Filter out empty lines and create comma-separated list
def imageList = allImages.split('\n').findAll { it.trim() != '' }.join(',')
// Filter out empty lines and create comma-separated list
def imageList = dockerHubImages.split('\n').findAll { it.trim() != '' }.join(',')

Copilot uses AI. Check for mistakes.


echo "Scanning the following standard MarkLogic Docker images with BlackDuck: ${imageList}"

build job: 'securityscans/Blackduck/KubeNinjas/docker', wait: false, parameters: [
string(name: 'branch', value: "${env.BRANCH_NAME}"),
string(name: 'CONTAINER_IMAGES', value: "${imageList}")
]
} else {
// Default behavior - scan only the current built image
build job: 'securityscans/Blackduck/KubeNinjas/docker', wait: false, parameters: [
string(name: 'branch', value: "${env.BRANCH_NAME}"),
string(name: 'CONTAINER_IMAGES', value: "${dockerRegistry}/${publishImage}")
]
}
}

/**
Expand Down Expand Up @@ -425,14 +454,16 @@ pipeline {
// Trigger nightly builds on the develop branch for every supported version of MarkLogic
// and for every supported image type.
// Include SCAP scan for rootless images
// Run weekly scan of all latest DockerHub images on Mondays at 1 AM
parameterizedCron( env.BRANCH_NAME == 'develop' ? '''00 02 * * * % marklogicVersion=10;dockerImageType=ubi
00 02 * * * % marklogicVersion=10;dockerImageType=ubi-rootless;SCAP_SCAN=true
00 02 * * * % marklogicVersion=11;dockerImageType=ubi
30 02 * * * % marklogicVersion=11;dockerImageType=ubi-rootless;SCAP_SCAN=true
30 02 * * * % marklogicVersion=12;dockerImageType=ubi
30 02 * * * % marklogicVersion=12;dockerImageType=ubi-rootless;SCAP_SCAN=true
00 03 * * * % marklogicVersion=11;dockerImageType=ubi9
00 03 * * * % marklogicVersion=11;dockerImageType=ubi9-rootless;SCAP_SCAN=true''' : '')
00 03 * * * % marklogicVersion=11;dockerImageType=ubi9-rootless;SCAP_SCAN=true
00 01 * * 1 % SCAN_LATEST_IMAGES=true''' : '')
}
environment {
QA_LICENSE_KEY = credentials('QA_LICENSE_KEY')
Expand All @@ -450,6 +481,7 @@ pipeline {
booleanParam(name: 'TEST_STRUCTURE', defaultValue: true, description: 'Run container structure tests')
booleanParam(name: 'DOCKER_TESTS', defaultValue: true, description: 'Run docker tests')
booleanParam(name: 'SCAP_SCAN', defaultValue: false, description: 'Run Open SCAP scan on the image.')
booleanParam(name: 'SCAN_LATEST_IMAGES', defaultValue: false, description: 'Scan all latest standard MarkLogic Docker images from DockerHub with BlackDuck')
}

stages {
Expand Down Expand Up @@ -546,13 +578,30 @@ pipeline {
when {
anyOf {
branch 'develop'
expression { return params.PUBLISH_IMAGE }
expression { return params.PUBLISH_IMAGE && env.BRANCH_NAME != 'master' }
}
}
steps {
scanWithBlackDuck()
}
}

// Stage: Scan all latest standard MarkLogic images from DockerHub
stage('Scan-Latest-Docker-Images') {
Copy link
Preview

Copilot AI Jun 25, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] This stage can be triggered on any branch when SCAN_LATEST_IMAGES=true; consider adding a branch filter (e.g., only on 'develop') to avoid unintended scans on feature or release branches.

Copilot uses AI. Check for mistakes.

when {
anyOf {
// Can be triggered manually with SCAN_LATEST_IMAGES=true
expression { return params.SCAN_LATEST_IMAGES }
// Schedule it to run weekly on Monday at 1 AM using a cron trigger at pipeline level
}
}
steps {
echo 'Scanning all latest standard MarkLogic Docker images from DockerHub...'
scanWithBlackDuck('latest')
}
}



}

Expand Down