Skip to content
Open
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
18 changes: 18 additions & 0 deletions .github/actions/trivy-iac/action.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
name: "Trivy IaC Scan"
description: "Scan Terraform IaC using Trivy"
runs:
using: "composite"
steps:
- name: "Trivy Terraform IaC Scan"
shell: bash
run: |
components_exit_code=0
modules_exit_code=0
./scripts/terraform/trivy-scan.sh --mode iac ./infrastructure/terraform/components || components_exit_code=$?
./scripts/terraform/trivy-scan.sh --mode iac ./infrastructure/terraform/modules || modules_exit_code=$?
if [ $components_exit_code -ne 0 ] || [ $modules_exit_code -ne 0 ]; then
echo "Trivy misconfigurations detected."
exit 1
fi
16 changes: 16 additions & 0 deletions .github/actions/trivy-package/action.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
name: "Trivy Package Scan"
description: "Scan project packages using Trivy"
runs:
using: "composite"
steps:
- name: "Trivy Package Scan"
shell: bash
run: |
exit_code=0
./scripts/terraform/trivy-scan.sh --mode package . || exit_code=$?
if [ $exit_code -ne 0 ]; then
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"
exit 1
fi
17 changes: 0 additions & 17 deletions .github/actions/trivy/action.yaml

This file was deleted.

42 changes: 33 additions & 9 deletions .github/workflows/stage-1-commit.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -146,8 +146,11 @@ jobs:
uses: actions/checkout@v5
- name: "Lint Terraform"
uses: ./.github/actions/lint-terraform
trivy:
name: "Trivy Scan"
trivy-iac:
name: "Trivy IaC Scan"
permissions:
contents: read
packages: read
runs-on: ubuntu-latest
timeout-minutes: 10
needs: detect-terraform-changes
Expand All @@ -156,18 +159,39 @@ jobs:
NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
steps:
- name: "Checkout code"
uses: actions/checkout@v5
- name: Setup NodeJS
uses: actions/setup-node@v4
uses: actions/checkout@v4
- name: "Setup ASDF"
uses: asdf-vm/actions/setup@1902764435ca0dd2f3388eea723a4f92a4eb8302
- name: "Repo setup"
uses: ./.github/actions/node-install
with:
node-version: ${{ inputs.nodejs_version }}
registry-url: 'https://npm.pkg.github.com'
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: "Perform Setup"
uses: ./.github/actions/setup
- name: "Trivy IaC Scan"
uses: ./.github/actions/trivy-iac
trivy-package:
name: "Trivy Package Scan"
permissions:
contents: read
packages: read
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- name: "Checkout code"
uses: actions/checkout@v4
- name: "Setup ASDF"
uses: asdf-vm/actions/setup@v4
uses: asdf-vm/actions/setup@1902764435ca0dd2f3388eea723a4f92a4eb8302
- name: "Repo setup"
uses: ./.github/actions/node-install
with:
node-version: ${{ inputs.nodejs_version }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: "Perform Setup"
uses: ./.github/actions/setup
- name: "Trivy Scan"
uses: ./.github/actions/trivy
- name: "Trivy Package Scan"
uses: ./.github/actions/trivy-package
count-lines-of-code:
name: "Count lines of code"
runs-on: ubuntu-latest
Expand Down
4 changes: 2 additions & 2 deletions .tool-versions
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ java openjdk-25.0.1
# The section below is reserved for Docker image versions.

# TODO: Move this section - consider using a different file for the repository template dependencies.
# docker/ghcr.io/anchore/grype v0.69.1@sha256:d41fcb371d0af59f311e72123dff46900ebd6d0482391b5a830853ee4f9d1a76 # SEE: https://github.com/anchore/grype/pkgs/container/grype
# docker/ghcr.io/anchore/syft v0.92.0@sha256:63c60f0a21efb13e80aa1359ab243e49213b6cc2d7e0f8179da38e6913b997e0 # SEE: https://github.com/anchore/syft/pkgs/container/syft
# docker/ghcr.io/anchore/grype v0.104.3@sha256:d340f4f8b3b7e6e72a6c9c0152f25402ed8a2d7375dba1dfce4e53115242feb6 # SEE: https://github.com/anchore/grype/pkgs/container/grype
# docker/ghcr.io/anchore/syft v1.39.0@sha256:6f13bb010923c33fb197047c8f88888e77071bd32596b3f605d62a133e493ce4 # SEE: https://github.com/anchore/syft/pkgs/container/syft
# docker/ghcr.io/gitleaks/gitleaks v8.18.0@sha256:fd2b5cab12b563d2cc538b14631764a1c25577780e3b7dba71657d58da45d9d9 # SEE: https://github.com/gitleaks/gitleaks/pkgs/container/gitleaks
# docker/ghcr.io/igorshubovych/markdownlint-cli v0.37.0@sha256:fb3e79946fce78e1cde84d6798c6c2a55f2de11fc16606a40d49411e281d950d # SEE: https://github.com/igorshubovych/markdownlint-cli/pkgs/container/markdownlint-cli
# docker/ghcr.io/make-ops-tools/gocloc latest@sha256:6888e62e9ae693c4ebcfed9f1d86c70fd083868acb8815fe44b561b9a73b5032 # SEE: https://github.com/make-ops-tools/gocloc/pkgs/container/gocloc
Expand Down
194 changes: 194 additions & 0 deletions scripts/terraform/trivy-scan.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,194 @@
#!/usr/bin/env bash

# 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.

set -euo pipefail

function usage() {
cat <<'EOF'
Usage: ./scripts/terraform/trivy-scan.sh --mode <iac|package> [directory]

Options:
--mode, -m Scan type to run. Accepts "iac" or "package" (required).
--help, -h Show this message.
[directory] Directory to scan. Defaults to the repository root.

Environment variables:
FORCE_USE_DOCKER=true Force execution through Docker even if Trivy is installed locally.
VERBOSE=true Enable bash -x tracing.
EOF
}

function main() {
cd "$(git rev-parse --show-toplevel)"

local scan_mode=""
local dir_to_scan="."

while [[ $# -gt 0 ]]; do
case "$1" in
--mode|-m)
if [[ $# -lt 2 ]]; then
echo "Error: --mode requires an argument." >&2
usage
exit 1
fi
scan_mode="$2"
shift 2
;;
--help|-h)
usage
exit 0
;;
--)
shift
break
;;
-*)
echo "Unknown option: $1" >&2
usage
exit 1
;;
*)
dir_to_scan="$1"
shift
;;
esac
done

if [[ $# -gt 0 ]]; then
dir_to_scan="$1"
fi

if [[ -z "$scan_mode" ]]; then
echo "Error: --mode must be provided (iac|package)." >&2
usage
exit 1
fi

case "$scan_mode" in
iac|package)
;;
*)
echo "Error: unknown mode '$scan_mode'. Expected 'iac' or 'package'." >&2
usage
exit 1
;;
esac

if command -v trivy > /dev/null 2>&1 && ! is-arg-true "${FORCE_USE_DOCKER:-false}"; then
run-trivy-natively "$scan_mode" "$dir_to_scan"
else
run-trivy-in-docker "$scan_mode" "$dir_to_scan"
fi
}

