From 0e0c33334bfebcf1ab2028052b8c56b4f56448fb Mon Sep 17 00:00:00 2001 From: bragesande94 Date: Thu, 16 Jul 2026 07:22:14 +0200 Subject: [PATCH 1/7] =?UTF-8?q?PF-2200=20Legg=20til=20st=C3=B8tte=20for=20?= =?UTF-8?q?Trivy=20scan=20p=C3=A5=20PR=20workflow=20for=20Dockerfile=20app?= =?UTF-8?q?s?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../workflows/ci-docker-container-scan.yml | 138 ++++++++++++++++++ .github/workflows/ci-pr-checks-image.yml | 48 +++++- 2 files changed, 179 insertions(+), 7 deletions(-) create mode 100644 .github/workflows/ci-docker-container-scan.yml diff --git a/.github/workflows/ci-docker-container-scan.yml b/.github/workflows/ci-docker-container-scan.yml new file mode 100644 index 00000000..21b05665 --- /dev/null +++ b/.github/workflows/ci-docker-container-scan.yml @@ -0,0 +1,138 @@ +# Workflow Name: Docker container scan +# +# Owner: Digdir Platform team +# +# Purpose: +# This is part of the golden path for PRs towards main branch. The workflow +# should not normally be used directly, but called from the ci-pr-checks-image +# workflow, which checks certain things before calling this workflow with the +# correct parameters. This workflow will build a temporary Docker image +# based on the Dockerfile found in the 'application-path' directory, or at +# 'docker/Dockerfile' relative to the repository root when +# 'add-git-package-token' is true (mirroring +# ci-docker-build-publish-image.yml, so PR-time scanning builds the same +# artifact the merge-time publish workflow will build). After building the +# image, the workflow will run Trivy vulnerability scans. +# +# Flow: +# 1. Set image metadata (name and tag) +# 2. Checkout repository +# 3. Build Docker image +# 4. Run Trivy vulnerability scan on the built image +# +# Trigger: +# Triggered by workflow calls (workflow_call) +# +# Inputs: +# See input section +# +# Outputs: +# None +# + +name: Docker container scan + +permissions: {} + +on: + workflow_call: + inputs: + add-git-package-token: + description: Adds GIT_PACKAGE_TOKEN build argument for Docker + default: false + required: false + type: boolean + application-path: + description: Path to the application directory containing the Dockerfile, and to scan with Trivy + default: "./" + required: false + type: string + docker-build-context: + description: Docker build context directory (resolves COPY/ADD paths). Defaults to the repository root. + default: "." + required: false + type: string + image-name: + description: Name of Docker image + required: false + type: string + trivy-library-disable-scan: + description: Disable Trivy library scan + type: boolean + required: false + default: false + trivy-library-ignore-unfixed: + description: Ignore unfixed vulnerabilities in Trivy library scan + type: boolean + required: false + default: true + trivy-library-severity: + description: When to fail the scan with Trivy library vulnerabilities + type: string + required: false + default: 'HIGH,CRITICAL' + trivy-os-disable-scan: + description: Disable Trivy OS scan + type: boolean + required: false + default: false + trivy-os-ignore-unfixed: + description: Ignore unfixed vulnerabilities in Trivy OS scan + type: boolean + required: false + default: true + trivy-os-severity: + description: When to fail the scan with Trivy OS vulnerabilities + type: string + required: false + default: 'CRITICAL' + trivy-version: + description: Version of Trivy to use for scanning + type: string + required: false + default: '' + +jobs: + build-and-scan-image: + runs-on: ubuntu-latest + permissions: + contents: read + + steps: + - name: Set image metadata + id: image-metadata + uses: felleslosninger/github-workflows/.github/actions/image-metadata@main + with: + image-name: ${{ inputs.image-name }} + container-registry: "my-local-registry" + + - name: Checkout + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # pin@v6.0.2 + + - name: Build image + env: + APP_PATH: ${{ inputs.application-path }} + BUILD_CONTEXT: ${{ inputs.docker-build-context }} + IMAGE_NAME: ${{ steps.image-metadata.outputs.image-name }} + IMAGE_TAG: ${{ steps.image-metadata.outputs.image-tag }} + ADD_TOKEN: ${{ inputs.add-git-package-token }} + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + if [ "$ADD_TOKEN" = "true" ]; then + docker build --tag "$IMAGE_NAME:$IMAGE_TAG" --file docker/Dockerfile --build-arg GIT_PACKAGE_TOKEN="$GITHUB_TOKEN" "$BUILD_CONTEXT" + else + docker build --tag "$IMAGE_NAME:$IMAGE_TAG" --file "$APP_PATH/Dockerfile" "$BUILD_CONTEXT" + fi + + - name: Run Trivy vulnerability scanner (image) + uses: felleslosninger/github-workflows/.github/actions/trivy-scan@main + with: + image-ref: ${{ steps.image-metadata.outputs.image-name }}:${{ steps.image-metadata.outputs.image-tag }} + application-path: ${{ inputs.application-path }} + library-disable-scan: ${{ inputs.trivy-library-disable-scan }} + library-ignore-unfixed: ${{ inputs.trivy-library-ignore-unfixed }} + library-severity: ${{ inputs.trivy-library-severity }} + os-disable-scan: ${{ inputs.trivy-os-disable-scan }} + os-ignore-unfixed: ${{ inputs.trivy-os-ignore-unfixed }} + os-severity: ${{ inputs.trivy-os-severity }} + trivy-version: ${{ inputs.trivy-version }} diff --git a/.github/workflows/ci-pr-checks-image.yml b/.github/workflows/ci-pr-checks-image.yml index 15485cf4..6c1d4647 100644 --- a/.github/workflows/ci-pr-checks-image.yml +++ b/.github/workflows/ci-pr-checks-image.yml @@ -6,14 +6,15 @@ # This is the golden path for PRs towards main branch for containerized # applications. It works as a proxy workflow that delegates the container # build and Trivy scans to the correct workflow based on the -# 'application-type' input ('spring-boot' or 'quarkus'). For library projects -# that do not build a container image, use ci-pr-checks-lib.yml instead. +# 'application-type' input ('spring-boot', 'quarkus', or 'docker'). For +# library projects that do not build a container image, use +# ci-pr-checks-lib.yml instead. # # Flow: # 1. Verifies PR title # 2. Builds the container image and runs Trivy library + OS scans, by -# calling the Spring Boot or Quarkus container-scan workflow selected -# by 'application-type' +# calling the Spring Boot, Quarkus, or Docker container-scan workflow +# selected by 'application-type' # 3. Auto-merges Dependabot PRs (optional) # 4. Dispatches a build-publish-image event for merged Dependabot PRs # (currently skipped automatically; see the note on call-build-image) @@ -34,13 +35,18 @@ permissions: {} on: workflow_call: inputs: + add-git-package-token: + description: Adds GIT_PACKAGE_TOKEN build argument for Docker. Only applies to 'docker' application type + default: false + required: false + type: boolean application-path: description: 'Path to the application to scan with Trivy. Default is root of the repository, but can be set to a specific module in multi-module projects.' default: "./" required: false type: string application-type: - description: Type of application to determine container build and scan steps. Supported values are 'spring-boot' and 'quarkus' + description: Type of application to determine container build and scan steps. Supported values are 'spring-boot', 'quarkus', and 'docker' type: string default: 'spring-boot' required: false @@ -52,6 +58,11 @@ on: default: "**/pom.xml" required: false type: string + docker-build-context: + description: Docker build context directory (resolves COPY/ADD paths). Only applies to 'docker' application type. Defaults to the repository root. + default: "." + required: false + type: string enable-auto-merge-dependabot: description: Set to true to enable auto-merge for Dependabot PRs type: boolean @@ -181,7 +192,7 @@ jobs: max-length-title: ${{ inputs.pull-request-max-length-title }} case-sensitive-prefix: ${{ inputs.pull-request-case-sensitive-prefix }} - + call-spring-boot-container-scan: name: Call Spring Boot container scan if: | @@ -234,17 +245,40 @@ jobs: trivy-version: ${{ inputs.trivy-version }} secrets: inherit + call-docker-container-scan: + name: Call Docker container scan + if: | + inputs.application-type == 'docker' + uses: felleslosninger/github-workflows/.github/workflows/ci-docker-container-scan.yml@main + permissions: + contents: read + with: + image-name: ${{ inputs.image-name }} + application-path: ${{ inputs.application-path }} + docker-build-context: ${{ inputs.docker-build-context }} + add-git-package-token: ${{ inputs.add-git-package-token }} + trivy-library-disable-scan: ${{ inputs.trivy-library-disable-scan }} + trivy-library-ignore-unfixed: ${{ inputs.trivy-library-ignore-unfixed }} + trivy-library-severity: ${{ inputs.trivy-library-severity }} + trivy-os-disable-scan: ${{ inputs.trivy-os-disable-scan }} + trivy-os-ignore-unfixed: ${{ inputs.trivy-os-ignore-unfixed }} + trivy-os-severity: ${{ inputs.trivy-os-severity }} + trivy-version: ${{ inputs.trivy-version }} + secrets: inherit + call-auto-merge: name: Call auto-merge if: | always() && inputs.enable-auto-merge-dependabot == true && (needs.call-spring-boot-container-scan.result == 'success' || needs.call-spring-boot-container-scan.result == 'skipped') && - (needs.call-quarkus-container-scan.result == 'success' || needs.call-quarkus-container-scan.result == 'skipped') + (needs.call-quarkus-container-scan.result == 'success' || needs.call-quarkus-container-scan.result == 'skipped') && + (needs.call-docker-container-scan.result == 'success' || needs.call-docker-container-scan.result == 'skipped') needs: [ call-spring-boot-container-scan, call-quarkus-container-scan, + call-docker-container-scan, ] uses: felleslosninger/github-workflows/.github/workflows/misc-approve-and-merge-dependabot-pr.yml@main permissions: From 3641fedb24d262008e9cf5a6da645621bd2fb5b0 Mon Sep 17 00:00:00 2001 From: bragesande94 Date: Thu, 16 Jul 2026 07:35:49 +0200 Subject: [PATCH 2/7] =?UTF-8?q?PF-2200=20Legg=20til=20st=C3=B8tte=20for=20?= =?UTF-8?q?Trivy=20scan=20p=C3=A5=20PR=20workflow=20for=20Dockerfile=20app?= =?UTF-8?q?s?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/ci-pr-checks-image.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci-pr-checks-image.yml b/.github/workflows/ci-pr-checks-image.yml index 6c1d4647..ea8cfefd 100644 --- a/.github/workflows/ci-pr-checks-image.yml +++ b/.github/workflows/ci-pr-checks-image.yml @@ -249,7 +249,7 @@ jobs: name: Call Docker container scan if: | inputs.application-type == 'docker' - uses: felleslosninger/github-workflows/.github/workflows/ci-docker-container-scan.yml@main + uses: felleslosninger/github-workflows/.github/workflows/ci-docker-container-scan.yml@PF-2200-legg-til-stotte-for-trivy-scan-pa-pr-workflow-for-dockerfile-apps permissions: contents: read with: From c0018064c38f6a01b379020d250ed3fc33ccc69b Mon Sep 17 00:00:00 2001 From: bragesande94 Date: Thu, 16 Jul 2026 08:18:29 +0200 Subject: [PATCH 3/7] =?UTF-8?q?PF-2200=20Legg=20til=20st=C3=B8tte=20for=20?= =?UTF-8?q?Trivy=20scan=20p=C3=A5=20PR=20workflow=20for=20Dockerfile=20app?= =?UTF-8?q?s?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/ci-pr-checks-image.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci-pr-checks-image.yml b/.github/workflows/ci-pr-checks-image.yml index ea8cfefd..6c1d4647 100644 --- a/.github/workflows/ci-pr-checks-image.yml +++ b/.github/workflows/ci-pr-checks-image.yml @@ -249,7 +249,7 @@ jobs: name: Call Docker container scan if: | inputs.application-type == 'docker' - uses: felleslosninger/github-workflows/.github/workflows/ci-docker-container-scan.yml@PF-2200-legg-til-stotte-for-trivy-scan-pa-pr-workflow-for-dockerfile-apps + uses: felleslosninger/github-workflows/.github/workflows/ci-docker-container-scan.yml@main permissions: contents: read with: From 56fa3888430f2ac47c3e36c598774a3ce540e5f4 Mon Sep 17 00:00:00 2001 From: bragesande94 Date: Thu, 16 Jul 2026 08:21:09 +0200 Subject: [PATCH 4/7] =?UTF-8?q?PF-2200=20Legg=20til=20st=C3=B8tte=20for=20?= =?UTF-8?q?Trivy=20scan=20p=C3=A5=20PR=20workflow=20for=20Dockerfile=20app?= =?UTF-8?q?s?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 58fd2880..c2007054 100644 --- a/README.md +++ b/README.md @@ -61,6 +61,8 @@ application-specific workflows Builds and scans temporary Spring Boot container images - [ci-quarkus-container-scan.yml](.github/workflows/ci-quarkus-container-scan.yml): Builds and scans temporary Quarkus JVM or GraalVM native container images +- [ci-docker-container-scan.yml](.github/workflows/ci-docker-container-scan.yml): + Builds and scans temporary custom Docker images and optionally runs the Dependabot auto-merge workflow From e308798ea6bd455978e68edaaa89d8ed9f46a69b Mon Sep 17 00:00:00 2001 From: Emil Lehre Arnesen Date: Mon, 20 Jul 2026 10:17:40 +0200 Subject: [PATCH 5/7] Apply suggestions from code review Co-authored-by: Emil Lehre Arnesen --- .github/workflows/ci-docker-container-scan.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/ci-docker-container-scan.yml b/.github/workflows/ci-docker-container-scan.yml index 21b05665..19336560 100644 --- a/.github/workflows/ci-docker-container-scan.yml +++ b/.github/workflows/ci-docker-container-scan.yml @@ -135,4 +135,5 @@ jobs: os-disable-scan: ${{ inputs.trivy-os-disable-scan }} os-ignore-unfixed: ${{ inputs.trivy-os-ignore-unfixed }} os-severity: ${{ inputs.trivy-os-severity }} + os-exit-code: "1" trivy-version: ${{ inputs.trivy-version }} From ab6fee3d5f0c1b61d470d7fd9d5ce417a7d5e0c6 Mon Sep 17 00:00:00 2001 From: bragesande94 Date: Mon, 20 Jul 2026 11:47:28 +0200 Subject: [PATCH 6/7] =?UTF-8?q?PF-2200=20Legg=20til=20st=C3=B8tte=20for=20?= =?UTF-8?q?Trivy=20scan=20p=C3=A5=20PR=20workflow=20for=20Dockerfile=20app?= =?UTF-8?q?s?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index c2007054..4accb4b8 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,7 @@ This repository contains reusable GitHub Workflows and composite Actions for common CI/CD tasks. Workflows are organized by purpose and application type. + ## Composite actions We have a set of composite actions that contain reusable steps to avoid From 9b4bbb8b67f0e724c35ea872b59d71236e6e0058 Mon Sep 17 00:00:00 2001 From: bragesande94 Date: Mon, 20 Jul 2026 11:47:54 +0200 Subject: [PATCH 7/7] =?UTF-8?q?PF-2200=20Legg=20til=20st=C3=B8tte=20for=20?= =?UTF-8?q?Trivy=20scan=20p=C3=A5=20PR=20workflow=20for=20Dockerfile=20app?= =?UTF-8?q?s?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index 4accb4b8..c2007054 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,6 @@ This repository contains reusable GitHub Workflows and composite Actions for common CI/CD tasks. Workflows are organized by purpose and application type. - ## Composite actions We have a set of composite actions that contain reusable steps to avoid