github.com/argoproj/argo-cd/v3@v3.2.1/hack/snyk-report.sh (about) 1 #!/usr/bin/env bash 2 3 set -e 4 set -o pipefail 5 6 function get_latest_minor_version_tags() { 7 count=$1 8 9 git tag -l \ 10 | sed -E 's/(v[0-9]\.[0-9]+).*/\1/' \ 11 | sort --version-sort --reverse --unique \ 12 | head -n "$count" 13 } 14 15 function get_latest_patch_versions() { 16 count=$1 17 18 echo "master" 19 while read -r minor; do 20 # For each minor release, find latest patch release tag 21 git tag -l | grep "^$minor" | sort --version-sort | tail -n 1 22 done < <(get_latest_minor_version_tags "$count") 23 } 24 25 npm install snyk snyk-to-html --location=global 26 27 # Choose the branch where docs changes will actually be written. 28 target_branch="$1" 29 if [ "$target_branch" != "" ]; then 30 git checkout "$target_branch" 31 fi 32 33 # In case the directory doesn't exist in the target branch. 34 mkdir -p docs/snyk 35 36 # Clear the docs directory in case we need to delete an old version. 37 rm -rf docs/snyk/* 38 39 cat > docs/snyk/index.md <<- EOM 40 # Snyk Scans 41 42 Every Sunday, Snyk scans are generated for Argo CD's \`master\` branch and the most recent patches of the three most 43 recent minor releases. 44 45 !!! note 46 For the most recent scans, view the [\`latest\` version of the docs](https://argo-cd.readthedocs.io/en/latest/snyk/). 47 You can return to your preferred version of the docs site using the dropdown selector at the top of the page. 48 49 ## Scans 50 EOM 51 52 argocd_dir=$(pwd) 53 temp_dir=$(mktemp -d) 54 cd "$temp_dir" 55 git clone https://github.com/argoproj/argo-cd.git 56 cd argo-cd 57 git checkout master 58 59 minor_version=$(git tag -l | sort -V | tail -n 1 | grep -Eo '[0-9]+\.[0-9]+') 60 patch_num=$(git tag -l | grep "v$minor_version." | grep -o "[a-z[:digit:]-]*$" | sort -V | tail -n 1) 61 62 version_count=3 63 # When the most recent version is still a release candidate, get reports for 4 versions (so the 3 most recent stable 64 # releases are included). 65 if [[ $patch_num == "0-rc"* ]]; then version_count=4; fi 66 versions="$(get_latest_patch_versions "$version_count")" 67 68 echo "Analyzing versions: $versions" 69 70 for version in $versions; do 71 printf '\n%s\n\n' "### $version" >> "$argocd_dir/docs/snyk/index.md" 72 73 mkdir -p "$argocd_dir/docs/snyk/$version" 74 75 git reset --hard # reset any pending changes to avoid checkout errors 76 git checkout "$version" 77 78 # Get the latest ignore rules. 79 cp "$argocd_dir/.snyk" .snyk 80 81 # || [ $? == 1 ] ignores errors due to vulnerabilities. 82 snyk test --all-projects --exclude=docs,site,ui-test --org=argoproj --policy-path=.snyk --sarif-file-output=/tmp/argocd-test.sarif --json-file-output=/tmp/argocd-test.json || [ $? == 1 ] 83 snyk-to-html -i /tmp/argocd-test.json -o "$argocd_dir/docs/snyk/$version/argocd-test.html" 84 { echo "| | Critical | High | Medium | Low |" 85 echo "|---:|:--------:|:----:|:------:|:---:|" 86 } >> "$argocd_dir/docs/snyk/index.md" 87 jq 'map( 88 { 89 # Collect all the vulnerabilities severities. Group by id to avoid double-counting. 90 severity: (.vulnerabilities | group_by(.id) | map(.[0])[].severity), 91 displayTargetFile: (.displayTargetFile) 92 } 93 ) 94 # Hack to make sure even if there are no vulnerabilities, a row is added to the table. 95 + [{displayTargetFile: "go.mod"}, {displayTargetFile: "ui/yarn.lock"}] 96 # Group by target file (e.g. go.mod) so we can see where the vulnerabilities are. 97 | group_by(.displayTargetFile) 98 | map( 99 "| [\(.[0].displayTargetFile)](\($version)/argocd-test.html) " 100 + "| \(map(select(.severity == "critical")) | length) " 101 + "| \(map(select(.severity == "high")) | length) " 102 + "| \(map(select(.severity == "medium")) | length) " 103 + "| \(map(select(.severity == "low")) | length) |") 104 | join("\n")' --arg version "$version" -r /tmp/argocd-test.json >> "$argocd_dir/docs/snyk/index.md" 105 106 107 images=$(grep 'image: ' manifests/install.yaml manifests/namespace-install.yaml manifests/ha/install.yaml | sed 's/.*image: //' | sort | uniq) 108 109 while IFS= read -r image; do 110 extra_args=() 111 if echo "$image" | grep "argocd"; then 112 # Pass the file arg only for the Argo CD image. The file arg also gives us access to sarif output. 113 extra_args+=("--file=Dockerfile" "--sarif-file-output=/tmp/${image//[\/:]/_}.sarif") 114 fi 115 116 set -x 117 # || [ $? == 1 ] ignores errors due to vulnerabilities. 118 snyk container test "$image" --org=argoproj "--json-file-output=/tmp/${image//[\/:]/_}.json" "${extra_args[@]}" || [ $? == 1 ] 119 set +x 120 121 snyk-to-html -i "/tmp/${image//[\/:]/_}.json" -o "$argocd_dir/docs/snyk/$version/${image//[\/:]/_}.html" 122 123 printf '%s' "| [${image/*\//}]($version/${image//[\/:]/_}.html) | " >> "$argocd_dir/docs/snyk/index.md" 124 125 # Add severity counts to index. 126 jq '[ 127 .vulnerabilities 128 # Group by ID to avoid double-counting. 129 | group_by(.id) 130 # Get the severity of the first vulnerability in the group (should be the same for every item in the group). 131 | map(.[0])[].severity 132 # Construct a summary using the counts of each severity level. 133 ] | "\(map(select(. == "critical")) | length) | \(map(select(. == "high")) | length) | \(map(select(. == "medium")) | length) | \(map(select(. == "low")) | length) |" 134 ' -r "/tmp/${image//[\/:]/_}.json" >> "$argocd_dir/docs/snyk/index.md" 135 done <<< "$images" 136 137 # || [ $? == 1 ] ignores errors due to vulnerabilities. 138 snyk iac test manifests/install.yaml --org=argoproj --policy-path=.snyk --sarif-file-output=/tmp/argocd-iac-install.sarif --json-file-output=/tmp/argocd-iac-install.json || [ $? == 1 ] 139 snyk-to-html -i /tmp/argocd-iac-install.json -o "$argocd_dir/docs/snyk/$version/argocd-iac-install.html" 140 echo "| [install.yaml]($version/argocd-iac-install.html) | - | - | - | - |" >> "$argocd_dir/docs/snyk/index.md" 141 142 # || [ $? == 1 ] ignores errors due to vulnerabilities. 143 snyk iac test manifests/namespace-install.yaml --org=argoproj --policy-path=.snyk --sarif-file-output=/tmp/argocd-iac-namespace-install.sarif --json-file-output=/tmp/argocd-iac-namespace-install.json || [ $? == 1 ] 144 snyk-to-html -i /tmp/argocd-iac-namespace-install.json -o "$argocd_dir/docs/snyk/$version/argocd-iac-namespace-install.html" 145 echo "| [namespace-install.yaml]($version/argocd-iac-namespace-install.html) | - | - | - | - |" >> "$argocd_dir/docs/snyk/index.md" 146 done 147 148 # clean up 149 cd "$argocd_dir" # Back to the main argo-cd clone. 150 rm -rf "$temp_dir" 151 152 # regex-escape the temp dir path 153 dir_r="${temp_dir//\//\\\/}" 154 155 # Make sed -i cross-platform: https://stackoverflow.com/a/51060063/684776 156 sedi=(-i) 157 case "$(uname)" in 158 Darwin*) sedi=(-i "") 159 esac 160 161 # remove temp dir path from Snyk output 162 sed "${sedi[@]}" "s/$dir_r//g" docs/snyk/*/*.html