Skip to content

Commit c4c1a49

Browse files
authored
NO-JIRA: chore(workflows): add Trivy scan action for container image and filesystem vulnerability scanning (#2788)
Improved bash script robustness in [`.github/actions/trivy-scan-action/action.yml`](.github/actions/trivy-scan-action/action.yml:1) by adding: **Error Handling:** - Added `set -Eeuo pipefail` at the beginning of all three bash script blocks (lines 71, 86, 128) - Ensures scripts fail fast on errors, undefined variables, and pipeline failures **Variable Quoting:** - Quoted all variable assignments and expansions to handle paths with spaces and special characters - Applied to: `REPORT_FOLDER`, `REPORT_FILE`, `REPORT_TEMPLATE`, `SCAN_TARGET`, `SCAN_TYPE` - Quoted all GitHub Actions inputs and step outputs references - Quoted command substitutions like `basename` - Quoted file operations: `mkdir`, `cp`, `cat` - Quoted `podman run` arguments including volume mounts and image references **Key Improvements:** - Prevents word splitting and globbing issues - Ensures silent failures are caught immediately - Handles edge cases with special characters in paths - Maintains compatibility with existing functionality while adding robustness
1 parent 52ff70e commit c4c1a49

File tree

3 files changed

+229
-35
lines changed

3 files changed

+229
-35
lines changed
Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
---
2+
name: 'Trivy Vulnerability Scanner'
3+
description: |
4+
Run [Trivy](https://trivy.dev) vulnerability scanner on container images or filesystems.
5+
6+
Features
7+
- Supports both container image and filesystem scanning
8+
- Configurable Trivy version
9+
- Customizable scan parameters (scanners, timeout, exit codes)
10+
- Generates markdown reports
11+
- Automatically adds reports to GitHub job summary
12+
13+
Requirements
14+
- Podman must be installed and running (for image scans)
15+
- The Trivy report template must exist at the specified path
16+
- For image scans, the image must be available in the local Podman storage
17+
18+
inputs:
19+
# https://trivy.dev/docs/latest/guide/target/container_image/#vulnerabilities
20+
scan-type:
21+
description: 'Type of scan to perform: "image" or "fs" (filesystem)'
22+
required: true
23+
scan-target:
24+
description: 'Target to scan (image name or filesystem path relative to workspace-path)'
25+
required: true
26+
trivy-version:
27+
description: 'Version of Trivy to use'
28+
required: false
29+
default: '0.68.2'
30+
podman-socket:
31+
description: 'Path to Podman socket (required for image scans)'
32+
required: false
33+
default: '/var/run/podman/podman.sock'
34+
workspace-path:
35+
description: 'Workspace path for filesystem scans'
36+
required: false
37+
default: ${{ github.workspace }}
38+
report-template:
39+
description: 'Path to Trivy report template'
40+
required: false
41+
default: 'ci/trivy-markdown.tpl'
42+
scanners:
43+
description: 'Comma-separated list of scanners to use'
44+
required: false
45+
default: 'vuln'
46+
ignore-unfixed:
47+
description: 'Ignore unfixed vulnerabilities'
48+
required: false
49+
default: 'true'
50+
timeout:
51+
description: 'Scan timeout'
52+
required: false
53+
default: '30m'
54+
exit-code:
55+
description: 'Exit code when vulnerabilities are found'
56+
required: false
57+
default: '0'
58+
59+
outputs:
60+
report-file:
61+
description: 'Path to the generated report file'
62+
value: ${{ steps.scan.outputs.report-file }}
63+
64+
runs:
65+
using: 'composite'
66+
steps:
67+
- name: Setup report directory
68+
id: setup
69+
shell: bash
70+
run: |
71+
set -Eeuo pipefail
72+
REPORT_FOLDER="${{ inputs.workspace-path }}/trivy-report"
73+
REPORT_FILE="trivy-report.md"
74+
REPORT_TEMPLATE="$(basename "${{ inputs.report-template }}")"
75+
76+
mkdir -p "$REPORT_FOLDER"
77+
cp "${{ inputs.report-template }}" "$REPORT_FOLDER/"
78+
79+
echo "report-folder=$REPORT_FOLDER" >> "$GITHUB_OUTPUT"
80+
echo "report-file=$REPORT_FILE" >> "$GITHUB_OUTPUT"
81+
echo "report-template=$REPORT_TEMPLATE" >> "$GITHUB_OUTPUT"
82+
83+
- name: Run Trivy vulnerability scanner
84+
id: scan
85+
shell: bash
86+
run: |
87+
set -Eeuo pipefail
88+
REPORT_FOLDER="${{ steps.setup.outputs.report-folder }}"
89+
REPORT_FILE="${{ steps.setup.outputs.report-file }}"
90+
REPORT_TEMPLATE="${{ steps.setup.outputs.report-template }}"
91+
92+
SCAN_TARGET="${{ inputs.scan-target }}"
93+
SCAN_TYPE="${{ inputs.scan-type }}"
94+
95+
# Initialize variables with defaults
96+
SCAN_ARGS=""
97+
PODMAN_ARGS=""
98+
99+
echo "Scanning $SCAN_TARGET ($SCAN_TYPE)"
100+
101+
# Configure scan arguments based on type
102+
if [[ "$SCAN_TYPE" == "image" ]]; then
103+
SCAN_ARGS="--image-src podman --podman-host /var/run/podman/podman.sock"
104+
PODMAN_ARGS="-v ${{ inputs.podman-socket }}:/var/run/podman/podman.sock"
105+
elif [[ "$SCAN_TYPE" == "fs" ]]; then
106+
WORKSPACE_FOLDER="/workspace"
107+
SCAN_TARGET="$WORKSPACE_FOLDER/$SCAN_TARGET"
108+
PODMAN_ARGS="-v ${{ inputs.workspace-path }}:$WORKSPACE_FOLDER"
109+
else
110+
echo "Error: Invalid scan type '$SCAN_TYPE'. Must be 'image' or 'fs'"
111+
exit 1
112+
fi
113+
114+
# Run Trivy scan in container
115+
# Note: PODMAN_ARGS and SCAN_ARGS are intentionally unquoted to allow word splitting
116+
podman run --rm \
117+
$PODMAN_ARGS \
118+
-v "${REPORT_FOLDER}:/report" \
119+
"docker.io/aquasec/trivy:${{ inputs.trivy-version }}" \
120+
"$SCAN_TYPE" \
121+
$SCAN_ARGS \
122+
--scanners "${{ inputs.scanners }}" \
123+
${{ inputs.ignore-unfixed == 'true' && '--ignore-unfixed' || '' }} \
124+
--exit-code "${{ inputs.exit-code }}" \
125+
--timeout "${{ inputs.timeout }}" \
126+
--format template --template "@/report/$REPORT_TEMPLATE" \
127+
-o "/report/$REPORT_FILE" \
128+
"$SCAN_TARGET"
129+
130+
echo "report-file=$REPORT_FOLDER/$REPORT_FILE" >> "$GITHUB_OUTPUT"
131+
132+
- name: Add report to job summary
133+
shell: bash
134+
run: |
135+
set -Eeuo pipefail
136+
REPORT_FILE="${{ steps.scan.outputs.report-file }}"
137+
if [[ -f "$REPORT_FILE" ]]; then
138+
cat "$REPORT_FILE" >> "$GITHUB_STEP_SUMMARY"
139+
else
140+
echo "Warning: Report file not found at $REPORT_FILE"
141+
fi

.github/workflows/build-notebooks-TEMPLATE.yaml

Lines changed: 6 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -363,41 +363,12 @@ jobs:
363363
364364
- name: Run Trivy vulnerability scanner
365365
if: ${{ steps.resolve-target.outputs.target }}
366-
run: |
367-
REPORT_FOLDER=${{ github.workspace }}/report
368-
REPORT_FILE=trivy-report.md
369-
REPORT_TEMPLATE=trivy-markdown.tpl
370-
371-
mkdir -p $REPORT_FOLDER
372-
cp ci/$REPORT_TEMPLATE $REPORT_FOLDER
373-
374-
SCAN_TARGET=${{ steps.resolve-target.outputs.target }}
375-
SCAN_TYPE=${{ steps.resolve-target.outputs.type }}
376-
echo "Scanning $SCAN_TARGET ($SCAN_TYPE)"
377-
378-
if [[ "$SCAN_TYPE" == "image" ]]; then
379-
SCAN_ARGS="--image-src podman --podman-host /var/run/podman/podman.sock"
380-
PODMAN_ARGS="-v ${PODMAN_SOCK}:/var/run/podman/podman.sock"
381-
elif [[ "$SCAN_TYPE" == "fs" ]]; then
382-
WORKSPACE_FOLDER="/workspace"
383-
SCAN_TARGET="$WORKSPACE_FOLDER/$SCAN_TARGET"
384-
PODMAN_ARGS="-v ${{ github.workspace }}:$WORKSPACE_FOLDER"
385-
fi
386-
387-
# have trivy access podman socket,
388-
# https://github.com/aquasecurity/trivy/issues/580#issuecomment-666423279
389-
podman run --rm \
390-
$PODMAN_ARGS \
391-
-v ${REPORT_FOLDER}:/report \
392-
docker.io/aquasec/trivy:$TRIVY_VERSION \
393-
$SCAN_TYPE \
394-
$SCAN_ARGS \
395-
--scanners vuln --ignore-unfixed \
396-
--exit-code 0 --timeout 30m \
397-
--format template --template "@/report/$REPORT_TEMPLATE" -o /report/$REPORT_FILE \
398-
$SCAN_TARGET
399-
400-
cat $REPORT_FOLDER/$REPORT_FILE >> $GITHUB_STEP_SUMMARY
366+
uses: ./.github/actions/trivy-scan-action
367+
with:
368+
scan-type: ${{ steps.resolve-target.outputs.type }}
369+
scan-target: ${{ steps.resolve-target.outputs.target }}
370+
trivy-version: ${{ env.TRIVY_VERSION }}
371+
podman-socket: /var/run/podman/podman.sock
401372

402373
# endregion
403374

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
---
2+
name: Test Trivy Scan Action
3+
"on":
4+
workflow_dispatch:
5+
pull_request:
6+
paths:
7+
- '.github/actions/trivy-scan-action/**'
8+
- '.github/workflows/test-trivy-scan-action.yaml'
9+
- 'ci/trivy-markdown.tpl'
10+
push:
11+
paths:
12+
- '.github/actions/trivy-scan-action/**'
13+
- '.github/workflows/test-trivy-scan-action.yaml'
14+
- 'ci/trivy-markdown.tpl'
15+
16+
jobs:
17+
test-scan-type-image:
18+
name: Test Image Scan
19+
runs-on: ubuntu-24.04
20+
env:
21+
# random image from our past, don't update it all the time
22+
TEST_IMAGE: quay.io/opendatahub/odh-pipeline-runtime-minimal-cpu-py312-ubi9:2025b-v1.40
23+
steps:
24+
- name: Checkout code
25+
uses: actions/checkout@v5
26+
27+
- name: Install missing dependencies
28+
run: |
29+
# Collect missing packages
30+
PACKAGES=()
31+
if ! command -v podman &> /dev/null; then
32+
PACKAGES+=(podman)
33+
fi
34+
if ! command -v setfacl &> /dev/null; then
35+
PACKAGES+=(acl)
36+
fi
37+
38+
# Install missing packages if any
39+
if [ ${#PACKAGES[@]} -gt 0 ]; then
40+
echo "Installing missing packages: ${PACKAGES[*]}"
41+
sudo apt-get update
42+
sudo apt-get install -y "${PACKAGES[@]}"
43+
fi
44+
45+
- name: Configure Podman
46+
run: |
47+
# Start podman socket for rootful podman
48+
sudo systemctl daemon-reload
49+
sudo systemctl enable --now podman.socket
50+
sudo systemctl status podman.socket
51+
52+
# Grant access to the podman socket for the current user
53+
sudo setfacl -m u:${USER}:x /var/run/podman
54+
sudo setfacl -m u:${USER}:rw /var/run/podman/podman.sock
55+
56+
# Verify socket is accessible
57+
ls -la /var/run/podman/podman.sock
58+
59+
- name: Pull test image
60+
run: |
61+
sudo podman pull ${{ env.TEST_IMAGE }}
62+
sudo podman images
63+
64+
- name: Test Trivy scan on container image
65+
uses: ./.github/actions/trivy-scan-action
66+
with:
67+
scan-type: image
68+
scan-target: ${{ env.TEST_IMAGE }}
69+
podman-socket: /var/run/podman/podman.sock
70+
71+
test-scan-type-fs:
72+
name: Test FS scan
73+
runs-on: ubuntu-24.04
74+
steps:
75+
- name: Checkout code
76+
uses: actions/checkout@v5
77+
78+
- name: Test Trivy scan on filesystem
79+
uses: ./.github/actions/trivy-scan-action
80+
with:
81+
scan-type: fs
82+
scan-target: './'

0 commit comments

Comments
 (0)