function run-trivy-natively() {
local scan_mode="$1"
local dir_to_scan="$2"

echo "Trivy found locally, running natively"
echo "Running Trivy ($scan_mode) on directory: $dir_to_scan"

if execute-trivy-command "$scan_mode" "$dir_to_scan"; then
check-trivy-status 0
else
local status=$?
check-trivy-status "$status"
fi
}

function run-trivy-in-docker() {
# shellcheck disable=SC1091
source ./scripts/docker/docker.lib.sh

local scan_mode="$1"
local dir_to_scan="$2"

# shellcheck disable=SC2155
local image=$(name=aquasec/trivy docker-get-image-version-and-pull)

echo "Trivy not found locally, running in Docker Container"
echo "Running Trivy ($scan_mode) on directory: $dir_to_scan"

if execute-trivy-in-docker "$image" "$scan_mode" "$dir_to_scan"; then
check-trivy-status 0
else
local status=$?
check-trivy-status "$status"
fi
}

function execute-trivy-command() {
local scan_mode="$1"
local dir_to_scan="$2"

if [[ "$scan_mode" == "iac" ]]; then
trivy config \
--config scripts/config/trivy.yaml \
--tf-exclude-downloaded-modules \
"$dir_to_scan"
else
trivy \
--config scripts/config/trivy.yaml \
fs "$dir_to_scan" \
--scanners vuln \
--severity HIGH,CRITICAL \
--include-dev-deps
fi
}

function execute-trivy-in-docker() {
local image="$1"
local scan_mode="$2"
local dir_to_scan="$3"

if [[ "$scan_mode" == "iac" ]]; then
docker run --rm --platform linux/amd64 \
--volume "$PWD":/workdir \
--workdir /workdir \
"$image" \
config \
--config scripts/config/trivy.yaml \
--tf-exclude-downloaded-modules \
"$dir_to_scan"
else
docker run --rm --platform linux/amd64 \
--volume "$PWD":/workdir \
--workdir /workdir \
"$image" \
--config scripts/config/trivy.yaml \
fs "$dir_to_scan" \
--scanners vuln \
--severity HIGH,CRITICAL \
--include-dev-deps
fi
}

function check-trivy-status() {
local status="$1"

if [[ "$status" -eq 0 ]]; then
echo "Trivy completed successfully."
return 0
fi

echo "Trivy found issues."
exit "$status"
}

function is-arg-true() {
if [[ "$1" =~ ^(true|yes|y|on|1|TRUE|YES|Y|ON)$ ]]; then
return 0
else
return 1
fi
}

# ==============================================================================

is-arg-true "${VERBOSE:-false}" && set -x

main "$@"

exit 0
Loading
Loading