From 7bb4687cff195d3c2c5e26effdcfbf314b1916c5 Mon Sep 17 00:00:00 2001 From: aidenvaines-cgi Date: Wed, 22 Jul 2026 15:56:32 +0100 Subject: [PATCH 1/2] CCM-17525: Implementing Grype Scanning --- .github/PULL_REQUEST_TEMPLATE.md | 2 +- .github/workflows/cicd-1-pull-request.yaml | 25 +-- .github/workflows/stage-1-commit.yaml | 38 +--- .tool-versions | 1 - scripts/config/pre-commit.yaml | 4 +- scripts/init.mk | 6 + scripts/terraform/terraform.mk | 5 - scripts/terraform/trivy-scan.sh | 211 ------------------ .../src/.devcontainer/Dockerfile | 2 +- .../src/.devcontainer/devcontainer-lock.json | 29 +++ 10 files changed, 43 insertions(+), 280 deletions(-) delete mode 100755 scripts/terraform/trivy-scan.sh create mode 100644 src/jekyll-devcontainer/src/.devcontainer/devcontainer-lock.json diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 5a5026ee..5ff9e6f0 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -25,7 +25,7 @@ - [ ] I have added tests to cover my changes - [ ] I have updated the documentation accordingly - [ ] This PR is a result of pair or mob programming - +- [ ] If I have used the 'skip-dependencies-check' label I have done so responsibly and in the knowledge that this is being fixed as part of a separate ticket/PR. --- diff --git a/.github/workflows/cicd-1-pull-request.yaml b/.github/workflows/cicd-1-pull-request.yaml index d25f476b..fa234393 100644 --- a/.github/workflows/cicd-1-pull-request.yaml +++ b/.github/workflows/cicd-1-pull-request.yaml @@ -33,8 +33,7 @@ jobs: is_version_prerelease: ${{ steps.variables.outputs.is_version_prerelease }} does_pull_request_exist: ${{ steps.pr_exists.outputs.does_pull_request_exist }} pr_number: ${{ steps.pr_exists.outputs.pr_number }} - #TODO - Re-visit Trivy usage https://nhsd-jira.digital.nhs.uk/browse/CCM-15549 - # skip_trivy_package: ${{ steps.skip_trivy.outputs.skip_trivy_package }} + steps: - name: "Checkout code" uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 @@ -75,27 +74,7 @@ jobs: echo "does_pull_request_exist=false" >> $GITHUB_OUTPUT echo "pr_number=" >> $GITHUB_OUTPUT fi - #TODO - Re-visit Trivy usage https://nhsd-jira.digital.nhs.uk/browse/CCM-15549 - # - name: "Determine if Trivy package scan should be skipped" - # id: skip_trivy - # env: - # GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - # PR_NUMBER: ${{ steps.pr_exists.outputs.pr_number }} - # run: | - # if [[ -z "$PR_NUMBER" ]]; then - # echo "No pull request detected; Trivy package scan will run." - # echo "skip_trivy_package=false" >> $GITHUB_OUTPUT - # exit 0 - # fi - - # labels=$(gh pr view "$PR_NUMBER" --json labels --jq '.labels[].name') - # echo "Labels on PR #$PR_NUMBER: $labels" - # if echo "$labels" | grep -Fxq 'skip-trivy-package'; then - # echo "skip_trivy_package=true" >> $GITHUB_OUTPUT - # else - # echo "skip_trivy_package=false" >> $GITHUB_OUTPUT - # fi - name: "List variables" run: | export BUILD_DATETIME_LONDON="${{ steps.variables.outputs.build_datetime_london }}" @@ -121,8 +100,6 @@ jobs: nodejs_version: "${{ needs.metadata.outputs.nodejs_version }}" pnpm_version: "${{ needs.metadata.outputs.pnpm_version }}" python_version: "${{ needs.metadata.outputs.python_version }}" - #TODO - Re-visit Trivy usage https://nhsd-jira.digital.nhs.uk/browse/CCM-15549 - # skip_trivy_package: ${{ needs.metadata.outputs.skip_trivy_package == 'true' }} terraform_version: "${{ needs.metadata.outputs.terraform_version }}" version: "${{ needs.metadata.outputs.version }}" secrets: inherit diff --git a/.github/workflows/stage-1-commit.yaml b/.github/workflows/stage-1-commit.yaml index aba22c13..b9d6887a 100644 --- a/.github/workflows/stage-1-commit.yaml +++ b/.github/workflows/stage-1-commit.yaml @@ -27,11 +27,6 @@ on: description: "Python version, set by the CI/CD pipeline workflow" required: true type: string - #TODO - Re-visit Trivy usage https://nhsd-jira.digital.nhs.uk/browse/CCM-15549 - # skip_trivy_package: - # description: "Skip Trivy package scan when true" - # type: boolean - # default: false terraform_version: description: "Terraform version, set by the CI/CD pipeline workflow" required: true @@ -157,36 +152,7 @@ jobs: uses: asdf-vm/actions/setup@b7bcd026f18772e44fe1026d729e1611cc435d47 # v4.0.1 - name: "Lint Terraform" uses: NHSDigital/nhs-notify-shared-modules/.github/actions/lint-terraform@5.0.1 - #TODO - Re-visit Trivy usage https://nhsd-jira.digital.nhs.uk/browse/CCM-15549 - # trivy-iac: - # name: "Trivy IaC Scan" - # permissions: - # contents: read - # runs-on: ubuntu-latest - # timeout-minutes: 10 - # needs: detect-terraform-changes - # if: needs.detect-terraform-changes.outputs.terraform_changed == 'true' - # steps: - # - name: "Checkout code" - # uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - # - name: "Setup ASDF" - # uses: asdf-vm/actions/setup@1902764435ca0dd2f3388eea723a4f92a4eb8302 # v4.0.0 - # - name: "Trivy IaC Scan" - # uses: NHSDigital/nhs-notify-shared-modules/.github/actions/trivy-iac@3.1.2 - # trivy-package: - # if: ${{ !inputs.skip_trivy_package }} - # name: "Trivy Package Scan" - # permissions: - # contents: read - # runs-on: ubuntu-latest - # timeout-minutes: 10 - # steps: - # - name: "Checkout code" - # uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - # - name: "Setup ASDF" - # uses: asdf-vm/actions/setup@1902764435ca0dd2f3388eea723a4f92a4eb8302 # v4.0.0 - # - name: "Trivy Package Scan" - # uses: NHSDigital/nhs-notify-shared-modules/.github/actions/trivy-package@3.1.2 + count-lines-of-code: name: "Count lines of code" runs-on: ubuntu-latest @@ -217,7 +183,7 @@ jobs: - name: "Checkout code" uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: "Scan dependencies" - uses: NHSDigital/nhs-notify-shared-modules/.github/actions/scan-dependencies@4.0.5 + uses: NHSDigital/nhs-notify-shared-modules/.github/actions/scan-dependencies@5.06 with: build_datetime: "${{ inputs.build_datetime }}" build_timestamp: "${{ inputs.build_timestamp }}" diff --git a/.tool-versions b/.tool-versions index 4d7e7392..59251d04 100644 --- a/.tool-versions +++ b/.tool-versions @@ -8,7 +8,6 @@ terraform 1.14.3 terraform-docs 0.21.0 vale 3.6.0 python 3.13.2 -# trivy 0.69.3 - TODO - Re-visit Trivy usage https://nhsd-jira.digital.nhs.uk/browse/CCM-15549 # ============================================================================== # The section below is reserved for Docker image versions. diff --git a/scripts/config/pre-commit.yaml b/scripts/config/pre-commit.yaml index 324a71ab..e056c7da 100644 --- a/scripts/config/pre-commit.yaml +++ b/scripts/config/pre-commit.yaml @@ -17,7 +17,7 @@ repos: # - id: ... - repo: https://github.com/NHSDigital/nhs-notify-shared-modules - rev: 5.0.1 + rev: 5.0.6 hooks: - id: sort-dictionary - id: scan-secrets @@ -32,3 +32,5 @@ repos: - id: generate-terraform-docs - id: check-todo-usage args: [check=branch] + - id: scan-dependencies # make githooks-dependencies + stages: [manual] diff --git a/scripts/init.mk b/scripts/init.mk index 0164db32..4e5922d5 100644 --- a/scripts/init.mk +++ b/scripts/init.mk @@ -40,6 +40,12 @@ githooks-run: # Run git hooks configured in this repository @Operations --config scripts/config/pre-commit.yaml \ --all-files +githooks-dependencies: # Run git hook for manually scanning depdencies + pre-commit run \ + --config scripts/config/pre-commit.yaml \ + --hook-stage manual scan-dependencies \ + --all-files + _install-dependency: # Install asdf dependency - mandatory: name=[listed in the '.tool-versions' file]; optional: version=[if not listed] echo ${name} asdf plugin add ${name} ||: diff --git a/scripts/terraform/terraform.mk b/scripts/terraform/terraform.mk index 146022b4..802e3c8f 100644 --- a/scripts/terraform/terraform.mk +++ b/scripts/terraform/terraform.mk @@ -118,11 +118,6 @@ terraform-validate-all: # Validate all Terraform components @Quality fi; \ done -#TODO - Re-visit Trivy usage https://nhsd-jira.digital.nhs.uk/browse/CCM-15549 -# terraform-sec: # Run Trivy IaC security scanning on Terraform code @Quality -# # Example: make terraform-sec -# ./scripts/terraform/trivy-scan.sh --mode iac infrastructure/terraform - terraform-docs: # Generate Terraform documentation - optional: component=[specific component, or all if omitted] @Quality # Example: make terraform-docs component=mycomp # Example: make terraform-docs (generates for all components) diff --git a/scripts/terraform/trivy-scan.sh b/scripts/terraform/trivy-scan.sh deleted file mode 100755 index 1588f531..00000000 --- a/scripts/terraform/trivy-scan.sh +++ /dev/null @@ -1,211 +0,0 @@ -#!/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 [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 - - return 0 -} - -function main() { - cd "$(git rev-parse --show-toplevel)" - - local scan_mode="" - local dir_to_scan="." - - while [[ $# -gt 0 ]]; do - local current_arg="$1" - case "$current_arg" in - --mode|-m) - if [[ $# -lt 2 ]]; then - echo "Error: --mode requires an argument." >&2 - usage - exit 1 - fi - local mode_arg="$2" - scan_mode="$mode_arg" - shift 2 - exit 0 - ;; - --) - shift - break - ;; - -*) - ;; - usage - exit 1 - ;; - *) - dir_to_scan="$current_arg" - shift - --help|-h) - dir_to_scan="$trailing_arg" - shift - ;; - esac - local trailing_arg="$1" - dir_to_scan="$trailing_arg" - - 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 - - return 0 -} - -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 - - return 0 -} - -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 - - return 0 -} - -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 - - return 0 -} - -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 - - return 0 -} - -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() { - local arg="$1" - - if [[ "$arg" =~ ^(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 diff --git a/src/jekyll-devcontainer/src/.devcontainer/Dockerfile b/src/jekyll-devcontainer/src/.devcontainer/Dockerfile index bada7fb5..5060af9f 100644 --- a/src/jekyll-devcontainer/src/.devcontainer/Dockerfile +++ b/src/jekyll-devcontainer/src/.devcontainer/Dockerfile @@ -1,4 +1,4 @@ -FROM --platform=linux/amd64 mcr.microsoft.com/devcontainers/jekyll:2-bullseye +FROM --platform=linux/amd64 mcr.microsoft.com/devcontainers/jekyll:3.4-bookworm LABEL org.opencontainers.image.source=https://github.com/NHSDigital/nhs-notify-repository-template COPY packages.txt packages.txt diff --git a/src/jekyll-devcontainer/src/.devcontainer/devcontainer-lock.json b/src/jekyll-devcontainer/src/.devcontainer/devcontainer-lock.json new file mode 100644 index 00000000..39e3c50a --- /dev/null +++ b/src/jekyll-devcontainer/src/.devcontainer/devcontainer-lock.json @@ -0,0 +1,29 @@ +{ + "features": { + "ghcr.io/devcontainers/features/aws-cli:1": { + "integrity": "sha256:1f93c8315b7a6d76982ebb2269f8b0d50413fc0f965c032edf4aee0caceb73ef", + "resolved": "ghcr.io/devcontainers/features/aws-cli@sha256:1f93c8315b7a6d76982ebb2269f8b0d50413fc0f965c032edf4aee0caceb73ef", + "version": "1.1.4" + }, + "ghcr.io/devcontainers/features/common-utils:2": { + "integrity": "sha256:cb0c4d3c276f157eed17935747e364178d75fee17f55c4e129966f64633deb3a", + "resolved": "ghcr.io/devcontainers/features/common-utils@sha256:cb0c4d3c276f157eed17935747e364178d75fee17f55c4e129966f64633deb3a", + "version": "2.5.9" + }, + "ghcr.io/devcontainers/features/docker-in-docker:2": { + "integrity": "sha256:25b9f05705ffba7dbe503230ac76081419306f8c8bc88e0ce78c4ecd99a0c78c", + "resolved": "ghcr.io/devcontainers/features/docker-in-docker@sha256:25b9f05705ffba7dbe503230ac76081419306f8c8bc88e0ce78c4ecd99a0c78c", + "version": "2.17.0" + }, + "ghcr.io/devcontainers/features/github-cli:1": { + "integrity": "sha256:d22f50b70ed75339b4eed1ba9ecde3a1791f90e88d37936517e3bace0bbad671", + "resolved": "ghcr.io/devcontainers/features/github-cli@sha256:d22f50b70ed75339b4eed1ba9ecde3a1791f90e88d37936517e3bace0bbad671", + "version": "1.1.0" + }, + "ghcr.io/devcontainers/features/node:1": { + "integrity": "sha256:8c0de46939b61958041700ee89e3493f3b2e4131a06dc46b4d9423427d06e5f6", + "resolved": "ghcr.io/devcontainers/features/node@sha256:8c0de46939b61958041700ee89e3493f3b2e4131a06dc46b4d9423427d06e5f6", + "version": "1.7.1" + } + } +} From d3f07f3d0f63c171c39df341a42960130381437c Mon Sep 17 00:00:00 2001 From: Aiden Vaines <54067008+aidenvaines-cgi@users.noreply.github.com> Date: Tue, 28 Jul 2026 15:58:37 +0100 Subject: [PATCH 2/2] Update stage-1-commit.yaml --- .github/workflows/stage-1-commit.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/stage-1-commit.yaml b/.github/workflows/stage-1-commit.yaml index b9d6887a..7a570801 100644 --- a/.github/workflows/stage-1-commit.yaml +++ b/.github/workflows/stage-1-commit.yaml @@ -183,7 +183,7 @@ jobs: - name: "Checkout code" uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: "Scan dependencies" - uses: NHSDigital/nhs-notify-shared-modules/.github/actions/scan-dependencies@5.06 + uses: NHSDigital/nhs-notify-shared-modules/.github/actions/scan-dependencies@5.0.6 with: build_datetime: "${{ inputs.build_datetime }}" build_timestamp: "${{ inputs.build_timestamp }}"