From b87ddac0cfc4bb7cb2ceb2101126f64fdf71d549 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iv=C3=A1n=20Contreras?= Date: Thu, 9 May 2024 16:45:02 -0500 Subject: [PATCH 01/21] NEXUS-42440 Change redhat docker release image --- Jenkinsfile.rh | 21 +++++++++++++++++++-- build_red_hat_image.sh | 4 +--- build_red_hat_image_for_java11.sh | 3 +-- 3 files changed, 21 insertions(+), 7 deletions(-) diff --git a/Jenkinsfile.rh b/Jenkinsfile.rh index cd0594b3..ee859b95 100644 --- a/Jenkinsfile.rh +++ b/Jenkinsfile.rh @@ -41,10 +41,19 @@ node('ubuntu-zion') { credentialsId: 'red-hat-api-token', variable: 'API_TOKEN') ]) { + def dockerfilePath = 'Dockerfile.rh.ubi' if (params.java_version == OPENJDK11) { - sh 'PATH="$PATH:." VERSION=$version ./build_red_hat_image_for_java11.sh' + dockerfilePath = 'Dockerfile.rh.ubi.java11' + } + + def baseImage = extractBaseImage(dockerfilePath) + def baseImageRefFactory = load 'scripts/BaseImageReference.groovy' + def baseImageReference = baseImageRefFactory.build(this, baseImage as String) + def baseImageReferenceStr = baseImageReference.getReference() + if (params.java_version == OPENJDK11) { + sh "PATH='\$PATH:.' VERSION=${version} DOCKERFILE=${dockerfilePath} BASE_IMG_REF=${baseImageReferenceStr} ./build_red_hat_image_for_java11.sh" } else { - sh 'PATH="$PATH:." VERSION=$version ./build_red_hat_image.sh' + sh "PATH='\$PATH:.' VERSION=${version} DOCKERFILE=${dockerfilePath} BASE_IMG_REF=${baseImageReferenceStr} ./build_red_hat_image.sh" } } } @@ -54,3 +63,11 @@ node('ubuntu-zion') { sh 'git clean -f && git reset --hard origin/main' } } + +def extractBaseImage (dockerFileLocation) { + def dockerFile = readFile(file: dockerFileLocation) + def baseImageRegex = "FROM\\s+([^\\s]+)" + def usedImages = dockerFile =~ baseImageRegex + + return usedImages[0][1] +} \ No newline at end of file diff --git a/build_red_hat_image.sh b/build_red_hat_image.sh index eed577aa..d8a217e3 100755 --- a/build_red_hat_image.sh +++ b/build_red_hat_image.sh @@ -28,8 +28,6 @@ set -x # log commands as they execute set -e # stop execution on the first failed command -DOCKERFILE=Dockerfile.rh.ubi - # from config/scanning page at red hat CERT_PROJECT_ID=5e61d90a38776799eb517bd2 @@ -39,7 +37,7 @@ IMAGE_LATEST="${REPOSITORY}/redhat-isv-containers/${CERT_PROJECT_ID}:latest" AUTHFILE="${HOME}/.docker/config.json" -docker build -f "${DOCKERFILE}" -t "${IMAGE_TAG}" . +docker build -f "${DOCKERFILE}" --label base-image-ref=${BASE_IMG_REF} -t "${IMAGE_TAG}" . docker tag "${IMAGE_TAG}" "${IMAGE_LATEST}" docker login "${REPOSITORY}" \ diff --git a/build_red_hat_image_for_java11.sh b/build_red_hat_image_for_java11.sh index f48de3fc..871281c6 100755 --- a/build_red_hat_image_for_java11.sh +++ b/build_red_hat_image_for_java11.sh @@ -28,7 +28,6 @@ set -x # log commands as they execute set -e # stop execution on the first failed command -DOCKERFILE=Dockerfile.rh.ubi.java11 JAVA_VERSION="java11" # from config/scanning page at red hat @@ -39,7 +38,7 @@ IMAGE_TAG="${REPOSITORY}/redhat-isv-containers/${CERT_PROJECT_ID}:${VERSION}-${J AUTHFILE="${HOME}/.docker/config.json" -docker build -f "${DOCKERFILE}" -t "${IMAGE_TAG}" . +docker build -f "${DOCKERFILE}" --label base-image-ref=${BASE_IMG_REF} -t "${IMAGE_TAG}" . docker tag "${IMAGE_TAG}" docker login "${REPOSITORY}" \ From ed4af4de74465a198f46f74a219475c7ce0bed3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iv=C3=A1n=20Contreras?= Date: Thu, 9 May 2024 19:41:25 -0500 Subject: [PATCH 02/21] NEXUS-42440 Comment changes to avoid publishing the image --- build_red_hat_image.sh | 34 +++++++++++++++++++------------ build_red_hat_image_for_java11.sh | 32 ++++++++++++++++++----------- 2 files changed, 41 insertions(+), 25 deletions(-) diff --git a/build_red_hat_image.sh b/build_red_hat_image.sh index d8a217e3..2af56c49 100755 --- a/build_red_hat_image.sh +++ b/build_red_hat_image.sh @@ -40,16 +40,24 @@ AUTHFILE="${HOME}/.docker/config.json" docker build -f "${DOCKERFILE}" --label base-image-ref=${BASE_IMG_REF} -t "${IMAGE_TAG}" . docker tag "${IMAGE_TAG}" "${IMAGE_LATEST}" -docker login "${REPOSITORY}" \ - -u "${REGISTRY_LOGIN}" \ - --password "${REGISTRY_PASSWORD}" - -docker push "${IMAGE_TAG}" -docker push "${IMAGE_LATEST}" - -preflight check container \ - "${IMAGE_TAG}" \ - --docker-config="${AUTHFILE}" \ - --submit \ - --certification-project-id="${CERT_PROJECT_ID}" \ - --pyxis-api-token="${API_TOKEN}" +echo "SLEEPING BEFORE PROCEEDING WITH THE TEST" +sleep 5 + +docker inspect ${IMAGE_TAG} +docker inspect ${IMAGE_LATEST} + +#docker login "${REPOSITORY}" \ +# -u "${REGISTRY_LOGIN}" \ +# --password "${REGISTRY_PASSWORD}" +# +#docker push "${IMAGE_TAG}" +#docker push "${IMAGE_LATEST}" +# +#preflight check container \ +# "${IMAGE_TAG}" \ +# --docker-config="${AUTHFILE}" \ +# --submit \ +# --certification-project-id="${CERT_PROJECT_ID}" \ +# --pyxis-api-token="${API_TOKEN}" + +echo "FINISHING" \ No newline at end of file diff --git a/build_red_hat_image_for_java11.sh b/build_red_hat_image_for_java11.sh index 871281c6..1cc6f4b4 100755 --- a/build_red_hat_image_for_java11.sh +++ b/build_red_hat_image_for_java11.sh @@ -41,15 +41,23 @@ AUTHFILE="${HOME}/.docker/config.json" docker build -f "${DOCKERFILE}" --label base-image-ref=${BASE_IMG_REF} -t "${IMAGE_TAG}" . docker tag "${IMAGE_TAG}" -docker login "${REPOSITORY}" \ - -u "${REGISTRY_LOGIN}" \ - --password "${REGISTRY_PASSWORD}" - -docker push "${IMAGE_TAG}" - -preflight check container \ - "${IMAGE_TAG}" \ - --docker-config="${AUTHFILE}" \ - --submit \ - --certification-project-id="${CERT_PROJECT_ID}" \ - --pyxis-api-token="${API_TOKEN}" +echo "SLEEPING BEFORE PROCEEDING WITH THE TEST" +sleep 5 + +docker inspect ${IMAGE_TAG} +docker inspect ${IMAGE_LATEST} + +#docker login "${REPOSITORY}" \ +# -u "${REGISTRY_LOGIN}" \ +# --password "${REGISTRY_PASSWORD}" +# +#docker push "${IMAGE_TAG}" +# +#preflight check container \ +# "${IMAGE_TAG}" \ +# --docker-config="${AUTHFILE}" \ +# --submit \ +# --certification-project-id="${CERT_PROJECT_ID}" \ +# --pyxis-api-token="${API_TOKEN}" + +echo "FINISHING" \ No newline at end of file From 6d54dd91cc0c6e9f00409304f24593b5ab0e2589 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iv=C3=A1n=20Contreras?= Date: Thu, 9 May 2024 20:09:11 -0500 Subject: [PATCH 03/21] NEXUS-42440 Comment withCredentials block --- Jenkinsfile.rh | 24 ++++++++++++------------ build_red_hat_image.sh | 3 +-- build_red_hat_image_for_java11.sh | 5 ++--- 3 files changed, 15 insertions(+), 17 deletions(-) diff --git a/Jenkinsfile.rh b/Jenkinsfile.rh index ee859b95..d8345dcd 100644 --- a/Jenkinsfile.rh +++ b/Jenkinsfile.rh @@ -32,15 +32,15 @@ node('ubuntu-zion') { ''' } stage('Build') { - withCredentials([ - usernamePassword( - credentialsId: 'red-hat-quay-nexus-repository-manager', - usernameVariable: 'REGISTRY_LOGIN', - passwordVariable: 'REGISTRY_PASSWORD'), - string( - credentialsId: 'red-hat-api-token', - variable: 'API_TOKEN') - ]) { + //withCredentials([ + // usernamePassword( + // credentialsId: 'red-hat-quay-nexus-repository-manager', + // usernameVariable: 'REGISTRY_LOGIN', + // passwordVariable: 'REGISTRY_PASSWORD'), + // string( + // credentialsId: 'red-hat-api-token', + // variable: 'API_TOKEN') + //]) { def dockerfilePath = 'Dockerfile.rh.ubi' if (params.java_version == OPENJDK11) { dockerfilePath = 'Dockerfile.rh.ubi.java11' @@ -51,11 +51,11 @@ node('ubuntu-zion') { def baseImageReference = baseImageRefFactory.build(this, baseImage as String) def baseImageReferenceStr = baseImageReference.getReference() if (params.java_version == OPENJDK11) { - sh "PATH='\$PATH:.' VERSION=${version} DOCKERFILE=${dockerfilePath} BASE_IMG_REF=${baseImageReferenceStr} ./build_red_hat_image_for_java11.sh" + sh "PATH=\$PATH:. VERSION='${version}' DOCKERFILE='${dockerfilePath}' BASE_IMG_REF='${baseImageReferenceStr}' ./build_red_hat_image_for_java11.sh" } else { - sh "PATH='\$PATH:.' VERSION=${version} DOCKERFILE=${dockerfilePath} BASE_IMG_REF=${baseImageReferenceStr} ./build_red_hat_image.sh" + sh "PATH=\$PATH:. VERSION='${version}' DOCKERFILE='${dockerfilePath}' BASE_IMG_REF='${baseImageReferenceStr}' ./build_red_hat_image.sh" } - } + //} } } finally { sh 'docker logout' diff --git a/build_red_hat_image.sh b/build_red_hat_image.sh index 2af56c49..f33da181 100755 --- a/build_red_hat_image.sh +++ b/build_red_hat_image.sh @@ -40,10 +40,9 @@ AUTHFILE="${HOME}/.docker/config.json" docker build -f "${DOCKERFILE}" --label base-image-ref=${BASE_IMG_REF} -t "${IMAGE_TAG}" . docker tag "${IMAGE_TAG}" "${IMAGE_LATEST}" -echo "SLEEPING BEFORE PROCEEDING WITH THE TEST" +echo "##### CHECK HERE IF THE PRODUCED IMAGE CONTAINS A VALID VALUE OF base-image-ref IN LABELS ######" sleep 5 -docker inspect ${IMAGE_TAG} docker inspect ${IMAGE_LATEST} #docker login "${REPOSITORY}" \ diff --git a/build_red_hat_image_for_java11.sh b/build_red_hat_image_for_java11.sh index 1cc6f4b4..8c008629 100755 --- a/build_red_hat_image_for_java11.sh +++ b/build_red_hat_image_for_java11.sh @@ -39,13 +39,12 @@ IMAGE_TAG="${REPOSITORY}/redhat-isv-containers/${CERT_PROJECT_ID}:${VERSION}-${J AUTHFILE="${HOME}/.docker/config.json" docker build -f "${DOCKERFILE}" --label base-image-ref=${BASE_IMG_REF} -t "${IMAGE_TAG}" . -docker tag "${IMAGE_TAG}" +docker tag "${IMAGE_TAG}" "${IMAGE_TAG}" -echo "SLEEPING BEFORE PROCEEDING WITH THE TEST" +echo "##### CHECK HERE IF THE PRODUCED IMAGE CONTAINS A VALID VALUE OF base-image-ref IN LABELS ######" sleep 5 docker inspect ${IMAGE_TAG} -docker inspect ${IMAGE_LATEST} #docker login "${REPOSITORY}" \ # -u "${REGISTRY_LOGIN}" \ From 709eef24ae1a0e69382fea2749929bc9d9b4eb1a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iv=C3=A1n=20Contreras?= Date: Thu, 9 May 2024 21:31:08 -0500 Subject: [PATCH 04/21] NEXUS-42440 Uncomment and delete temporal lines added for testing --- Jenkinsfile.rh | 22 +++++++++++----------- build_red_hat_image.sh | 31 +++++++++++++------------------ build_red_hat_image_for_java11.sh | 29 ++++++++++++----------------- 3 files changed, 36 insertions(+), 46 deletions(-) diff --git a/Jenkinsfile.rh b/Jenkinsfile.rh index d8345dcd..bb48b901 100644 --- a/Jenkinsfile.rh +++ b/Jenkinsfile.rh @@ -32,15 +32,15 @@ node('ubuntu-zion') { ''' } stage('Build') { - //withCredentials([ - // usernamePassword( - // credentialsId: 'red-hat-quay-nexus-repository-manager', - // usernameVariable: 'REGISTRY_LOGIN', - // passwordVariable: 'REGISTRY_PASSWORD'), - // string( - // credentialsId: 'red-hat-api-token', - // variable: 'API_TOKEN') - //]) { + withCredentials([ + usernamePassword( + credentialsId: 'red-hat-quay-nexus-repository-manager', + usernameVariable: 'REGISTRY_LOGIN', + passwordVariable: 'REGISTRY_PASSWORD'), + string( + credentialsId: 'red-hat-api-token', + variable: 'API_TOKEN') + ]) { def dockerfilePath = 'Dockerfile.rh.ubi' if (params.java_version == OPENJDK11) { dockerfilePath = 'Dockerfile.rh.ubi.java11' @@ -55,7 +55,7 @@ node('ubuntu-zion') { } else { sh "PATH=\$PATH:. VERSION='${version}' DOCKERFILE='${dockerfilePath}' BASE_IMG_REF='${baseImageReferenceStr}' ./build_red_hat_image.sh" } - //} + } } } finally { sh 'docker logout' @@ -70,4 +70,4 @@ def extractBaseImage (dockerFileLocation) { def usedImages = dockerFile =~ baseImageRegex return usedImages[0][1] -} \ No newline at end of file +} diff --git a/build_red_hat_image.sh b/build_red_hat_image.sh index f33da181..976a1d12 100755 --- a/build_red_hat_image.sh +++ b/build_red_hat_image.sh @@ -20,6 +20,8 @@ # * https://github.com/redhat-openshift-ecosystem/openshift-preflight # * https://podman.io/ # * environment variables: +# * DOCKERFILE to be built +# * BASE_IMG_REF to add as a label to the image # * VERSION of the docker image to build for the red hat registry # * REGISTRY_LOGIN from Red Hat config page for image # * REGISTRY_PASSWORD from Red Hat config page for image @@ -40,23 +42,16 @@ AUTHFILE="${HOME}/.docker/config.json" docker build -f "${DOCKERFILE}" --label base-image-ref=${BASE_IMG_REF} -t "${IMAGE_TAG}" . docker tag "${IMAGE_TAG}" "${IMAGE_LATEST}" -echo "##### CHECK HERE IF THE PRODUCED IMAGE CONTAINS A VALID VALUE OF base-image-ref IN LABELS ######" -sleep 5 +docker login "${REPOSITORY}" \ + -u "${REGISTRY_LOGIN}" \ + --password "${REGISTRY_PASSWORD}" -docker inspect ${IMAGE_LATEST} +docker push "${IMAGE_TAG}" +docker push "${IMAGE_LATEST}" -#docker login "${REPOSITORY}" \ -# -u "${REGISTRY_LOGIN}" \ -# --password "${REGISTRY_PASSWORD}" -# -#docker push "${IMAGE_TAG}" -#docker push "${IMAGE_LATEST}" -# -#preflight check container \ -# "${IMAGE_TAG}" \ -# --docker-config="${AUTHFILE}" \ -# --submit \ -# --certification-project-id="${CERT_PROJECT_ID}" \ -# --pyxis-api-token="${API_TOKEN}" - -echo "FINISHING" \ No newline at end of file +preflight check container \ + "${IMAGE_TAG}" \ + --docker-config="${AUTHFILE}" \ + --submit \ + --certification-project-id="${CERT_PROJECT_ID}" \ + --pyxis-api-token="${API_TOKEN}" diff --git a/build_red_hat_image_for_java11.sh b/build_red_hat_image_for_java11.sh index 8c008629..40578ecf 100755 --- a/build_red_hat_image_for_java11.sh +++ b/build_red_hat_image_for_java11.sh @@ -20,6 +20,8 @@ # * https://github.com/redhat-openshift-ecosystem/openshift-preflight # * https://podman.io/ # * environment variables: +# * DOCKERFILE to be built +# * BASE_IMG_REF to add as a label to the image # * VERSION of the docker image to build for the red hat registry # * REGISTRY_LOGIN from Red Hat config page for image # * REGISTRY_PASSWORD from Red Hat config page for image @@ -41,22 +43,15 @@ AUTHFILE="${HOME}/.docker/config.json" docker build -f "${DOCKERFILE}" --label base-image-ref=${BASE_IMG_REF} -t "${IMAGE_TAG}" . docker tag "${IMAGE_TAG}" "${IMAGE_TAG}" -echo "##### CHECK HERE IF THE PRODUCED IMAGE CONTAINS A VALID VALUE OF base-image-ref IN LABELS ######" -sleep 5 +docker login "${REPOSITORY}" \ + -u "${REGISTRY_LOGIN}" \ + --password "${REGISTRY_PASSWORD}" -docker inspect ${IMAGE_TAG} +docker push "${IMAGE_TAG}" -#docker login "${REPOSITORY}" \ -# -u "${REGISTRY_LOGIN}" \ -# --password "${REGISTRY_PASSWORD}" -# -#docker push "${IMAGE_TAG}" -# -#preflight check container \ -# "${IMAGE_TAG}" \ -# --docker-config="${AUTHFILE}" \ -# --submit \ -# --certification-project-id="${CERT_PROJECT_ID}" \ -# --pyxis-api-token="${API_TOKEN}" - -echo "FINISHING" \ No newline at end of file +preflight check container \ + "${IMAGE_TAG}" \ + --docker-config="${AUTHFILE}" \ + --submit \ + --certification-project-id="${CERT_PROJECT_ID}" \ + --pyxis-api-token="${API_TOKEN}" From ac8dbda2fc604c20ecc3b6753d0ffa11ba8016dc Mon Sep 17 00:00:00 2001 From: Sonatype Date: Thu, 16 May 2024 14:29:12 +0000 Subject: [PATCH 05/21] Update Repository Manager to 3.68.1-02. --- Dockerfile.java11 | 8 ++++---- Dockerfile.rh.ubi.java11 | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Dockerfile.java11 b/Dockerfile.java11 index 8a965af8..c536ef64 100644 --- a/Dockerfile.java11 +++ b/Dockerfile.java11 @@ -17,8 +17,8 @@ FROM registry.access.redhat.com/ubi8/ubi-minimal LABEL name="Nexus Repository Manager" \ maintainer="Sonatype " \ vendor=Sonatype \ - version="3.68.0-04" \ - release="3.68.0" \ + version="3.68.1-02" \ + release="3.68.1" \ url="https://sonatype.com" \ summary="The Nexus Repository Manager server \ with universal support for popular component formats." \ @@ -36,10 +36,10 @@ LABEL name="Nexus Repository Manager" \ io.openshift.expose-services="8081:8081" \ io.openshift.tags="Sonatype,Nexus,Repository Manager" -ARG NEXUS_VERSION=3.68.0-04 +ARG NEXUS_VERSION=3.68.1-02 ARG JAVA_VERSION=java11 ARG NEXUS_DOWNLOAD_URL=https://download.sonatype.com/nexus/3/nexus-${NEXUS_VERSION}-${JAVA_VERSION}-unix.tar.gz -ARG NEXUS_DOWNLOAD_SHA256_HASH=aa03f3c5511579f42b6bdacdfe9f1e1634aea41ff31a9a8a02cc47ab53cc8739 +ARG NEXUS_DOWNLOAD_SHA256_HASH=6a04eb770e0c4415d3033de757b07ddfdfd15beadbf839d4b33438246e4325a7 # configure nexus runtime ENV SONATYPE_DIR=/opt/sonatype diff --git a/Dockerfile.rh.ubi.java11 b/Dockerfile.rh.ubi.java11 index 99675b4c..7e7baac7 100644 --- a/Dockerfile.rh.ubi.java11 +++ b/Dockerfile.rh.ubi.java11 @@ -17,8 +17,8 @@ FROM registry.access.redhat.com/ubi8/ubi-minimal LABEL name="Nexus Repository Manager" \ vendor=Sonatype \ maintainer="Sonatype " \ - version="3.68.0-04" \ - release="3.68.0" \ + version="3.68.1-02" \ + release="3.68.1" \ url="https://sonatype.com" \ summary="The Nexus Repository Manager server \ with universal support for popular component formats." \ @@ -36,10 +36,10 @@ LABEL name="Nexus Repository Manager" \ io.openshift.expose-services="8081:8081" \ io.openshift.tags="Sonatype,Nexus,Repository Manager" -ARG NEXUS_VERSION=3.68.0-04 +ARG NEXUS_VERSION=3.68.1-02 ARG JAVA_VERSION=java11 ARG NEXUS_DOWNLOAD_URL=https://download.sonatype.com/nexus/3/nexus-${NEXUS_VERSION}-${JAVA_VERSION}-unix.tar.gz -ARG NEXUS_DOWNLOAD_SHA256_HASH=aa03f3c5511579f42b6bdacdfe9f1e1634aea41ff31a9a8a02cc47ab53cc8739 +ARG NEXUS_DOWNLOAD_SHA256_HASH=6a04eb770e0c4415d3033de757b07ddfdfd15beadbf839d4b33438246e4325a7 # configure nexus runtime ENV SONATYPE_DIR=/opt/sonatype From be5ce4cb855ff67693dc1c927a97dd2ea88ee212 Mon Sep 17 00:00:00 2001 From: Matthew Piggott Date: Thu, 16 May 2024 10:43:47 -0400 Subject: [PATCH 06/21] NEXUS-42789 - Remove quiet flag from buidls (#187) --- Jenkinsfile | 2 +- Jenkinsfile-Internal-Release | 2 +- Jenkinsfile-Release | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index 9f80515d..8176fda4 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -42,7 +42,7 @@ node('ubuntu-zion') { stage('Build') { gitHub.statusUpdate commitId, 'pending', 'build', 'Build is running' - def hash = OsTools.runSafe(this, "docker build --quiet --no-cache --tag ${imageName} .") + def hash = OsTools.runSafe(this, "docker build --no-cache --tag ${imageName} .") imageId = hash.split(':')[1] if (currentBuild.result == 'FAILURE') { diff --git a/Jenkinsfile-Internal-Release b/Jenkinsfile-Internal-Release index 3fe6ec7e..14aaa15f 100644 --- a/Jenkinsfile-Internal-Release +++ b/Jenkinsfile-Internal-Release @@ -75,7 +75,7 @@ node('ubuntu-zion') { def baseImageRefFactory = load 'scripts/BaseImageReference.groovy' def baseImageReference = baseImageRefFactory.build(this, baseImage as String) def baseImageReferenceStr = baseImageReference.getReference() - def hash = OsTools.runSafe(this, "docker build --quiet --label base-image-ref='${baseImageReferenceStr}' --no-cache --tag ${imageName} . -f ${dockerfilePath}") + def hash = OsTools.runSafe(this, "docker build --label base-image-ref='${baseImageReferenceStr}' --no-cache --tag ${imageName} . -f ${dockerfilePath}") imageId = hash.split(':')[1] } if (params.scan_for_policy_violations) { diff --git a/Jenkinsfile-Release b/Jenkinsfile-Release index 9a1fe1bc..eeb3c106 100644 --- a/Jenkinsfile-Release +++ b/Jenkinsfile-Release @@ -113,7 +113,7 @@ node('ubuntu-zion') { def baseImageRefFactory = load 'scripts/BaseImageReference.groovy' def baseImageReference = baseImageRefFactory.build(this, baseImage as String) def baseImageReferenceStr = baseImageReference.getReference() - def hash = OsTools.runSafe(this, "docker build --quiet --label base-image-ref='${baseImageReferenceStr}' --no-cache --tag ${imageName} . -f ${dockerfilePath}") + def hash = OsTools.runSafe(this, "docker build --label base-image-ref='${baseImageReferenceStr}' --no-cache --tag ${imageName} . -f ${dockerfilePath}") imageId = hash.split(':')[1] if (currentBuild.result == 'FAILURE') { From fd1dffce15b8042867243a27c16cec3b6798557d Mon Sep 17 00:00:00 2001 From: Olu Shiyanbade Date: Thu, 16 May 2024 16:19:43 +0100 Subject: [PATCH 07/21] fix docker tag command --- build_red_hat_image.sh | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/build_red_hat_image.sh b/build_red_hat_image.sh index eae0f5aa..9ab5e703 100755 --- a/build_red_hat_image.sh +++ b/build_red_hat_image.sh @@ -39,18 +39,16 @@ CERT_PROJECT_ID=5e61d90a38776799eb517bd2 REPOSITORY="quay.io" IMAGE_LATEST="${REPOSITORY}/redhat-isv-containers/${CERT_PROJECT_ID}:latest" IMAGE_TAG="${REPOSITORY}/redhat-isv-containers/${CERT_PROJECT_ID}:${VERSION}" -DOCKER_TAG_CMD="${IMAGE_TAG} ${IMAGE_LATEST}" if [[ $JAVA_VERSION != $JAVA_8 ]]; then DOCKERFILE="Dockerfile.rh.ubi.${JAVA_VERSION}" IMAGE_TAG="${REPOSITORY}/redhat-isv-containers/${CERT_PROJECT_ID}:${VERSION}-${JAVA_VERSION}" - DOCKER_TAG_CMD="${IMAGE_TAG}" fi AUTHFILE="${HOME}/.docker/config.json" docker build -f "${DOCKERFILE}" -t "${IMAGE_TAG}" . -docker tag "${DOCKER_TAG_CMD}" +docker tag "${IMAGE_TAG}" "${IMAGE_LATEST}" docker login "${REPOSITORY}" \ -u "${REGISTRY_LOGIN}" \ From 9571127694821a5ad22b7cdc5b468d9d7f8b3077 Mon Sep 17 00:00:00 2001 From: Jerson Huerfano Date: Thu, 16 May 2024 13:34:31 -0500 Subject: [PATCH 08/21] NEXUS-42442: Created Jenkinsfile to publish docker SBOMs --- Jenkinsfile-sbom-release | 195 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 195 insertions(+) create mode 100644 Jenkinsfile-sbom-release diff --git a/Jenkinsfile-sbom-release b/Jenkinsfile-sbom-release new file mode 100644 index 00000000..d0b099f3 --- /dev/null +++ b/Jenkinsfile-sbom-release @@ -0,0 +1,195 @@ +@Library(['private-pipeline-library', 'jenkins-shared']) _ + +import com.sonatype.jenkins.pipeline.OsTools + +import groovy.json.JsonSlurper + +IQ_URL_BASE = "https://sonatype.sonatype.app/platform" +REPO_BASE_URL = "https://repo.sonatype.com/service/rest" +TARGET_REPO_NAME = "sonatype-sboms" +REDHAT_SBOM_REPO_URL_BASE = "https://access.redhat.com/security/data/sbom/beta" +REDHAT_CONTAINER_API_URL_BASE = "https://catalog.redhat.com/api/containers/v1" +CYCLONEDX_VERSION = "1.5" + +properties([ + parameters([ + string(name: 'docker_nexus3_tag', defaultValue: '', + description: 'Nexus Repository Manager Version. The result SBOMs will be tagged with this version.') + ]) +]) + + +node('ubuntu-zion') { + def buildDir = "./.sbom-build/job-${env.BUILD_NUMBER}" + def ubiImageName = '' + def ubiImageVersion = '' + def nexusVersion = '' + def dockerImageVersion = '' + def ubiSbomAvailable = true + + try { + stage('Inspect Release Image') { + // Get RedHat UBI version + sh "docker pull sonatype/nexus3:${params.docker_nexus3_tag}" + + nexusVersion = sh(script: "docker inspect sonatype/nexus3:${params.docker_nexus3_tag} \ + | jq -r '.[0].Config.Labels.version' ", + returnStdout: true).trim() + dockerImageVersion = sh(script: "docker inspect sonatype/nexus3:${params.docker_nexus3_tag} \ + | jq -r '.[0].Config.Labels.release' ", + returnStdout: true).trim() + + def ubiImageId = sh(script: "docker inspect sonatype/nexus3:${params.docker_nexus3_tag} \ + | jq -r '.[0].Config.Labels.\"base-image-ref\"' \ + | sed -En 's/^.+image=(.+)\$/\\1/p'", + returnStdout: true).trim() + + ubiImageName = sh(script: "curl -s -X 'GET' '${REDHAT_CONTAINER_API_URL_BASE}/images/id/${ubiImageId}' -H 'accept: application/json' \ + | jq -r '.brew.build' \ + | sed -En 's/(ubi[0-9]+-minimal)-container-([0-9]+\\.[0-9]+-[0-9]+\\.?[0-9]*)/\\1-\\2/p'", + returnStdout: true).trim() + + ubiImageVersion = sh(script: "curl -s -X 'GET' '${REDHAT_CONTAINER_API_URL_BASE}/images/id/${ubiImageId}' -H 'accept: application/json' \ + | jq -r '.brew.build' \ + | sed -En 's/ubi[0-9]+-minimal-container-([0-9]+\\.[0-9]+-[0-9]+\\.?[0-9]*)/\\1/p'", + returnStdout: true).trim() + } + stage('Download SBOMs') { + sh "mkdir -p ${buildDir}/spdx && mkdir -p ${buildDir}/cyclonedx" + + // Get nexus-internal SBOM + getComponentSbom(buildDir, "nexus-internal", nexusVersion) + // Get nxrm-db-migrator SBOM + getComponentSbom(buildDir, "nxrm-db-migrator", nexusVersion) + // Get docker-nexus3 SBOM + getComponentSbom(buildDir, "docker-nexus3", dockerImageVersion) + // Get UBI Minimal SBOM + ubiSbomAvailable = getUbiImageSbom(buildDir, ubiImageName, ubiImageVersion) + + sh "echo 'Available SPDX SBOMS' && ls ${buildDir}/spdx" + sh "echo 'Available CycloneDx SBOMS' && ls ${buildDir}/cyclonedx" + } + + stage('Merge supported sboms') { + def pythonEnvDir = "${buildDir}/.spdxmerge" + + sh """#!/bin/bash + if ! [ -d "${buildDir}/SPDXMerge" ]; then + git clone https://github.com/philips-software/SPDXMerge.git '${buildDir}/SPDXMerge' + fi + """ + + sh """#!/bin/bash + if mkdir -p '${pythonEnvDir}' && python3 -m venv '${pythonEnvDir}' && ls '${pythonEnvDir}' && . '${pythonEnvDir}/bin/activate'; then + if python3 -m pip install -r '${buildDir}/SPDXMerge/requirements.txt' \ + && python3 -m pip install setuptools \ + && python3 '${buildDir}/SPDXMerge/spdxmerge/SPDXMerge.py' --docpath '${buildDir}/spdx' --outpath '${buildDir}/' \ + --name "docker-nexus3-aggregate" --mergetype "1" --author "Sonatype Inc." --email "support@sonatype.com" \ + --docnamespace "https://sonatype.sonatype.app/platform/ui/links/application/docker-nexus3/report/b0c5f7f12ac84b439ded3ff255bd5eef" \ + --filetype J \ + && mv '${buildDir}/merged-SBoM-deep.json' '${buildDir}/spdx/docker-nexus3-aggregate-${dockerImageVersion}-spdx.json'; then + echo 'Merge completed!' + else + echo 'Merge failed!' + FAILED=1 + fi + + deactivate + fi + + exit \${FAILED:-0} + """ + } + + stage('Publish SBOMs') { + if (ubiSbomAvailable) { + publishComponent(buildDir, "ubi-minimal", ubiImageVersion, false) + } + publishComponent(buildDir, "nexus-internal", nexusVersion) + publishComponent(buildDir, "nxrm-db-migrator", nexusVersion) + publishComponent(buildDir, "docker-nexus3", dockerImageVersion) + publishComponent(buildDir, "docker-nexus3-aggregate", dockerImageVersion, false) + } + } finally { + OsTools.runSafe(this, "rm -rf '${buildDir}'") + } +} + +def getComponentSbom(String buildDir, String componentName, String componentVersion) { + def componentInfo = getComponentInfo(componentName) + def componentId = componentInfo.applications[0].id + + withCredentials([ + usernamePassword( + credentialsId: 'jenkins-saas-service-acct', + usernameVariable: 'IQ_USER', + passwordVariable: 'IQ_PASSWORD') + ]) { + // Get SPDX + sh "curl -s -L -w 'Status: %{http_code}' -u \$IQ_USER:\$IQ_PASSWORD -o '${buildDir}/spdx/${componentName}-${componentVersion}-spdx.json' -X GET \ + -H 'Accept: application/json' '${IQ_URL_BASE}/api/v2/spdx/${componentId}/stages/release?format=json'" + // Get CycloneDx + sh "curl -s -L -w 'Status: %{http_code}' -u \$IQ_USER:\$IQ_PASSWORD -o '${buildDir}/cyclonedx/${componentName}-${componentVersion}-cyclonedx.json' -X GET \ + -H 'Accept: application/json' '${IQ_URL_BASE}/api/v2/cycloneDx/${CYCLONEDX_VERSION}/${componentId}/stages/release'" + } +} + +def getUbiImageSbom(String buildDir, String ubiMinimalName, String ubiMinimalVersion) { + // Get ubi-minimal SBOM (as RedHat SBOM repo is still in beta, this has to be optional) + def httpStatus = sh( + script: "curl -s -w \"%{http_code}\" \ + -X GET ${REDHAT_SBOM_REPO_URL_BASE}/spdx/${ubiMinimalName}.json.bz2 \ + -o '${buildDir}/spdx/ubi-minimal-${ubiMinimalVersion}.json.bz2'", + returnStdout: true) + + if (!"200".equals(httpStatus)) { + echo """ Error ${httpStatus}: Could not load UBI minimal SBOM version ${ubiMinimalVersion}. + This could happen because RedHat SBOM repo is still in beta. UBI SBOM will be skipped. + Please visit https://access.redhat.com/security/data for further information. + """ + + sh "rm '${buildDir}/spdx/ubi-minimal-${ubiMinimalVersion}.json.bz2'" + + return false + } else { + sh "(cd ${buildDir}/spdx && bzip2 -d 'ubi-minimal-${ubiMinimalVersion}.json.bz2')" + return true + } +} + +def getComponentInfo(String componentName) { + def jsonSlurper = new JsonSlurper() + def response = null + + withCredentials([ + usernamePassword( + credentialsId: 'jenkins-saas-service-acct', + usernameVariable: 'IQ_USER', + passwordVariable: 'IQ_PASSWORD') + ]) { + def rawResponse = sh(returnStdout: true, script: "curl -s -u \$IQ_USER:\$IQ_PASSWORD -X GET '${IQ_URL_BASE}/api/v2/applications?publicId=${componentName}'") + response = jsonSlurper.parseText(rawResponse) + } +} + +def publishComponent(String buildDir, String componentName, String componentVersion, boolean cyclonedxAvailable = true) { + def publishCommand = "curl -v -s -w 'Status: %{http_code}' -u \$NXRM_USER:\$NXRM_PASSWORD -X POST '${REPO_BASE_URL}/v1/components?repository=${TARGET_REPO_NAME}' \ + -F 'raw.directory=/${componentName}/${componentVersion}/' \ + -F 'raw.asset1=@${buildDir}/spdx/${componentName}-${componentVersion}-spdx.json' \ + -F 'raw.asset1.filename=${componentName}-${componentVersion}-spdx.json'" + + if (cyclonedxAvailable) { + publishCommand = "${publishCommand} \ + -F 'raw.asset2=@${buildDir}/cyclonedx/${componentName}-${componentVersion}-cyclonedx.json' \ + -F 'raw.asset2.filename=${componentName}-${componentVersion}-cyclonedx.json'" + } + + withCredentials([ + usernamePassword( + credentialsId: 'sonatype-sbom-deployer', + usernameVariable: 'NXRM_USER', + passwordVariable: 'NXRM_PASSWORD') + ]) { + sh(publishCommand) + } +} \ No newline at end of file From f2adeac0e53dc5112a90643c888684e3cd660044 Mon Sep 17 00:00:00 2001 From: mburkert3 <126404216+mburkert3@users.noreply.github.com> Date: Fri, 17 May 2024 01:59:01 -0400 Subject: [PATCH 09/21] Create Jenkinsfile-PrismaCloud --- Jenkinsfile-PrismaCloud | 179 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 179 insertions(+) create mode 100644 Jenkinsfile-PrismaCloud diff --git a/Jenkinsfile-PrismaCloud b/Jenkinsfile-PrismaCloud new file mode 100644 index 00000000..5a7947ec --- /dev/null +++ b/Jenkinsfile-PrismaCloud @@ -0,0 +1,179 @@ +@Library(['private-pipeline-library', 'jenkins-shared']) _ + +import com.sonatype.jenkins.pipeline.OsTools +import groovy.json.JsonSlurper + +IQ_URL_BASE = "https://sonatype.sonatype.app/platform" +PRISMA_CLOUD_ADDRESS = 'https://us-west1.cloud.twistlock.com/us-4-161054503' +CYCLONEDX_VERSION = "1.5" + +properties([ + parameters([ + string(name: 'BRANCH_TO_BUILD', defaultValue: '', + description: 'Branch the script will be loaded from'), + string(name: 'DOCKER_IMAGE_TAG', defaultValue: 'latest', + description: 'Tag of the Docker image to be scanned'), + string(name: 'NXRM_Version', defaultValue: '', + description: 'Nexus Repository Manager Version. The result SBOMs will be tagged with this version.') + ]) +]) + +def getComponentSbom(String componentName, String componentVersion, String buildDir) { + def componentInfo = getComponentInfo(componentName) + def componentId = componentInfo.applications[0].id + + withCredentials([ + usernamePassword( + credentialsId: 'jenkins-saas-service-acct', + usernameVariable: 'IQ_USER', + passwordVariable: 'IQ_PASSWORD') + ]) { + // Get CycloneDx + sh "curl -L -u \$IQ_USER:\$IQ_PASSWORD -o '${buildDir}/cyclonedx/${componentName}-${componentVersion}-cyclonedx.json' -X GET \ + -H 'Accept: application/json' '${IQ_URL_BASE}/api/v2/cycloneDx/${CYCLONEDX_VERSION}/${componentId}/stages/release'" + } +} + +def getComponentInfo(String componentName) { + def jsonSlurper = new JsonSlurper() + def response = null + + withCredentials([ + usernamePassword( + credentialsId: 'jenkins-saas-service-acct', + usernameVariable: 'IQ_USER', + passwordVariable: 'IQ_PASSWORD') + ]) { + def rawResponse = sh(returnStdout: true, script: "curl -s -u \$IQ_USER:\$IQ_PASSWORD -X GET '${IQ_URL_BASE}/api/v2/applications?publicId=${componentName}'") + response = jsonSlurper.parseText(rawResponse) + } + return response +} + +pipeline { + agent any + environment { + buildDir = "./.sbom-build/job-${env.BUILD_NUMBER}" + } + stages { + stage('Checkout') { + steps { + git branch: params.BRANCH_TO_BUILD, url: 'https://github.com/sonatype/docker-nexus3.git' + } + } + stage('Build Image') { + steps { + script { + runSafely("docker build -t docker-nexus3:${params.DOCKER_IMAGE_TAG} .") + } + } + } + stage('Analyze Image with Prisma Cloud') { + steps { + script { + prismaCloudScanImage( + ca: '', + cert: '', + dockerAddress: 'unix:///var/run/docker.sock', + ignoreImageBuildTime: true, + image: "docker-nexus3:${params.DOCKER_IMAGE_TAG}", + key: '', + logLevel: 'debug', + podmanPath: '', + project: '', + resultsFile: 'prisma-cloud-scan-results.json' + ) + } + } + } + stage('Analyze Image with IQ') { + steps { + script { + nexusPolicyEvaluation( + iqApplication: 'docker-nexus3', + iqStage: 'release', + iqScanPatterns: [[scanPattern: "container:docker-nexus3:${params.DOCKER_IMAGE_TAG}"]], + failBuildOnNetworkError: true, + serverUrl: IQ_URL_BASE, + credentialsId: 'nexus_iq_credentials' + ) + } + } + } + stage('Download SBOM') { + steps { + script { + sh "mkdir -p ${buildDir}/cyclonedx" + + // Get docker-nexus3 SBOM + getComponentSbom("docker-nexus3", params.nexus_repository_manager_version, buildDir) + + sh "echo 'Available CycloneDx SBOMS' && ls ${buildDir}/cyclonedx" + } + } + } + stage('Compare Red Hat Patched Versions') { + steps { + script { + // Pull latest Red Hat UBI image + def redHatImage = "registry.access.redhat.com/ubi8/ubi-minimal:8.9-1161.1715068733" + sh "docker pull ${redHatImage}" + + // Inspect the image to get the list of installed packages + def redHatPackages = sh(script: "docker run --rm ${redHatImage} rpm -qa --queryformat '%{NAME} %{VERSION}-%{RELEASE}\n'", returnStdout: true).trim().split('\n').collectEntries { + def parts = it.split(' ') + [(parts[0]): parts[1]] + } + + // Read the Prisma Cloud scan results + def prismaReportPath = "prisma-cloud-scan-results.json" + def prismaReportContent = readFile(file: prismaReportPath) + def prismaReport = new JsonSlurper().parseText(prismaReportContent) + + // Collect package names and versions from the Prisma Cloud report + def prismaPackages = prismaReport.results[0].entityInfo.packages.findAll { it.pkgsType == 'package' }[0].pkgs.collectEntries { + [(it.name): it.version ?: "unknown"] + } + + // Compare with Red Hat patched versions and amend to report + def mismatchedDependencies = [] + redHatPackages.each { name, version -> + def prismaVersion = prismaPackages.get(name, "unknown") + def match = prismaVersion == version + mismatchedDependencies << [ + name: name, + redHatVersion: version, + prismaVersion: prismaVersion, + match: match + ] + } + + // JSON format + def mismatchedReportJson = mismatchedDependencies.collect { dep -> + """{ + "name": "${dep.name}", + "redHatVersion": "${dep.redHatVersion}", + "prismaVersion": "${dep.prismaVersion}", + "match": ${dep.match} +}""" + }.join(',\n') + + def mismatchedReportPath = "${buildDir}/mismatched_report.json" + writeFile(file: mismatchedReportPath, text: mismatchedReportJson) + + sh "echo 'Mismatched Lifecycle Report' && cat ${mismatchedReportPath}" + } + } + } + } + post { + always { + prismaCloudPublish resultsFilePattern: 'prisma-cloud-scan-results.json' + archiveArtifacts artifacts: "prisma-cloud-scan-results.json", fingerprint: true + archiveArtifacts artifacts: ".sbom-build/job-${env.BUILD_NUMBER}/mismatched_report.json", fingerprint: true + script { + OsTools.runSafe(this, "rm -rf '${buildDir}'") + } + } + } +} From db05880884bda56fc3988f0b9a12790b4aa16afb Mon Sep 17 00:00:00 2001 From: Jerson Huerfano Date: Thu, 16 May 2024 21:51:32 -0500 Subject: [PATCH 10/21] NEXUS-42442: Switched to declarative pipeline syntax - Added Dockerfile.sbom-deployer to include missing tools - Include missing headers to files required by licence-check step - Using dockerizedRunPipeline function to dockerize the script. --- CONTRIBUTORS.md | 9 +- Dockerfile | 6 +- Jenkinsfile | 2 +- Jenkinsfile-sbom-release | 199 +++++++++++++------------- README.md | 7 +- SECURITY.md | 5 +- build-images/Dockerfile.sbom-deployer | 3 + build_red_hat_image.sh | 5 +- header.txt | 3 + rh-docker/help.md | 7 + rh-docker/uid_entrypoint.sh | 5 +- rh-docker/uid_template.sh | 5 +- scripts/BaseImageReference.groovy | 3 +- 13 files changed, 146 insertions(+), 113 deletions(-) create mode 100644 build-images/Dockerfile.sbom-deployer create mode 100644 header.txt diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index cea96504..360db89f 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -1,6 +1,11 @@ + + --> A lot of awesome people have contributed to this project! Here they are: diff --git a/Dockerfile b/Dockerfile index 6dfabf34..b2d9fc59 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,9 @@ -# Copyright (c) 2016-present Sonatype, Inc. # +# Copyright (c) 2016-present Sonatype, Inc. All rights reserved. +# Includes the third-party code listed at http://links.sonatype.com/products/nxrm/attributions. +# "Sonatype" is a trademark of Sonatype, Inc. +# + # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at diff --git a/Jenkinsfile b/Jenkinsfile index 8176fda4..30405c37 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -1,6 +1,6 @@ /* * Copyright (c) 2016-present Sonatype, Inc. All rights reserved. - * Includes the third-party code listed at http://links.sonatype.com/products/nexus/attributions. + * Includes the third-party code listed at http://links.sonatype.com/products/nxrm/attributions. * "Sonatype" is a trademark of Sonatype, Inc. */ @Library(['private-pipeline-library', 'jenkins-shared']) _ diff --git a/Jenkinsfile-sbom-release b/Jenkinsfile-sbom-release index d0b099f3..b7704ec7 100644 --- a/Jenkinsfile-sbom-release +++ b/Jenkinsfile-sbom-release @@ -1,6 +1,10 @@ -@Library(['private-pipeline-library', 'jenkins-shared']) _ +/* + * Copyright (c) 2011-present Sonatype, Inc. All rights reserved. + * Includes the third-party code listed at http://links.sonatype.com/products/clm/attributions. + * "Sonatype" is a trademark of Sonatype, Inc. + */ -import com.sonatype.jenkins.pipeline.OsTools +@Library(['private-pipeline-library', 'jenkins-shared']) _ import groovy.json.JsonSlurper @@ -18,103 +22,6 @@ properties([ ]) ]) - -node('ubuntu-zion') { - def buildDir = "./.sbom-build/job-${env.BUILD_NUMBER}" - def ubiImageName = '' - def ubiImageVersion = '' - def nexusVersion = '' - def dockerImageVersion = '' - def ubiSbomAvailable = true - - try { - stage('Inspect Release Image') { - // Get RedHat UBI version - sh "docker pull sonatype/nexus3:${params.docker_nexus3_tag}" - - nexusVersion = sh(script: "docker inspect sonatype/nexus3:${params.docker_nexus3_tag} \ - | jq -r '.[0].Config.Labels.version' ", - returnStdout: true).trim() - dockerImageVersion = sh(script: "docker inspect sonatype/nexus3:${params.docker_nexus3_tag} \ - | jq -r '.[0].Config.Labels.release' ", - returnStdout: true).trim() - - def ubiImageId = sh(script: "docker inspect sonatype/nexus3:${params.docker_nexus3_tag} \ - | jq -r '.[0].Config.Labels.\"base-image-ref\"' \ - | sed -En 's/^.+image=(.+)\$/\\1/p'", - returnStdout: true).trim() - - ubiImageName = sh(script: "curl -s -X 'GET' '${REDHAT_CONTAINER_API_URL_BASE}/images/id/${ubiImageId}' -H 'accept: application/json' \ - | jq -r '.brew.build' \ - | sed -En 's/(ubi[0-9]+-minimal)-container-([0-9]+\\.[0-9]+-[0-9]+\\.?[0-9]*)/\\1-\\2/p'", - returnStdout: true).trim() - - ubiImageVersion = sh(script: "curl -s -X 'GET' '${REDHAT_CONTAINER_API_URL_BASE}/images/id/${ubiImageId}' -H 'accept: application/json' \ - | jq -r '.brew.build' \ - | sed -En 's/ubi[0-9]+-minimal-container-([0-9]+\\.[0-9]+-[0-9]+\\.?[0-9]*)/\\1/p'", - returnStdout: true).trim() - } - stage('Download SBOMs') { - sh "mkdir -p ${buildDir}/spdx && mkdir -p ${buildDir}/cyclonedx" - - // Get nexus-internal SBOM - getComponentSbom(buildDir, "nexus-internal", nexusVersion) - // Get nxrm-db-migrator SBOM - getComponentSbom(buildDir, "nxrm-db-migrator", nexusVersion) - // Get docker-nexus3 SBOM - getComponentSbom(buildDir, "docker-nexus3", dockerImageVersion) - // Get UBI Minimal SBOM - ubiSbomAvailable = getUbiImageSbom(buildDir, ubiImageName, ubiImageVersion) - - sh "echo 'Available SPDX SBOMS' && ls ${buildDir}/spdx" - sh "echo 'Available CycloneDx SBOMS' && ls ${buildDir}/cyclonedx" - } - - stage('Merge supported sboms') { - def pythonEnvDir = "${buildDir}/.spdxmerge" - - sh """#!/bin/bash - if ! [ -d "${buildDir}/SPDXMerge" ]; then - git clone https://github.com/philips-software/SPDXMerge.git '${buildDir}/SPDXMerge' - fi - """ - - sh """#!/bin/bash - if mkdir -p '${pythonEnvDir}' && python3 -m venv '${pythonEnvDir}' && ls '${pythonEnvDir}' && . '${pythonEnvDir}/bin/activate'; then - if python3 -m pip install -r '${buildDir}/SPDXMerge/requirements.txt' \ - && python3 -m pip install setuptools \ - && python3 '${buildDir}/SPDXMerge/spdxmerge/SPDXMerge.py' --docpath '${buildDir}/spdx' --outpath '${buildDir}/' \ - --name "docker-nexus3-aggregate" --mergetype "1" --author "Sonatype Inc." --email "support@sonatype.com" \ - --docnamespace "https://sonatype.sonatype.app/platform/ui/links/application/docker-nexus3/report/b0c5f7f12ac84b439ded3ff255bd5eef" \ - --filetype J \ - && mv '${buildDir}/merged-SBoM-deep.json' '${buildDir}/spdx/docker-nexus3-aggregate-${dockerImageVersion}-spdx.json'; then - echo 'Merge completed!' - else - echo 'Merge failed!' - FAILED=1 - fi - - deactivate - fi - - exit \${FAILED:-0} - """ - } - - stage('Publish SBOMs') { - if (ubiSbomAvailable) { - publishComponent(buildDir, "ubi-minimal", ubiImageVersion, false) - } - publishComponent(buildDir, "nexus-internal", nexusVersion) - publishComponent(buildDir, "nxrm-db-migrator", nexusVersion) - publishComponent(buildDir, "docker-nexus3", dockerImageVersion) - publishComponent(buildDir, "docker-nexus3-aggregate", dockerImageVersion, false) - } - } finally { - OsTools.runSafe(this, "rm -rf '${buildDir}'") - } -} - def getComponentSbom(String buildDir, String componentName, String componentVersion) { def componentInfo = getComponentInfo(componentName) def componentId = componentInfo.applications[0].id @@ -192,4 +99,96 @@ def publishComponent(String buildDir, String componentName, String componentVers ]) { sh(publishCommand) } -} \ No newline at end of file +} + +def mergeSpdxComponents(String buildDir, String finalComponentName, String finalComponentVersion, String finalNamespace) { + def pythonEnvDir = "${buildDir}/.spdxmerge" + + sh """#!/bin/bash + if ! [ -d "${buildDir}/SPDXMerge" ]; then + git clone https://github.com/philips-software/SPDXMerge.git '${buildDir}/SPDXMerge' + fi + """ + + sh """#!/bin/bash + if mkdir -p '${pythonEnvDir}' && python3 -m venv '${pythonEnvDir}' && ls '${pythonEnvDir}' && . '${pythonEnvDir}/bin/activate'; then + if python3 -m pip install -r '${buildDir}/SPDXMerge/requirements.txt' \ + && python3 -m pip install setuptools \ + && python3 '${buildDir}/SPDXMerge/spdxmerge/SPDXMerge.py' --docpath '${buildDir}/spdx' --outpath '${buildDir}/' \ + --name "docker-nexus3-aggregate" --mergetype "1" --author "Sonatype Inc." --email "support@sonatype.com" \ + --docnamespace "${finalNamespace}" \ + --filetype J \ + && mv '${buildDir}/merged-SBoM-deep.json' '${buildDir}/spdx/${finalComponentName}-${finalComponentVersion}-spdx.json'; then + echo 'Merge completed!' + else + echo 'Merge failed!' + FAILED=1 + fi + + deactivate + fi + + exit \${FAILED:-0} + """ +} + +dockerizedRunPipeline( + skipVulnerabilityScan: true, + pathToDockerfile: "./build-images/Dockerfile.sbom-deployer", + prepare: { + withSonatypeDockerRegistry() { + sh "docker pull sonatype/nexus3:${params.docker_nexus3_tag}" + env['nexusVersion'] = sh(script: "docker inspect sonatype/nexus3:${params.docker_nexus3_tag} \ + | jq -r '.[0].Config.Labels.version' ", + returnStdout: true).trim() + env['dockerImageVersion'] = sh(script: "docker inspect sonatype/nexus3:${params.docker_nexus3_tag} \ + | jq -r '.[0].Config.Labels.release' ", + returnStdout: true).trim() + env['ubiImageId'] = sh(script: "docker inspect sonatype/nexus3:${params.docker_nexus3_tag} \ + | jq -r '.[0].Config.Labels.\"base-image-ref\"' \ + | sed -En 's/^.+image=(.+)\$/\\1/p'", + returnStdout: true).trim() + } + }, + run: { + def buildDir = "./.sbom-build/job-${env.BUILD_NUMBER}" + def ubiImageName = sh(script: "curl -s -X 'GET' '${REDHAT_CONTAINER_API_URL_BASE}/images/id/${env.ubiImageId}' -H 'accept: application/json' \ + | jq -r '.brew.build' \ + | sed -En 's/(ubi[0-9]+-minimal)-container-([0-9]+\\.[0-9]+-[0-9]+\\.?[0-9]*)/\\1-\\2/p'", + returnStdout: true).trim() + def ubiImageVersion = sh(script: "curl -s -X 'GET' '${REDHAT_CONTAINER_API_URL_BASE}/images/id/${env.ubiImageId}' -H 'accept: application/json' \ + | jq -r '.brew.build' \ + | sed -En 's/ubi[0-9]+-minimal-container-([0-9]+\\.[0-9]+-[0-9]+\\.?[0-9]*)/\\1/p'", + returnStdout: true).trim() + + // Download SBOMs + sh "mkdir -p ${buildDir}/spdx && mkdir -p ${buildDir}/cyclonedx" + + // Get nexus-internal SBOM + getComponentSbom(buildDir, "nexus-internal", env.nexusVersion) + // Get nxrm-db-migrator SBOM + getComponentSbom(buildDir, "nxrm-db-migrator", env.nexusVersion) + // Get docker-nexus3 SBOM + getComponentSbom(buildDir, "docker-nexus3", env.dockerImageVersion) + // Get UBI Minimal SBOM + def ubiSbomAvailable = getUbiImageSbom(buildDir, ubiImageName, ubiImageVersion) + + sh "echo 'Available SPDX SBOMS' && ls ${buildDir}/spdx" + sh "echo 'Available CycloneDx SBOMS' && ls ${buildDir}/cyclonedx" + + // Merge supported sboms + def dockerImageNamespace = sh(script: "cat ${buildDir}/spdx/docker-nexus3-${env.dockerImageVersion}-spdx.json | jq -r '.documentNamespace'", returnStdout: true).trim() + mergeSpdxComponents(buildDir, "docker-nexus3-aggregate", env.dockerImageVersion, dockerImageNamespace) + + // Publish SBOMs + if (ubiSbomAvailable) { + publishComponent(buildDir, "ubi-minimal", ubiImageVersion, false) + } + publishComponent(buildDir, "nexus-internal", env.nexusVersion) + publishComponent(buildDir, "nxrm-db-migrator", env.nexusVersion) + publishComponent(buildDir, "docker-nexus3", env.dockerImageVersion) + publishComponent(buildDir, "docker-nexus3-aggregate", env.dockerImageVersion, false) + + sh "rm -rf '${buildDir}'" + } +) \ No newline at end of file diff --git a/README.md b/README.md index e4833a76..27fb3bef 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,11 @@ + - # Sonatype Nexus Repository Docker: sonatype/nexus3 [![Join the chat at https://gitter.im/sonatype/nexus-developers](https://badges.gitter.im/sonatype/nexus-developers.svg)](https://gitter.im/sonatype/nexus-developers?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) diff --git a/SECURITY.md b/SECURITY.md index 35d4abcb..73cf4ae9 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -1,11 +1,10 @@ - # Reporting Security Vulnerabilities ## When to report diff --git a/build-images/Dockerfile.sbom-deployer b/build-images/Dockerfile.sbom-deployer new file mode 100644 index 00000000..9bb9810a --- /dev/null +++ b/build-images/Dockerfile.sbom-deployer @@ -0,0 +1,3 @@ +FROM docker-all.repo.sonatype.com/python:3.12 + +RUN apt-get update && apt-get install -y jq curl \ No newline at end of file diff --git a/build_red_hat_image.sh b/build_red_hat_image.sh index 9ab5e703..8f678937 100755 --- a/build_red_hat_image.sh +++ b/build_red_hat_image.sh @@ -1,7 +1,10 @@ #!/usr/bin/env bash # -# Copyright (c) 2017-present Sonatype, Inc. +# Copyright (c) 2016-present Sonatype, Inc. All rights reserved. +# Includes the third-party code listed at http://links.sonatype.com/products/nxrm/attributions. +# "Sonatype" is a trademark of Sonatype, Inc. # + # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at diff --git a/header.txt b/header.txt new file mode 100644 index 00000000..1d860183 --- /dev/null +++ b/header.txt @@ -0,0 +1,3 @@ +Copyright (c) 2016-present Sonatype, Inc. All rights reserved. +Includes the third-party code listed at http://links.sonatype.com/products/nxrm/attributions. +"Sonatype" is a trademark of Sonatype, Inc. \ No newline at end of file diff --git a/rh-docker/help.md b/rh-docker/help.md index f4726539..9e4151ea 100644 --- a/rh-docker/help.md +++ b/rh-docker/help.md @@ -1,3 +1,10 @@ + % NEXUS(1) Container Image Pages % Sonatype % December 15, 2017 diff --git a/rh-docker/uid_entrypoint.sh b/rh-docker/uid_entrypoint.sh index 487482ce..35515269 100644 --- a/rh-docker/uid_entrypoint.sh +++ b/rh-docker/uid_entrypoint.sh @@ -1,7 +1,10 @@ #!/bin/sh # -# Copyright:: Copyright (c) 2017-present Sonatype, Inc. Apache License, Version 2.0. +# Copyright (c) 2016-present Sonatype, Inc. All rights reserved. +# Includes the third-party code listed at http://links.sonatype.com/products/nxrm/attributions. +# "Sonatype" is a trademark of Sonatype, Inc. # + # arbitrary uid recognition at runtime - for OpenShift deployments USER_ID=$(id -u) if [[ ${USER_UID} != ${USER_ID} ]]; then diff --git a/rh-docker/uid_template.sh b/rh-docker/uid_template.sh index f150e6e1..578d2ed9 100644 --- a/rh-docker/uid_template.sh +++ b/rh-docker/uid_template.sh @@ -1,6 +1,9 @@ #!/bin/sh # -# Copyright:: Copyright (c) 2017-present Sonatype, Inc. Apache License, Version 2.0. +# Copyright (c) 2016-present Sonatype, Inc. All rights reserved. +# Includes the third-party code listed at http://links.sonatype.com/products/nxrm/attributions. +# "Sonatype" is a trademark of Sonatype, Inc. # + # arbitrary uid recognition at runtime - for OpenShift deployments sed "s@${USER_NAME}:x:${USER_UID}:@${USER_NAME}:x:\${USER_ID}:@g" /etc/passwd > /etc/passwd.template diff --git a/scripts/BaseImageReference.groovy b/scripts/BaseImageReference.groovy index 41ffd6e9..81a51ae1 100644 --- a/scripts/BaseImageReference.groovy +++ b/scripts/BaseImageReference.groovy @@ -1,9 +1,8 @@ /* * Copyright (c) 2016-present Sonatype, Inc. All rights reserved. - * Includes the third-party code listed at http://links.sonatype.com/products/nexus/attributions. + * Includes the third-party code listed at http://links.sonatype.com/products/nxrm/attributions. * "Sonatype" is a trademark of Sonatype, Inc. */ - interface BaseImageReference { String getReference() From ee38b2e875b7b008d5a718f4a54727534e660e56 Mon Sep 17 00:00:00 2001 From: Jerson Huerfano Date: Fri, 17 May 2024 12:27:36 -0500 Subject: [PATCH 11/21] NEXUS-42442: Cloned specific version of SPDXMerge tool --- Jenkinsfile-sbom-release | 5 +++-- build-images/Dockerfile.sbom-deployer | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/Jenkinsfile-sbom-release b/Jenkinsfile-sbom-release index b7704ec7..709464e6 100644 --- a/Jenkinsfile-sbom-release +++ b/Jenkinsfile-sbom-release @@ -14,6 +14,7 @@ TARGET_REPO_NAME = "sonatype-sboms" REDHAT_SBOM_REPO_URL_BASE = "https://access.redhat.com/security/data/sbom/beta" REDHAT_CONTAINER_API_URL_BASE = "https://catalog.redhat.com/api/containers/v1" CYCLONEDX_VERSION = "1.5" +SPDXMERGE_VERSION_TAG = "v0.2.0" properties([ parameters([ @@ -106,7 +107,7 @@ def mergeSpdxComponents(String buildDir, String finalComponentName, String final sh """#!/bin/bash if ! [ -d "${buildDir}/SPDXMerge" ]; then - git clone https://github.com/philips-software/SPDXMerge.git '${buildDir}/SPDXMerge' + git clone --branch '${SPDXMERGE_VERSION_TAG}' https://github.com/philips-software/SPDXMerge.git '${buildDir}/SPDXMerge' fi """ @@ -191,4 +192,4 @@ dockerizedRunPipeline( sh "rm -rf '${buildDir}'" } -) \ No newline at end of file +) diff --git a/build-images/Dockerfile.sbom-deployer b/build-images/Dockerfile.sbom-deployer index 9bb9810a..f50a61bb 100644 --- a/build-images/Dockerfile.sbom-deployer +++ b/build-images/Dockerfile.sbom-deployer @@ -1,3 +1,3 @@ FROM docker-all.repo.sonatype.com/python:3.12 -RUN apt-get update && apt-get install -y jq curl \ No newline at end of file +RUN apt-get update && apt-get install -y jq curl From db7ec0607f4b5a6d9f22fcf66105b7b70cfdd56c Mon Sep 17 00:00:00 2001 From: Jerson Huerfano Date: Mon, 20 May 2024 14:44:09 -0500 Subject: [PATCH 12/21] NEXUS-42442: Update Jenkinsfile-sbom-release Co-authored-by: mburkert3 <126404216+mburkert3@users.noreply.github.com> --- Jenkinsfile-sbom-release | 24 ++++++++---------------- 1 file changed, 8 insertions(+), 16 deletions(-) diff --git a/Jenkinsfile-sbom-release b/Jenkinsfile-sbom-release index 709464e6..31813a96 100644 --- a/Jenkinsfile-sbom-release +++ b/Jenkinsfile-sbom-release @@ -24,22 +24,14 @@ properties([ ]) def getComponentSbom(String buildDir, String componentName, String componentVersion) { - def componentInfo = getComponentInfo(componentName) - def componentId = componentInfo.applications[0].id - - withCredentials([ - usernamePassword( - credentialsId: 'jenkins-saas-service-acct', - usernameVariable: 'IQ_USER', - passwordVariable: 'IQ_PASSWORD') - ]) { - // Get SPDX - sh "curl -s -L -w 'Status: %{http_code}' -u \$IQ_USER:\$IQ_PASSWORD -o '${buildDir}/spdx/${componentName}-${componentVersion}-spdx.json' -X GET \ - -H 'Accept: application/json' '${IQ_URL_BASE}/api/v2/spdx/${componentId}/stages/release?format=json'" - // Get CycloneDx - sh "curl -s -L -w 'Status: %{http_code}' -u \$IQ_USER:\$IQ_PASSWORD -o '${buildDir}/cyclonedx/${componentName}-${componentVersion}-cyclonedx.json' -X GET \ - -H 'Accept: application/json' '${IQ_URL_BASE}/api/v2/cycloneDx/${CYCLONEDX_VERSION}/${componentId}/stages/release'" - } + def componentId = getComponentInfo(componentName).applications[0].id + withCredentials([usernamePassword(credentialsId: 'jenkins-saas-service-acct', usernameVariable: 'IQ_USER', passwordVariable: 'IQ_PASSWORD')]) { + def formats = ['spdx', 'cyclonedx'] + formats.each { format -> + def urlPath = format == 'spdx' ? "spdx/${componentId}/stages/release?format=json" : "cycloneDx/${CYCLONEDX_VERSION}/${componentId}/stages/release" + sh "curl -s -L -u \$IQ_USER:\$IQ_PASSWORD -o '${buildDir}/${format}/${componentName}-${componentVersion}-${format}.json' -X GET -H 'Accept: application/json' '${IQ_URL_BASE}/api/v2/${urlPath}'" + } + } } def getUbiImageSbom(String buildDir, String ubiMinimalName, String ubiMinimalVersion) { From cc2c8e8ced784940c4e86753720d7fb68fd7dc4f Mon Sep 17 00:00:00 2001 From: mburkert3 <126404216+mburkert3@users.noreply.github.com> Date: Tue, 21 May 2024 00:33:04 -0400 Subject: [PATCH 13/21] Update Jenkinsfile-PrismaCloud --- Jenkinsfile-PrismaCloud | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/Jenkinsfile-PrismaCloud b/Jenkinsfile-PrismaCloud index 5a7947ec..31fc27f1 100644 --- a/Jenkinsfile-PrismaCloud +++ b/Jenkinsfile-PrismaCloud @@ -86,6 +86,27 @@ pipeline { } } } + stage('Analyze UBI Image with Prisma Cloud') { + steps { + script { + def ubiImage = "registry.access.redhat.com/ubi8/ubi-minimal:8.9-1161.1715068733" + sh "docker pull ${ubiImage}" + + prismaCloudScanImage( + ca: '', + cert: '', + dockerAddress: 'unix:///var/run/docker.sock', + ignoreImageBuildTime: true, + image: ubiImage, + key: '', + logLevel: 'debug', + podmanPath: '', + project: '', + resultsFile: 'ubi-prisma-cloud-scan-results.json' + ) + } + } + } stage('Analyze Image with IQ') { steps { script { From d4ae49e57822eedc940c9b5388514b8332bf6c40 Mon Sep 17 00:00:00 2001 From: Jerson Huerfano Date: Tue, 21 May 2024 16:32:07 -0500 Subject: [PATCH 14/21] NEXUS-42442: Changed parameter description --- Jenkinsfile-sbom-release | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Jenkinsfile-sbom-release b/Jenkinsfile-sbom-release index 31813a96..9e190ff4 100644 --- a/Jenkinsfile-sbom-release +++ b/Jenkinsfile-sbom-release @@ -19,7 +19,7 @@ SPDXMERGE_VERSION_TAG = "v0.2.0" properties([ parameters([ string(name: 'docker_nexus3_tag', defaultValue: '', - description: 'Nexus Repository Manager Version. The result SBOMs will be tagged with this version.') + description: 'NXRM Docker image tag. The result SBOMs will be tagged with this version.') ]) ]) From bb10986ba78479d7f8a9bc050c47324944d426e0 Mon Sep 17 00:00:00 2001 From: mburkert3 <126404216+mburkert3@users.noreply.github.com> Date: Tue, 21 May 2024 21:58:31 -0400 Subject: [PATCH 15/21] PrismaCloud Reports --- Jenkinsfile-PrismaCloud | 197 +++++++++++++++------------------------- 1 file changed, 71 insertions(+), 126 deletions(-) diff --git a/Jenkinsfile-PrismaCloud b/Jenkinsfile-PrismaCloud index 31fc27f1..d2e801f0 100644 --- a/Jenkinsfile-PrismaCloud +++ b/Jenkinsfile-PrismaCloud @@ -4,7 +4,8 @@ import com.sonatype.jenkins.pipeline.OsTools import groovy.json.JsonSlurper IQ_URL_BASE = "https://sonatype.sonatype.app/platform" -PRISMA_CLOUD_ADDRESS = 'https://us-west1.cloud.twistlock.com/us-4-161054503' +REPO_BASE_URL = "https://repo.sonatype.com/service/rest" +TARGET_REPO_NAME = "sonatype-sboms" CYCLONEDX_VERSION = "1.5" properties([ @@ -14,23 +15,22 @@ properties([ string(name: 'DOCKER_IMAGE_TAG', defaultValue: 'latest', description: 'Tag of the Docker image to be scanned'), string(name: 'NXRM_Version', defaultValue: '', - description: 'Nexus Repository Manager Version. The result SBOMs will be tagged with this version.') + description: 'Nexus Repository Manager Version. The result SBOMs will be tagged with this version.'), + string(name: 'UBI_IMAGE_TAG', defaultValue: 'latest', + description: 'Tag of the UBI image to be scanned') ]) ]) -def getComponentSbom(String componentName, String componentVersion, String buildDir) { - def componentInfo = getComponentInfo(componentName) - def componentId = componentInfo.applications[0].id - - withCredentials([ - usernamePassword( - credentialsId: 'jenkins-saas-service-acct', - usernameVariable: 'IQ_USER', - passwordVariable: 'IQ_PASSWORD') - ]) { - // Get CycloneDx - sh "curl -L -u \$IQ_USER:\$IQ_PASSWORD -o '${buildDir}/cyclonedx/${componentName}-${componentVersion}-cyclonedx.json' -X GET \ - -H 'Accept: application/json' '${IQ_URL_BASE}/api/v2/cycloneDx/${CYCLONEDX_VERSION}/${componentId}/stages/release'" +def getComponentSbom(String buildDir, String componentName, String componentVersion) { + def componentId = getComponentInfo(componentName).applications[0].id + withCredentials([usernamePassword(credentialsId: 'jenkins-saas-service-acct', usernameVariable: 'IQ_USER', passwordVariable: 'IQ_PASSWORD')]) { + def formats = ['spdx', 'cyclonedx'] + formats.each { format -> + def urlPath = format == 'spdx' ? "spdx/${componentId}/stages/release?format=json" : "cycloneDx/${CYCLONEDX_VERSION}/${componentId}/stages/release" + sh "curl -s -L -u \$IQ_USER:\$IQ_PASSWORD -o '${buildDir}/${format}/${componentName}-${componentVersion}-${format}.json' -X GET -H 'Accept: application/json' '${IQ_URL_BASE}/api/v2/${urlPath}'" + sh "jq . ${buildDir}/${format}/${componentName}-${componentVersion}-${format}.json > ${buildDir}/${format}/${componentName}-${componentVersion}-${format}-formatted.json" + sh "mv ${buildDir}/${format}/${componentName}-${componentVersion}-${format}-formatted.json ${buildDir}/${format}/${componentName}-${componentVersion}-${format}.json" + } } } @@ -50,6 +50,42 @@ def getComponentInfo(String componentName) { return response } +def publishComponent(String buildDir, String componentName, String componentVersion) { + def publishCommand = """ + curl -v -u \$NXRM_USER:\$NXRM_PASSWORD -X POST '${REPO_BASE_URL}/v1/components?repository=${TARGET_REPO_NAME}' \ + -F 'raw.directory=/PrismaCloud/${componentName}/${componentVersion}/' \ + -F 'raw.asset1=@${buildDir}/${componentName}-prisma-cloud-scan-results.json' \ + -F 'raw.asset1.filename=${componentName}-${componentVersion}-prisma-cloud-scan-results.json' + """ + withCredentials([ + usernamePassword( + credentialsId: 'sonatype-sbom-deployer', + usernameVariable: 'NXRM_USER', + passwordVariable: 'NXRM_PASSWORD') + ]) { + sh(publishCommand) + } +} + +def scanAndCopyResults(String image, String resultsFileName) { + prismaCloudScanImage( + ca: '', + cert: '', + dockerAddress: 'unix:///var/run/docker.sock', + ignoreImageBuildTime: true, + image: image, + key: '', + logLevel: 'debug', + podmanPath: '', + project: '', + resultsFile: "${env.buildDir}/${resultsFileName}" + ) + sh "jq . ${env.buildDir}/${resultsFileName} > ${env.buildDir}/${resultsFileName}-formatted.json" + sh "mv ${env.buildDir}/${resultsFileName}-formatted.json ${env.buildDir}/${resultsFileName}" + sh "cp ${env.buildDir}/${resultsFileName} ${resultsFileName}" + sh "ls -la ${env.buildDir}" +} + pipeline { agent any environment { @@ -68,132 +104,41 @@ pipeline { } } } - stage('Analyze Image with Prisma Cloud') { + stage('Analyze Images with Prisma Cloud') { steps { script { - prismaCloudScanImage( - ca: '', - cert: '', - dockerAddress: 'unix:///var/run/docker.sock', - ignoreImageBuildTime: true, - image: "docker-nexus3:${params.DOCKER_IMAGE_TAG}", - key: '', - logLevel: 'debug', - podmanPath: '', - project: '', - resultsFile: 'prisma-cloud-scan-results.json' - ) - } - } - } - stage('Analyze UBI Image with Prisma Cloud') { - steps { - script { - def ubiImage = "registry.access.redhat.com/ubi8/ubi-minimal:8.9-1161.1715068733" - sh "docker pull ${ubiImage}" - - prismaCloudScanImage( - ca: '', - cert: '', - dockerAddress: 'unix:///var/run/docker.sock', - ignoreImageBuildTime: true, - image: ubiImage, - key: '', - logLevel: 'debug', - podmanPath: '', - project: '', - resultsFile: 'ubi-prisma-cloud-scan-results.json' - ) - } - } - } - stage('Analyze Image with IQ') { - steps { - script { - nexusPolicyEvaluation( - iqApplication: 'docker-nexus3', - iqStage: 'release', - iqScanPatterns: [[scanPattern: "container:docker-nexus3:${params.DOCKER_IMAGE_TAG}"]], - failBuildOnNetworkError: true, - serverUrl: IQ_URL_BASE, - credentialsId: 'nexus_iq_credentials' - ) - } - } - } - stage('Download SBOM') { - steps { - script { - sh "mkdir -p ${buildDir}/cyclonedx" - - // Get docker-nexus3 SBOM - getComponentSbom("docker-nexus3", params.nexus_repository_manager_version, buildDir) + sh "mkdir -p ${env.buildDir}/spdx && mkdir -p ${env.buildDir}/cyclonedx" + echo "Analyzing docker-nexus3 image with Prisma Cloud" + scanAndCopyResults("docker-nexus3:${params.DOCKER_IMAGE_TAG}", "docker-nexus3-prisma-cloud-scan-results.json") - sh "echo 'Available CycloneDx SBOMS' && ls ${buildDir}/cyclonedx" + def ubiImage = "registry.access.redhat.com/ubi8/ubi-minimal:${params.UBI_IMAGE_TAG}" + sh "docker pull ${ubiImage}" + echo "Analyzing UBI image with Prisma Cloud" + scanAndCopyResults(ubiImage, "ubi-minimal-prisma-cloud-scan-results.json") } } } - stage('Compare Red Hat Patched Versions') { + stage('Publish Scan Results') { steps { script { - // Pull latest Red Hat UBI image - def redHatImage = "registry.access.redhat.com/ubi8/ubi-minimal:8.9-1161.1715068733" - sh "docker pull ${redHatImage}" - - // Inspect the image to get the list of installed packages - def redHatPackages = sh(script: "docker run --rm ${redHatImage} rpm -qa --queryformat '%{NAME} %{VERSION}-%{RELEASE}\n'", returnStdout: true).trim().split('\n').collectEntries { - def parts = it.split(' ') - [(parts[0]): parts[1]] - } - - // Read the Prisma Cloud scan results - def prismaReportPath = "prisma-cloud-scan-results.json" - def prismaReportContent = readFile(file: prismaReportPath) - def prismaReport = new JsonSlurper().parseText(prismaReportContent) - - // Collect package names and versions from the Prisma Cloud report - def prismaPackages = prismaReport.results[0].entityInfo.packages.findAll { it.pkgsType == 'package' }[0].pkgs.collectEntries { - [(it.name): it.version ?: "unknown"] - } - - // Compare with Red Hat patched versions and amend to report - def mismatchedDependencies = [] - redHatPackages.each { name, version -> - def prismaVersion = prismaPackages.get(name, "unknown") - def match = prismaVersion == version - mismatchedDependencies << [ - name: name, - redHatVersion: version, - prismaVersion: prismaVersion, - match: match - ] - } - - // JSON format - def mismatchedReportJson = mismatchedDependencies.collect { dep -> - """{ - "name": "${dep.name}", - "redHatVersion": "${dep.redHatVersion}", - "prismaVersion": "${dep.prismaVersion}", - "match": ${dep.match} -}""" - }.join(',\n') - - def mismatchedReportPath = "${buildDir}/mismatched_report.json" - writeFile(file: mismatchedReportPath, text: mismatchedReportJson) - - sh "echo 'Mismatched Lifecycle Report' && cat ${mismatchedReportPath}" + publishComponent(env.buildDir, "docker-nexus3", params.DOCKER_IMAGE_TAG) + publishComponent(env.buildDir, "ubi-minimal", params.UBI_IMAGE_TAG) } } } } post { always { - prismaCloudPublish resultsFilePattern: 'prisma-cloud-scan-results.json' - archiveArtifacts artifacts: "prisma-cloud-scan-results.json", fingerprint: true - archiveArtifacts artifacts: ".sbom-build/job-${env.BUILD_NUMBER}/mismatched_report.json", fingerprint: true + prismaCloudPublish resultsFilePattern: "${env.buildDir}/docker-nexus3-prisma-cloud-scan-results.json" + prismaCloudPublish resultsFilePattern: "${env.buildDir}/ubi-minimal-prisma-cloud-scan-results.json" + + prismaCloudPublish resultsFilePattern: 'docker-nexus3-prisma-cloud-scan-results.json' + prismaCloudPublish resultsFilePattern: 'ubi-minimal-prisma-cloud-scan-results.json' + archiveArtifacts artifacts: "docker-nexus3-prisma-cloud-scan-results.json", fingerprint: true + archiveArtifacts artifacts: "ubi-minimal-prisma-cloud-scan-results.json", fingerprint: true + script { - OsTools.runSafe(this, "rm -rf '${buildDir}'") + OsTools.runSafe(this, "rm -rf '${env.buildDir}'") } } } From 76e2df088fb1b9c51f3a6c9b88d585cae9822979 Mon Sep 17 00:00:00 2001 From: mburkert3 <126404216+mburkert3@users.noreply.github.com> Date: Fri, 24 May 2024 12:47:28 -0400 Subject: [PATCH 16/21] Update tags pushed to RSC --- Jenkinsfile-PrismaCloud | 42 ++++++++++++++++++++++++----------------- 1 file changed, 25 insertions(+), 17 deletions(-) diff --git a/Jenkinsfile-PrismaCloud b/Jenkinsfile-PrismaCloud index d2e801f0..c8d17a57 100644 --- a/Jenkinsfile-PrismaCloud +++ b/Jenkinsfile-PrismaCloud @@ -12,12 +12,10 @@ properties([ parameters([ string(name: 'BRANCH_TO_BUILD', defaultValue: '', description: 'Branch the script will be loaded from'), - string(name: 'DOCKER_IMAGE_TAG', defaultValue: 'latest', - description: 'Tag of the Docker image to be scanned'), - string(name: 'NXRM_Version', defaultValue: '', - description: 'Nexus Repository Manager Version. The result SBOMs will be tagged with this version.'), - string(name: 'UBI_IMAGE_TAG', defaultValue: 'latest', - description: 'Tag of the UBI image to be scanned') + string(name: 'IMAGE_VERSION', defaultValue: '', + description: 'Version for the Docker image and NXRM. The result SBOMs will be tagged with this version.'), + string(name: 'UBI_IMAGE_TAG', defaultValue: '', + description: 'Tag of the UBI image to be scanned. ('https://catalog.redhat.com/software/containers/ubi8/ubi-minimal/') ]) ]) @@ -54,7 +52,7 @@ def publishComponent(String buildDir, String componentName, String componentVers def publishCommand = """ curl -v -u \$NXRM_USER:\$NXRM_PASSWORD -X POST '${REPO_BASE_URL}/v1/components?repository=${TARGET_REPO_NAME}' \ -F 'raw.directory=/PrismaCloud/${componentName}/${componentVersion}/' \ - -F 'raw.asset1=@${buildDir}/${componentName}-prisma-cloud-scan-results.json' \ + -F 'raw.asset1=@${buildDir}/${componentName}-${componentVersion}-prisma-cloud-scan-results.json' \ -F 'raw.asset1.filename=${componentName}-${componentVersion}-prisma-cloud-scan-results.json' """ withCredentials([ @@ -65,6 +63,14 @@ def publishComponent(String buildDir, String componentName, String componentVers ]) { sh(publishCommand) } + // Publish the latest version tag + def latestPublishCommand = """ + curl -v -u \$NXRM_USER:\$NXRM_PASSWORD -X POST '${REPO_BASE_URL}/v1/components?repository=${TARGET_REPO_NAME}' \ + -F 'raw.directory=/PrismaCloud/${componentName}/latest/' \ + -F 'raw.asset1=@${buildDir}/${componentName}-${componentVersion}-prisma-cloud-scan-results.json' \ + -F 'raw.asset1.filename=${componentName}-latest-prisma-cloud-scan-results.json' + """ + sh(latestPublishCommand) } def scanAndCopyResults(String image, String resultsFileName) { @@ -100,7 +106,9 @@ pipeline { stage('Build Image') { steps { script { - runSafely("docker build -t docker-nexus3:${params.DOCKER_IMAGE_TAG} .") + runSafely("docker build -t docker-nexus3:${params.IMAGE_VERSION} .") + // Tag the latest version + runSafely("docker tag docker-nexus3:${params.IMAGE_VERSION} docker-nexus3:latest") } } } @@ -109,19 +117,19 @@ pipeline { script { sh "mkdir -p ${env.buildDir}/spdx && mkdir -p ${env.buildDir}/cyclonedx" echo "Analyzing docker-nexus3 image with Prisma Cloud" - scanAndCopyResults("docker-nexus3:${params.DOCKER_IMAGE_TAG}", "docker-nexus3-prisma-cloud-scan-results.json") + scanAndCopyResults("docker-nexus3:${params.IMAGE_VERSION}", "docker-nexus3-${params.IMAGE_VERSION}-prisma-cloud-scan-results.json") def ubiImage = "registry.access.redhat.com/ubi8/ubi-minimal:${params.UBI_IMAGE_TAG}" sh "docker pull ${ubiImage}" echo "Analyzing UBI image with Prisma Cloud" - scanAndCopyResults(ubiImage, "ubi-minimal-prisma-cloud-scan-results.json") + scanAndCopyResults(ubiImage, "ubi-minimal-${params.UBI_IMAGE_TAG}-prisma-cloud-scan-results.json") } } } stage('Publish Scan Results') { steps { script { - publishComponent(env.buildDir, "docker-nexus3", params.DOCKER_IMAGE_TAG) + publishComponent(env.buildDir, "docker-nexus3", params.IMAGE_VERSION) publishComponent(env.buildDir, "ubi-minimal", params.UBI_IMAGE_TAG) } } @@ -129,13 +137,13 @@ pipeline { } post { always { - prismaCloudPublish resultsFilePattern: "${env.buildDir}/docker-nexus3-prisma-cloud-scan-results.json" - prismaCloudPublish resultsFilePattern: "${env.buildDir}/ubi-minimal-prisma-cloud-scan-results.json" + prismaCloudPublish resultsFilePattern: "${env.buildDir}/docker-nexus3-${params.IMAGE_VERSION}-prisma-cloud-scan-results.json" + prismaCloudPublish resultsFilePattern: "${env.buildDir}/ubi-minimal-${params.UBI_IMAGE_TAG}-prisma-cloud-scan-results.json" - prismaCloudPublish resultsFilePattern: 'docker-nexus3-prisma-cloud-scan-results.json' - prismaCloudPublish resultsFilePattern: 'ubi-minimal-prisma-cloud-scan-results.json' - archiveArtifacts artifacts: "docker-nexus3-prisma-cloud-scan-results.json", fingerprint: true - archiveArtifacts artifacts: "ubi-minimal-prisma-cloud-scan-results.json", fingerprint: true + prismaCloudPublish resultsFilePattern: "docker-nexus3-${params.IMAGE_VERSION}-prisma-cloud-scan-results.json" + prismaCloudPublish resultsFilePattern: "ubi-minimal-${params.UBI_IMAGE_TAG}-prisma-cloud-scan-results.json" + archiveArtifacts artifacts: "docker-nexus3-${params.IMAGE_VERSION}-prisma-cloud-scan-results.json", fingerprint: true + archiveArtifacts artifacts: "ubi-minimal-${params.UBI_IMAGE_TAG}-prisma-cloud-scan-results.json", fingerprint: true script { OsTools.runSafe(this, "rm -rf '${env.buildDir}'") From 91022f3b1f91180025bd083b63c53048071c4562 Mon Sep 17 00:00:00 2001 From: mburkert3 <126404216+mburkert3@users.noreply.github.com> Date: Fri, 24 May 2024 12:50:26 -0400 Subject: [PATCH 17/21] Fix parentheses --- Jenkinsfile-PrismaCloud | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Jenkinsfile-PrismaCloud b/Jenkinsfile-PrismaCloud index c8d17a57..dc41ebcb 100644 --- a/Jenkinsfile-PrismaCloud +++ b/Jenkinsfile-PrismaCloud @@ -15,7 +15,7 @@ properties([ string(name: 'IMAGE_VERSION', defaultValue: '', description: 'Version for the Docker image and NXRM. The result SBOMs will be tagged with this version.'), string(name: 'UBI_IMAGE_TAG', defaultValue: '', - description: 'Tag of the UBI image to be scanned. ('https://catalog.redhat.com/software/containers/ubi8/ubi-minimal/') + description: 'Tag of the UBI image to be scanned. Visit 'https://catalog.redhat.com/software/containers/ubi8/ubi-minimal/') ]) ]) From ca896645b66fcddaaa4e5fbb3b5b9861cf1422e7 Mon Sep 17 00:00:00 2001 From: mburkert3 <126404216+mburkert3@users.noreply.github.com> Date: Fri, 24 May 2024 12:51:50 -0400 Subject: [PATCH 18/21] Update Jenkinsfile-PrismaCloud --- Jenkinsfile-PrismaCloud | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Jenkinsfile-PrismaCloud b/Jenkinsfile-PrismaCloud index dc41ebcb..fb4e152e 100644 --- a/Jenkinsfile-PrismaCloud +++ b/Jenkinsfile-PrismaCloud @@ -15,7 +15,7 @@ properties([ string(name: 'IMAGE_VERSION', defaultValue: '', description: 'Version for the Docker image and NXRM. The result SBOMs will be tagged with this version.'), string(name: 'UBI_IMAGE_TAG', defaultValue: '', - description: 'Tag of the UBI image to be scanned. Visit 'https://catalog.redhat.com/software/containers/ubi8/ubi-minimal/') + description: 'Tag of the UBI image to be scanned. Visit https://catalog.redhat.com/software/containers/ubi8/ubi-minimal/') ]) ]) From 03aea79c52b68f0e7542945ec6038779a75a5e8d Mon Sep 17 00:00:00 2001 From: Matthew Piggott Date: Fri, 24 May 2024 14:51:43 -0400 Subject: [PATCH 19/21] Revert "NEXUS-42789 - Remove quiet flag from buidls (#187)" (#193) This reverts commit be5ce4cb855ff67693dc1c927a97dd2ea88ee212. --- Jenkinsfile | 2 +- Jenkinsfile-Internal-Release | 2 +- Jenkinsfile-Release | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index 30405c37..6516ec98 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -42,7 +42,7 @@ node('ubuntu-zion') { stage('Build') { gitHub.statusUpdate commitId, 'pending', 'build', 'Build is running' - def hash = OsTools.runSafe(this, "docker build --no-cache --tag ${imageName} .") + def hash = OsTools.runSafe(this, "docker build --quiet --no-cache --tag ${imageName} .") imageId = hash.split(':')[1] if (currentBuild.result == 'FAILURE') { diff --git a/Jenkinsfile-Internal-Release b/Jenkinsfile-Internal-Release index 14aaa15f..3fe6ec7e 100644 --- a/Jenkinsfile-Internal-Release +++ b/Jenkinsfile-Internal-Release @@ -75,7 +75,7 @@ node('ubuntu-zion') { def baseImageRefFactory = load 'scripts/BaseImageReference.groovy' def baseImageReference = baseImageRefFactory.build(this, baseImage as String) def baseImageReferenceStr = baseImageReference.getReference() - def hash = OsTools.runSafe(this, "docker build --label base-image-ref='${baseImageReferenceStr}' --no-cache --tag ${imageName} . -f ${dockerfilePath}") + def hash = OsTools.runSafe(this, "docker build --quiet --label base-image-ref='${baseImageReferenceStr}' --no-cache --tag ${imageName} . -f ${dockerfilePath}") imageId = hash.split(':')[1] } if (params.scan_for_policy_violations) { diff --git a/Jenkinsfile-Release b/Jenkinsfile-Release index eeb3c106..9a1fe1bc 100644 --- a/Jenkinsfile-Release +++ b/Jenkinsfile-Release @@ -113,7 +113,7 @@ node('ubuntu-zion') { def baseImageRefFactory = load 'scripts/BaseImageReference.groovy' def baseImageReference = baseImageRefFactory.build(this, baseImage as String) def baseImageReferenceStr = baseImageReference.getReference() - def hash = OsTools.runSafe(this, "docker build --label base-image-ref='${baseImageReferenceStr}' --no-cache --tag ${imageName} . -f ${dockerfilePath}") + def hash = OsTools.runSafe(this, "docker build --quiet --label base-image-ref='${baseImageReferenceStr}' --no-cache --tag ${imageName} . -f ${dockerfilePath}") imageId = hash.split(':')[1] if (currentBuild.result == 'FAILURE') { From 72fe094cec49aa7e32f3031374ca332caef7b8f9 Mon Sep 17 00:00:00 2001 From: mburkert3 <126404216+mburkert3@users.noreply.github.com> Date: Sun, 26 May 2024 10:37:56 -0400 Subject: [PATCH 20/21] Add license header --- Jenkinsfile-PrismaCloud | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Jenkinsfile-PrismaCloud b/Jenkinsfile-PrismaCloud index fb4e152e..cb6f50b3 100644 --- a/Jenkinsfile-PrismaCloud +++ b/Jenkinsfile-PrismaCloud @@ -1,3 +1,8 @@ +/* + * Copyright (c) 2024-present Sonatype, Inc. All rights reserved. + * "Sonatype" is a trademark of Sonatype, Inc. + */ + @Library(['private-pipeline-library', 'jenkins-shared']) _ import com.sonatype.jenkins.pipeline.OsTools From d01d894c1954af9be55eeaf27a663f7e38bcef50 Mon Sep 17 00:00:00 2001 From: mburkert3 <126404216+mburkert3@users.noreply.github.com> Date: Thu, 30 May 2024 14:31:32 -0400 Subject: [PATCH 21/21] Update Jenkinsfile-PrismaCloud --- Jenkinsfile-PrismaCloud | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Jenkinsfile-PrismaCloud b/Jenkinsfile-PrismaCloud index cb6f50b3..8a9a5113 100644 --- a/Jenkinsfile-PrismaCloud +++ b/Jenkinsfile-PrismaCloud @@ -20,7 +20,7 @@ properties([ string(name: 'IMAGE_VERSION', defaultValue: '', description: 'Version for the Docker image and NXRM. The result SBOMs will be tagged with this version.'), string(name: 'UBI_IMAGE_TAG', defaultValue: '', - description: 'Tag of the UBI image to be scanned. Visit https://catalog.redhat.com/software/containers/ubi8/ubi-minimal/') + description: 'Tag of the UBI image to be scanned. Visit https://catalog.redhat.com/software/containers/ubi8/ubi-minimal/5c359a62bed8bd75a2c3fba8') ]) ])