From acb1899517752562a3a3035a3ad78809901efee6 Mon Sep 17 00:00:00 2001 From: sidey79 Date: Sat, 2 May 2026 22:16:02 +0200 Subject: [PATCH] Add Trivy image scan workflow --- .github/workflows/build.yml | 154 ++++++++++++++++++++++++++++++------ 1 file changed, 128 insertions(+), 26 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index a578c83e..f356ea69 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -427,13 +427,13 @@ jobs: --report "${CPAN_ARTIFACT_DIR}/verify/all/all-result.json" - test_build: - # The type of runner that the job will run on - needs: [get_dependencies, base_build] - runs-on: ubuntu-latest - strategy: - matrix: - dockerfile: [-bookworm, -threaded-bookworm] + test_build: + # The type of runner that the job will run on + needs: [get_dependencies, base_build] + runs-on: ubuntu-latest + strategy: + matrix: + dockerfile: [-bookworm, -threaded-bookworm] # Steps represent a sequence of tasks that will be executed as part of the job env: TAG_LATEST: ${{ (contains(matrix.dockerfile,'threaded') || github.event.release.prerelease == 1) && 'false' || 'auto' }} @@ -465,9 +465,9 @@ jobs: name: cpanfile-3rdParty path: 3rdParty - - name: Prepare docker for build and publish - id: prepareDOCKER - uses: ./.github/workflows/prepare-docker + - name: Prepare docker for build and publish + id: prepareDOCKER + uses: ./.github/workflows/prepare-docker with: DOCKER_HUB_USERNAME: ${{ secrets.DOCKER_HUB_USERNAME }} DOCKER_HUB_ACCESS_TOKEN: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }} @@ -475,6 +475,15 @@ jobs: GHCR_ACCESS_TOKEN: ${{ secrets.GITHUB_TOKEN }} DOCKERFILE: ${{ matrix.dockerfile }} + - name: Prepare local image tag variables + run: | + DOCKERFILE_SLUG="${{ matrix.dockerfile }}" + DOCKERFILE_SLUG="${DOCKERFILE_SLUG#-}" + echo "TRIVY_FULL_IMAGE=fhem-docker:${DOCKERFILE_SLUG}-amd64" >> "$GITHUB_ENV" + echo "TRIVY_MINIMAL_IMAGE=fhem-minimal-docker:${DOCKERFILE_SLUG}-amd64" >> "$GITHUB_ENV" + echo "TRIVY_FULL_SARIF=trivy-fhem-docker-${DOCKERFILE_SLUG}-amd64.sarif" >> "$GITHUB_ENV" + echo "TRIVY_MINIMAL_SARIF=trivy-fhem-minimal-docker-${DOCKERFILE_SLUG}-amd64.sarif" >> "$GITHUB_ENV" + - name: Restore CPM cache for amd64 uses: actions/cache/restore@v5 id: cache-cpm-restore @@ -624,9 +633,9 @@ jobs: type=gha,scope=full_linux/amd64${{ matrix.dockerfile }} type=gha,scope=fhem_linux/amd64${{ matrix.dockerfile }} cache-to: type=gha,mode=max,scope=full_linux/amd64${{ matrix.dockerfile }} - tags: ${{ steps.meta.outputs.tags }} - labels: ${{ steps.meta.outputs.labels }} - build-args: | + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + build-args: | BUILD_DATE=${{ fromJSON(steps.meta.outputs.json).labels['org.opencontainers.image.created'] }} IMAGE_VERSION=${{ fromJSON(steps.meta.outputs.json).labels['org.opencontainers.image.version'] }} IMAGE_VCS_REF=${{ fromJSON(steps.meta.outputs.json).labels['org.opencontainers.image.revision'] }} @@ -634,12 +643,18 @@ jobs: CPAN_CPM_VERSION=${{ env.CPAN_CPM_VERSION }} CPAN_CPM_MIRROR=${{ env.CPAN_CPM_MIRROR }} L_USAGE=${{ github.server_url }}/${{ github.repository }}/blob/${{ github.sha }}/README.md - L_VCS_URL=${{ github.server_url }}/${{ github.repository }}/ - L_AUTHORS=${{ github.server_url }}/${{ github.repository }}/graphs/contributors - - - name: Inspect and run integration tests - run: | - docker image inspect ${{ fromJSON(steps.meta.outputs.json).tags[0] }} + L_VCS_URL=${{ github.server_url }}/${{ github.repository }}/ + L_AUTHORS=${{ github.server_url }}/${{ github.repository }}/graphs/contributors + + - name: Tag full image for Trivy scan + run: | + docker image tag \ + "${{ fromJSON(steps.meta.outputs.json).tags[0] }}" \ + "${TRIVY_FULL_IMAGE}" + + - name: Inspect and run integration tests + run: | + docker image inspect ${{ fromJSON(steps.meta.outputs.json).tags[0] }} ./scripts/test-integration.sh; - name: Run build in unittests @@ -678,13 +693,100 @@ jobs: L_VCS_URL=${{ github.server_url }}/${{ github.repository }}/ L_AUTHORS=${{ github.server_url }}/${{ github.repository }}/graphs/contributors - - uses: Wandalen/wretry.action@v3.8.0 - name: Run bats unit and integration tests in host network mode - with: - attempt_limit: 3 - command: timeout 1m docker run --rm -e GITHUB_RUN_ID=$GITHUB_RUN_ID -v "${PWD}/src/tests/bats:/code" bats-withfhem-extended:latest -T -t . --filter-tags 'extendedOnly' - - published_build: + - uses: Wandalen/wretry.action@v3.8.0 + name: Run bats unit and integration tests in host network mode + with: + attempt_limit: 3 + command: timeout 1m docker run --rm -e GITHUB_RUN_ID=$GITHUB_RUN_ID -v "${PWD}/src/tests/bats:/code" bats-withfhem-extended:latest -T -t . --filter-tags 'extendedOnly' + + - name: Run Trivy scan for full image + id: trivy_full + continue-on-error: true + uses: aquasecurity/trivy-action@v0.35.0 + with: + image-ref: ${{ env.TRIVY_FULL_IMAGE }} + scan-type: image + format: sarif + output: ${{ env.TRIVY_FULL_SARIF }} + vuln-type: os,library + severity: HIGH,CRITICAL + ignore-unfixed: true + exit-code: '1' + + - name: Upload Trivy full image scan artifact + if: always() + uses: actions/upload-artifact@v7 + with: + name: trivy-fhem-docker${{ matrix.dockerfile }}-amd64 + path: ${{ env.TRIVY_FULL_SARIF }} + if-no-files-found: ignore + overwrite: true + + - name: Build minimal image for Trivy scan + uses: docker/build-push-action@v7 + id: docker_build_minimal_trivy + with: + context: . + load: true + file: ./Dockerfile${{ matrix.dockerfile }} + platforms: linux/amd64 + push: false + target: with-fhem + cache-from: | + type=gha,scope=fhem_linux/amd64${{ matrix.dockerfile }} + type=gha,scope=base_linux/amd64${{ matrix.dockerfile }} + type=gha,scope=base-cpan_linux/amd64${{ matrix.dockerfile }} + tags: ${{ env.TRIVY_MINIMAL_IMAGE }} + labels: ${{ steps.meta.outputs.labels }} + build-args: | + BUILD_DATE=${{ fromJSON(steps.meta.outputs.json).labels['org.opencontainers.image.created'] }} + IMAGE_VERSION=${{ fromJSON(steps.meta.outputs.json).labels['org.opencontainers.image.version'] }} + IMAGE_VCS_REF=${{ fromJSON(steps.meta.outputs.json).labels['org.opencontainers.image.revision'] }} + CPAN_CPM_CACHE_ID=perl-cpm${{ matrix.dockerfile }}-${{ env.CPAN_CPM_CACHE_VERSION }} + CPAN_CPM_VERSION=${{ env.CPAN_CPM_VERSION }} + CPAN_CPM_MIRROR=${{ env.CPAN_CPM_MIRROR }} + L_USAGE=${{ github.server_url }}/${{ github.repository }}/blob/${{ github.sha }}/README.md + L_VCS_URL=${{ github.server_url }}/${{ github.repository }}/ + L_AUTHORS=${{ github.server_url }}/${{ github.repository }}/graphs/contributors + + - name: Run Trivy scan for minimal image + id: trivy_minimal + continue-on-error: true + uses: aquasecurity/trivy-action@v0.35.0 + with: + image-ref: ${{ env.TRIVY_MINIMAL_IMAGE }} + scan-type: image + format: sarif + output: ${{ env.TRIVY_MINIMAL_SARIF }} + vuln-type: os,library + severity: HIGH,CRITICAL + ignore-unfixed: true + exit-code: '1' + + - name: Upload Trivy minimal image scan artifact + if: always() + uses: actions/upload-artifact@v7 + with: + name: trivy-fhem-minimal-docker${{ matrix.dockerfile }}-amd64 + path: ${{ env.TRIVY_MINIMAL_SARIF }} + if-no-files-found: ignore + overwrite: true + + - name: Assert Trivy scan results + if: always() + run: | + STATUS=0 + if [ "${{ steps.trivy_full.outcome }}" != "success" ]; then + echo "Trivy reported HIGH or CRITICAL findings for ${TRIVY_FULL_IMAGE}." + STATUS=1 + fi + if [ "${{ steps.trivy_minimal.outcome }}" != "success" ]; then + echo "Trivy reported HIGH or CRITICAL findings for ${TRIVY_MINIMAL_IMAGE}." + STATUS=1 + fi + exit "$STATUS" + + published_build: runs-on: ubuntu-latest needs: [test_build, cpan_build] strategy: