Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
141 changes: 141 additions & 0 deletions .github/actions/trivy-scan-action/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
---
name: 'Trivy Vulnerability Scanner'
description: |
Run [Trivy](https://trivy.dev) vulnerability scanner on container images or filesystems.

Features
- Supports both container image and filesystem scanning
- Configurable Trivy version
- Customizable scan parameters (scanners, timeout, exit codes)
- Generates markdown reports
- Automatically adds reports to GitHub job summary

Requirements
- Podman must be installed and running (for image scans)
- The Trivy report template must exist at the specified path
- For image scans, the image must be available in the local Podman storage

inputs:
# https://trivy.dev/docs/latest/guide/target/container_image/#vulnerabilities
scan-type:
description: 'Type of scan to perform: "image" or "fs" (filesystem)'
required: true
scan-target:
description: 'Target to scan (image name or filesystem path relative to workspace-path)'
required: true
trivy-version:
description: 'Version of Trivy to use'
required: false
default: '0.68.2'
podman-socket:
description: 'Path to Podman socket (required for image scans)'
required: false
default: '/var/run/podman/podman.sock'
workspace-path:
description: 'Workspace path for filesystem scans'
required: false
default: ${{ github.workspace }}
report-template:
description: 'Path to Trivy report template'
required: false
default: 'ci/trivy-markdown.tpl'
scanners:
description: 'Comma-separated list of scanners to use'
required: false
default: 'vuln'
ignore-unfixed:
description: 'Ignore unfixed vulnerabilities'
required: false
default: 'true'
timeout:
description: 'Scan timeout'
required: false
default: '30m'
exit-code:
description: 'Exit code when vulnerabilities are found'
required: false
default: '0'

outputs:
report-file:
description: 'Path to the generated report file'
value: ${{ steps.scan.outputs.report-file }}

runs:
using: 'composite'
steps:
- name: Setup report directory
id: setup
shell: bash
run: |
set -Eeuo pipefail
REPORT_FOLDER="${{ inputs.workspace-path }}/trivy-report"
REPORT_FILE="trivy-report.md"
REPORT_TEMPLATE="$(basename "${{ inputs.report-template }}")"

mkdir -p "$REPORT_FOLDER"
cp "${{ inputs.report-template }}" "$REPORT_FOLDER/"

echo "report-folder=$REPORT_FOLDER" >> "$GITHUB_OUTPUT"
echo "report-file=$REPORT_FILE" >> "$GITHUB_OUTPUT"
echo "report-template=$REPORT_TEMPLATE" >> "$GITHUB_OUTPUT"

- name: Run Trivy vulnerability scanner
id: scan
shell: bash
run: |
set -Eeuo pipefail
REPORT_FOLDER="${{ steps.setup.outputs.report-folder }}"
REPORT_FILE="${{ steps.setup.outputs.report-file }}"
REPORT_TEMPLATE="${{ steps.setup.outputs.report-template }}"

SCAN_TARGET="${{ inputs.scan-target }}"
SCAN_TYPE="${{ inputs.scan-type }}"

# Initialize variables with defaults
SCAN_ARGS=""
PODMAN_ARGS=""

echo "Scanning $SCAN_TARGET ($SCAN_TYPE)"

# Configure scan arguments based on type
if [[ "$SCAN_TYPE" == "image" ]]; then
SCAN_ARGS="--image-src podman --podman-host /var/run/podman/podman.sock"
PODMAN_ARGS="-v ${{ inputs.podman-socket }}:/var/run/podman/podman.sock"
elif [[ "$SCAN_TYPE" == "fs" ]]; then
WORKSPACE_FOLDER="/workspace"
SCAN_TARGET="$WORKSPACE_FOLDER/$SCAN_TARGET"
PODMAN_ARGS="-v ${{ inputs.workspace-path }}:$WORKSPACE_FOLDER"
else
echo "Error: Invalid scan type '$SCAN_TYPE'. Must be 'image' or 'fs'"
exit 1
fi

# Run Trivy scan in container
# Note: PODMAN_ARGS and SCAN_ARGS are intentionally unquoted to allow word splitting
podman run --rm \
$PODMAN_ARGS \
-v "${REPORT_FOLDER}:/report" \
"docker.io/aquasec/trivy:${{ inputs.trivy-version }}" \
"$SCAN_TYPE" \
$SCAN_ARGS \
--scanners "${{ inputs.scanners }}" \
${{ inputs.ignore-unfixed == 'true' && '--ignore-unfixed' || '' }} \
--exit-code "${{ inputs.exit-code }}" \
--timeout "${{ inputs.timeout }}" \
--format template --template "@/report/$REPORT_TEMPLATE" \
-o "/report/$REPORT_FILE" \
"$SCAN_TARGET"

echo "report-file=$REPORT_FOLDER/$REPORT_FILE" >> "$GITHUB_OUTPUT"

- name: Add report to job summary
shell: bash
run: |
set -Eeuo pipefail
REPORT_FILE="${{ steps.scan.outputs.report-file }}"
if [[ -f "$REPORT_FILE" ]]; then
cat "$REPORT_FILE" >> "$GITHUB_STEP_SUMMARY"
else
echo "Warning: Report file not found at $REPORT_FILE"
fi
41 changes: 6 additions & 35 deletions .github/workflows/build-notebooks-TEMPLATE.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -363,41 +363,12 @@ jobs:

- name: Run Trivy vulnerability scanner
if: ${{ steps.resolve-target.outputs.target }}
run: |
REPORT_FOLDER=${{ github.workspace }}/report
REPORT_FILE=trivy-report.md
REPORT_TEMPLATE=trivy-markdown.tpl

mkdir -p $REPORT_FOLDER
cp ci/$REPORT_TEMPLATE $REPORT_FOLDER

SCAN_TARGET=${{ steps.resolve-target.outputs.target }}
SCAN_TYPE=${{ steps.resolve-target.outputs.type }}
echo "Scanning $SCAN_TARGET ($SCAN_TYPE)"

if [[ "$SCAN_TYPE" == "image" ]]; then
SCAN_ARGS="--image-src podman --podman-host /var/run/podman/podman.sock"
PODMAN_ARGS="-v ${PODMAN_SOCK}:/var/run/podman/podman.sock"
elif [[ "$SCAN_TYPE" == "fs" ]]; then
WORKSPACE_FOLDER="/workspace"
SCAN_TARGET="$WORKSPACE_FOLDER/$SCAN_TARGET"
PODMAN_ARGS="-v ${{ github.workspace }}:$WORKSPACE_FOLDER"
fi

# have trivy access podman socket,
# https://github.com/aquasecurity/trivy/issues/580#issuecomment-666423279
podman run --rm \
$PODMAN_ARGS \
-v ${REPORT_FOLDER}:/report \
docker.io/aquasec/trivy:$TRIVY_VERSION \
$SCAN_TYPE \
$SCAN_ARGS \
--scanners vuln --ignore-unfixed \
--exit-code 0 --timeout 30m \
--format template --template "@/report/$REPORT_TEMPLATE" -o /report/$REPORT_FILE \
$SCAN_TARGET

cat $REPORT_FOLDER/$REPORT_FILE >> $GITHUB_STEP_SUMMARY
uses: ./.github/actions/trivy-scan-action
with:
scan-type: ${{ steps.resolve-target.outputs.type }}
scan-target: ${{ steps.resolve-target.outputs.target }}
trivy-version: ${{ env.TRIVY_VERSION }}
podman-socket: /var/run/podman/podman.sock

# endregion

Expand Down
82 changes: 82 additions & 0 deletions .github/workflows/test-trivy-scan-action.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
---
name: Test Trivy Scan Action
"on":
workflow_dispatch:
pull_request:
paths:
- '.github/actions/trivy-scan-action/**'
- '.github/workflows/test-trivy-scan-action.yaml'
- 'ci/trivy-markdown.tpl'
push:
paths:
- '.github/actions/trivy-scan-action/**'
- '.github/workflows/test-trivy-scan-action.yaml'
- 'ci/trivy-markdown.tpl'

jobs:
test-scan-type-image:
name: Test Image Scan
runs-on: ubuntu-24.04
env:
# random image from our past, don't update it all the time
TEST_IMAGE: quay.io/opendatahub/odh-pipeline-runtime-minimal-cpu-py312-ubi9:2025b-v1.40
steps:
- name: Checkout code
uses: actions/checkout@v5

- name: Install missing dependencies
run: |
# Collect missing packages
PACKAGES=()
if ! command -v podman &> /dev/null; then
PACKAGES+=(podman)
fi
if ! command -v setfacl &> /dev/null; then
PACKAGES+=(acl)
fi

# Install missing packages if any
if [ ${#PACKAGES[@]} -gt 0 ]; then
echo "Installing missing packages: ${PACKAGES[*]}"
sudo apt-get update
sudo apt-get install -y "${PACKAGES[@]}"
fi

- name: Configure Podman
run: |
# Start podman socket for rootful podman
sudo systemctl daemon-reload
sudo systemctl enable --now podman.socket
sudo systemctl status podman.socket

# Grant access to the podman socket for the current user
sudo setfacl -m u:${USER}:x /var/run/podman
sudo setfacl -m u:${USER}:rw /var/run/podman/podman.sock

# Verify socket is accessible
ls -la /var/run/podman/podman.sock

- name: Pull test image
run: |
sudo podman pull ${{ env.TEST_IMAGE }}
sudo podman images

- name: Test Trivy scan on container image
uses: ./.github/actions/trivy-scan-action
with:
scan-type: image
scan-target: ${{ env.TEST_IMAGE }}
podman-socket: /var/run/podman/podman.sock

test-scan-type-fs:
name: Test FS scan
runs-on: ubuntu-24.04
steps:
- name: Checkout code
uses: actions/checkout@v5

- name: Test Trivy scan on filesystem
uses: ./.github/actions/trivy-scan-action
with:
scan-type: fs
scan-target: './'
Loading