@@ -8,7 +8,7 @@ set -eou pipefail
88
99# If using a locally built stateless CI container, export SYSDIG_CI_IMAGE=<image_name>.
1010# This will override the image name from Dockerhub.
11- INLINE_SCAN_IMAGE=" ${SYSDIG_CI_IMAGE:- docker.io/ anchore/ inline-scan: v0.5.0 } "
11+ INLINE_SCAN_IMAGE=" ${SYSDIG_CI_IMAGE:- docker.io/ anchore/ inline-scan: v0.6.1 } "
1212DOCKER_NAME=" ${RANDOM:- temp} -inline-anchore-engine"
1313DOCKER_ID=" "
1414ANALYZE=false
@@ -33,9 +33,24 @@ SYSDIG_ANCHORE_URL="http://localhost:9040/api/scanning/v1/anchore"
3333SYSDIG_ANNOTATIONS=" foo=bar"
3434SYSDIG_IMAGE_DIGEST=" sha256:123456890abcdefg"
3535SYSDIG_IMAGE_ID=" 123456890abcdefg"
36+ SYSDIG_API_TOKEN=" test-token"
3637MANIFEST_FILE=" ./manifest.json"
38+ PDF_DIRECTORY=$( echo $PWD )
3739GET_CALL_STATUS=' '
3840GET_CALL_RETRIES=300
41+ DETAIL=false
42+
43+ if command -v sha256sum > /dev/null 2>&1 ; then
44+ SHASUM_COMMAND=" sha256sum"
45+ else
46+ if command -v shasum > /dev/null 2>&1 ; then
47+ SHASUM_COMMAND=" shasum -a 256"
48+ else
49+ printf " ERROR: sha256sum or shasum command is required but missing\n"
50+ exit 1
51+ fi
52+ fi
53+
3954
4055display_usage () {
4156cat << EOF
@@ -63,8 +78,8 @@ Sysdig Inline Analyzer --
6378
6479 Usage: ${0##*/ } analyze -k <API Token> [ OPTIONS ] <FULL_IMAGE_TAG>
6580
66- -k <TEXT> [required] API token for Sysdig Scanning auth (ex: -k '924c7ddc-4c09-4d22-bd52-2f7db22f3066 ')
67- -s <TEXT> [optional] Sysdig Secure URL (ex: -s 'https://secure-sysdig.svc.cluster.local').
81+ -k <TEXT> [required] API token for Sysdig Scanning auth (ex: -k 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx ')
82+ -s <TEXT> [optional] Sysdig Secure URL (ex: -s 'https://secure-sysdig.svc.cluster.local').
6883 If not specified, it will default to Sysdig Secure SaaS URL (https://secure.sysdig.com/).
6984 -a <TEXT> [optional] Add annotations (ex: -a 'key=value,key=value')
7085 -f <PATH> [optional] Path to Dockerfile (ex: -f ./Dockerfile)
@@ -73,6 +88,7 @@ Sysdig Inline Analyzer --
7388 -m <PATH> [optional] Path to Docker image manifest (ex: -m ./manifest.json)
7489 -P [optional] Pull container image from registry
7590 -V [optional] Increase verbosity
91+ -R <PATH> [optional] Download scan result pdf in a specified local directory (ex: -R /staging/reports)
7692
7793EOF
7894}
@@ -103,7 +119,7 @@ main() {
103119
104120get_and_validate_analyzer_options () {
105121 # Parse options
106- while getopts ' :k:s:r:u:p: a:d:f:i:m:t:PgVh ' option; do
122+ while getopts ' :k:s:a:d:f:i:m:R:PVh ' option; do
107123 case " ${option} " in
108124 k ) k_flag=true; SYSDIG_API_TOKEN=" ${OPTARG} " ;;
109125 s ) s_flag=true; SYSDIG_BASE_SCANNING_URL=" ${OPTARG%% } " ;;
@@ -114,6 +130,7 @@ get_and_validate_analyzer_options() {
114130 m ) m_flag=true; MANIFEST_FILE=" ${OPTARG} " ;;
115131 P ) P_flag=true;;
116132 V ) V_flag=true;;
133+ R ) R_flag=true; PDF_DIRECTORY=" ${OPTARG} " ;;
117134 h ) display_usage_analyzer; exit ;;
118135 \? ) printf " \n\t%s\n\n" " Invalid option: -${OPTARG} " >&2 ; display_usage_analyzer >&2 ; exit 1;;
119136 : ) printf " \n\t%s\n\n%s\n\n" " Option -${OPTARG} requires an argument." >&2 ; display_usage_analyzer >&2 ; exit 1;;
@@ -148,7 +165,7 @@ get_and_validate_analyzer_options() {
148165 printf ' \n\t%s\n\n' " ERROR - must specify a valid sha256:<digestID>: ${SYSDIG_IMAGE_DIGEST} " >&2
149166 display_usage_analyzer >&2
150167 exit 1
151- elif ! curl -k -s --fail -H " Authorization: Bearer ${SYSDIG_API_TOKEN} " " ${SYSDIG_SCANNING_URL} /policies " > /dev/null; then
168+ elif ! curl -k -s --fail -H " Authorization: Bearer ${SYSDIG_API_TOKEN} " " ${SYSDIG_ANCHORE_URL} /images " > /dev/null; then
152169 printf ' \n\t%s\n\n' " ERROR - invalid combination of Sysdig secure endpoint : token provided - ${SYSDIG_SCANNING_URL} : ${SYSDIG_API_TOKEN} " >&2
153170 display_usage_analyzer >&2
154171 exit 1
@@ -171,9 +188,18 @@ get_and_validate_analyzer_options() {
171188 printf ' \n\t%s\n\n' " ERROR - Manifest: ${MANIFEST_FILE} does not exist" >&2
172189 display_usage_analyzer >&2
173190 exit 1
191+ elif [[ " ${R_flag:- } " ]] && [[ ! -d " ${PDF_DIRECTORY} " ]]; then
192+ printf ' \n\t%s\n\n' " ERROR - Directory: ${PDF_DIRECTORY} does not exist" >&2
193+ display_usage_analyzer >&2
194+ exit 1
195+ elif [[ " ${R_flag:- } " ]] && [[ " ${PDF_DIRECTORY: -1} " == ' /' ]]; then
196+ printf ' \n\t%s\n\n' " ERROR - must specify file path - ${PDF_DIRECTORY} without trailing slash" >&2
197+ display_usage_analyzer >&2
198+ exit 1
174199 fi
175200
176201 if [[ " ${V_flag:- } " ]]; then
202+ DETAIL=true
177203 set -x
178204 fi
179205
@@ -220,7 +246,7 @@ get_and_validate_images() {
220246
221247prepare_inline_container () {
222248 # Check if env var is overriding which inline-scan image to utilize.
223- if [[ -z " ${SYSDIG_CI_IMAGE-docker.io/ anchore/ inline-scan: v0.5.0 } " ]]; then
249+ if [[ -z " ${SYSDIG_CI_IMAGE-docker.io/ anchore/ inline-scan: v0.6.1 } " ]]; then
224250 printf ' \n%s\n' " Pulling ${INLINE_SCAN_IMAGE} "
225251 docker pull " ${INLINE_SCAN_IMAGE} "
226252 else
@@ -260,6 +286,7 @@ start_analysis() {
260286
261287 FULLTAG=" ${SCAN_IMAGES[0]} "
262288
289+ printf ' %s\n\n' " Image id: ${SYSDIG_IMAGE_ID} "
263290 get_scan_result_code_by_id
264291 if [[ " ${GET_CALL_STATUS} " != 200 ]]; then
265292 post_analysis
@@ -287,7 +314,7 @@ post_analysis() {
287314
288315 # finally, get the account from Sysdig for the input username
289316 mkdir -p /tmp/sysdig
290- HCODE=$( curl -sSk --output /tmp/sysdig/sysdig_output.log --write-out " %{http_code}" -H " Authorization: Bearer ${SYSDIG_API_TOKEN} " " ${SYSDIG_ANCHORE_URL %%/ } /account" )
317+ HCODE=$( curl -sSk --output /tmp/sysdig/sysdig_output.log --write-out " %{http_code}" -H " Authorization: Bearer ${SYSDIG_API_TOKEN} " " ${SYSDIG_SCANNING_URL %%/ } /account" )
291318 if [[ " ${HCODE} " == 200 ]] && [[ -f " /tmp/sysdig/sysdig_output.log" ]]; then
292319 ANCHORE_ACCOUNT=$( cat /tmp/sysdig/sysdig_output.log | grep ' "name"' | awk -F' "' ' {print $4}' )
293320 CREATE_CMD+=(' -u "${ANCHORE_ACCOUNT}"' )
@@ -322,7 +349,7 @@ post_analysis() {
322349 fi
323350
324351 # Posting the archive to the secure backend
325- HCODE=$( curl -sSk --output /tmp/sysdig/sysdig_output.log --write-out " %{http_code}" -H " Content-Type: multipart/form-data" -H " Authorization: Bearer ${SYSDIG_API_TOKEN} " -F " archive_file=@/tmp/sysdig/${analysis_archive_name} " " ${SYSDIG_SCANNING_URL} /import/images" )
352+ HCODE=$( curl -sSk --output /tmp/sysdig/sysdig_output.log --write-out " %{http_code}" -H " Content-Type: multipart/form-data" -H " Authorization: Bearer ${SYSDIG_API_TOKEN} " -H " imageId: ${SYSDIG_IMAGE_ID} " -H " digestId: ${SYSDIG_IMAGE_DIGEST} " -H " imageName: ${FULLTAG} " - F " archive_file=@/tmp/sysdig/${analysis_archive_name} " " ${SYSDIG_SCANNING_URL} /import/images" )
326353
327354 if [[ " ${HCODE} " != 200 ]]; then
328355 printf ' \n\t%s\n\n' " ERROR - unable to POST ${analysis_archive_name} to ${SYSDIG_SCANNING_URL%%/ } /import/images" >&2
@@ -341,47 +368,100 @@ get_repo_digest_id() {
341368 # Check to see if repo digest exists
342369 DIGESTS=$( docker inspect --format=" {{.RepoDigests}}" " ${SCAN_IMAGES[0]} " )
343370
344- BASE_IMAGE=$( echo ${IMAGE_NAMES[0]} | cut -d / -f 2 | cut -d : -f 1)
345-
346- if [[ ${DIGESTS} == * " ${BASE_IMAGE} " * ]]; then
347- DIGEST=$( echo ${DIGESTS} | tr -d ' [' | tr -d ' ]' | cut -d : -f 2 | cut -d ' ' -f 1)
348- SYSDIG_IMAGE_DIGEST=$( echo " sha256:${DIGEST} " )
349- fi
371+ REPO=$( echo ${IMAGE_NAMES[0]} | rev | cut -d / -f 2 | rev)
372+ BASE_IMAGE=$( echo ${IMAGE_NAMES[0]} | rev | cut -d / -f 1 | rev | cut -d : -f 1)
373+ TAG=$( echo ${IMAGE_NAMES[0]} | rev | cut -d / -f 1 | rev | cut -d : -f 2)
350374
375+ if [[ -z " ${TAG// } " ]]; then
376+ TAG=' latest'
377+ fi
378+
379+ FINAL_DIGEST=" sha256@12345"
380+ for DIGEST in " ${DIGESTS[@]} "
381+ do
382+ if [[ ${DIGEST} == * " ${REPO} /${BASE_IMAGE} :${TAG} " * || ${DIGEST} == * " ${REPO} /${BASE_IMAGE} " * || ${DIGEST} == * " ${BASE_IMAGE} " * ]]; then
383+ FINAL_DIGEST=$( echo ${DIGEST} | rev | cut -d : -f 1 | rev | tr -d ' ]' | cut -d ' ' -f 1)
384+ else
385+ printf ' %s\n' " Unable to compute the digest from docker inspect ${SCAN_IMAGES[0]} !"
386+ printf ' %s\n' " Consider running with -d option with a valid sha256:<digestID>."
387+ fi
388+ done
389+
351390 # Generate Image digest ID for given image, if repo digest is not present
352391 if [[ " ${SYSDIG_IMAGE_DIGEST} " == ' sha256:123456890abcdefg' ]]; then
353- SYSDIG_IMAGE_DIGEST=$( docker inspect " ${SCAN_IMAGES[0]} " | sha256sum | awk ' { print $1 }' | tr -d " \n" )
392+ SYSDIG_IMAGE_DIGEST=$( docker inspect " ${SCAN_IMAGES[0]} " | ${SHASUM_COMMAND} | awk ' { print $1 }' | tr -d " \n" )
354393 SYSDIG_IMAGE_DIGEST=$( echo " sha256:${SYSDIG_IMAGE_DIGEST} " )
394+ else # Use parsed digest from array of digests based on docker inspect result
395+ SYSDIG_IMAGE_DIGEST=$( echo " sha256:${FINAL_DIGEST} " )
355396 fi
397+ printf ' \n%s\n' " Repo name: ${REPO} "
398+ printf ' %s\n' " Base image name: ${BASE_IMAGE} "
399+ printf ' %s\n\n' " Tag name: ${TAG} "
356400}
357401
358402get_scan_result_code_by_id () {
359- GET_CALL_STATUS=$( curl -sk -o /dev/null --write-out " %{http_code}" --header " Content-Type: application/json" -H " Authorization: Bearer ${SYSDIG_API_TOKEN} " " ${SYSDIG_ANCHORE_URL} /images/by_id/${SYSDIG_IMAGE_ID} /check?tag=$FULLTAG &detail=false " )
403+ GET_CALL_STATUS=$( curl -sk -o /dev/null --write-out " %{http_code}" --header " Content-Type: application/json" -H " Authorization: Bearer ${SYSDIG_API_TOKEN} " " ${SYSDIG_ANCHORE_URL} /images/by_id/${SYSDIG_IMAGE_ID} /check?tag=$FULLTAG &detail=${DETAIL} " )
360404}
361405
362406get_scan_result_by_id_with_retries () {
363407 # Fetching the result of each scanned digest
364408 for (( i= 0 ; i< ${GET_CALL_RETRIES} ; i++ )) ; do
365409 get_scan_result_code_by_id
366410 if [[ " ${GET_CALL_STATUS} " == 200 ]]; then
367- status=$( curl -sk --header " Content-Type: application/json" -H " Authorization: Bearer ${SYSDIG_API_TOKEN} " " ${SYSDIG_ANCHORE_URL} /images/by_id/${SYSDIG_IMAGE_ID} /check?tag=$FULLTAG &detail=false " | grep " status" | cut -d : -f 2 | awk -F\" ' { print $2 }' )
411+ status=$( curl -sk --header " Content-Type: application/json" -H " Authorization: Bearer ${SYSDIG_API_TOKEN} " " ${SYSDIG_ANCHORE_URL} /images/by_id/${SYSDIG_IMAGE_ID} /check?tag=$FULLTAG &detail=${DETAIL} " | grep " status" | cut -d : -f 2 | awk -F\" ' { print $2 }' )
368412 break
369413 fi
370414 echo -n " ." && sleep 1
371415 done
372-
416+
373417 printf " Scan Report - \n"
374- curl -s -k --header " Content-Type: application/json" -H " Authorization: Bearer ${SYSDIG_API_TOKEN} " " ${SYSDIG_ANCHORE_URL} /images/by_id/${SYSDIG_IMAGE_ID} /check?tag=$FULLTAG &detail=false"
418+ curl -s -k --header " Content-Type: application/json" -H " Authorization: Bearer ${SYSDIG_API_TOKEN} " " ${SYSDIG_ANCHORE_URL} /images/by_id/${SYSDIG_IMAGE_ID} /check?tag=$FULLTAG &detail=${DETAIL} "
419+
420+ if [[ " ${R_flag-" " } " ]]; then
421+ printf " \nDownloading PDF Scan result for image id: ${SYSDIG_IMAGE_ID} / digest: ${SYSDIG_IMAGE_DIGEST} "
422+ get_scan_result_pdf_by_digest
423+ fi
375424
376425 if [[ " ${status} " = " pass" ]]; then
377426 printf " \nStatus is pass\n"
427+ print_scan_result_summary_message
378428 exit 0
379429 else
380430 printf " \nStatus is fail\n"
431+ print_scan_result_summary_message
381432 exit 1
382433 fi
383434}
384435
436+ urlencode () {
437+ # urlencode <string>
438+ local length=" ${# 1} "
439+ for (( i = 0 ; i < length; i++ )) ; do
440+ local c=" ${1: i: 1} "
441+ case $c in
442+ [a-zA-Z0-9.~_-]) printf " $c " ;;
443+ * ) printf ' %%%02X' " '$c "
444+ esac
445+ done
446+ }
447+
448+ print_scan_result_summary_message () {
449+ if [[ ! " ${V_flag-" " } " && ! " ${R_flag-" " } " ]]; then
450+ if [[ ! " ${status} " = " pass" ]]; then
451+ echo " Result Details: "
452+ curl -s -k --header " Content-Type: application/json" -H " Authorization: Bearer ${SYSDIG_API_TOKEN} " " ${SYSDIG_ANCHORE_URL} /images/by_id/${SYSDIG_IMAGE_ID} /check?tag=$FULLTAG &detail=true"
453+ fi
454+ ENCODED_TAG=$( urlencode ${FULLTAG} )
455+ echo " View the full result @ ${SYSDIG_BASE_SCANNING_URL} /#/scanning/scan-results/${ENCODED_TAG} /${SYSDIG_IMAGE_DIGEST} /summaries"
456+ printf " PDF report of the scan results can be generated with -R option.\n"
457+ fi
458+ }
459+
460+ get_scan_result_pdf_by_digest () {
461+ date_format=$( date +' %Y-%m-%d' )
462+ curl -sk --header " Content-Type: application/json" -H " Authorization: Bearer ${SYSDIG_API_TOKEN} " -o " ${PDF_DIRECTORY} /${date_format} -${FULLTAG##*/ } -scan-result.pdf" " ${SYSDIG_SCANNING_URL} /images/${SYSDIG_IMAGE_DIGEST} /report?tag=$FULLTAG "
463+ }
464+
385465save_and_copy_images () {
386466 # Save all image files to /tmp and copy to created container
387467 for image in " ${SCAN_IMAGES[@]-} " ; do
0 commit comments