Skip to content

Commit 3a6c7e5

Browse files
CCM-13343_Trivy_Package_and_Library_Scans
1 parent 92573c0 commit 3a6c7e5

File tree

7 files changed

+263
-124
lines changed

7 files changed

+263
-124
lines changed
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
name: "Trivy IaC Scan"
2+
description: "Scan Terraform IaC using Trivy"
3+
runs:
4+
using: "composite"
5+
steps:
6+
- name: "Trivy Terraform IaC Scan"
7+
shell: bash
8+
run: |
9+
components_exit_code=0
10+
modules_exit_code=0
11+
12+
./scripts/terraform/trivy-scan.sh --mode iac ./infrastructure/terraform/components || components_exit_code=$?
13+
./scripts/terraform/trivy-scan.sh --mode iac ./infrastructure/terraform/modules || modules_exit_code=$?
14+
15+
if [ $components_exit_code -ne 0 ] || [ $modules_exit_code -ne 0 ]; then
16+
echo "Trivy misconfigurations detected."
17+
exit 1
18+
fi
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
name: "Trivy Package Scan"
2+
description: "Scan project packages using Trivy"
3+
runs:
4+
using: "composite"
5+
steps:
6+
- name: "Trivy Package Scan"
7+
shell: bash
8+
run: |
9+
exit_code=0
10+
11+
./scripts/terraform/trivy-scan.sh --mode package . || exit_code=$?
12+
13+
if [ $exit_code -ne 0 ]; then
14+
echo "Trivy has detected package vulnerablilites. Please refer to https://nhsd-confluence.digital.nhs.uk/spaces/RIS/pages/1257636917/PLAT-KOP-012+-+Trivy+Pipeline+Vulnerability+Scanning+Exemption"
15+
exit 1
16+
fi

.github/actions/trivy/action.yaml

Lines changed: 0 additions & 17 deletions
This file was deleted.

.github/workflows/stage-1-commit.yaml

Lines changed: 33 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -146,8 +146,11 @@ jobs:
146146
uses: actions/checkout@v5
147147
- name: "Lint Terraform"
148148
uses: ./.github/actions/lint-terraform
149-
trivy:
150-
name: "Trivy Scan"
149+
trivy-iac:
150+
name: "Trivy IaC Scan"
151+
permissions:
152+
contents: read
153+
packages: read
151154
runs-on: ubuntu-latest
152155
timeout-minutes: 10
153156
needs: detect-terraform-changes
@@ -156,18 +159,39 @@ jobs:
156159
NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
157160
steps:
158161
- name: "Checkout code"
159-
uses: actions/checkout@v5
160-
- name: Setup NodeJS
161-
uses: actions/setup-node@v4
162+
uses: actions/checkout@v4
163+
- name: "Setup ASDF"
164+
uses: asdf-vm/actions/setup@1902764435ca0dd2f3388eea723a4f92a4eb8302
165+
- name: "Repo setup"
166+
uses: ./.github/actions/node-install
162167
with:
163168
node-version: ${{ inputs.nodejs_version }}
164-
registry-url: 'https://npm.pkg.github.com'
169+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
170+
- name: "Perform Setup"
171+
uses: ./.github/actions/setup
172+
- name: "Trivy IaC Scan"
173+
uses: ./.github/actions/trivy-iac
174+
trivy-package:
175+
name: "Trivy Package Scan"
176+
permissions:
177+
contents: read
178+
packages: read
179+
runs-on: ubuntu-latest
180+
timeout-minutes: 10
181+
steps:
182+
- name: "Checkout code"
183+
uses: actions/checkout@v4
165184
- name: "Setup ASDF"
166-
uses: asdf-vm/actions/setup@v4
185+
uses: asdf-vm/actions/setup@1902764435ca0dd2f3388eea723a4f92a4eb8302
186+
- name: "Repo setup"
187+
uses: ./.github/actions/node-install
188+
with:
189+
node-version: ${{ inputs.nodejs_version }}
190+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
167191
- name: "Perform Setup"
168192
uses: ./.github/actions/setup
169-
- name: "Trivy Scan"
170-
uses: ./.github/actions/trivy
193+
- name: "Trivy Package Scan"
194+
uses: ./.github/actions/trivy-package
171195
count-lines-of-code:
172196
name: "Count lines of code"
173197
runs-on: ubuntu-latest

