From 67e6b0bdc4298c31e88e1bb7b48a25afcf4099d2 Mon Sep 17 00:00:00 2001 From: Steven Quan <70890758+stevenquanheycar@users.noreply.github.com> Date: Thu, 21 Mar 2024 15:25:12 +0000 Subject: [PATCH] feat(TECH): gh action ecr scan results (#1) * feat/(TECH): initial commit ecr scan results action * pre-commit fix * updating due to requested changes * removing extra declare * correcting path for source scripts * pre-commit fix * fix suggestions * fixing docker file * pinning jq and curl --- Dockerfile | 10 +++++--- action.yml | 32 ++++++++++++++----------- scripts/gh-utils.sh | 26 +++++++++++++++++++++ scripts/script.sh | 57 +++++++++++++++++++++++++++++++-------------- 4 files changed, 92 insertions(+), 33 deletions(-) create mode 100644 scripts/gh-utils.sh diff --git a/Dockerfile b/Dockerfile index b7eb09c..9705431 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,14 +1,17 @@ ARG ALPINE_VERSION="3.19" -ARG BASH_VERSION="5.2.26-r0" - FROM alpine:${ALPINE_VERSION} +ARG BASH_VERSION="5" +ARG AWS_CLI_VERSION="2" +ARG JQ_VERSION="1" +ARG CURL_VERSION="8" + WORKDIR /scripts RUN apk update --no-cache; \ apk upgrade --no-cache; \ - apk add --no-cache bash=${BASH_VERSION}; \ + apk add --no-cache bash~=${BASH_VERSION} aws-cli~=${AWS_CLI_VERSION} jq~=${JQ_VERSION} curl~=${CURL_VERSION} ; \ rm -rf /var/cache/apk/* ENV LOG_LEVEL "INFO" @@ -16,6 +19,7 @@ ENV LOG_TIMESTAMPED "true" ENV DEBUG_MODE "false" COPY scripts/utils.sh . +COPY scripts/gh-utils.sh . COPY scripts/script.sh . ENTRYPOINT ["/scripts/script.sh"] diff --git a/action.yml b/action.yml index f55c3c9..99aea76 100644 --- a/action.yml +++ b/action.yml @@ -1,9 +1,9 @@ -name: Some action # TODO(user): Replace this with your action name +name: ECR Scan branding: icon: arrow-right-circle color: gray-dark -description: | # TODO(user): replace this with your action description - This action does something +description: | + This action scans ecr scan result and reports results back to pr inputs: debug-mode: @@ -18,15 +18,19 @@ inputs: description: Set to true in order to enable timestamps on log messages required: false default: 'true' - # TODO(user): Specify your inputs here - input-name: - description: Some input description + aws-account-id: + description: AWS account ID to use for ECR repo required: true - -# TODO(user): Define your outputs here -outputs: - some-output: - description: 'Some output description' + ecr-repo-name: + description: AWS ECR Repo Name to use to view scan + required: true + ecr-repo-tag: + description: AWS ECR Repo image tag to use to view scan + required: true + use-alpha: + description: AWS ECR Repo Alpha image + required: false + default: 'true' runs: using: 'docker' @@ -35,5 +39,7 @@ runs: DEBUG_MODE: ${{ inputs.debug-mode }} LOG_LEVEL: ${{ inputs.log-level }} LOG_TIMESTAMPED: ${{ inputs.log-timestamped }} - # TODO(user): Define your environment variables here - SOME_INPUT: ${{ inputs.input-name }} + AWS_ACCOUNT_ID: ${{ inputs.aws-account-id }} + ECR_REPO_NAME: ${{ inputs.ecr-repo-name }} + ECR_REPO_TAG: ${{ inputs.ecr-repo-tag }} + USE_ALPHA_REGISTRY: ${{ inputs.use-alpha }} diff --git a/scripts/gh-utils.sh b/scripts/gh-utils.sh new file mode 100644 index 0000000..036ff1e --- /dev/null +++ b/scripts/gh-utils.sh @@ -0,0 +1,26 @@ +#!/usr/bin/env bash + +# The `comment_on_pull_request` function pushes a comment to a pull request. +function comment_on_pull_request() { + _repo_org="${1}" + _repo_name="${2}" + _pr_number="${3}" + _comment_body="${4}" + _delete_previous_comments="${5}" + _comment_id="${6}" + + if [[ "$(check_bool "${_delete_previous_comments}")" ]]; then + if [[ -z "${_comment_id}" ]]; then + log_out "No comment id was provided for deleting previous comments. Aborting." "FATAL" 1 + else + delete_previous_comments "${_repo_org}" "${_repo_name}" "${_pr_number}" + fi + fi + + log_out "Commenting on ${_repo_org}/${_repo_name}#${_pr_number}" + if [[ -z "${_comment_id}" ]]; then + printf "%s" "${_comment_body}" | gh pr comment "${_pr_number}" -R "${_repo_org}/${_repo_name}" -F - + else + printf "%s \n %s" "$(get_formatted_comment_id "${_comment_id}")" "${_comment_body}" | gh pr comment "${_pr_number}" -R "${_repo_org}/${_repo_name}" -F - + fi +} diff --git a/scripts/script.sh b/scripts/script.sh index 068071c..d63f727 100755 --- a/scripts/script.sh +++ b/scripts/script.sh @@ -1,25 +1,48 @@ #!/usr/bin/env bash . "$(dirname "$0")/utils.sh" +. "$(dirname "$0")/gh-utils.sh" -# Your action logic goes here +REPO_ORG=${GITHUB_REPOSITORY_OWNER} +REPO_NAME=$(echo "${GITHUB_REPOSITORY}" |cut -d "/" -f2) +PR_NUMBER=${GITHUB_SHA} +check_env_var "AWS_ACCOUNT_ID" +check_env_var "ECR_REPO_NAME" +check_env_var "ECR_REPO_TAG" +check_env_var "USE_ALPHA_REGISTRY" -# TODO(user): Use this helper function to check if a required env variable is set or not -check_env_var "SOME_INPUT" +if [[ "$(check_bool "${USE_ALPHA_REGISTRY}")" ]]; then + _scan_repo_name="alpha-image/${ECR_REPO_NAME}" +else + _scan_repo_name="image/${ECR_REPO_NAME}" +fi +_scan_repo_link="https://eu-central-1.console.aws.amazon.com/ecr/repositories/private/${AWS_ACCOUNT_ID}/${_scan_repo_name}" + +log_info "Fetching scan results from ECR" +log_debug "repo=\"${_scan_repo_name}\" | imageTag=\"${ECR_REPO_TAG}\"" +_scan_results="$(aws ecr describe-image-scan-findings --repository-name "${_scan_repo_name}" --image-id="imageTag=${ECR_REPO_TAG}" | jq '.imageScanFindings.findingSeverityCounts // {}')" -# TODO(user): Use the `check_bool` helper function to check for bool values -if [[ "$(check_bool "true")" ]]; then - # TODO(user): Use the `log_out` helper function to log messages - log_out "hello world" "INFO" - # The following are some handy logging functions - log_debug "This is a DEBUG log" - log_info "This is a INFO log" - log_warning "This is a WARNING log" - log_error "This is a ERROR log" - log_fatal "This is a FATAL log" # <- This one exists with an error - log_fatal "This is a FATAL log with custom exit code" 5 # <- This one exists with an error - log_out "This is a custom log message that exits with code 10" "FATAL" 10 +_scan_results_comment="" +if [[ "${_scan_results}" == "{}" ]]; then + log_info "Did not find any vulnerabilities on the ECR repo." + echo ":tada: Did not find any vulnerabilities in [${_scan_repo_name}](${_scan_repo_link}). Good job :+1:" >>"${_scan_results_comment}" +else + log_info "Found vulnerabilities on ECR." + { + echo ":warning: Found the following number of vulnerabilities on [${_scan_repo_name}](${_scan_repo_link}):" + echo "- type \`CRITICAL\`: **$(echo "${_scan_results}" | jq '.CRITICAL // 0')**" + echo "- type \`HIGH\`: **$(echo "${_scan_results}" | jq '.HIGH // 0')**" + echo "- type \`MEDIUM\`: **$(echo "${_scan_results}" | jq '.MEDIUM // 0')**" + echo "- type \`LOW\`: **$(echo "${_scan_results}" | jq '.LOW // 0')**" + echo "- type \`UNDEFINED\`: **$(echo "${_scan_results}" | jq '.UNDEFINED // 0')**" + echo "- type \`INFORMATIONAL\`: **$(echo "${_scan_results}" | jq '.INFORMATIONAL // 0')**" + } >>"${_scan_results_comment}" fi -# TODO(user): This is how to output something to GH actions -echo "some-output=HelloThereGeneralKenobi" >>"${GITHUB_OUTPUT}" +comment_on_pull_request "${REPO_ORG}" \ + "${REPO_NAME}" \ + "${PR_NUMBER}" \ + "${_scan_results_comment}" \ + "true" \ + "scan-results:${_scan_repo_name}" +