diff --git a/docker-image/Dockerfiles/Dockerfile b/docker-image/Dockerfiles/Dockerfile index 14ffc4c..6f2653a 100644 --- a/docker-image/Dockerfiles/Dockerfile +++ b/docker-image/Dockerfiles/Dockerfile @@ -1,7 +1,5 @@ -ARG JAVA_MINOR_PATCH_VERSION=0.2 - # first stage -FROM registry.access.redhat.com/ubi9/nodejs-18 as builder +FROM registry.access.redhat.com/ubi9/nodejs-20 as builder # use privilaged user USER root @@ -9,77 +7,63 @@ USER root # assign token for reading packages from github package registry ARG PACKAGE_REGISTRY_ACCESS_TOKEN='' -ARG JAVA_MINOR_PATCH_VERSION - # install Java -RUN curl -kL https://download.oracle.com/java/21/latest/jdk-21_linux-x64_bin.tar.gz -o /tmp/java-package.tar.gz \ +RUN curl -kL https://download.oracle.com/java/21/archive/jdk-21.0.1_linux-x64_bin.tar.gz -o /tmp/java-package.tar.gz \ && tar xvzf /tmp/java-package.tar.gz -C /usr/ # install Maven package manager -RUN curl -kL https://dlcdn.apache.org/maven/maven-3/3.9.4/binaries/apache-maven-3.9.4-bin.tar.gz -o /tmp/maven-package.tar.gz \ +RUN curl -kL https://dlcdn.apache.org/maven/maven-3/3.9.6/binaries/apache-maven-3.9.6-bin.tar.gz -o /tmp/maven-package.tar.gz \ && tar xvzf /tmp/maven-package.tar.gz -C /usr/ # install golang package manager -RUN curl -kL https://go.dev/dl/go1.21.1.linux-amd64.tar.gz -o /tmp/golang-package.tar.gz \ +RUN curl -kL https://go.dev/dl/go1.21.5.linux-amd64.tar.gz -o /tmp/golang-package.tar.gz \ && tar xvzf /tmp/golang-package.tar.gz -C /usr/ -# install python package manager (pip) -RUN python3 -m ensurepip --upgrade - # install jq JSON formating tool -RUN curl -kL https://github.com/jqlang/jq/releases/download/jq-1.6/jq-linux64 -o /usr/bin/jq - -# install linux utils Package to enable UUID generation -RUN yum install util-linux +RUN curl -kL https://github.com/jqlang/jq/releases/download/jq-1.7.1/jq-linux64 -o /usr/bin/jq # copy the .npmrc file COPY configs/.npmrc . # replace placeholder with the actual environment variable RUN sed -i "s/__PACKAGE_REGISTRY_ACCESS_TOKEN__/${PACKAGE_REGISTRY_ACCESS_TOKEN}/g" ./.npmrc # install Exhort javascript API -RUN npm install --global @RHEcosystemAppEng/exhort-javascript-api +RUN npm install --global @RHEcosystemAppEng/exhort-javascript-api@0.1.1-ea.26 # add RHDA script -COPY scripts/rhda.sh / +COPY scripts/rhda.sh /rhda.sh -ENV JDK_VERSION=jdk-21.${JAVA_MINOR_PATCH_VERSION} # assign executable permissions to all installed binaries -RUN chmod +x /usr/${JDK_VERSION} \ - && chmod +x /usr/apache-maven-3.9.4/bin/mvn \ +RUN chmod +x /usr/jdk-21.0.1/bin/java \ + && chmod +x /usr/apache-maven-3.9.6/bin/mvn \ && chmod +x /usr/go/bin/go \ - && chmod +x /usr/local/bin/pip3 \ && chmod +x /usr/bin/jq \ - && chmod +x /usr/bin/uuidgen \ && chmod +x /opt/app-root/src/.npm-global/bin/exhort-javascript-api \ - && chmod +x /rhda.sh + && chmod +x /rhda.sh # use default user -USER default +USER default # second stage -FROM registry.access.redhat.com/ubi9/nodejs-18-minimal +FROM registry.access.redhat.com/ubi9/nodejs-20-minimal LABEL org.opencontainers.image.source https://github.com/RHEcosystemAppEng/exhort-javascript-api -ARG JAVA_MINOR_PATCH_VERSION - -# assign token for exhort authentication with Snyk provider -ENV EXHORT_SNYK_TOKEN='' -# assign rhda token for rhda user authentication with exhort -ENV RHDA_TOKEN='' # assign rhda source for exhort tracking purposes ENV RHDA_SOURCE='' +# contains pip feeze --all data, base64 encoded +ENV EXHORT_PIP_FREEZE='' +# contains pip show data for all packages, base64 encoded +ENV EXHORT_PIP_SHOW='' +# indicate whether to use the Minimal version selection (MVS) algorithm to select a set of module versions to use when building Go packages. +ENV EXHORT_GO_MVS_LOGIC_ENABLED='false' -ENV JDK_VERSION=jdk-21.${JAVA_MINOR_PATCH_VERSION} - -USER root # Copy java executable from the builder stage -COPY --from=builder /usr/$JDK_VERSION/ /usr/$JDK_VERSION/ -ENV JAVA_HOME=/usr/$JDK_VERSION +COPY --from=builder /usr/jdk-21.0.1/ /usr/jdk-21.0.1/ +ENV JAVA_HOME=/usr/jdk-21.0.1 # Copy maven executable from the builder stage -COPY --from=builder /usr/apache-maven-3.9.4/ /usr/apache-maven-3.9.4/ -ENV MAVEN_HOME=/usr/apache-maven-3.9.4 +COPY --from=builder /usr/apache-maven-3.9.6/ /usr/apache-maven-3.9.6/ +ENV MAVEN_HOME=/usr/apache-maven-3.9.6 # Copy golang executable from the builder stage COPY --from=builder /usr/go/ /usr/go/ @@ -88,28 +72,11 @@ ENV GOLANG_HOME=/usr/go # Update PATH ENV PATH=$PATH:$JAVA_HOME/bin:$MAVEN_HOME/bin:$GOLANG_HOME/bin -# Copy python executable from the builder stage -COPY --from=builder /usr/bin/python3 /usr/bin/python3 -COPY --from=builder /usr/local/bin/pip3 /usr/local/bin/pip3 -COPY --from=builder /usr/lib64/python3.9 /usr/lib64/python3.9 -COPY --from=builder /usr/local/lib/python3.9 /usr/local/lib/python3.9 -COPY --from=builder /usr/lib64/libpython3.9.so.1.0 /usr/lib64/libpython3.9.so.1.0 -COPY --from=builder /usr/lib64/libexpat.so.1 /usr/lib64/libexpat.so.1 - -RUN ln -s /usr/bin/python3 /usr/bin/python \ - && ln -s /usr/local/bin/pip3 /usr/bin/pip - # Copy jq executable from the builder stage COPY --from=builder /usr/bin/jq /usr/bin/jq -# Copy uuidgen executable from the builder stage -COPY --from=builder /usr/bin/uuidgen /usr/bin/uuidgen - # Copy exhort-javascript-api executable from the builder stage COPY --from=builder /opt/app-root/src/.npm-global/ /opt/app-root/src/.npm-global/ # Copy RHDA executable script from the builder stage -COPY --from=builder /rhda.sh /rhda.sh - -#Original UID in base image -USER 1001 +COPY --from=builder /rhda.sh /rhda.sh \ No newline at end of file diff --git a/docker-image/README.md b/docker-image/README.md index eac343f..b31e8b8 100644 --- a/docker-image/README.md +++ b/docker-image/README.md @@ -13,7 +13,27 @@ Both Docker and Podman are container runtimes that can be used to build and run ## Images generated for Exhort Javascript API -Ecosystem | Version | IMAGE | TAG | -----------------------| ------------------------------------------------------------------ | ----------------------------------------------- |-------------------| -Maven & NPM | mvn 3.9.4,
npm 9.5.0 | quay.io/ecosystem-appeng/exhort-javascript-api | 0.7.0-alpha | -Maven, NPM & Golang | mvn 3.9.4,
npm 9.5.0,
go 1.21.1 | quay.io/ecosystem-appeng/exhort-javascript-api | 0.7.3-alpha | +Ecosystem | Version | IMAGE | TAG | +------------------------------| ------------------------------------------------------------------ | ----------------------------------------------- |-------------------| +Maven, NPM, Golang | mvn 3.9.6,
npm 10.2.4,
go 1.21.5,
python \ | quay.io/ecosystem-appeng/exhort-javascript-api | 0.1.1-ea.26 | + + +## Usage Notes + +To perform RHDA analysis on a **Python** ecosystem, the data from both `pip freeze --all` and `pip show` commands should be generated for all packages listed in the requirements.txt manifest. This data should be encoded in base64 and passed through the `EXHORT_PIP_FREEZE` and `EXHORT_PIP_SHOW` environment variables, respectively. +Code example: +``` shell +# Install requirements.txt +pip3 install -r requirements.txt + +# Generate pip freeze --all data +pip3 freeze --all > pip_freeze.txt + +# Generate pip show data +SHOW_LIST=$(awk -F '==' '{print $1}' < pip_freeze.txt) +pip3 show $(echo "$SHOW_LIST") > pip_show.txt + +# Encode data using base64 and export to environment variables +export EXHORT_PIP_FREEZE=$(cat pip_freeze.txt | base64 -w 0) +export EXHORT_PIP_SHOW=$(cat pip_show.txt | base64 -w 0) +``` \ No newline at end of file diff --git a/docker-image/scripts/rhda.sh b/docker-image/scripts/rhda.sh index fdfc914..32e821e 100644 --- a/docker-image/scripts/rhda.sh +++ b/docker-image/scripts/rhda.sh @@ -5,7 +5,7 @@ output_file_path="$2" printf "Analysing the stack. Please wait..\n\n" -# Getting stack analysis report using exhort Javascript CLI. +# Getting RHDA stack analysis report using Exhort Javascript CLI. report=$(exhort-javascript-api stack $manifest_file_path 2>error.log) exit_code=$? @@ -22,26 +22,41 @@ then printf "\n[ERROR] Red Hat Dependency Analytics failed with exit code $exit_code.\n$error_message" exit 1 else - # In case of success print details from report into console - printf "Red Hat Dependency Analytics task is being executed.\n" - printf "=%.0s" {1..50} - printf "\nRed Hat Dependency Analytics Report\n" - printf "=%.0s" {1..50} - printf "\n" - printf "Total Scanned Dependencies : %s \n" "$(jq -r '.summary.dependencies.scanned' <<< $report)" - printf "Total Scanned Transitive Dependencies : %s \n" "$(jq -r '.summary.dependencies.transitive' <<< $report)" - printf "Total Vulnerabilities : %s \n" "$(jq -r '.summary.vulnerabilities.total' <<< $report)" - printf "Direct Vulnerable Dependencies : %s \n" "$(jq -r '.summary.vulnerabilities.direct' <<< $report)" - - provider_status=$(jq -rc '.summary.providerStatuses[] | select(.provider == "snyk")' <<< $report) +# In case of success print report summary into console +printf "\nRed Hat Dependency Analytics Report\n" +printf "=%.0s" {1..50} +printf "\n" +printf "Dependencies\n" +printf " Total Scanned : %s \n" "$(jq -r '.scanned.total' <<< $report)" +printf " Total Direct : %s \n" "$(jq -r '.scanned.direct' <<< $report)" +printf " Total Transitive : %s \n" "$(jq -r '.scanned.transitive' <<< $report)" + +providers=$(jq -rc '.providers | keys[] | select(. != "trusted-content")' <<< "$report") +for provider in $providers; do + printf "\nProvider: %s\n" "${provider^}" + + provider_status=$(jq -r --arg provider "$provider" '.providers[$provider].status' <<< $report) message=$(echo $provider_status | jq -r '.message') - printf "Snyk Provider Status : " + printf " Provider Status :" printf "%+40s" $message $'\n' | sed 's/ */ /g' - printf "Critical Vulnerabilities : %s \n" "$(jq -r '.summary.vulnerabilities.critical' <<< $report)" - printf "High Vulnerabilities : %s \n" "$(jq -r '.summary.vulnerabilities.high' <<< $report)" - printf "Medium Vulnerabilities : %s \n" "$(jq -r '.summary.vulnerabilities.medium' <<< $report)" - printf "Low Vulnerabilities : %s \n" "$(jq -r '.summary.vulnerabilities.low' <<< $report)" - printf "=%.0s" {1..50} + + code=$(echo $provider_status | jq -r '.code') + if [ "$code" -eq 200 ]; then + sources=$(jq -r --arg provider "$provider" '.providers[$provider].sources | keys[]' <<< "$report") + for source in $sources; do + printf " Source: %s\n" "${source^}" + printf " Vulnerabilities\n" + printf " Total : %s \n" "$(jq -r --arg provider "$provider" --arg source "$source" '.providers[$provider].sources[$source].summary.total' <<< $report)" + printf " Direct : %s \n" "$(jq -r --arg provider "$provider" --arg source "$source" '.providers[$provider].sources[$source].summary.direct' <<< $report)" + printf " Transitive : %s \n" "$(jq -r --arg provider "$provider" --arg source "$source" '.providers[$provider].sources[$source].summary.transitive' <<< $report)" + printf " Critical : %s \n" "$(jq -r --arg provider "$provider" --arg source "$source" '.providers[$provider].sources[$source].summary.critical' <<< $report)" + printf " High : %s \n" "$(jq -r --arg provider "$provider" --arg source "$source" '.providers[$provider].sources[$source].summary.high' <<< $report)" + printf " Medium : %s \n" "$(jq -r --arg provider "$provider" --arg source "$source" '.providers[$provider].sources[$source].summary.medium' <<< $report)" + printf " Low : %s \n" "$(jq -r --arg provider "$provider" --arg source "$source" '.providers[$provider].sources[$source].summary.low' <<< $report)" + done + fi +done +printf "=%.0s" {1..50} # Save report along with exit code into output file. jq -n {} | \