Skip to content

Commit e31e252

Browse files
authored
Chore: [AEA-0000] - add docker scan (#55)
## Summary - Routine Change ### Details - add docker scan
1 parent 27a44fb commit e31e252

File tree

4 files changed

+194
-3
lines changed

4 files changed

+194
-3
lines changed

.github/workflows/quality-checks.yml

Lines changed: 164 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,16 @@ on:
2323
type: boolean
2424
description: Toggle to reinstall poetry on top of python version installed by asdf.
2525
default: false
26+
run_docker_scan:
27+
type: boolean
28+
description: Toggle to run docker vulnerability scan on this repository.
29+
default: false
30+
required: false
31+
docker_images:
32+
type: string
33+
description: comma separated list of docker image references to scan when docker scanning is enabled.
34+
default: ""
35+
required: false
2636

2737
jobs:
2838
quality_checks:
@@ -237,7 +247,6 @@ jobs:
237247
238248
- name: Run unit tests
239249
run: make test
240-
241250
- name: Generate SBOM
242251
uses: aquasecurity/trivy-action@b6643a29fecd7f34b3597bc6acb0a98b03d33ff8
243252
with:
@@ -344,7 +353,160 @@ jobs:
344353
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
345354
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
346355

347-
# CloudFormation validation (runs only if templates exist, ~3-5 minutes)
356+
get_docker_images_to_scan:
357+
outputs:
358+
docker_images: ${{ steps.normalized_docker_images.outputs.images }}
359+
runs-on: ubuntu-22.04
360+
steps:
361+
- name: Checkout code
362+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
363+
with:
364+
ref: ${{ env.BRANCH_NAME }}
365+
fetch-depth: 0
366+
- name: Determine docker images to scan
367+
id: normalized_docker_images
368+
env:
369+
DOCKER_IMAGES: ${{ inputs.docker_images }}
370+
run: |
371+
if [ "${{ inputs.run_docker_scan }}" != "true" ]; then
372+
echo "Docker scanning disabled; emitting empty image list."
373+
echo 'images=[]' >> "$GITHUB_OUTPUT"
374+
exit 0
375+
fi
376+
377+
INPUT="${DOCKER_IMAGES}"
378+
379+
if [ -z "$INPUT" ]; then
380+
INPUT="[]"
381+
fi
382+
383+
normalize_to_json_array() {
384+
local raw="$1"
385+
386+
# If the input already looks like JSON, return as-is
387+
if echo "$raw" | grep -q '^[[:space:]]*\['; then
388+
echo "$raw"
389+
return
390+
fi
391+
392+
local json="["
393+
local first=true
394+
IFS=',' read -ra ITEMS <<< "$raw"
395+
for item in "${ITEMS[@]}"; do
396+
# Trim whitespace around each image reference
397+
item=$(echo "$item" | xargs)
398+
if [ -z "$item" ]; then
399+
continue
400+
fi
401+
if [ "$first" = true ]; then
402+
first=false
403+
else
404+
json+=", "
405+
fi
406+
json+="\"$item\""
407+
done
408+
json+="]"
409+
echo "$json"
410+
}
411+
412+
NORMALIZED=$(normalize_to_json_array "$INPUT")
413+
414+
if [ "$NORMALIZED" = "[]" ]; then
415+
echo "No docker images provided"
416+
exit 1
417+
fi
418+
419+
echo "Using provided docker images: $NORMALIZED"
420+
echo "images=$NORMALIZED" >> "$GITHUB_OUTPUT"
421+
422+
docker_vulnerability_scan:
423+
runs-on: ubuntu-22.04
424+
needs: get_docker_images_to_scan
425+
if: ${{ inputs.run_docker_scan == true }}
426+
strategy:
427+
matrix:
428+
docker_image: ${{ fromJson(needs.get_docker_images_to_scan.outputs.docker_images) }}
429+
steps:
430+
- name: Checkout code
431+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
432+
with:
433+
ref: ${{ env.BRANCH_NAME }}
434+
fetch-depth: 0
435+
# using git commit sha for version of action to ensure we have stable version
436+
- name: Install asdf
437+
uses: asdf-vm/actions/setup@b7bcd026f18772e44fe1026d729e1611cc435d47
438+
with:
439+
asdf_version: ${{ inputs.asdfVersion }}
440+
441+
- name: Cache asdf
442+
uses: actions/cache@9255dc7a253b0ccc959486e2bca901246202afeb
443+
with:
444+
path: |
445+
~/.asdf
446+
key: ${{ runner.os }}-asdf-${{ hashFiles('**/.tool-versions') }}-${{ inputs.asdfVersion }}
447+
restore-keys: |
448+
${{ runner.os }}-asdf-${{ hashFiles('**/.tool-versions') }}-${{ inputs.asdfVersion }}
449+
450+
- name: Install asdf dependencies in .tool-versions
451+
uses: asdf-vm/actions/install@b7bcd026f18772e44fe1026d729e1611cc435d47
452+
with:
453+
asdf_version: ${{ inputs.asdfVersion }}
454+
env:
455+
PYTHON_CONFIGURE_OPTS: --enable-shared
456+
457+
- name: Reinstall poetry
458+
if: ${{ inputs.reinstall_poetry }}
459+
run: |
460+
poetry_tool_version=$(cat .tool-versions | grep poetry)
461+
poetry_version=${poetry_tool_version//"poetry "}
462+
asdf uninstall poetry "$poetry_version"
463+
asdf install poetry
464+
465+
- name: Setting up .npmrc
466+
env:
467+
NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
468+
run: |
469+
echo "//npm.pkg.github.com/:_authToken=${NODE_AUTH_TOKEN}" >> ~/.npmrc
470+
echo "@nhsdigital:registry=https://npm.pkg.github.com" >> ~/.npmrc
471+
472+
- name: Cache npm dependencies
473+
uses: actions/cache@9255dc7a253b0ccc959486e2bca901246202afeb
474+
with:
475+
path: ./node_modules
476+
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
477+
restore-keys: |
478+
${{ runner.os }}-node-
479+
480+
- name: make install
481+
run: |
482+
make install
483+
484+
- name: Build docker images
485+
if: ${{ inputs.run_docker_scan == true }}
486+
run: |
487+
make docker-build
488+
489+
- name: Check docker vulnerabilities
490+
uses: aquasecurity/trivy-action@b6643a29fecd7f34b3597bc6acb0a98b03d33ff8
491+
with:
492+
scan-type: "image"
493+
image-ref: ${{ matrix.docker_image }}
494+
severity: "CRITICAL,HIGH"
495+
scanners: "vuln"
496+
vuln-type: "os,library"
497+
format: "table"
498+
output: "dependency_results_docker.txt"
499+
exit-code: "1"
500+
trivy-config: trivy.yaml
501+
502+
- name: Show docker vulnerability output
503+
if: always()
504+
run: |
505+
echo "Scan output for ${{ matrix.docker_image }}"
506+
if [ -f dependency_results_docker.txt ]; then
507+
cat dependency_results_docker.txt
508+
fi
509+
348510
IaC-validation:
349511
runs-on: ubuntu-22.04
350512
steps:

.trivyignore.yaml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
vulnerabilities:
2+
- id: CVE-2026-24842
3+
paths:
4+
- "package-lock.json"
5+
statement: downstream dependency for tar - waiting for new npm release
6+
expired_at: 2026-06-01

README.md

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,24 @@ A collection of common workflows used by other EPS repositories
44

55
The workflows that are available to use are
66

7+
## Adding exclusions to trivy scanning
8+
The quality checks job uses trivy to scan for vulnerabilities.
9+
There may be times you want to add an exclusion for a known vulnerability that we are happy to accept
10+
To do this, in the calling repo, add trivy.yaml with this content
11+
```
12+
ignorefile: ".trivyignore.yaml"
13+
```
14+
and add a .trivyignore.yaml with this content
15+
```
16+
vulnerabilities:
17+
- id: CVE-2026-24842
18+
paths:
19+
- "package-lock.json"
20+
statement: downstream dependency for tar - waiting for new npm release
21+
expired_at: 2026-06-01
22+
```
23+
See https://trivy.dev/docs/latest/configuration/filtering/#trivyignoreyaml for more details
24+
725
## combine dependabot prs
826

927
This workflow can be called to combine multiple open Dependabot PRs into a single PR.
@@ -96,17 +114,21 @@ jobs:
96114
This workflow runs common quality checks.
97115
To use this, you must have the following Makefile targets defined
98116
- install
99-
- check-licences
100117
- lint
101118
- test
119+
- install-node (only for cdk projects)
120+
- compile (only for cdk projects)
102121
- cdk-synth (only for cdk projects)
122+
- docker-build (only if run_docker_scan is set to true)
103123

104124
#### Inputs
105125

106126
- `install_java`: Whether to install java or not
107127
- `run_sonar`: Whether to run sonar checks or not.
108128
- `asdfVersion`: Override the version of asdf to install.
109129
- `reinstall_poetry`: If you are using this from a primarily python based project, you should set this to true to force a poetry reinstallation after python is installed
130+
- `run_docker_scan`: whether to run a scan of docker images
131+
- `docker_images`: csv list of docker images to scan. These must match images produced by make docker-build
110132

111133
#### Secret Inputs
112134
- `SONAR_TOKEN`: Token used to authenticate to sonar

trivy.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
ignorefile: ".trivyignore.yaml"

0 commit comments

Comments
 (0)