Security #490
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
name: Security | |
on: | |
schedule: | |
- cron: "30 5 * * MON-FRI" # Every weekday at 05:30 UTC | |
workflow_dispatch: | |
push: | |
branches: | |
- main | |
paths: | |
- '**/.trivyignore' | |
jobs: | |
get-projects: | |
runs-on: ubuntu-latest | |
outputs: | |
projects: ${{ steps.get-projects.outputs.projects }} | |
steps: | |
- uses: actions/checkout@v4 | |
- id: get-projects | |
run: echo "projects=$(find projects -mindepth 1 -maxdepth 1 -printf "%f\n" | jq --raw-input . | jq --slurp --compact-output .)" | tee -a "$GITHUB_OUTPUT" | |
trivy-scan: | |
runs-on: ubuntu-latest | |
needs: | |
- get-projects | |
strategy: | |
fail-fast: false | |
matrix: | |
project: ${{ fromJson(needs.get-projects.outputs.projects) }} | |
steps: | |
- uses: actions/checkout@v4 | |
- name: Scan image | |
uses: aquasecurity/trivy-action@b77b85c0254bba6789e787844f0585cde1e56320 # v0.13.0 | |
with: | |
image-ref: 'ghcr.io/ministryofjustice/hmpps-probation-integration-services/${{ matrix.project }}:latest' | |
ignore-unfixed: true | |
severity: 'CRITICAL,HIGH' | |
exit-code: '1' | |
format: 'sarif' | |
output: 'trivy-results.sarif' | |
trivyignores: 'projects/${{ matrix.project }}/.trivyignore' | |
limit-severities-for-sarif: true | |
- name: Upload Trivy scan results to GitHub Security tab | |
uses: github/codeql-action/upload-sarif@v2 | |
if: always() | |
with: | |
sarif_file: 'trivy-results.sarif' | |
- name: Get Trivy results | |
if: always() | |
uses: aquasecurity/trivy-action@b77b85c0254bba6789e787844f0585cde1e56320 # v0.13.0 | |
with: | |
image-ref: 'ghcr.io/ministryofjustice/hmpps-probation-integration-services/${{ matrix.project }}:latest' | |
ignore-unfixed: true | |
severity: 'CRITICAL,HIGH' | |
format: 'json' | |
output: 'results.json' | |
trivyignores: 'projects/${{ matrix.project }}/.trivyignore' | |
- name: Output Trivy results | |
if: always() | |
run: cat results.json | |
- name: Create GitHub issues | |
if: failure() | |
run: | | |
jq -c '.Results[].Vulnerabilities | select(. != null) | flatten | .[]' results.json | while read -r vulnerability; do | |
id=$(echo "$vulnerability" | jq -r '.VulnerabilityID') | |
if [[ $(gh issue list --state open --label dependencies --label security --search "$id (${{ matrix.project }})" | wc -l) -gt 0 ]]; then | |
echo "Issue '$id (${{ matrix.project }})' already exists" | |
else | |
gh issue create \ | |
--title "$id (${{ matrix.project }})" \ | |
--body "$(echo "$vulnerability" | jq -r '.Title + "\n* Project: ${{ matrix.project }}\n* Package: `" + .PkgName + ":" + .InstalledVersion + "`\n* Location: `" + .PkgPath + "`\n\n>" + .Description + "\n\n" + .PrimaryURL + "\n\nIf the vulnerability does not impact the `${{ matrix.project }}` project, you can suppress this alert by adding a comment starting with `Suppress`. For example, \"Suppressed because we do not process any untrusted XML content\"."')" \ | |
--label 'dependencies,security' | |
fi | |
done | |
env: | |
GITHUB_TOKEN: ${{ github.token }} | |
- name: Check & Close GH Issue | |
if: always() | |
run: | | |
openissues="$(gh issue list --state open --label dependencies --label security --search '(${{ matrix.project }})' | awk '{print $3}')" | |
scanresults="$(jq -r -c '.Results[].Vulnerabilities | select(. != null) | flatten | .[].VulnerabilityID' results.json)" | |
issuestoclose="$(comm -23 <(echo "$openissues" | sort -u) <(echo "$scanresults" | sort -u))" #print lines only present in first file | |
echo "openissues=$openissues" | |
echo "scanresults=$scanresults" | |
echo "issuestoclose=$issuestoclose" | |
for cve in $issuestoclose; do | |
echo "$cve is already resolved, removing matching issue..." | |
issuenumber=$(gh issue list --state open --label dependencies --label security --search "$cve (${{ matrix.project }})" | awk '{print $1}') | |
echo "$issuenumber" | xargs -n1 gh issue close | |
done | |
env: | |
GITHUB_TOKEN: ${{ github.token }} | |
veracode-scan: | |
runs-on: ubuntu-latest | |
needs: | |
- get-projects | |
steps: | |
- uses: actions/checkout@v4 | |
- uses: actions/setup-java@v3 | |
with: | |
java-version: 17 | |
distribution: temurin | |
- name: Build jars | |
uses: gradle/gradle-build-action@v2 | |
with: | |
arguments: jar | |
- name: Package jars | |
run: find . -name '*.jar' | zip -r package.zip -@ | |
- name: Upload to Veracode | |
uses: veracode/[email protected] | |
with: | |
appname: hmpps-probation-integration-services | |
createprofile: false | |
deleteincompletescan: 2 # force delete any incomplete scans | |
filepath: package.zip | |
vid: ${{ secrets.CYBERSECURITY_VERACODE_API_ID }} | |
vkey: ${{ secrets.CYBERSECURITY_VERACODE_API_KEY }} |