From 6883910f08bd420e20d6c85255ab885702618410 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niccol=C3=B2=20Fei?= Date: Fri, 10 Oct 2025 17:47:56 +0200 Subject: [PATCH] ci: add a composite action for security scanners MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Niccolò Fei --- .github/actions/security-scans/README.md | 71 +++++++++++++++++++++++ .github/actions/security-scans/action.yml | 64 ++++++++++++++++++++ .github/workflows/bake_targets.yml | 44 ++------------ 3 files changed, 141 insertions(+), 38 deletions(-) create mode 100644 .github/actions/security-scans/README.md create mode 100644 .github/actions/security-scans/action.yml diff --git a/.github/actions/security-scans/README.md b/.github/actions/security-scans/README.md new file mode 100644 index 00000000..c2aba7ae --- /dev/null +++ b/.github/actions/security-scans/README.md @@ -0,0 +1,71 @@ +# Security Scans Action + +This composite GitHub Action wraps all the security scanners used to +analyze CloudNativePG container images. + +--- + +## Requirements + +This composite action relies on the calling workflow’s `GITHUB_TOKEN`. +Make sure your calling workflow includes: + +``` +permissions: + contents: read + packages: read + security-events: write # required for SARIF upload +``` + +--- + +## Security scanners + +- [Dockle](https://github.com/goodwithtech/dockle): + - Best-practice and configuration checks. + +- [Snyk](https://github.com/snyk/actions): + - Detects vulnerabilities in OS packages, libraries, and dependencies. + - Generates a `snyk.sarif` that gets uploaded to GitHub Code Scanning + +--- + +## Inputs + +| Name | Description | Required | Default | +| ---------------- | -------------------------------------------------- | --------- | -------------- | +| `image` | The image to scan (e.g. `ghcr.io/org/image:tag`) | ✅ Yes | — | +| `registry_user` | The user used to pull the image | ✅ Yes | — | +| `registry_token` | The token used to pull the image | ✅ Yes | — | +| `snyk_token` | The Snyk authentication token | ❌ No | — | +| `dockerfile` | Path to the image’s Dockerfile (for Snyk scanning) | ❌ No | `./Dockerfile` | + +Note: +- If a `snyk_token` is not provided, Snyk scans won't be performed. +- The `dockerfile` path is currently only required by Snyk. + +--- + +## Usage + +Example workflow: + +``` +jobs: + security-scan: + runs-on: ubuntu-latest + permissions: + contents: read + packages: read + security-events: write + steps: + - uses: actions/checkout@v5 + - name: Security checks + uses: cloudnative-pg/postgres-containers/.github/actions/security-scans@main + with: + image: ghcr.io/org/image:tag + registry_user: ${{ github.actor }} + registry_token: ${{ secrets.GITHUB_TOKEN }} + snyk_token: ${{ secrets.SNYK_TOKEN }} + dockerfile: "./Dockerfile" +``` diff --git a/.github/actions/security-scans/action.yml b/.github/actions/security-scans/action.yml new file mode 100644 index 00000000..3dc97d90 --- /dev/null +++ b/.github/actions/security-scans/action.yml @@ -0,0 +1,64 @@ +name: Security Scans +description: Security Scans +inputs: + image: + description: "The image to scan" + required: true + registry_user: + description: "The user used to pull the image" + required: true + registry_token: + description: "The token used to pull the image" + required: true + snyk_token: + description: "The snyk authentication token" + required: false + dockerfile: + description: "The image's Dockerfile" + required: false + default: './Dockerfile' + +runs: + using: composite + steps: + - name: Log in to the GitHub Container registry + uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3 + with: + registry: ghcr.io + username: ${{ inputs.registry_user }} + password: ${{ inputs.registry_token }} + + - name: Dockle + uses: erzz/dockle-action@69369bc745ee29813f730231a821bcd4f71cd290 # v1 + with: + image: "${{ inputs.image }}" + exit-code: '1' + failure-threshold: WARN + accept-keywords: key + accept-filenames: usr/share/postgresql-common/pgdg/apt.postgresql.org.asc,etc/ssl/private/ssl-cert-snakeoil.key,usr/local/lib/python3.9/dist-packages/azure/core/settings.py,usr/local/lib/python3.11/dist-packages/azure/core/settings.py,usr/local/lib/python3.13/dist-packages/azure/core/settings.py + + - name: Snyk + uses: snyk/actions/docker@master + id: snyk + if: ${{ inputs.snyk_token != '' }} + # Snyk can be used to break the build when it detects vulnerabilities. + # In this case we want to upload the issues to GitHub Code Scanning. + continue-on-error: true + env: + SNYK_TOKEN: ${{ inputs.snyk_token }} + with: + image: "${{ inputs.image }}" + args: --severity-threshold=high --file=${{ inputs.dockerfile }} + + - name: Replace sarif security-severity invalid values + if: ${{ steps.snyk.conclusion == 'success' }} + shell: bash + run: | + sed -i 's/"security-severity": "null"/"security-severity": "0"/g' snyk.sarif + sed -i 's/"security-severity": "undefined"/"security-severity": "0"/g' snyk.sarif + + - name: Upload result to GitHub Code Scanning + uses: github/codeql-action/upload-sarif@f443b600d91635bebf5b0d9ebc620189c0d6fba5 # v4 + if: ${{ steps.snyk.conclusion == 'success' }} + with: + sarif_file: snyk.sarif diff --git a/.github/workflows/bake_targets.yml b/.github/workflows/bake_targets.yml index b501a58b..c1c1e444 100644 --- a/.github/workflows/bake_targets.yml +++ b/.github/workflows/bake_targets.yml @@ -143,46 +143,14 @@ jobs: - name: Checkout Code uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5 - - name: Log in to the GitHub Container registry - uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3 - with: - registry: ghcr.io - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - - name: Dockle - uses: erzz/dockle-action@69369bc745ee29813f730231a821bcd4f71cd290 # v1 - with: - image: ${{ matrix.image }} - exit-code: '1' - failure-threshold: WARN - accept-keywords: key - accept-filenames: usr/share/postgresql-common/pgdg/apt.postgresql.org.asc,etc/ssl/private/ssl-cert-snakeoil.key,usr/local/lib/python3.9/dist-packages/azure/core/settings.py,usr/local/lib/python3.11/dist-packages/azure/core/settings.py,usr/local/lib/python3.13/dist-packages/azure/core/settings.py - - - name: Snyk - uses: snyk/actions/docker@master - id: snyk - if: ${{ env.SNYK_TOKEN != '' }} - # Snyk can be used to break the build when it detects vulnerabilities. - # In this case we want to upload the issues to GitHub Code Scanning. - continue-on-error: true - env: - SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }} + - name: Security checks + uses: ./.github/actions/security-scans with: image: "${{ matrix.image }}" - args: --severity-threshold=high --file=Dockerfile - - - name: Replace sarif security-severity invalid values - if: ${{ steps.snyk.conclusion == 'success' }} - run: | - sed -i 's/"security-severity": "null"/"security-severity": "0"/g' snyk.sarif - sed -i 's/"security-severity": "undefined"/"security-severity": "0"/g' snyk.sarif - - - name: Upload result to GitHub Code Scanning - uses: github/codeql-action/upload-sarif@f443b600d91635bebf5b0d9ebc620189c0d6fba5 # v4 - if: ${{ steps.snyk.conclusion == 'success' }} - with: - sarif_file: snyk.sarif + registry_user: ${{ github.actor }} + registry_token: ${{ secrets.GITHUB_TOKEN }} + snyk_token: ${{ secrets.SNYK_TOKEN }} + dockerfile: "./Dockerfile" # Use the metadata generated in the `testbuild` step to find all the images # that have been built. We copy them one by one to the production registry