diff --git a/.github/workflows/ci-docker-container-scan.yml b/.github/workflows/ci-docker-container-scan.yml new file mode 100644 index 00000000..19336560 --- /dev/null +++ b/.github/workflows/ci-docker-container-scan.yml @@ -0,0 +1,139 @@ +# 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 }} + os-exit-code: "1" + 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: 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