Skip to content

Commit

Permalink
ci: add re-usable workflow for scans from published img and automatic… (
Browse files Browse the repository at this point in the history
#73)

* ci: add re-usable workflow for scans from published img and automatic reports

This commit adds get-published-images-scan-and-report.yaml, a re-usable workflow
that enables repositories to scan images from a public registry (in the case
of the Analytics team it defaults to charmedkubeflow) and reports back
the security vulnerabilities as Github issues.
This workflow is intended to be used on demand (using a workflow dispatch)
and on schedule, as it will be used for continuous testing of the published
images a rock repository generates.

Part of #69
  • Loading branch information
DnPlas authored Oct 15, 2024
1 parent a4e604c commit ade2a28
Show file tree
Hide file tree
Showing 4 changed files with 202 additions and 0 deletions.
46 changes: 46 additions & 0 deletions .github/workflows/get-image-names-from-rockcraft.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
name: Get oci-images names from rockcraft files

on:
workflow_call:
inputs:
branch:
required: false
type: string
outputs:
images-names:
description: "A JSON array of all images that have their rockcraft project stored in this repository"
value: ${{ jobs.get-images-names.outputs.images-names }}

jobs:
get-images-names:
name: Get image names
runs-on: ubuntu-22.04
outputs:
images-names: ${{ steps.get-images.outputs.images-names }}
steps:
- name: Checkout repository code
uses: actions/checkout@v4
with:
fetch-depth: 0
ref: ${{ inputs.branch }}

- name: Install tools
run: |
sudo snap install yq
sudo apt install jq
- name: Get images names
id: get-images
run: |
set -xeu
IMAGES_NAMES=()
paths=$(find ./ -name "rockcraft.yaml" | sed 's/\.\///g')
for d in $paths
do
short_hash=$(git log -n 1 --pretty=%h -- ${d})
image_name=$(cat ${d} | yq -r '.name')
image_version=$(cat ${d} | yq -r '.version')
IMAGES_NAMES+=(${image_name}:${image_version}-${short_hash})
done
IMAGES_ARRAY=$(jq -c -n '$ARGS.positional' --args "${IMAGES_NAMES[@]}")
echo "images-names=${IMAGES_ARRAY}" >> "$GITHUB_OUTPUT"
36 changes: 36 additions & 0 deletions .github/workflows/get-published-images-scan-and-report.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
name: Get image names and report vulnerabilties in Github

on:
workflow_call:
secrets:
GH_TOKEN:
required: true
inputs:
severity:
description: "Comma separated list of severities of vulnerabilities to scanned for and displayed"
required: false
type: string
default: "UNKNOWN,LOW,MEDIUM,HIGH,CRITICAL"
branch:
required: false
type: string

jobs:
get-published-images-names:
name: Get images names from rockcraft
uses: ./.github/workflows/get-image-names-from-rockcraft.yaml
with:
branch: ${{ inputs.branch }}

scan-report-vulnerability:
needs: get-published-images-names
name: Scan and report
strategy:
fail-fast: false
matrix:
image-name: ${{ fromJson(needs.get-published-images-names.outputs.images-names) }}
uses: ./.github/workflows/scan-from-dockerhub-report-issue.yaml
secrets: inherit
with:
image-name: ${{ matrix.image-name }}
severity: ${{ inputs.severity }}
31 changes: 31 additions & 0 deletions .github/workflows/scan-from-dockerhub-report-issue.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
name: Scan published image and report vulnerabilities

on:
workflow_call:
inputs:
image-name:
description: "The published image name to be scanned."
required: true
type: string
severity:
description: "Comma separated list of severities of vulnerabilities to scanned for and displayed"
required: false
type: string
default: "UNKNOWN,LOW,MEDIUM,HIGH,CRITICAL"
jobs:
scan:
uses: ./.github/workflows/scan-from-published-image.yaml
secrets: inherit
with:
image-name: ${{ inputs.image-name }}
severity: ${{ inputs.severity }}

report-vulnerability:
needs: scan
uses: ./.github/workflows/report-vulnerability-in-gh.yaml
secrets: inherit
if: ${{ always() && (needs.scan.result == 'failure') }}
with:
issue-title: 'Vulnerabilities found for'
image-name: ${{ inputs.image-name }}
vulnerability-report-artefact: ${{ needs.scan.outputs.vulnerability-report-artefact-name }}
89 changes: 89 additions & 0 deletions .github/workflows/scan-from-published-image.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
name: Scan

on:
workflow_call:
outputs:
vulnerability-report-artefact-name:
description: "The name of the artefact that contains the vulnerability report."
value: ${{ jobs.scan.outputs.vulnerability-report-artefact-name }}
inputs:
container-registry:
description: "The name of the container registry where images are hosted."
required: false
type: string
default: "charmedkubeflow"
image-name:
description: "The published image name to be scanned."
required: true
type: string
severity:
description: "Comma separated list of severities of vulnerabilities to scanned for and displayed"
required: false
type: string
default: "UNKNOWN,LOW,MEDIUM,HIGH,CRITICAL"
jobs:
scan:
name: Scan of ${{ inputs.image-name }}
runs-on: ubuntu-22.04
outputs:
vulnerability-report-artefact-name: ${{ steps.report-name.outputs.report-name }}
strategy:
fail-fast: false
steps:
# Ideally we'd use self-hosted runners, but this effort is still not stable.
# This action will remove unused software (dotnet, haskell, android libs, codeql,
# and docker images) from the GH runner, which will liberate around 60 GB of storage
# distributed in 40GB for root and around 20 for a mnt point.
# We need it to avoid cases where scanning fails due to "no space left on device".
- name: Maximise GH runner space
uses: easimon/maximize-build-space@v7
with:
root-reserve-mb: 29696
remove-dotnet: 'true'
remove-haskell: 'true'
remove-android: 'true'
remove-codeql: 'true'

- name: Checkout repo
uses: actions/checkout@v4

- name: Generate report name
id: report-name
run: |
IMAGE_NAME=$(echo ${{ inputs.image-name }} | rev | cut -f2- -d"-" | rev)
IMAGE_NAME_DASHES=$(echo $IMAGE_NAME | sed 's/\:/-/g')
echo "report-name=trivy-report-${IMAGE_NAME_DASHES}" >> "$GITHUB_OUTPUT"
- name: Scan for vulnerabilities
id: scan
uses: aquasecurity/[email protected]
# Workaround for https://github.com/aquasecurity/trivy-action/issues/389
env:
TRIVY_DB_REPOSITORY: public.ecr.aws/aquasecurity/trivy-db:2
TRIVY_JAVA_DB_REPOSITORY: public.ecr.aws/aquasecurity/trivy-java-db:1
with:
scan-type: 'image'
image-ref: '${{ inputs.container-registry }}/${{ inputs.image-name }}'
format: 'table'
output: '${{ steps.report-name.outputs.report-name }}.txt'
ignore-unfixed: true
timeout: '50m0s'
exit-code: 1
severity: ${{ inputs.severity }}
# NOTE: pebble is flagged with a HIGH vuln because of golang.org/x/crypto
# CVE-2021-43565, CVE-2022-27191
skip-files: '/bin/pebble,/usr/bin/pebble,usr/bin/pebble,bin/pebble'

- name: Print vulnerabilities report
# The report should be printed regardless of the success of the previous step
if: success() || failure()
run: cat ${{ steps.report-name.outputs.report-name }}.txt

- name: Upload Trivy reports
# The report should be uploaded regardless of the success of the previous steps
if: success() || failure()
uses: actions/upload-artifact@v4
with:
compression-level: 0
name: ${{ steps.report-name.outputs.report-name }}
path: ${{ steps.report-name.outputs.report-name }}.txt

0 comments on commit ade2a28

Please sign in to comment.