github.com/argoproj/argo-cd/v2@v2.10.9/hack/snyk-report.sh (about)

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