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