1+ void checkImageForDocker (String IMAGE_SUFFIX ){
2+ try {
3+ withCredentials([usernamePassword(credentialsId : ' hub.docker.com' , passwordVariable : ' PASS' , usernameVariable : ' USER' ), string(credentialsId : ' SNYK_ID' , variable : ' SNYK_ID' )]) {
4+ sh """
5+ IMAGE_TAG=\$ (echo ${ IMAGE_SUFFIX} | sed 's^/^-^g; s^[.]^-^g;' | tr '[:upper:]' '[:lower:]')
6+ IMAGE_NAME="fluentbit"
7+ PATH_TO_DOCKERFILE="/source/build/fluentbit"
8+
9+ sg docker -c "
10+ set -e
11+ docker login -u '${ USER} ' -p '${ PASS} '
12+
13+ snyk container test --platform=linux/amd64 --exclude-base-image-vulns --file=./\$ {PATH_TO_DOCKERFILE}/Dockerfile \
14+ --severity-threshold=high --json-file-output=\$ {IMAGE_TAG}-report.json perconalab/\$ IMAGE_NAME:\$ {IMAGE_TAG}
15+ "
16+ """
17+ }
18+ } catch (Exception e) {
19+ echo " Stage failed: ${ e.getMessage()} "
20+ sh """
21+ exit 1
22+ """
23+ } finally {
24+ echo " Executing post actions..."
25+ sh """
26+ IMAGE_TAG=\$ (echo ${ IMAGE_SUFFIX} | sed 's^/^-^g; s^[.]^-^g;' | tr '[:upper:]' '[:lower:]')
27+ snyk-to-html -i \$ {IMAGE_TAG}-report.json -o \$ {IMAGE_TAG}-report.html
28+ """
29+ archiveArtifacts artifacts : ' *.html' , allowEmptyArchive : true
30+ }
31+ }
32+
33+ void generateImageSummary (filePath ) {
34+ def images = readFile(filePath). trim(). split(" \n " )
35+
36+ def report = " <h2>Image Summary Report</h2>\n "
37+ report + = " <p><strong>Total Images:</strong> ${ images.size()} </p>\n "
38+ report + = " <ul>\n "
39+
40+ images. each { image ->
41+ report + = " <li>${ image} </li>\n "
42+ }
43+
44+ report + = " </ul>\n "
45+ return report
46+ }
147void build (String IMAGE_PREFIX ){
248 withCredentials([usernamePassword(credentialsId : ' hub.docker.com' , passwordVariable : ' PASS' , usernameVariable : ' USER' ), file(credentialsId : ' DOCKER_REPO_KEY' , variable : ' docker_key' )]) {
349 sh """
@@ -9,20 +55,6 @@ void build(String IMAGE_PREFIX){
955 """
1056 }
1157}
12- void checkImageForDocker (String IMAGE_PREFIX ){
13- withCredentials([usernamePassword(credentialsId : ' hub.docker.com' , passwordVariable : ' PASS' , usernameVariable : ' USER' )]) {
14- sh """
15- IMAGE_PREFIX=${ IMAGE_PREFIX}
16- IMAGE_NAME='percona-xtradb-cluster-operator'
17- TrivyLog="$WORKSPACE /trivy-hight-\$ IMAGE_NAME-${ IMAGE_PREFIX} .xml"
18-
19- sg docker -c "
20- docker login -u '${ USER} ' -p '${ PASS} '
21- /usr/local/bin/trivy -q --cache-dir /mnt/jenkins/trivy-${ JOB_NAME} / image --format template --template @/tmp/junit.tpl -o \$ TrivyLog --ignore-unfixed --timeout 10m --exit-code 0 --severity HIGH,CRITICAL perconalab/\$ IMAGE_NAME:${ GIT_PD_BRANCH} -${ IMAGE_PREFIX}
22- "
23- """
24- }
25- }
2658
2759void pushImageToDocker (String IMAGE_PREFIX ){
2860 withCredentials([usernamePassword(credentialsId : ' hub.docker.com' , passwordVariable : ' PASS' , usernameVariable : ' USER' ), file(credentialsId : ' DOCKER_REPO_KEY' , variable : ' docker_key' )]) {
@@ -57,6 +89,8 @@ pipeline {
5789 label ' docker'
5890 }
5991 environment {
92+ PATH = " ${ WORKSPACE} /node_modules/.bin:$PATH " // Add local npm bin to PATH
93+ SNYK_TOKEN = credentials(' SNYK_ID' )
6094 DOCKER_REPOSITORY_PASSPHRASE = credentials(' DOCKER_REPOSITORY_PASSPHRASE' )
6195 }
6296 options {
@@ -69,13 +103,10 @@ pipeline {
69103 steps {
70104 git branch : ' master' , url : ' https://github.com/Percona-Lab/jenkins-pipelines'
71105 sh """
72- TRIVY_VERSION=\$ (curl --silent 'https://api.github.com/repos/aquasecurity/trivy/releases/latest' | grep '"tag_name":' | tr -d '"' | sed -E 's/.*v(.+),.*/\\ 1/')
73- wget https://github.com/aquasecurity/trivy/releases/download/v\$ {TRIVY_VERSION}/trivy_\$ {TRIVY_VERSION}_Linux-64bit.tar.gz
74- sudo tar zxvf trivy_\$ {TRIVY_VERSION}_Linux-64bit.tar.gz -C /usr/local/bin/
75-
76- if [ ! -f junit.tpl ]; then
77- wget --directory-prefix=/tmp https://raw.githubusercontent.com/aquasecurity/trivy/v\$ {TRIVY_VERSION}/contrib/junit.tpl
78- fi
106+ curl -sL https://static.snyk.io/cli/latest/snyk-linux -o snyk
107+ chmod +x snyk
108+ sudo mv ./snyk /usr/local/bin/
109+ sudo npm install snyk-to-html -g
79110
80111 # sudo is needed for better node recovery after compilation failure
81112 # if building failed on compilation stage directory will have files owned by docker user
@@ -103,25 +134,27 @@ pipeline {
103134 }
104135 }
105136 }
106- // stage('Push Images to Docker registry') {
107- // steps {
108- // pushImageToDocker('logcollector')
109- // }
110- // }
111- stage(' Trivy Checks' ) {
137+ stage(' Snyk CVEs Checks' ) {
112138 steps {
113- checkImageForDocker(' logcollector' )
114- }
115- post {
116- always {
117- junit allowEmptyResults : true , skipPublishingChecks : true , testResults : " *-logcollector.xml"
118- }
139+ checkImageForDocker(' \$ GIT_BRANCH' )
119140 }
120141 }
121142 }
122143 post {
123144 always {
124- archiveArtifacts artifacts : ' *.pdf' , allowEmptyArchive : true
145+ script {
146+ if (fileExists(' ./source/list-of-images.txt' )) {
147+ def summary = generateImageSummary(' ./source/list-of-images.txt' )
148+
149+ addSummary(icon : ' symbol-aperture-outline plugin-ionicons-api' ,
150+ text : " <pre>${ summary} </pre>"
151+ )
152+ // Also save as a file if needed
153+ writeFile(file : ' image-summary.html' , text : summary)
154+ } else {
155+ echo ' No ./source/list-of-images.txt file found - skipping summary generation'
156+ }
157+ }
125158 sh '''
126159 sudo docker rmi -f \$ (sudo docker images -q) || true
127160 '''
0 commit comments