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
2737jobs :
2838 quality_checks :
2939 runs-on : ubuntu-22.04
3040 steps :
31- - uses : actions/setup-java@f2beeb24e141e01a676f977032f5a29d81c9e27e
41+ - uses : actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654
3242 if : ${{ inputs.install_java }}
3343 with :
3444 java-version : " 21"
3545 distribution : " corretto"
3646
3747 - name : Checkout code
38- uses : actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8
48+ uses : actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
3949 with :
4050 ref : ${{ env.BRANCH_NAME }}
4151 fetch-depth : 0
@@ -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 :
@@ -328,7 +337,14 @@ jobs:
328337
329338 - name : Run SonarQube analysis
330339 if : ${{ steps.check_languages.outputs.uses_java == 'true' && env.SONAR_TOKEN_EXISTS == 'true' }}
331- run : mvn sonar:sonar -Dsonar.login=${{ secrets.SONAR_TOKEN }}
340+ run : |
341+ # issues with sonar scanner and sslcontext-kickstart 9.1.0, forcing re-download
342+ rm -rf ~/.m2/repository/io/github/hakky54/sslcontext-kickstart/9.1.0
343+ mvn dependency:get -U -Dartifact=io.github.hakky54:sslcontext-kickstart:9.1.0
344+ # run sonar scan
345+ mvn sonar:sonar -Dsonar.token="$SONAR_TOKEN"
346+ env :
347+ SONAR_TOKEN : ${{ secrets.SONAR_TOKEN }}
332348
333349 - name : SonarCloud Scan
334350 uses : SonarSource/sonarqube-scan-action@a31c9398be7ace6bbfaf30c0bd5d415f843d45e9
@@ -337,16 +353,199 @@ jobs:
337353 GITHUB_TOKEN : ${{ secrets.GITHUB_TOKEN }}
338354 SONAR_TOKEN : ${{ secrets.SONAR_TOKEN }}
339355
340- # 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+
341510 IaC-validation :
342511 runs-on : ubuntu-22.04
343512 steps :
344513 - name : Checkout code
345- uses : actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8
514+ uses : actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
346515 with :
347516 ref : ${{ env.BRANCH_NAME }}
348517 fetch-depth : 0
349518
519+ # using git commit sha for version of action to ensure we have stable version
520+ - name : Install asdf
521+ uses : asdf-vm/actions/setup@b7bcd026f18772e44fe1026d729e1611cc435d47
522+ with :
523+ asdf_version : ${{ inputs.asdfVersion }}
524+
525+ - name : Cache asdf
526+ uses : actions/cache@9255dc7a253b0ccc959486e2bca901246202afeb
527+ with :
528+ path : |
529+ ~/.asdf
530+ key : ${{ runner.os }}-asdf-${{ hashFiles('**/.tool-versions') }}-${{ inputs.asdfVersion }}
531+ restore-keys : |
532+ ${{ runner.os }}-asdf-${{ hashFiles('**/.tool-versions') }}-${{ inputs.asdfVersion }}
533+
534+ - name : Install asdf dependencies in .tool-versions
535+ uses : asdf-vm/actions/install@b7bcd026f18772e44fe1026d729e1611cc435d47
536+ with :
537+ asdf_version : ${{ inputs.asdfVersion }}
538+ env :
539+ PYTHON_CONFIGURE_OPTS : --enable-shared
540+
541+ - name : Reinstall poetry
542+ if : ${{ inputs.reinstall_poetry }}
543+ run : |
544+ poetry_tool_version=$(cat .tool-versions | grep poetry)
545+ poetry_version=${poetry_tool_version//"poetry "}
546+ asdf uninstall poetry "$poetry_version"
547+ asdf install poetry
548+
350549 - name : Check for SAM templates
351550 id : check_sam_templates
352551 run : |
0 commit comments