.tool-versions

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@ java openjdk-25.0.1
1515
# The section below is reserved for Docker image versions.
1616

1717
# TODO: Move this section - consider using a different file for the repository template dependencies.
18-
# docker/ghcr.io/anchore/grype v0.69.1@sha256:d41fcb371d0af59f311e72123dff46900ebd6d0482391b5a830853ee4f9d1a76 # SEE: https://github.com/anchore/grype/pkgs/container/grype
19-
# docker/ghcr.io/anchore/syft v0.92.0@sha256:63c60f0a21efb13e80aa1359ab243e49213b6cc2d7e0f8179da38e6913b997e0 # SEE: https://github.com/anchore/syft/pkgs/container/syft
18+
# docker/ghcr.io/anchore/grype v0.104.3@sha256:d340f4f8b3b7e6e72a6c9c0152f25402ed8a2d7375dba1dfce4e53115242feb6 # SEE: https://github.com/anchore/grype/pkgs/container/grype
19+
# docker/ghcr.io/anchore/syft v1.39.0@sha256:6f13bb010923c33fb197047c8f88888e77071bd32596b3f605d62a133e493ce4 # SEE: https://github.com/anchore/syft/pkgs/container/syft
2020
# docker/ghcr.io/gitleaks/gitleaks v8.18.0@sha256:fd2b5cab12b563d2cc538b14631764a1c25577780e3b7dba71657d58da45d9d9 # SEE: https://github.com/gitleaks/gitleaks/pkgs/container/gitleaks
2121
# docker/ghcr.io/igorshubovych/markdownlint-cli v0.37.0@sha256:fb3e79946fce78e1cde84d6798c6c2a55f2de11fc16606a40d49411e281d950d # SEE: https://github.com/igorshubovych/markdownlint-cli/pkgs/container/markdownlint-cli
2222
# docker/ghcr.io/make-ops-tools/gocloc latest@sha256:6888e62e9ae693c4ebcfed9f1d86c70fd083868acb8815fe44b561b9a73b5032 # SEE: https://github.com/make-ops-tools/gocloc/pkgs/container/gocloc

scripts/terraform/trivy-scan.sh

