github.com/verrazzano/verrazzano@v1.7.0/release/scripts/get_ocir_scan_results.sh (about) 1 #!/usr/bin/env bash 2 # 3 # Copyright (c) 2021, 2023, Oracle and/or its affiliates. 4 # Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. 5 # 6 # Generate OCIR image scan report 7 8 SCRIPT_DIR=$(cd $(dirname "$0"); pwd -P) 9 TOOL_SCRIPT_DIR=${SCRIPT_DIR}/../../tools/scripts 10 11 . $SCRIPT_DIR/common.sh 12 13 usage() { 14 cat <<EOM 15 Generates OCIR image scan report 16 17 Usage: 18 $(basename $0) scan-bom-file 19 20 Example: 21 $(basename $0) verrazzano-bom.json 22 23 The script expects the OCI CLI is installed. It also expects the following environment variables - 24 OCI_REGION - OCI region 25 OCIR_SCAN_REGISTRY - OCIR Registry 26 OCIR_REPOSITORY_BASE - Base OCIR repository path 27 OCIR_COMPARTMENT_ID - Compartment the OCIR repository is in 28 OCIR_PATH_FILTER - Regular expression to limit repository paths to include in report 29 SCAN_RESULTS_DIR 30 EOM 31 exit 0 32 } 33 34 [ -z "$OCI_REGION" ] || [ -z "$OCIR_SCAN_REGISTRY" ] || [ -z "$OCIR_REPOSITORY_BASE" ] || [ -z "$OCIR_COMPARTMENT_ID" ] || [ -z "$OCIR_PATH_FILTER" ] \ 35 || [ -z "$SCAN_RESULTS_DIR" ] || [ "$1" == "-h" ] || [ ! -f "$1" ]&& { usage; } 36 37 function get_repository_list() { 38 # TBD: See if we can just filter of the OCI list results to use the path filter, limit the json as well 39 oci artifacts container repository list --compartment-id $OCIR_COMPARTMENT_ID --region $OCI_REGION --all > $SCAN_RESULTS_DIR/scan-all-repos.json 40 cat $SCAN_RESULTS_DIR/scan-all-repos.json | jq '.data.items[]."display-name" | select(test("$OCIR_PATH_FILTER")?)' > $SCAN_RESULTS_DIR/filtered-repository-list.out 41 } 42 43 function get_scan_summaries() { 44 # TBD: Add filtering here 45 # TBD: Need to add more fields here so we can at least have the result OCIDs and may also want times in case there are multiple scan results to differentiate 46 # TBD: For multiple scans assuming -u will be mostly a noop here, ie: if we include all fields we wouldn't see any duplicates 47 oci vulnerability-scanning container scan result list --compartment-id $OCIR_COMPARTMENT_ID --region $OCI_REGION --all --is-latest-only true > $SCAN_RESULTS_DIR/ocir-scan-all-summary.json 48 cat $SCAN_RESULTS_DIR/ocir-scan-all-summary.json | jq -r '.data.items[] | { finished: ."time-finished", sev: ."highest-problem-severity", full: (.repository + ":" + .image), repo: .repository, image: .image, count: ."problem-count", id: .id } ' | jq -r '[.[]] | @csv' | sort -u > $SCAN_RESULTS_DIR/ocir-scan-all-summary.csv 49 } 50 51 # This will generate a more human readable text report. More suitable for forming a BUG report with than the CSV alone. 52 # 53 # $1 Scan result severity 54 # $2 Repository image with tag 55 # $3 Issue count 56 # $4 Scan result OCID 57 # $5 Result file basename (path and file prefix to use) 58 # $6 time finished 59 # $7 Overall Summary Report File 60 function generate_detail_text_report() { 61 [ -z "$1" ] || [ -z "$2" ] || [ -z "$3" ] || [ -z "$4" ] || [ -z "$5" ] || [ -z "$6" ] || [ -z "$7" ] && { echo "ERROR: generate_detail_text_report invalid args: $1 $2 $3 $4 $5 $6 $7"; return; } 62 RESULT_SEVERITY=$1 63 RESULT_REPOSITORY_IMAGE=$2 64 RESULT_COUNT=$3 65 SCAN_RESULT_OCID=$4 66 RESULT_FILE_BASE=$5 67 TIME_FINISHED=$6 68 OVERALL_SUMMARY=$7 69 # REVIEW: Rudimentary for now, can work on the format later, etc... 70 echo "OCIR Result Scan ID: $SCAN_RESULT_OCID" > $RESULT_FILE_BASE-ocir-report.out 71 echo "Scan Finished: $TIME_FINISHED" >> $RESULT_FILE_BASE-ocir-report.out 72 echo "Image: $RESULT_REPOSITORY_IMAGE" >> $RESULT_FILE_BASE-ocir-report.out 73 echo "Issue Count: $RESULT_COUNT" >> $RESULT_FILE_BASE-ocir-report.out 74 echo "Highest Severity: $RESULT_SEVERITY" >> $RESULT_FILE_BASE-ocir-report.out 75 echo "Issues:" >> $RESULT_FILE_BASE-ocir-report.out 76 cat $RESULT_FILE_BASE-ocir-details.csv >> $RESULT_FILE_BASE-ocir-report.out 77 78 # Contribute a subset of details to the overall summary report. This includes only CRITICAL and HIGH CVE's 79 echo "+++++" 80 echo "Image: $RESULT_REPOSITORY_IMAGE" >> $OVERALL_SUMMARY 81 cat $RESULT_FILE_BASE-ocir-details.csv | grep -e 'CRITICAL' -e 'HIGH' >> $OVERALL_SUMMARY 82 echo "-----" 83 } 84 85 # This will get the detailed scan results in JSON, form a CSV report, and also form a more human readable report 86 # 87 # $1 Scan result severity 88 # $2 Repository image with tag 89 # $3 Issue count 90 # $4 Scan result OCID 91 # $5 Result file path 92 # $6 Overall Summary Report File 93 function get_scan_details() { 94 [ -z "$1" ] || [ -z "$2" ] || [ -z "$3" ] || [ -z "$4" ] || [ -z "$5" ] || [ -z "$6" ] && { echo "ERROR: get_scan_details invalid args: $1 $2 $3 $4 $5 $6"; return; } 95 RESULT_SEVERITY=$1 96 RESULT_REPOSITORY_IMAGE=$2 97 RESULT_COUNT=$3 98 SCAN_RESULT_OCID=$4 99 RESULT_FILE_PREFIX="$5/$RESULT_REPOSITORY_IMAGE" 100 oci vulnerability-scanning container scan result get --container-scan-result-id $4 --region $OCI_REGION > $RESULT_FILE_PREFIX-ocir-details.json 101 cat $RESULT_FILE_PREFIX-ocir-details.json | jq -r '.data.problems[] | { sev: .severity, cve: ."cve-reference", description: .description } ' | sed 's/\\[nt]/ /g' | jq -r '[.[]] | @csv' | sort -u > $RESULT_FILE_PREFIX-ocir-details.csv 102 TIME_FINISHED=$(cat $RESULT_FILE_PREFIX-ocir-details.json | jq -r '.data."time-finished"') 103 generate_detail_text_report $1 $2 $3 $4 $RESULT_FILE_PREFIX $TIME_FINISHED $6 104 } 105 106 # This will get the scan summaries and details for all of the repositories 107 # 108 # It will also verify that all repositories found have scan results as well 109 # 110 # $1 Scan BOM file 111 function get_all_scan_details() { 112 [ ! -f "$1" ] && { echo "ERROR: get_all_scan_details invalid args: $1"; return; } 113 114 local bomimages=$(mktemp temp-bom-images-XXXXXX.out) 115 local overallsummary=$SCAN_RESULTS_DIR/overall-scan-ocir-report.out 116 sh $TOOL_SCRIPT_DIR/vz-registry-image-helper.sh -m $bomimages -t $OCIR_SCAN_REGISTRY -r $OCIR_REPOSITORY_BASE -b $1 117 118 # trim off the registry and base info so the images we have can be used for lookups in the CSV data 119 sed -i "s;$OCIR_SCAN_REGISTRY/$OCIR_REPOSITORY_BASE/;;g" $bomimages 120 121 # Get the scan summaries 122 get_scan_summaries 123 124 # For each image listed in the BOM, find the summary entries in the CSV list 125 while read BOM_IMAGE; do 126 echo "Getting scan details for $BOM_IMAGE" 127 128 # Find all scan summary entries for the image 129 local imagecsv=(mktemp temp_image-csv-XXXXXX.csv) 130 grep $BOM_IMAGE $SCAN_RESULTS_DIR/ocir-scan-all-summary.csv > $imagecsv 131 132 if [ ! -s "$imagecsv" ]; then 133 echo "ERROR: No scan results found for $BOM_IMAGE" 134 echo "$BOM_IMAGE" >> $SCAN_RESULTS_DIR/IMAGES-MISSING-OCIR-SCANS.OUT 135 else 136 # The summary is sorted ascending with the finished time as the first field, so get the last non-empty line 137 # of the CSV matches for this image for the most recent scan 138 CSV_LINE=$(tail -n 1 $imagecsv) 139 RESULT_FINISHED=$(echo "$CSV_LINE" | cut -d, -f"1" | sed 's/"//g') 140 RESULT_SEVERITY=$(echo "$CSV_LINE" | cut -d, -f"2" | sed 's/"//g') 141 RESULT_REPOSITORY_IMAGE=$(echo "$BOM_IMAGE" | sed 's;/;_;g') 142 RESULT_COUNT=$(echo "$CSV_LINE" | cut -d, -f"6" | sed 's/"//g') 143 SCAN_RESULT_OCID=$(echo "$CSV_LINE" | cut -d, -f"7" | sed 's/"//g') 144 145 # We only are reporting the last scan for the specific tagged image, so we should be OK using the image name/tag here for the filename) 146 get_scan_details $RESULT_SEVERITY $RESULT_REPOSITORY_IMAGE $RESULT_COUNT $SCAN_RESULT_OCID $SCAN_RESULTS_DIR $overallsummary 147 fi 148 rm $imagecsv 149 done <$bomimages 150 rm $bomimages 151 } 152 153 # Validate OCI CLI 154 validate_oci_cli || exit 1 155 156 mkdir -p $SCAN_RESULTS_DIR 157 158 get_all_scan_details $1 || exit 1