From 28a7993ac9f78e20da32616957ff07456898ebea Mon Sep 17 00:00:00 2001 From: Juho Nurminen Date: Tue, 24 Mar 2020 09:19:41 +0200 Subject: [PATCH] MM-22889: Integrate Dependency-Check to CircleCI (#14023) * Add basic dependency-check job * Include summary in alert * Link to NVD * Move the alert script to a separate file --- .circleci/config.yml | 44 ++++++++++++++++++++++++++++ dependency-suppression.xml | 59 ++++++++++++++++++++++++++++++++++++++ scripts/depcheck-alert.sh | 50 ++++++++++++++++++++++++++++++++ 3 files changed, 153 insertions(+) create mode 100644 dependency-suppression.xml create mode 100755 scripts/depcheck-alert.sh diff --git a/.circleci/config.yml b/.circleci/config.yml index a073ec9175..608ca3ffe9 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -2,6 +2,7 @@ version: 2.1 orbs: aws-s3: circleci/aws-s3@1.0.11 + owasp: entur/owasp@0.0.10 executors: ubuntu: @@ -40,6 +41,45 @@ jobs: - mattermost-webapp - mattermost-server + check-deps: + parameters: + cve_data_directory: + type: string + default: "~/.owasp/dependency-check-data" + working_directory: ~/mattermost/mattermost-server + executor: owasp/default + environment: + version_url: "https://jeremylong.github.io/DependencyCheck/current.txt" + executable_url: "https://dl.bintray.com/jeremy-long/owasp/dependency-check-VERSION-release.zip" + steps: + - attach_workspace: + at: ~/mattermost/ + - run: + name: Install Go + command: sudo apt-get update && sudo apt-get install golang + - owasp/with_commandline: + steps: + # Taken from https://github.com/entur/owasp-orb/blob/master/src/%40orb.yml#L349-L361 + - owasp/generate_cache_keys: + cache_key: commmandline-default-cache-key-v6 + - owasp/restore_owasp_cache + - run: + name: Update OWASP Dependency-Check Database + command: ~/.owasp/dependency-check/bin/dependency-check.sh --data << parameters.cve_data_directory >> --updateonly + - owasp/store_owasp_cache: + cve_data_directory: <> + - run: + name: Run OWASP Dependency-Check Analyzer + command: | + ~/.owasp/dependency-check/bin/dependency-check.sh --data << parameters.cve_data_directory >> \ + --format ALL --noupdate --enableExperimental --suppression ./dependency-suppression.xml \ + --scan './**/*' || true + - owasp/collect_reports: + persist_to_workspace: false + - run: + name: Post results to Mattermost + command: ./scripts/depcheck-alert.sh + # TODO: enable this step when the i18n-extract works with mattermost-server only # and not depend on both mm-server/enterprise # check-i18n: @@ -352,6 +392,10 @@ workflows: ignore: - master - /^release-.*/ + - check-deps: + context: sast-webhook + requires: + - setup # - check-i18n: # requires: # - setup diff --git a/dependency-suppression.xml b/dependency-suppression.xml new file mode 100644 index 0000000000..9151f3b4c1 --- /dev/null +++ b/dependency-suppression.xml @@ -0,0 +1,59 @@ + + + + + ^pkg:golang/golang\.org/x/crypto@.*$ + CVE-2019-11840 + + + + ^pkg:golang/github\.com/go\-sql\-driver/mysql@.*$ + cpe:/a:mysql:mysql + + + + ^pkg:golang/github\.com/.*$ + cpe:/a:github:github + + + + ^pkg:golang/github\.com/prometheus/client_model@.*$ + cpe:/a:prometheus:prometheus + + + + ^pkg:golang/github\.com/coreos/etcd@.*$ + CVE-2018-16886 + + + + ^pkg:golang/golang\.org/x/tools@.*$ + cpe:/a:data-tools_project:data_tools + + + + ^pkg:golang/golang\.org/x/crypto@.*$ + CVE-2017-3204 + + + + ^pkg:golang/golang\.org/x/crypto@.*$ + cpe:/a:ssh:ssh + + diff --git a/scripts/depcheck-alert.sh b/scripts/depcheck-alert.sh new file mode 100755 index 0000000000..d7ac08c9e9 --- /dev/null +++ b/scripts/depcheck-alert.sh @@ -0,0 +1,50 @@ +#!/usr/bin/env bash +# This is a script to post alerts about new Dependency-Check +# findings to the community server + +# Get artifacts from CircleCI +report_artifacts=$(curl -s https://circleci.com/api/v1.1/project/gh/$CIRCLE_PROJECT_USERNAME/$CIRCLE_PROJECT_REPONAME/$CIRCLE_BUILD_NUM/artifacts) +json_url=$(echo $report_artifacts | jq -r 'map(select(.path == "Reports/OWASP/dependency-check-report.json").url)[0]') +json_report=$(curl -s $json_url) + +# Anything new? +vulnerability_count=$(echo $json_report | jq '[.dependencies[]?.vulnerabilities[]?.name]|length') +if [ $vulnerability_count -ne 0 ] +then + alert_message="Dependency-Check made $vulnerability_count findings in [\`$CIRCLE_PROJECT_REPONAME\` build #$CIRCLE_BUILD_NUM]($CIRCLE_BUILD_URL)\n\n" + alert_message="$alert_message|Dependency|CPEs|CVEs|Severity|\n|----------|----|----|--------|\n" + html_url=$(echo $report_artifacts | jq -r 'map(select(.path == "Reports/OWASP/dependency-check-report.html").url)[0]') + + # Build the rows of the summary table + vulnerable_dependencies=($(echo $json_report | jq -r '[.dependencies[]?]|map(select(.vulnerabilities).fileName)[]')) + for dependency in ${vulnerable_dependencies[@]} + do + json_dependency=$(echo $json_report | jq -r '[.dependencies[]?]|map(select(.fileName=="'$dependency'"))[]') + index=$(echo $json_report | jq '[.dependencies[]?]|map(.fileName)|index("'$dependency'")+1') + sha1=$(echo $json_dependency | jq -r '.sha1') + # The SHA-1 is set on the JSON report only for non-virtual dependencies + # Calculation for virtual dependencies is analyzer-specific + if [ $sha1 = 'null' ] + then + evidence_source=$(echo $json_dependency | jq -r '.evidenceCollected|.vendorEvidence+.productEvidence+.versionEvidence|map(.source)|unique[0]') + if [ $evidence_source = 'Gopkg.lock' ] + then + sha1=($(echo $json_dependency | jq -r '.packages[0].id' | tr -d '\n' | sha1sum)) + else + sha1=($(echo $json_dependency | jq -r '.filePath' | tr -d '\n' | sha1sum)) + fi + fi + dependency_url="$html_url#l${index}_$sha1" + cpes=$(echo $json_dependency | jq -r '.vulnerabilityIds|select(.)|map("`"+.id+"`")|join(", ")') + cves=$(echo $json_dependency | jq -r '.vulnerabilities|select(.)|map("[`"+.name+"`](http://web.nvd.nist.gov/view/vuln/detail?vulnId="+.name+")")|join(", ")') + severities=$(echo $json_dependency | jq '.vulnerabilities|select(.)|map(.severity)|unique') + severity=$(echo $severities | jq -r 'if contains(["HIGH"]) then "`HIGH`" elif contains(["MEDIUM"]) then "`MEDIUM`" elif contains(["LOW"]) then "`LOW`" else "`Unknown`" end') + alert_message="$alert_message|[$dependency]"'('$dependency_url')'"|$cpes|$cves|$severity|\n" + done + alert_message=$alert_message'\nView the full report [here]('$html_url').' + + # Post to Mattermost + curl -s -X POST -d 'payload={"username": "Dependency-Check", "icon_url": "https://www.mattermost.org/wp-content/uploads/2016/04/icon.png", "text": + "'"$alert_message"'" + }' "$SAST_WEBHOOK_URL" +fi \ No newline at end of file