Lines changed: 194 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,194 @@
1+
#!/usr/bin/env bash
2+
3+
# WARNING: Please DO NOT edit this file! It is maintained in the Repository Template (https://github.com/NHSDigital/nhs-notify-repository-template). Raise a PR instead.
4+
5+
set -euo pipefail
6+
7+
function usage() {
8+
cat <<'EOF'
9+
Usage: ./scripts/terraform/trivy-scan.sh --mode <iac|package> [directory]
10+
11+
Options:
12+
--mode, -m Scan type to run. Accepts "iac" or "package" (required).
13+
--help, -h Show this message.
14+
[directory] Directory to scan. Defaults to the repository root.
15+
16+
Environment variables:
17+
FORCE_USE_DOCKER=true Force execution through Docker even if Trivy is installed locally.
18+
VERBOSE=true Enable bash -x tracing.
19+
EOF
20+
}
21+
22+
function main() {
23+
cd "$(git rev-parse --show-toplevel)"
24+
25+
local scan_mode=""
26+
local dir_to_scan="."
27+
28+
while [[ $# -gt 0 ]]; do
29+
case "$1" in
30+
--mode|-m)
31+
if [[ $# -lt 2 ]]; then
32+
echo "Error: --mode requires an argument." >&2
33+
usage
34+
exit 1
35+
fi
36+
scan_mode="$2"
37+
shift 2
38+
;;
39+
--help|-h)
40+
usage
41+
exit 0
42+
;;
43+
--)
44+
shift
45+
break
46+
;;
47+
-*)
48+
echo "Unknown option: $1" >&2
49+
usage
50+
exit 1
51+
;;
52+
*)
53+
dir_to_scan="$1"
54+
shift
55+
;;
56+
esac
57+
done
58+
59+
if [[ $# -gt 0 ]]; then
60+
dir_to_scan="$1"
61+
fi
62+
63+
if [[ -z "$scan_mode" ]]; then
64+
echo "Error: --mode must be provided (iac|package)." >&2
65+
usage
66+
exit 1
67+
fi
68+
69+
case "$scan_mode" in
70+
iac|package)
71+
;;
72+
*)
73+
echo "Error: unknown mode '$scan_mode'. Expected 'iac' or 'package'." >&2
74+
usage
75+
exit 1
76+
;;
77+
esac
78+
79+
if command -v trivy > /dev/null 2>&1 && ! is-arg-true "${FORCE_USE_DOCKER:-false}"; then
80+
run-trivy-natively "$scan_mode" "$dir_to_scan"
81+
else
82+
run-trivy-in-docker "$scan_mode" "$dir_to_scan"
83+
fi
84+
}
85+
86+
function run-trivy-natively() {
87+
local scan_mode="$1"
88+
local dir_to_scan="$2"
89+
90+
echo "Trivy found locally, running natively"
91+
echo "Running Trivy ($scan_mode) on directory: $dir_to_scan"
92+
93+
if execute-trivy-command "$scan_mode" "$dir_to_scan"; then
94+
check-trivy-status 0
95+
else
96+
local status=$?
97+
check-trivy-status "$status"
98+
fi
99+
}
100+
101+
function run-trivy-in-docker() {
102+
# shellcheck disable=SC1091
103+
source ./scripts/docker/docker.lib.sh
104+
105+
local scan_mode="$1"
106+
local dir_to_scan="$2"
107+
108+
# shellcheck disable=SC2155
109+
local image=$(name=aquasec/trivy docker-get-image-version-and-pull)
110+
111+
echo "Trivy not found locally, running in Docker Container"
112+
echo "Running Trivy ($scan_mode) on directory: $dir_to_scan"
113+
114+
if execute-trivy-in-docker "$image" "$scan_mode" "$dir_to_scan"; then
115+
check-trivy-status 0
116+
else
117+
local status=$?
118+
check-trivy-status "$status"
119+
fi
120+
}
121+
122+
function execute-trivy-command() {
123+
local scan_mode="$1"
124+
local dir_to_scan="$2"
125+
126+
if [[ "$scan_mode" == "iac" ]]; then
127+
trivy config \
128+
--config scripts/config/trivy.yaml \
129+
--tf-exclude-downloaded-modules \
130+
"$dir_to_scan"
131+
else
132+
trivy \
133+
--config scripts/config/trivy.yaml \
134+
fs "$dir_to_scan" \
135+
--scanners vuln \
136+
--severity HIGH,CRITICAL \
137+
--include-dev-deps
138+
fi
139+
}
140+
141+
function execute-trivy-in-docker() {
142+
local image="$1"
143+
local scan_mode="$2"
144+
local dir_to_scan="$3"
145+
146+
if [[ "$scan_mode" == "iac" ]]; then
147+
docker run --rm --platform linux/amd64 \
148+
--volume "$PWD":/workdir \
149+
--workdir /workdir \
150+
"$image" \
151+
config \
152+
--config scripts/config/trivy.yaml \
153+
--tf-exclude-downloaded-modules \
154+
"$dir_to_scan"
155+
else
156+
docker run --rm --platform linux/amd64 \
157+
--volume "$PWD":/workdir \
158+
--workdir /workdir \
159+
"$image" \
160+
--config scripts/config/trivy.yaml \
161+
fs "$dir_to_scan" \
162+
--scanners vuln \
163+
--severity HIGH,CRITICAL \
164+
--include-dev-deps
165+
fi
166+
}
167+
168+
function check-trivy-status() {
169+
local status="$1"
170+
171+
if [[ "$status" -eq 0 ]]; then
172+
echo "Trivy completed successfully."
173+
return 0
174+
fi
175+
176+
echo "Trivy found issues."
177+
exit "$status"
178+
}
179+
180+
function is-arg-true() {
181+
if [[ "$1" =~ ^(true|yes|y|on|1|TRUE|YES|Y|ON)$ ]]; then
182+
return 0
183+
else
184+
return 1
185+
fi
186+
}
187+
188+
# ==============================================================================
189+
190+
is-arg-true "${VERBOSE:-false}" && set -x
191+
192+
main "$@"
193+
194+
exit 0

0 commit comments

Comments
 (0)