From 25a4858a67338fc368198b8d6828115ce6c57342 Mon Sep 17 00:00:00 2001 From: Tim Bastin Date: Fri, 6 Mar 2026 12:59:52 +0100 Subject: [PATCH 01/30] adds nix workflows, adds container-lifecycle --- .github/workflows/build-nix-image.yml | 147 ++++++++++++++++ .github/workflows/code-scanning.yml | 93 +++++++++++ .github/workflows/container-lifecycle-nix.yml | 148 ++++++++++++++++ .github/workflows/container-lifecycle.yml | 145 ++++++++++++++++ .github/workflows/full-with-nix.yml | 158 ++++++++++++++++++ .github/workflows/full.yml | 54 +----- 6 files changed, 697 insertions(+), 48 deletions(-) create mode 100644 .github/workflows/build-nix-image.yml create mode 100644 .github/workflows/code-scanning.yml create mode 100644 .github/workflows/container-lifecycle-nix.yml create mode 100644 .github/workflows/container-lifecycle.yml create mode 100644 .github/workflows/full-with-nix.yml diff --git a/.github/workflows/build-nix-image.yml b/.github/workflows/build-nix-image.yml new file mode 100644 index 0000000..e5e5e4f --- /dev/null +++ b/.github/workflows/build-nix-image.yml @@ -0,0 +1,147 @@ +name: Build Nix OCI Image + +on: + workflow_call: + inputs: + nix-target: + description: 'Nix flake build target (e.g. devguardOCI)' + required: true + type: string + image-name: + description: 'Full OCI image name without tag (e.g. ghcr.io/l3montree-dev/devguard/scanner)' + required: true + type: string + artifact-name-suffix: + description: 'Suffix appended to artifact names to avoid conflicts when building multiple images in the same workflow' + required: false + type: string + default: '' + asset-name: + description: 'DevGuard asset name for supply chain tracking' + required: true + type: string + api-url: + description: 'DevGuard API URL' + required: false + type: string + default: 'https://api.devguard.org' + secrets: + devguard-token: + required: false + outputs: + image-tag: + description: 'Full image tag of the built image' + value: ${{ jobs.build.outputs.image-tag }} + image-digest: + description: 'Digest of the built image' + value: ${{ jobs.build.outputs.image-digest }} + artifact-purl: + description: 'Package URL (PURL) of the built artifact' + value: ${{ jobs.build.outputs.artifact-purl }} + +jobs: + build: + runs-on: ubuntu-latest + outputs: + image-tag: ${{ steps.set-image-tag.outputs.image_tag }} + image-digest: ${{ steps.get-digest.outputs.digest }} + artifact-purl: ${{ steps.set-purl.outputs.purl }} + steps: + - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5 - https://github.com/actions/checkout/releases/tag/v5.0.0 + with: + fetch-depth: 0 # needed for flake.nix to resolve self.shortRev + persist-credentials: false + + - name: In-Toto Provenance record start + uses: docker://ghcr.io/l3montree-dev/devguard/scanner:v1.0.0 + with: + args: devguard-scanner intoto start --step=build --token=${{ secrets.devguard-token }} --apiUrl=${{ inputs.api-url }} --assetName=${{ inputs.asset-name }} --supplyChainId=${{ github.sha }} + continue-on-error: true + + - uses: cachix/install-nix-action@v31 + with: + extra_nix_config: | + experimental-features = nix-command flakes + + - uses: imjasonh/setup-crane@v0.1 + + - name: Build OCI image with Nix + run: nix build .#${{ inputs.nix-target }} + + - name: Prepare image.tar + run: gunzip -c "$(readlink -f result)" > image.tar + + - name: Get image digest + id: get-digest + run: | + crane digest --tarball=image.tar > image-digest.txt + echo "digest=$(cat image-digest.txt)" >> $GITHUB_OUTPUT + + - name: Upload oci-image artifact + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 - https://github.com/actions/upload-artifact/releases/tag/v4.6.2 + with: + name: oci-image${{ inputs.artifact-name-suffix }} + path: image.tar + + - name: Set image tag + id: set-image-tag + run: | + if [[ "${GITHUB_REF}" == refs/tags/* ]]; then + IMAGE_TAG="${{ inputs.image-name }}:${GITHUB_REF#refs/tags/}" + else + branch=${GITHUB_REF##*/} + sha=${GITHUB_SHA::8} + ts=$(date +%s) + IMAGE_TAG="${{ inputs.image-name }}:${branch}-${sha}-${ts}" + fi + IMAGE_TAG=$(echo "$IMAGE_TAG" | tr '[:upper:]' '[:lower:]') + echo "$IMAGE_TAG" > image-tag.txt + echo "IMAGE_TAG=$IMAGE_TAG" >> $GITHUB_ENV + echo "image_tag=$IMAGE_TAG" >> $GITHUB_OUTPUT + + - name: Upload image-tag artifact + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 - https://github.com/actions/upload-artifact/releases/tag/v4.6.2 + with: + name: image-tag${{ inputs.artifact-name-suffix }} + path: image-tag.txt + + - name: Upload image-digest artifact + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 - https://github.com/actions/upload-artifact/releases/tag/v4.6.2 + with: + name: image-digest${{ inputs.artifact-name-suffix }} + path: image-digest.txt + + - name: Set artifact PURL + id: set-purl + run: | + REGISTRY_AND_IMAGE=${IMAGE_TAG%:*} + NAME=${REGISTRY_AND_IMAGE##*/} + PURL="pkg:oci/$NAME?repository_url=$REGISTRY_AND_IMAGE" + echo "$PURL" > artifact-purl.txt + SAFE_PURL=$(echo -n "$PURL" | jq -s -R -r @uri) + echo "$SAFE_PURL" > artifact-purl-safe.txt + echo "purl=$PURL" >> $GITHUB_OUTPUT + + - name: Upload artifact-purl artifact + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 - https://github.com/actions/upload-artifact/releases/tag/v4.6.2 + with: + name: artifact-purl${{ inputs.artifact-name-suffix }} + path: artifact-purl.txt + + - name: Upload artifact-purl-safe artifact + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 - https://github.com/actions/upload-artifact/releases/tag/v4.6.2 + with: + name: artifact-purl-safe${{ inputs.artifact-name-suffix }} + path: artifact-purl-safe.txt + + - name: In-Toto Provenance record stop + uses: docker://ghcr.io/l3montree-dev/devguard/scanner:v1.0.0 + with: + args: devguard-scanner intoto stop --step=build --products=image-digest.txt --products=image-tag.txt --token=${{ secrets.devguard-token }} --apiUrl=${{ inputs.api-url }} --assetName=${{ inputs.asset-name }} --supplyChainId=${{ github.sha }} --generateSlsaProvenance + continue-on-error: true + + - name: Upload SLSA Provenance + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 - https://github.com/actions/upload-artifact/releases/tag/v4.6.2 + with: + name: build${{ inputs.artifact-name-suffix }}.provenance.json + path: build.provenance.json diff --git a/.github/workflows/code-scanning.yml b/.github/workflows/code-scanning.yml new file mode 100644 index 0000000..4c96f9d --- /dev/null +++ b/.github/workflows/code-scanning.yml @@ -0,0 +1,93 @@ +name: Code Scanning + +on: + workflow_call: + inputs: + asset-name: + description: 'Name of the asset to be scanned' + type: string + required: true + + api-url: + type: string + required: false + default: "https://api.devguard.org" + + path: + description: 'Path to the source code to be scanned' + type: string + required: false + default: "/github/workspace" + + web-ui: + type: string + required: false + default: "https://app.devguard.org" + description: "The URL of the DevGuard Web UI. This is used to link the results in the DevGuard Web UI." + + fail-on-risk: + description: 'Fail the job if a risk is higher than the configured threshold, e.g. critical, high, medium, low' + type: string + required: false + + fail-on-cvss: + description: 'Fail the job if a CVSS score is higher than the configured threshold, e.g. critical, high, medium, low' + type: string + required: false + + continue-on-open-code-risk: + type: boolean + required: false + default: true + + secrets: + devguard-token: + description: 'DevGuard API token' + required: true + + +jobs: + call-secret-scanning: + uses: ./.github/workflows/secret-scanning.yml + with: + asset-name: ${{ inputs.asset-name }} + api-url: ${{ inputs.api-url }} + path: ${{ inputs.path }} + web-ui: ${{ inputs.web-ui }} + continue-on-open-code-risk: ${{ inputs.continue-on-open-code-risk }} + secrets: + devguard-token: ${{ secrets.devguard-token }} + + call-sast: + uses: ./.github/workflows/static-application-security-testing.yml + with: + asset-name: ${{ inputs.asset-name }} + api-url: ${{ inputs.api-url }} + path: ${{ inputs.path }} + web-ui: ${{ inputs.web-ui }} + continue-on-open-code-risk: ${{ inputs.continue-on-open-code-risk }} + secrets: + devguard-token: ${{ secrets.devguard-token }} + + call-iac: + uses: ./.github/workflows/iac.yml + with: + asset-name: ${{ inputs.asset-name }} + api-url: ${{ inputs.api-url }} + path: ${{ inputs.path }} + web-ui: ${{ inputs.web-ui }} + continue-on-open-code-risk: ${{ inputs.continue-on-open-code-risk }} + secrets: + devguard-token: ${{ secrets.devguard-token }} + + call-software-composition-analysis: + uses: ./.github/workflows/software-composition-analysis.yml + with: + asset-name: ${{ inputs.asset-name }} + api-url: ${{ inputs.api-url }} + path: ${{ inputs.path }} + fail-on-risk: ${{ inputs.fail-on-risk }} + fail-on-cvss: ${{ inputs.fail-on-cvss }} + web-ui: ${{ inputs.web-ui }} + secrets: + devguard-token: ${{ secrets.devguard-token }} diff --git a/.github/workflows/container-lifecycle-nix.yml b/.github/workflows/container-lifecycle-nix.yml new file mode 100644 index 0000000..05d01e5 --- /dev/null +++ b/.github/workflows/container-lifecycle-nix.yml @@ -0,0 +1,148 @@ +name: Container Lifecycle (Nix) + +on: + workflow_call: + inputs: + nix-target: + description: 'Nix flake build target (e.g. devguardOCI)' + required: true + type: string + + image-name: + description: 'Full OCI image name without tag (e.g. ghcr.io/l3montree-dev/devguard/scanner)' + required: true + type: string + + asset-name: + description: 'DevGuard asset name for supply chain tracking' + required: true + type: string + + api-url: + description: 'DevGuard API URL' + required: false + type: string + default: 'https://api.devguard.org' + + web-ui: + description: 'DevGuard web UI URL' + required: false + type: string + default: 'https://app.devguard.org' + + artifact-name-suffix: + description: 'Suffix appended to artifact names to avoid conflicts when building multiple images in the same workflow' + required: false + type: string + default: '' + + should-deploy: + description: 'Whether to push the image to the container registry' + required: false + type: boolean + default: true + + fail-on-risk: + description: 'Fail if risk level reaches this threshold (none|low|medium|high|critical)' + required: false + type: string + + fail-on-cvss: + description: 'Fail if CVSS score reaches this threshold (none|low|medium|high|critical)' + required: false + type: string + + secrets: + devguard-token: + required: true + + outputs: + image-tag: + description: 'Full image tag of the built image' + value: ${{ jobs.build-image.outputs.image-tag }} + image-digest: + description: 'Digest of the built image' + value: ${{ jobs.build-image.outputs.image-digest }} + artifact-purl: + description: 'Package URL (PURL) of the built artifact' + value: ${{ jobs.build-image.outputs.artifact-purl }} + + +permissions: + contents: read + packages: write + +jobs: + build-image: + uses: ./.github/workflows/build-nix-image.yml + permissions: + contents: read + with: + nix-target: ${{ inputs.nix-target }} + image-name: ${{ inputs.image-name }} + artifact-name-suffix: ${{ inputs.artifact-name-suffix }} + asset-name: ${{ inputs.asset-name }} + api-url: ${{ inputs.api-url }} + secrets: + devguard-token: ${{ secrets.devguard-token }} + + container-scanning: + needs: build-image + uses: ./.github/workflows/container-scanning.yml + permissions: + contents: read + security-events: write + with: + asset-name: ${{ inputs.asset-name }} + api-url: ${{ inputs.api-url }} + artifact-name: ${{ needs.build-image.outputs.artifact-purl }} + web-ui: ${{ inputs.web-ui }} + fail-on-cvss: ${{ inputs.fail-on-cvss }} + fail-on-risk: ${{ inputs.fail-on-risk }} + image-suffix: ${{ inputs.artifact-name-suffix }} + secrets: + devguard-token: ${{ secrets.devguard-token }} + + deploy: + if: ${{ inputs.should-deploy }} + needs: [build-image, container-scanning] + uses: ./.github/workflows/deploy.yml + permissions: + contents: read + packages: write + with: + asset-name: ${{ inputs.asset-name }} + api-url: ${{ inputs.api-url }} + image-suffix: ${{ inputs.artifact-name-suffix }} + secrets: + devguard-token: ${{ secrets.devguard-token }} + + sign: + if: ${{ inputs.should-deploy }} + needs: [build-image, container-scanning, deploy] + uses: ./.github/workflows/sign.yml + permissions: + contents: read + packages: write + with: + asset-name: ${{ inputs.asset-name }} + api-url: ${{ inputs.api-url }} + artifact-name: ${{ needs.build-image.outputs.artifact-purl }} + image-suffix: ${{ inputs.artifact-name-suffix }} + secrets: + devguard-token: ${{ secrets.devguard-token }} + + attest: + if: ${{ inputs.should-deploy }} + needs: [build-image, container-scanning, deploy] + uses: ./.github/workflows/attest.yml + permissions: + contents: read + packages: write + with: + asset-name: ${{ inputs.asset-name }} + api-url: ${{ inputs.api-url }} + artifact-name: ${{ needs.build-image.outputs.artifact-purl }} + image-suffix: ${{ inputs.artifact-name-suffix }} + secrets: + devguard-token: ${{ secrets.devguard-token }} diff --git a/.github/workflows/container-lifecycle.yml b/.github/workflows/container-lifecycle.yml new file mode 100644 index 0000000..d1d8936 --- /dev/null +++ b/.github/workflows/container-lifecycle.yml @@ -0,0 +1,145 @@ +name: Container Lifecycle + +on: + workflow_call: + inputs: + asset-name: + description: 'Name of the asset' + type: string + required: true + + api-url: + type: string + required: false + default: "https://api.devguard.org" + + web-ui: + type: string + required: false + default: "https://app.devguard.org" + description: "The URL of the DevGuard Web UI. This is used to link the results in the DevGuard Web UI." + + image-destination-path: + description: 'Path to the oci image to be scanned.' + type: string + required: false + default: "image.tar" + + image: + description: 'OCI image tag' + type: string + required: false + + disable-artifact-registry-as-image-store: + required: false + default: false + type: boolean + description: "If the artifact size is too big for your github usage quota, set this to true. This will push the image directly to the registry instead of uploading it as artifact." + + image-suffix: + description: 'Suffix for the image name. You probably need this if you are building multiple images.' + type: string + required: false + default: '' + + artifact-name: + type: string + required: false + default: '' + description: "The name of the artifact you are building. Leave empty if building a single artifact." + + should-deploy: + description: 'Should the deploy job run' + type: boolean + required: false + default: true + + fail-on-risk: + description: 'Fail the job if a risk is higher than the configured threshold, e.g. critical, high, medium, low' + type: string + required: false + + fail-on-cvss: + description: 'Fail the job if a CVSS score is higher than the configured threshold, e.g. critical, high, medium, low' + type: string + required: false + + secrets: + devguard-token: + description: 'DevGuard API token' + required: true + build-args: + description: 'Build arguments. Useful to overwrite context and dockerfile.' + required: false + + +permissions: + contents: read + packages: write + +jobs: + call-build-image: + uses: ./.github/workflows/build-image.yml + with: + image-destination-path: ${{ inputs.image-destination-path }} + image: ${{ inputs.image }} + asset-name: ${{ inputs.asset-name }} + api-url: ${{ inputs.api-url }} + disable-artifact-registry-as-image-store: ${{ inputs.disable-artifact-registry-as-image-store }} + artifact-name: ${{ inputs.artifact-name }} + image-suffix: ${{ inputs.image-suffix }} + secrets: + devguard-token: ${{ secrets.devguard-token }} + build-args: ${{ secrets.build-args }} + + call-container-scanning: + needs: call-build-image + uses: ./.github/workflows/container-scanning.yml + with: + asset-name: ${{ inputs.asset-name }} + api-url: ${{ inputs.api-url }} + image-path: ${{ inputs.image-destination-path }} + fetch-image-from-registry: ${{ inputs.disable-artifact-registry-as-image-store }} + fail-on-risk: ${{ inputs.fail-on-risk }} + fail-on-cvss: ${{ inputs.fail-on-cvss }} + web-ui: ${{ inputs.web-ui }} + artifact-name: ${{ inputs.artifact-name }} + image-suffix: ${{ inputs.image-suffix }} + secrets: + devguard-token: ${{ secrets.devguard-token }} + + call-deploy: + needs: [call-build-image, call-container-scanning] + uses: ./.github/workflows/deploy.yml + with: + should-deploy: ${{ inputs.should-deploy }} + asset-name: ${{ inputs.asset-name }} + api-url: ${{ inputs.api-url }} + image-already-in-registry: ${{ inputs.disable-artifact-registry-as-image-store }} + image-suffix: ${{ inputs.image-suffix }} + secrets: + devguard-token: ${{ secrets.devguard-token }} + + call-sign: + needs: [call-build-image, call-container-scanning, call-deploy] + uses: ./.github/workflows/sign.yml + with: + should-deploy: ${{ inputs.should-deploy }} + api-url: ${{ inputs.api-url }} + asset-name: ${{ inputs.asset-name }} + artifact-name: ${{ inputs.artifact-name }} + image-suffix: ${{ inputs.image-suffix }} + secrets: + devguard-token: ${{ secrets.devguard-token }} + + call-attest: + needs: [call-build-image, call-container-scanning, call-deploy] + uses: ./.github/workflows/attest.yml + with: + should-deploy: ${{ inputs.should-deploy }} + api-url: ${{ inputs.api-url }} + asset-name: ${{ inputs.asset-name }} + artifact-name: ${{ inputs.artifact-name }} + image-suffix: ${{ inputs.image-suffix }} + secrets: + devguard-token: ${{ secrets.devguard-token }} diff --git a/.github/workflows/full-with-nix.yml b/.github/workflows/full-with-nix.yml new file mode 100644 index 0000000..6ebcc62 --- /dev/null +++ b/.github/workflows/full-with-nix.yml @@ -0,0 +1,158 @@ +name: Full Nix Image Pipeline + + +on: + workflow_call: + inputs: + nix-target: + description: 'Nix flake build target (e.g. devguardOCI)' + required: true + type: string + image-name: + description: 'Full OCI image name without tag (e.g. ghcr.io/l3montree-dev/devguard/scanner)' + required: true + type: string + artifact-name-suffix: + description: 'Suffix appended to artifact names to avoid conflicts when building multiple images in the same workflow' + required: false + type: string + default: '' + asset-name: + description: 'DevGuard asset name for supply chain tracking' + required: true + type: string + api-url: + description: 'DevGuard API URL' + required: false + type: string + default: 'https://api.devguard.org' + web-ui: + description: 'DevGuard web UI URL' + required: false + type: string + default: 'https://app.devguard.org' + fail-on-risk: + description: 'Fail if risk level reaches this threshold (none|low|medium|high|critical)' + required: false + type: string + default: 'critical' + fail-on-cvss: + description: 'Fail if CVSS score reaches this threshold (none|low|medium|high|critical)' + required: false + type: string + default: 'critical' + should-deploy: + description: 'Whether to push the image to the container registry' + required: false + type: boolean + default: true + path: + description: 'Path to the source code to be scanned' + type: string + required: false + default: "/github/workspace" + continue-on-open-code-risk: + type: boolean + required: false + default: true + secrets: + devguard-token: + required: true + outputs: + image-tag: + description: 'Full image tag of the built image' + value: ${{ jobs.build-image.outputs.image-tag }} + image-digest: + description: 'Digest of the built image' + value: ${{ jobs.build-image.outputs.image-digest }} + artifact-purl: + description: 'Package URL (PURL) of the built artifact' + value: ${{ jobs.build-image.outputs.artifact-purl }} + +jobs: + call-code-scanning: + uses: l3montree-dev/devguard-action/.github/workflows/code-scanning.yml@main + with: + asset-name: ${{ inputs.asset-name }} + api-url: ${{ inputs.api-url }} + path: ${{ inputs.path }} + web-ui: ${{ inputs.web-ui }} + fail-on-risk: ${{ inputs.fail-on-risk }} + fail-on-cvss: ${{ inputs.fail-on-cvss }} + continue-on-open-code-risk: ${{ inputs.continue-on-open-code-risk }} + secrets: + devguard-token: ${{ secrets.devguard-token }} + + build-image: + uses: l3montree-dev/devguard-action/.github/workflows/build-nix-image.yml@main + permissions: + contents: read + with: + nix-target: ${{ inputs.nix-target }} + image-name: ${{ inputs.image-name }} + artifact-name-suffix: ${{ inputs.artifact-name-suffix }} + asset-name: ${{ inputs.asset-name }} + api-url: ${{ inputs.api-url }} + secrets: + devguard-token: ${{ secrets.devguard-token }} + + container-scanning: + uses: l3montree-dev/devguard-action/.github/workflows/container-scanning.yml@main + permissions: + contents: read + security-events: write + needs: [build-image] + with: + asset-name: ${{ inputs.asset-name }} + api-url: ${{ inputs.api-url }} + artifact-name: ${{ needs.build-image.outputs.artifact-purl }} + web-ui: ${{ inputs.web-ui }} + fail-on-cvss: ${{ inputs.fail-on-cvss }} + fail-on-risk: ${{ inputs.fail-on-risk }} + image-suffix: ${{ inputs.artifact-name-suffix }} + secrets: + devguard-token: ${{ secrets.devguard-token }} + + deploy: + if: ${{ inputs.should-deploy }} + needs: [build-image, container-scanning, call-code-scanning] + uses: l3montree-dev/devguard-action/.github/workflows/deploy.yml@main + permissions: + contents: read + packages: write + with: + asset-name: ${{ inputs.asset-name }} + api-url: ${{ inputs.api-url }} + image-suffix: ${{ inputs.artifact-name-suffix }} + secrets: + devguard-token: ${{ secrets.devguard-token }} + + sign: + if: ${{ inputs.should-deploy }} + needs: [build-image, container-scanning, call-code-scanning] + uses: l3montree-dev/devguard-action/.github/workflows/sign.yml@main + permissions: + contents: read + packages: write + with: + asset-name: ${{ inputs.asset-name }} + api-url: ${{ inputs.api-url }} + artifact-name: ${{ needs.build-image.outputs.artifact-purl }} + image-suffix: ${{ inputs.artifact-name-suffix }} + secrets: + devguard-token: ${{ secrets.devguard-token }} + + attest: + if: ${{ inputs.should-deploy }} + needs: [build-image, container-scanning, call-code-scanning] + uses: l3montree-dev/devguard-action/.github/workflows/attest.yml@main + permissions: + contents: read + packages: write + with: + asset-name: ${{ inputs.asset-name }} + api-url: ${{ inputs.api-url }} + artifact-name: ${{ needs.build-image.outputs.artifact-purl }} + image-suffix: ${{ inputs.artifact-name-suffix }} + secrets: + devguard-token: ${{ secrets.devguard-token }} diff --git a/.github/workflows/full.yml b/.github/workflows/full.yml index 6404438..3434f0f 100644 --- a/.github/workflows/full.yml +++ b/.github/workflows/full.yml @@ -89,49 +89,16 @@ permissions: packages: write jobs: - call-secret-scanning: - uses: ./.github/workflows/secret-scanning.yml + call-code-scanning: + uses: ./.github/workflows/code-scanning.yml with: asset-name: ${{ inputs.asset-name }} api-url: ${{ inputs.api-url }} path: ${{ inputs.path }} web-ui: ${{ inputs.web-ui }} - continue-on-open-code-risk: ${{ inputs.continue-on-open-code-risk }} - secrets: - devguard-token: ${{ secrets.devguard-token }} - - call-sast: - uses: ./.github/workflows/static-application-security-testing.yml - with: - asset-name: ${{ inputs.asset-name }} - api-url: ${{ inputs.api-url }} - path: ${{ inputs.path }} - web-ui: ${{ inputs.web-ui }} - continue-on-open-code-risk: ${{ inputs.continue-on-open-code-risk }} - secrets: - devguard-token: ${{ secrets.devguard-token }} - - call-iac: - uses: ./.github/workflows/iac.yml - with: - asset-name: ${{ inputs.asset-name }} - api-url: ${{ inputs.api-url }} - path: ${{ inputs.path }} - web-ui: ${{ inputs.web-ui }} - continue-on-open-code-risk: ${{ inputs.continue-on-open-code-risk }} - secrets: - devguard-token: ${{ secrets.devguard-token }} - - call-software-compsition-analysis: - uses: ./.github/workflows/software-composition-analysis.yml - with: - asset-name: ${{ inputs.asset-name }} - api-url: ${{ inputs.api-url }} - path: ${{ inputs.path }} fail-on-risk: ${{ inputs.fail-on-risk }} fail-on-cvss: ${{ inputs.fail-on-cvss }} - web-ui: ${{ inputs.web-ui }} -# artifact-name: // WE ARE NOT!! PROVIDING THE ARTIFACT NAME RIGHT HERE - OTHERWISE CONTAINER AND SCA WOULD DO THE SAME ARTIFACT + continue-on-open-code-risk: ${{ inputs.continue-on-open-code-risk }} secrets: devguard-token: ${{ secrets.devguard-token }} @@ -169,10 +136,7 @@ jobs: needs: - call-build-image - call-container-scanning - - call-software-compsition-analysis - - call-sast - - call-secret-scanning - - call-iac + - call-code-scanning uses: ./.github/workflows/deploy.yml with: should-deploy: ${{ inputs.should-deploy }} @@ -187,10 +151,7 @@ jobs: needs: - call-build-image - call-container-scanning - - call-software-compsition-analysis - - call-sast - - call-secret-scanning - - call-iac + - call-code-scanning - call-deploy uses: ./.github/workflows/sign.yml with: @@ -206,10 +167,7 @@ jobs: needs: - call-build-image - call-container-scanning - - call-software-compsition-analysis - - call-sast - - call-secret-scanning - - call-iac + - call-code-scanning - call-deploy uses: ./.github/workflows/attest.yml with: From 399c7d967bab42d395e24130ddd06c97cac6c2b6 Mon Sep 17 00:00:00 2001 From: Tim Bastin Date: Sat, 28 Mar 2026 21:19:26 +0100 Subject: [PATCH 02/30] adds cache inputs --- .github/workflows/build-nix-image.yml | 52 +++++++++++++++++++ .github/workflows/container-lifecycle-nix.yml | 35 +++++++++++++ 2 files changed, 87 insertions(+) diff --git a/.github/workflows/build-nix-image.yml b/.github/workflows/build-nix-image.yml index e5e5e4f..f9a9f8e 100644 --- a/.github/workflows/build-nix-image.yml +++ b/.github/workflows/build-nix-image.yml @@ -25,9 +25,40 @@ on: required: false type: string default: 'https://api.devguard.org' + nix-cache-substituter: + description: 'Nix binary cache substituter URL (e.g. https://nix.garage.l3montree.cloud)' + required: false + type: string + default: '' + nix-cache-public-key: + description: 'Trusted public key for the Nix binary cache' + required: false + type: string + default: '' + nix-cache-s3-endpoint: + description: 'S3 API endpoint for pushing to the cache (e.g. s3.garage.l3montree.cloud)' + required: false + type: string + default: '' + nix-cache-s3-bucket: + description: 'S3 bucket name for pushing to the cache' + required: false + type: string + default: 'nix' + nix-cache-region: + description: 'S3 region for the cache bucket' + required: false + type: string + default: 'garage' secrets: devguard-token: required: false + nix-cache-secret-key: + required: false + nix-cache-aws-access-key-id: + required: false + nix-cache-aws-secret-access-key: + required: false outputs: image-tag: description: 'Full image tag of the built image' @@ -62,12 +93,33 @@ jobs: with: extra_nix_config: | experimental-features = nix-command flakes + ${{ inputs.nix-cache-substituter != '' && format('substituters = https://cache.nixos.org {0}', inputs.nix-cache-substituter) || '' }} + ${{ inputs.nix-cache-public-key != '' && format('trusted-public-keys = cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY= {0}', inputs.nix-cache-public-key) || '' }} - uses: imjasonh/setup-crane@v0.1 + - name: Write Nix cache secret key + if: ${{ secrets.nix-cache-secret-key != '' }} + run: | + echo "${{ secrets.nix-cache-secret-key }}" > /tmp/nix-cache-priv-key.pem + - name: Build OCI image with Nix run: nix build .#${{ inputs.nix-target }} + - name: Push build results to Nix cache + if: ${{ inputs.nix-cache-s3-endpoint != '' && secrets.nix-cache-aws-access-key-id != '' }} + env: + AWS_ACCESS_KEY_ID: ${{ secrets.nix-cache-aws-access-key-id }} + AWS_SECRET_ACCESS_KEY: ${{ secrets.nix-cache-aws-secret-access-key }} + run: | + mkdir -p ~/.aws + echo "[profile nix-cache]" >> ~/.aws/config + echo "s3.addressing_style = path" >> ~/.aws/config + nix copy $(nix-store -qR $(nix-store -r $(nix eval --raw .#${{ inputs.nix-target }}.drvPath 2>/dev/null || readlink result))) \ + --to 's3://${{ inputs.nix-cache-s3-bucket }}?endpoint=${{ inputs.nix-cache-s3-endpoint }}®ion=${{ inputs.nix-cache-region }}&scheme=https&profile=nix-cache&secret-key=/tmp/nix-cache-priv-key.pem' \ + || nix copy $(readlink result) \ + --to 's3://${{ inputs.nix-cache-s3-bucket }}?endpoint=${{ inputs.nix-cache-s3-endpoint }}®ion=${{ inputs.nix-cache-region }}&scheme=https&profile=nix-cache&secret-key=/tmp/nix-cache-priv-key.pem' + - name: Prepare image.tar run: gunzip -c "$(readlink -f result)" > image.tar diff --git a/.github/workflows/container-lifecycle-nix.yml b/.github/workflows/container-lifecycle-nix.yml index 05d01e5..0b1e96e 100644 --- a/.github/workflows/container-lifecycle-nix.yml +++ b/.github/workflows/container-lifecycle-nix.yml @@ -52,9 +52,36 @@ on: required: false type: string + nix-cache-substituter: + description: 'Nix binary cache substituter URL (e.g. https://nix.garage.l3montree.cloud)' + required: false + type: string + nix-cache-public-key: + description: 'Trusted public key for the Nix binary cache' + required: false + type: string + nix-cache-s3-endpoint: + description: 'S3 API endpoint for pushing to the cache. Leave empty to skip pushing.' + required: false + type: string + nix-cache-s3-bucket: + description: 'S3 bucket name for the cache' + required: false + type: string + nix-cache-region: + description: 'S3 region for the cache bucket' + required: false + type: string + secrets: devguard-token: required: true + nix-cache-secret-key: + required: false + nix-cache-aws-access-key-id: + required: false + nix-cache-aws-secret-access-key: + required: false outputs: image-tag: @@ -83,8 +110,16 @@ jobs: artifact-name-suffix: ${{ inputs.artifact-name-suffix }} asset-name: ${{ inputs.asset-name }} api-url: ${{ inputs.api-url }} + nix-cache-substituter: ${{ inputs.nix-cache-substituter }} + nix-cache-public-key: ${{ inputs.nix-cache-public-key }} + nix-cache-s3-endpoint: ${{ inputs.nix-cache-s3-endpoint }} + nix-cache-s3-bucket: ${{ inputs.nix-cache-s3-bucket }} + nix-cache-region: ${{ inputs.nix-cache-region }} secrets: devguard-token: ${{ secrets.devguard-token }} + nix-cache-secret-key: ${{ secrets.nix-cache-secret-key }} + nix-cache-aws-access-key-id: ${{ secrets.nix-cache-aws-access-key-id }} + nix-cache-aws-secret-access-key: ${{ secrets.nix-cache-aws-secret-access-key }} container-scanning: needs: build-image From e89c2966a97ab95e4181b130a95c8bc6559ea28e Mon Sep 17 00:00:00 2001 From: Tim Bastin Date: Sun, 29 Mar 2026 10:14:11 +0200 Subject: [PATCH 03/30] fixes if condition --- .github/workflows/build-nix-image.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-nix-image.yml b/.github/workflows/build-nix-image.yml index f9a9f8e..80a66c0 100644 --- a/.github/workflows/build-nix-image.yml +++ b/.github/workflows/build-nix-image.yml @@ -99,7 +99,7 @@ jobs: - uses: imjasonh/setup-crane@v0.1 - name: Write Nix cache secret key - if: ${{ secrets.nix-cache-secret-key != '' }} + if: ${{ inputs.nix-cache-s3-endpoint != '' }} run: | echo "${{ secrets.nix-cache-secret-key }}" > /tmp/nix-cache-priv-key.pem @@ -107,7 +107,7 @@ jobs: run: nix build .#${{ inputs.nix-target }} - name: Push build results to Nix cache - if: ${{ inputs.nix-cache-s3-endpoint != '' && secrets.nix-cache-aws-access-key-id != '' }} + if: ${{ inputs.nix-cache-s3-endpoint != '' }} env: AWS_ACCESS_KEY_ID: ${{ secrets.nix-cache-aws-access-key-id }} AWS_SECRET_ACCESS_KEY: ${{ secrets.nix-cache-aws-secret-access-key }} From f0487397a8ca90fbd34499ed82b02d09a0887fb5 Mon Sep 17 00:00:00 2001 From: Tim Bastin Date: Sun, 29 Mar 2026 21:02:33 +0200 Subject: [PATCH 04/30] adds full-nix --- .github/workflows/build-nix-image.yml | 38 ++-- .github/workflows/full-nix.yml | 292 ++++++++++++++++++++++++++ 2 files changed, 317 insertions(+), 13 deletions(-) create mode 100644 .github/workflows/full-nix.yml diff --git a/.github/workflows/build-nix-image.yml b/.github/workflows/build-nix-image.yml index 80a66c0..ec99d72 100644 --- a/.github/workflows/build-nix-image.yml +++ b/.github/workflows/build-nix-image.yml @@ -50,6 +50,16 @@ on: required: false type: string default: 'garage' + arch: + description: 'Target architecture suffix appended to the generated image tag (e.g. amd64, arm64). Leave empty for single-arch builds.' + required: false + type: string + default: '' + upstream-version: + description: 'Upstream version passed to devguard-scanner generate-tag (matches the nix package version segment, e.g. 0)' + required: false + type: string + default: '0' secrets: devguard-token: required: false @@ -137,19 +147,21 @@ jobs: - name: Set image tag id: set-image-tag - run: | - if [[ "${GITHUB_REF}" == refs/tags/* ]]; then - IMAGE_TAG="${{ inputs.image-name }}:${GITHUB_REF#refs/tags/}" - else - branch=${GITHUB_REF##*/} - sha=${GITHUB_SHA::8} - ts=$(date +%s) - IMAGE_TAG="${{ inputs.image-name }}:${branch}-${sha}-${ts}" - fi - IMAGE_TAG=$(echo "$IMAGE_TAG" | tr '[:upper:]' '[:lower:]') - echo "$IMAGE_TAG" > image-tag.txt - echo "IMAGE_TAG=$IMAGE_TAG" >> $GITHUB_ENV - echo "image_tag=$IMAGE_TAG" >> $GITHUB_OUTPUT + uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main-latest + with: + args: > + sh -c " + devguard-scanner generate-tag + --imagePath='${{ inputs.image-name }}' + --ref='${{ github.ref_name }}' + --upstreamVersion='${{ inputs.upstream-version }}' + --architecture='${{ inputs.arch }}' + >> image-tag-env.txt + IMAGE_TAG=$(grep '^IMAGE_TAG=' image-tag-env.txt | cut -d= -f2-) + echo \"\$IMAGE_TAG\" > image-tag.txt + echo \"image_tag=\$IMAGE_TAG\" >> \"\$GITHUB_OUTPUT\" + echo \"IMAGE_TAG=\$IMAGE_TAG\" >> \"\$GITHUB_ENV\" + " - name: Upload image-tag artifact uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 - https://github.com/actions/upload-artifact/releases/tag/v4.6.2 diff --git a/.github/workflows/full-nix.yml b/.github/workflows/full-nix.yml new file mode 100644 index 0000000..a2949df --- /dev/null +++ b/.github/workflows/full-nix.yml @@ -0,0 +1,292 @@ +name: Full Nix Multi-Arch Pipeline + +on: + workflow_call: + inputs: + nix-target-amd64: + description: 'Nix flake build target for amd64 (e.g. devguard-0-amd64)' + required: true + type: string + nix-target-arm64: + description: 'Nix flake build target for arm64 (e.g. devguard-0-arm64)' + required: true + type: string + image-name: + description: 'Full OCI image name without tag (e.g. ghcr.io/l3montree-dev/devguard)' + required: true + type: string + upstream-version: + description: 'Upstream version segment used by generate-tag (matches the nix package version, e.g. 0)' + required: false + type: string + default: '0' + artifact-name-suffix: + description: 'Suffix appended to artifact names to avoid conflicts when building multiple images in the same workflow' + required: false + type: string + default: '' + asset-name: + description: 'DevGuard asset name for supply chain tracking' + required: true + type: string + api-url: + description: 'DevGuard API URL' + required: false + type: string + default: 'https://api.devguard.org' + web-ui: + description: 'DevGuard web UI URL' + required: false + type: string + default: 'https://app.devguard.org' + fail-on-risk: + description: 'Fail if risk level reaches this threshold (none|low|medium|high|critical)' + required: false + type: string + default: 'critical' + fail-on-cvss: + description: 'Fail if CVSS score reaches this threshold (none|low|medium|high|critical)' + required: false + type: string + default: 'critical' + should-deploy: + description: 'Whether to push the images and manifest to the container registry' + required: false + type: boolean + default: true + nix-cache-substituter: + description: 'Nix binary cache substituter URL' + required: false + type: string + default: '' + nix-cache-public-key: + description: 'Trusted public key for the Nix binary cache' + required: false + type: string + default: '' + nix-cache-s3-endpoint: + description: 'S3 API endpoint for pushing to the Nix cache' + required: false + type: string + default: '' + nix-cache-s3-bucket: + description: 'S3 bucket name for the Nix cache' + required: false + type: string + default: 'nix' + nix-cache-region: + description: 'S3 region for the Nix cache bucket' + required: false + type: string + default: 'garage' + secrets: + devguard-token: + required: true + nix-cache-secret-key: + required: false + nix-cache-aws-access-key-id: + required: false + nix-cache-aws-secret-access-key: + required: false + outputs: + manifest-tag: + description: 'Full image tag of the multi-arch manifest' + value: ${{ jobs.create-manifest.outputs.manifest-tag }} + +permissions: + contents: read + packages: write + +jobs: + build-amd64: + uses: l3montree-dev/devguard-action/.github/workflows/build-nix-image.yml@main + permissions: + contents: read + with: + nix-target: ${{ inputs.nix-target-amd64 }} + image-name: ${{ inputs.image-name }} + artifact-name-suffix: ${{ inputs.artifact-name-suffix }}-amd64 + asset-name: ${{ inputs.asset-name }} + api-url: ${{ inputs.api-url }} + arch: amd64 + upstream-version: ${{ inputs.upstream-version }} + nix-cache-substituter: ${{ inputs.nix-cache-substituter }} + nix-cache-public-key: ${{ inputs.nix-cache-public-key }} + nix-cache-s3-endpoint: ${{ inputs.nix-cache-s3-endpoint }} + nix-cache-s3-bucket: ${{ inputs.nix-cache-s3-bucket }} + nix-cache-region: ${{ inputs.nix-cache-region }} + secrets: + devguard-token: ${{ secrets.devguard-token }} + nix-cache-secret-key: ${{ secrets.nix-cache-secret-key }} + nix-cache-aws-access-key-id: ${{ secrets.nix-cache-aws-access-key-id }} + nix-cache-aws-secret-access-key: ${{ secrets.nix-cache-aws-secret-access-key }} + + build-arm64: + uses: l3montree-dev/devguard-action/.github/workflows/build-nix-image.yml@main + permissions: + contents: read + with: + nix-target: ${{ inputs.nix-target-arm64 }} + image-name: ${{ inputs.image-name }} + artifact-name-suffix: ${{ inputs.artifact-name-suffix }}-arm64 + asset-name: ${{ inputs.asset-name }} + api-url: ${{ inputs.api-url }} + arch: arm64 + upstream-version: ${{ inputs.upstream-version }} + nix-cache-substituter: ${{ inputs.nix-cache-substituter }} + nix-cache-public-key: ${{ inputs.nix-cache-public-key }} + nix-cache-s3-endpoint: ${{ inputs.nix-cache-s3-endpoint }} + nix-cache-s3-bucket: ${{ inputs.nix-cache-s3-bucket }} + nix-cache-region: ${{ inputs.nix-cache-region }} + secrets: + devguard-token: ${{ secrets.devguard-token }} + nix-cache-secret-key: ${{ secrets.nix-cache-secret-key }} + nix-cache-aws-access-key-id: ${{ secrets.nix-cache-aws-access-key-id }} + nix-cache-aws-secret-access-key: ${{ secrets.nix-cache-aws-secret-access-key }} + + container-scanning-amd64: + needs: build-amd64 + uses: l3montree-dev/devguard-action/.github/workflows/container-scanning.yml@main + permissions: + contents: read + security-events: write + with: + asset-name: ${{ inputs.asset-name }} + api-url: ${{ inputs.api-url }} + artifact-name: ${{ needs.build-amd64.outputs.artifact-purl }} + web-ui: ${{ inputs.web-ui }} + fail-on-cvss: ${{ inputs.fail-on-cvss }} + fail-on-risk: ${{ inputs.fail-on-risk }} + image-suffix: ${{ inputs.artifact-name-suffix }}-amd64 + secrets: + devguard-token: ${{ secrets.devguard-token }} + + container-scanning-arm64: + needs: build-arm64 + uses: l3montree-dev/devguard-action/.github/workflows/container-scanning.yml@main + permissions: + contents: read + security-events: write + with: + asset-name: ${{ inputs.asset-name }} + api-url: ${{ inputs.api-url }} + artifact-name: ${{ needs.build-arm64.outputs.artifact-purl }} + web-ui: ${{ inputs.web-ui }} + fail-on-cvss: ${{ inputs.fail-on-cvss }} + fail-on-risk: ${{ inputs.fail-on-risk }} + image-suffix: ${{ inputs.artifact-name-suffix }}-arm64 + secrets: + devguard-token: ${{ secrets.devguard-token }} + + deploy-amd64: + if: ${{ inputs.should-deploy }} + needs: [build-amd64, container-scanning-amd64] + uses: l3montree-dev/devguard-action/.github/workflows/deploy.yml@main + permissions: + contents: read + packages: write + with: + asset-name: ${{ inputs.asset-name }} + api-url: ${{ inputs.api-url }} + image-suffix: ${{ inputs.artifact-name-suffix }}-amd64 + secrets: + devguard-token: ${{ secrets.devguard-token }} + + deploy-arm64: + if: ${{ inputs.should-deploy }} + needs: [build-arm64, container-scanning-arm64] + uses: l3montree-dev/devguard-action/.github/workflows/deploy.yml@main + permissions: + contents: read + packages: write + with: + asset-name: ${{ inputs.asset-name }} + api-url: ${{ inputs.api-url }} + image-suffix: ${{ inputs.artifact-name-suffix }}-arm64 + secrets: + devguard-token: ${{ secrets.devguard-token }} + + create-manifest: + if: ${{ inputs.should-deploy }} + needs: [build-amd64, build-arm64, deploy-amd64, deploy-arm64] + runs-on: ubuntu-latest + outputs: + manifest-tag: ${{ steps.manifest.outputs.manifest-tag }} + steps: + - uses: imjasonh/setup-crane@v0.1 + + - name: Log in to ghcr.io + run: crane auth login ghcr.io -u ${{ github.actor }} -p ${{ secrets.GITHUB_TOKEN }} + + - name: Download amd64 image-tag artifact + uses: actions/download-artifact@v4 + with: + name: image-tag${{ inputs.artifact-name-suffix }}-amd64 + path: amd64 + + - name: Download arm64 image-tag artifact + uses: actions/download-artifact@v4 + with: + name: image-tag${{ inputs.artifact-name-suffix }}-arm64 + path: arm64 + + - name: Create and push multi-arch manifest + id: manifest + run: | + AMD64_TAG=$(cat amd64/image-tag.txt) + ARM64_TAG=$(cat arm64/image-tag.txt) + + # Derive manifest tag by stripping the -amd64 arch suffix + MANIFEST_TAG="${AMD64_TAG%-amd64}" + MANIFEST_TAG_LATEST="${{ inputs.image-name }}:${{ github.ref_name }}-latest" + MANIFEST_TAG_LATEST=$(echo "$MANIFEST_TAG_LATEST" | tr '[:upper:]' '[:lower:]') + + crane index append \ + --tag "$MANIFEST_TAG" \ + -m "$AMD64_TAG" \ + -m "$ARM64_TAG" + + crane index append \ + --tag "$MANIFEST_TAG_LATEST" \ + -m "$AMD64_TAG" \ + -m "$ARM64_TAG" + + echo "manifest-tag=$MANIFEST_TAG" >> $GITHUB_OUTPUT + echo "MANIFEST_TAG=$MANIFEST_TAG" >> $GITHUB_ENV + echo "$MANIFEST_TAG" > manifest-tag.txt + + - name: Upload manifest-tag artifact + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 + with: + name: manifest-tag${{ inputs.artifact-name-suffix }} + path: manifest-tag.txt + + sign: + if: ${{ inputs.should-deploy }} + needs: [build-amd64, create-manifest] + uses: l3montree-dev/devguard-action/.github/workflows/sign.yml@main + permissions: + contents: read + packages: write + with: + asset-name: ${{ inputs.asset-name }} + api-url: ${{ inputs.api-url }} + artifact-name: ${{ needs.build-amd64.outputs.artifact-purl }} + image-suffix: ${{ inputs.artifact-name-suffix }}-amd64 + secrets: + devguard-token: ${{ secrets.devguard-token }} + + attest: + if: ${{ inputs.should-deploy }} + needs: [build-amd64, create-manifest] + uses: l3montree-dev/devguard-action/.github/workflows/attest.yml@main + permissions: + contents: read + packages: write + with: + asset-name: ${{ inputs.asset-name }} + api-url: ${{ inputs.api-url }} + artifact-name: ${{ needs.build-amd64.outputs.artifact-purl }} + image-suffix: ${{ inputs.artifact-name-suffix }}-amd64 + secrets: + devguard-token: ${{ secrets.devguard-token }} From 2d0c5d1cb065bdcea38cee5f6f6459055221319e Mon Sep 17 00:00:00 2001 From: Tim Bastin Date: Sun, 29 Mar 2026 21:03:05 +0200 Subject: [PATCH 05/30] using @nix --- .github/workflows/full-nix.yml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/full-nix.yml b/.github/workflows/full-nix.yml index a2949df..bbd73ea 100644 --- a/.github/workflows/full-nix.yml +++ b/.github/workflows/full-nix.yml @@ -99,7 +99,7 @@ permissions: jobs: build-amd64: - uses: l3montree-dev/devguard-action/.github/workflows/build-nix-image.yml@main + uses: l3montree-dev/devguard-action/.github/workflows/build-nix-image.yml@nix permissions: contents: read with: @@ -122,7 +122,7 @@ jobs: nix-cache-aws-secret-access-key: ${{ secrets.nix-cache-aws-secret-access-key }} build-arm64: - uses: l3montree-dev/devguard-action/.github/workflows/build-nix-image.yml@main + uses: l3montree-dev/devguard-action/.github/workflows/build-nix-image.yml@nix permissions: contents: read with: @@ -146,7 +146,7 @@ jobs: container-scanning-amd64: needs: build-amd64 - uses: l3montree-dev/devguard-action/.github/workflows/container-scanning.yml@main + uses: l3montree-dev/devguard-action/.github/workflows/container-scanning.yml@nix permissions: contents: read security-events: write @@ -163,7 +163,7 @@ jobs: container-scanning-arm64: needs: build-arm64 - uses: l3montree-dev/devguard-action/.github/workflows/container-scanning.yml@main + uses: l3montree-dev/devguard-action/.github/workflows/container-scanning.yml@nix permissions: contents: read security-events: write @@ -181,7 +181,7 @@ jobs: deploy-amd64: if: ${{ inputs.should-deploy }} needs: [build-amd64, container-scanning-amd64] - uses: l3montree-dev/devguard-action/.github/workflows/deploy.yml@main + uses: l3montree-dev/devguard-action/.github/workflows/deploy.yml@nix permissions: contents: read packages: write @@ -195,7 +195,7 @@ jobs: deploy-arm64: if: ${{ inputs.should-deploy }} needs: [build-arm64, container-scanning-arm64] - uses: l3montree-dev/devguard-action/.github/workflows/deploy.yml@main + uses: l3montree-dev/devguard-action/.github/workflows/deploy.yml@nix permissions: contents: read packages: write @@ -264,7 +264,7 @@ jobs: sign: if: ${{ inputs.should-deploy }} needs: [build-amd64, create-manifest] - uses: l3montree-dev/devguard-action/.github/workflows/sign.yml@main + uses: l3montree-dev/devguard-action/.github/workflows/sign.yml@nix permissions: contents: read packages: write @@ -279,7 +279,7 @@ jobs: attest: if: ${{ inputs.should-deploy }} needs: [build-amd64, create-manifest] - uses: l3montree-dev/devguard-action/.github/workflows/attest.yml@main + uses: l3montree-dev/devguard-action/.github/workflows/attest.yml@nix permissions: contents: read packages: write From 560ce5c7b3c274cb6afb6c71493414c9e02ef71a Mon Sep 17 00:00:00 2001 From: Tim Bastin Date: Sun, 29 Mar 2026 21:11:56 +0200 Subject: [PATCH 06/30] signing and attesting each image individually --- .github/workflows/full-nix.yml | 34 ++++++++++++++++++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) diff --git a/.github/workflows/full-nix.yml b/.github/workflows/full-nix.yml index bbd73ea..3af7c7c 100644 --- a/.github/workflows/full-nix.yml +++ b/.github/workflows/full-nix.yml @@ -261,7 +261,7 @@ jobs: name: manifest-tag${{ inputs.artifact-name-suffix }} path: manifest-tag.txt - sign: + sign-amd64: if: ${{ inputs.should-deploy }} needs: [build-amd64, create-manifest] uses: l3montree-dev/devguard-action/.github/workflows/sign.yml@nix @@ -276,7 +276,22 @@ jobs: secrets: devguard-token: ${{ secrets.devguard-token }} - attest: + sign-arm64: + if: ${{ inputs.should-deploy }} + needs: [build-arm64, create-manifest] + uses: l3montree-dev/devguard-action/.github/workflows/sign.yml@nix + permissions: + contents: read + packages: write + with: + asset-name: ${{ inputs.asset-name }} + api-url: ${{ inputs.api-url }} + artifact-name: ${{ needs.build-arm64.outputs.artifact-purl }} + image-suffix: ${{ inputs.artifact-name-suffix }}-arm64 + secrets: + devguard-token: ${{ secrets.devguard-token }} + + attest-amd64: if: ${{ inputs.should-deploy }} needs: [build-amd64, create-manifest] uses: l3montree-dev/devguard-action/.github/workflows/attest.yml@nix @@ -290,3 +305,18 @@ jobs: image-suffix: ${{ inputs.artifact-name-suffix }}-amd64 secrets: devguard-token: ${{ secrets.devguard-token }} + + attest-arm64: + if: ${{ inputs.should-deploy }} + needs: [build-arm64, create-manifest] + uses: l3montree-dev/devguard-action/.github/workflows/attest.yml@nix + permissions: + contents: read + packages: write + with: + asset-name: ${{ inputs.asset-name }} + api-url: ${{ inputs.api-url }} + artifact-name: ${{ needs.build-arm64.outputs.artifact-purl }} + image-suffix: ${{ inputs.artifact-name-suffix }}-arm64 + secrets: + devguard-token: ${{ secrets.devguard-token }} From b96700e4a0278129a56fdc766eb81e501fe9fa52 Mon Sep 17 00:00:00 2001 From: Tim Bastin Date: Tue, 31 Mar 2026 09:48:56 +0200 Subject: [PATCH 07/30] removes upstream version from build-nix-image and full-nix --- .github/workflows/build-nix-image.yml | 9 ++++----- .github/workflows/full-nix.yml | 19 ++++++++++++------- 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/.github/workflows/build-nix-image.yml b/.github/workflows/build-nix-image.yml index ec99d72..761f63b 100644 --- a/.github/workflows/build-nix-image.yml +++ b/.github/workflows/build-nix-image.yml @@ -55,11 +55,11 @@ on: required: false type: string default: '' - upstream-version: - description: 'Upstream version passed to devguard-scanner generate-tag (matches the nix package version segment, e.g. 0)' + runner: + description: 'GitHub Actions runner label to use (e.g. ubuntu-latest, ubuntu-24.04-arm)' required: false type: string - default: '0' + default: 'ubuntu-latest' secrets: devguard-token: required: false @@ -82,7 +82,7 @@ on: jobs: build: - runs-on: ubuntu-latest + runs-on: ${{ inputs.runner }} outputs: image-tag: ${{ steps.set-image-tag.outputs.image_tag }} image-digest: ${{ steps.get-digest.outputs.digest }} @@ -154,7 +154,6 @@ jobs: devguard-scanner generate-tag --imagePath='${{ inputs.image-name }}' --ref='${{ github.ref_name }}' - --upstreamVersion='${{ inputs.upstream-version }}' --architecture='${{ inputs.arch }}' >> image-tag-env.txt IMAGE_TAG=$(grep '^IMAGE_TAG=' image-tag-env.txt | cut -d= -f2-) diff --git a/.github/workflows/full-nix.yml b/.github/workflows/full-nix.yml index 3af7c7c..9e2a49e 100644 --- a/.github/workflows/full-nix.yml +++ b/.github/workflows/full-nix.yml @@ -15,11 +15,6 @@ on: description: 'Full OCI image name without tag (e.g. ghcr.io/l3montree-dev/devguard)' required: true type: string - upstream-version: - description: 'Upstream version segment used by generate-tag (matches the nix package version, e.g. 0)' - required: false - type: string - default: '0' artifact-name-suffix: description: 'Suffix appended to artifact names to avoid conflicts when building multiple images in the same workflow' required: false @@ -54,6 +49,16 @@ on: required: false type: boolean default: true + runner-amd64: + description: 'GitHub Actions runner label for the amd64 build' + required: false + type: string + default: 'ubuntu-latest' + runner-arm64: + description: 'GitHub Actions runner label for the arm64 build' + required: false + type: string + default: 'ubuntu-24.04-arm' nix-cache-substituter: description: 'Nix binary cache substituter URL' required: false @@ -109,7 +114,7 @@ jobs: asset-name: ${{ inputs.asset-name }} api-url: ${{ inputs.api-url }} arch: amd64 - upstream-version: ${{ inputs.upstream-version }} + runner: ${{ inputs.runner-amd64 }} nix-cache-substituter: ${{ inputs.nix-cache-substituter }} nix-cache-public-key: ${{ inputs.nix-cache-public-key }} nix-cache-s3-endpoint: ${{ inputs.nix-cache-s3-endpoint }} @@ -132,7 +137,7 @@ jobs: asset-name: ${{ inputs.asset-name }} api-url: ${{ inputs.api-url }} arch: arm64 - upstream-version: ${{ inputs.upstream-version }} + runner: ${{ inputs.runner-arm64 }} nix-cache-substituter: ${{ inputs.nix-cache-substituter }} nix-cache-public-key: ${{ inputs.nix-cache-public-key }} nix-cache-s3-endpoint: ${{ inputs.nix-cache-s3-endpoint }} From 23e054eed0fdd4b58ab45c94592e95438f2b1324 Mon Sep 17 00:00:00 2001 From: Tim Bastin Date: Tue, 31 Mar 2026 10:14:14 +0200 Subject: [PATCH 08/30] replaces crane with nixpkgs#crane --- .github/workflows/build-nix-image.yml | 3 ++- .github/workflows/full-nix.yml | 8 +++++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-nix-image.yml b/.github/workflows/build-nix-image.yml index 761f63b..de617f0 100644 --- a/.github/workflows/build-nix-image.yml +++ b/.github/workflows/build-nix-image.yml @@ -106,7 +106,8 @@ jobs: ${{ inputs.nix-cache-substituter != '' && format('substituters = https://cache.nixos.org {0}', inputs.nix-cache-substituter) || '' }} ${{ inputs.nix-cache-public-key != '' && format('trusted-public-keys = cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY= {0}', inputs.nix-cache-public-key) || '' }} - - uses: imjasonh/setup-crane@v0.1 + - name: Install crane + run: nix profile install nixpkgs#crane - name: Write Nix cache secret key if: ${{ inputs.nix-cache-s3-endpoint != '' }} diff --git a/.github/workflows/full-nix.yml b/.github/workflows/full-nix.yml index 9e2a49e..a1a4f95 100644 --- a/.github/workflows/full-nix.yml +++ b/.github/workflows/full-nix.yml @@ -218,7 +218,13 @@ jobs: outputs: manifest-tag: ${{ steps.manifest.outputs.manifest-tag }} steps: - - uses: imjasonh/setup-crane@v0.1 + - uses: cachix/install-nix-action@v31 + with: + extra_nix_config: | + experimental-features = nix-command flakes + + - name: Install crane + run: nix profile install nixpkgs#crane - name: Log in to ghcr.io run: crane auth login ghcr.io -u ${{ github.actor }} -p ${{ secrets.GITHUB_TOKEN }} From bc99d40498be734b6a5d6521c20fd3d6ef105716 Mon Sep 17 00:00:00 2001 From: Tim Bastin Date: Tue, 31 Mar 2026 10:37:44 +0200 Subject: [PATCH 09/30] using nixpkgs instead of setup routine --- .github/workflows/build-nix-image.yml | 42 +++++++++++---------------- 1 file changed, 17 insertions(+), 25 deletions(-) diff --git a/.github/workflows/build-nix-image.yml b/.github/workflows/build-nix-image.yml index de617f0..1101d3e 100644 --- a/.github/workflows/build-nix-image.yml +++ b/.github/workflows/build-nix-image.yml @@ -93,12 +93,6 @@ jobs: fetch-depth: 0 # needed for flake.nix to resolve self.shortRev persist-credentials: false - - name: In-Toto Provenance record start - uses: docker://ghcr.io/l3montree-dev/devguard/scanner:v1.0.0 - with: - args: devguard-scanner intoto start --step=build --token=${{ secrets.devguard-token }} --apiUrl=${{ inputs.api-url }} --assetName=${{ inputs.asset-name }} --supplyChainId=${{ github.sha }} - continue-on-error: true - - uses: cachix/install-nix-action@v31 with: extra_nix_config: | @@ -106,8 +100,12 @@ jobs: ${{ inputs.nix-cache-substituter != '' && format('substituters = https://cache.nixos.org {0}', inputs.nix-cache-substituter) || '' }} ${{ inputs.nix-cache-public-key != '' && format('trusted-public-keys = cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY= {0}', inputs.nix-cache-public-key) || '' }} - - name: Install crane - run: nix profile install nixpkgs#crane + - name: Install crane and devguard-scanner + run: nix profile install nixpkgs#crane .#devguardScanner + + - name: In-Toto Provenance record start + run: devguard-scanner intoto start --step=build --token=${{ secrets.devguard-token }} --apiUrl=${{ inputs.api-url }} --assetName=${{ inputs.asset-name }} --supplyChainId=${{ github.sha }} + continue-on-error: true - name: Write Nix cache secret key if: ${{ inputs.nix-cache-s3-endpoint != '' }} @@ -148,20 +146,16 @@ jobs: - name: Set image tag id: set-image-tag - uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main-latest - with: - args: > - sh -c " - devguard-scanner generate-tag - --imagePath='${{ inputs.image-name }}' - --ref='${{ github.ref_name }}' - --architecture='${{ inputs.arch }}' - >> image-tag-env.txt - IMAGE_TAG=$(grep '^IMAGE_TAG=' image-tag-env.txt | cut -d= -f2-) - echo \"\$IMAGE_TAG\" > image-tag.txt - echo \"image_tag=\$IMAGE_TAG\" >> \"\$GITHUB_OUTPUT\" - echo \"IMAGE_TAG=\$IMAGE_TAG\" >> \"\$GITHUB_ENV\" - " + run: | + devguard-scanner generate-tag \ + --imagePath='${{ inputs.image-name }}' \ + --ref='${{ github.ref_name }}' \ + --architecture='${{ inputs.arch }}' \ + >> image-tag-env.txt + IMAGE_TAG=$(grep '^IMAGE_TAG=' image-tag-env.txt | cut -d= -f2-) + echo "$IMAGE_TAG" > image-tag.txt + echo "image_tag=$IMAGE_TAG" >> "$GITHUB_OUTPUT" + echo "IMAGE_TAG=$IMAGE_TAG" >> "$GITHUB_ENV" - name: Upload image-tag artifact uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 - https://github.com/actions/upload-artifact/releases/tag/v4.6.2 @@ -199,9 +193,7 @@ jobs: path: artifact-purl-safe.txt - name: In-Toto Provenance record stop - uses: docker://ghcr.io/l3montree-dev/devguard/scanner:v1.0.0 - with: - args: devguard-scanner intoto stop --step=build --products=image-digest.txt --products=image-tag.txt --token=${{ secrets.devguard-token }} --apiUrl=${{ inputs.api-url }} --assetName=${{ inputs.asset-name }} --supplyChainId=${{ github.sha }} --generateSlsaProvenance + run: devguard-scanner intoto stop --step=build --products=image-digest.txt --products=image-tag.txt --token=${{ secrets.devguard-token }} --apiUrl=${{ inputs.api-url }} --assetName=${{ inputs.asset-name }} --supplyChainId=${{ github.sha }} --generateSlsaProvenance continue-on-error: true - name: Upload SLSA Provenance From ca409c35acf29e50568350b72f78f6b3c7679957 Mon Sep 17 00:00:00 2001 From: Tim Bastin Date: Tue, 31 Mar 2026 11:06:02 +0200 Subject: [PATCH 10/30] removes latest push --- .github/workflows/deploy.yml | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 80554d4..9e76230 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -27,6 +27,11 @@ on: required: false default: 'container' description: "The name of the artifact you are building. This is useful when a single pipeline builds more than a single artifact like a container with a shell inside and one without. If you build a single artifact - leave it empty." + artifact-suffix: + type: string + required: false + default: '' + description: "Suffix used to look up build artifacts by name. Defaults to image-suffix when not set." secrets: devguard-token: @@ -80,17 +85,3 @@ jobs: run: crane push image.tar $(cat image-tag.txt) if: inputs.image-already-in-registry == false - - name: Push oci image to GitHub image Registry with latest - run: | - branch=${GITHUB_REF##*/} - - if [ "${IMAGE_SUFFIX}" != "" ]; then - name="ghcr.io/${{ github.repository }}/${IMAGE_SUFFIX}:$branch-latest" - else - name="ghcr.io/${{ github.repository }}:$branch-latest" - fi - - name=$(echo "$name" | tr '[:upper:]' '[:lower:]') - crane copy $(cat image-tag.txt) $name - env: - IMAGE_SUFFIX: ${{ inputs.image-suffix }} \ No newline at end of file From 1ed7bd623d9f2f96b9f362b45eb5d3f4aba17d45 Mon Sep 17 00:00:00 2001 From: Tim Bastin Date: Tue, 31 Mar 2026 15:09:47 +0200 Subject: [PATCH 11/30] removes latest manifest push in full-nix --- .github/workflows/full-nix.yml | 7 ------- 1 file changed, 7 deletions(-) diff --git a/.github/workflows/full-nix.yml b/.github/workflows/full-nix.yml index a1a4f95..9ffdfce 100644 --- a/.github/workflows/full-nix.yml +++ b/.github/workflows/full-nix.yml @@ -249,19 +249,12 @@ jobs: # Derive manifest tag by stripping the -amd64 arch suffix MANIFEST_TAG="${AMD64_TAG%-amd64}" - MANIFEST_TAG_LATEST="${{ inputs.image-name }}:${{ github.ref_name }}-latest" - MANIFEST_TAG_LATEST=$(echo "$MANIFEST_TAG_LATEST" | tr '[:upper:]' '[:lower:]') crane index append \ --tag "$MANIFEST_TAG" \ -m "$AMD64_TAG" \ -m "$ARM64_TAG" - crane index append \ - --tag "$MANIFEST_TAG_LATEST" \ - -m "$AMD64_TAG" \ - -m "$ARM64_TAG" - echo "manifest-tag=$MANIFEST_TAG" >> $GITHUB_OUTPUT echo "MANIFEST_TAG=$MANIFEST_TAG" >> $GITHUB_ENV echo "$MANIFEST_TAG" > manifest-tag.txt From d83be949f0235af19a4e1899ac4f957dbe31cfcb Mon Sep 17 00:00:00 2001 From: Tim Bastin Date: Wed, 1 Apr 2026 12:00:11 +0200 Subject: [PATCH 12/30] using new nix based scanner --- .github/workflows/attest.yml | 14 +++++++------- .github/workflows/build-image.yml | 4 ++-- .github/workflows/code-risk-identification.yml | 2 +- .github/workflows/container-scanning.yml | 2 +- .../workflows/dependency-risk-identification.yml | 2 +- .github/workflows/deploy.yml | 2 +- .github/workflows/iac.yml | 2 +- .github/workflows/secret-scanning.yml | 2 +- .github/workflows/sign.yml | 2 +- .../workflows/software-composition-analysis.yml | 2 +- .../static-application-security-testing.yml | 2 +- 11 files changed, 18 insertions(+), 18 deletions(-) diff --git a/.github/workflows/attest.yml b/.github/workflows/attest.yml index 06e5369..d6a68c5 100644 --- a/.github/workflows/attest.yml +++ b/.github/workflows/attest.yml @@ -86,7 +86,7 @@ jobs: fi - name: Get SBOM - uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main-latest + uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main with: args: > sh -c " @@ -95,7 +95,7 @@ jobs: env: API_ARTIFACT_NAME: ${{ env.API_ARTIFACT_NAME }} - name: Get VeX - uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main-latest + uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main with: args: > sh -c " @@ -104,14 +104,14 @@ jobs: env: API_ARTIFACT_NAME: ${{ env.API_ARTIFACT_NAME }} - name: Get SAST-Results - uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main-latest + uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main with: args: > sh -c " slug=$(devguard-scanner slug ${{ github.ref_name }}) && devguard-scanner curl '${{ inputs.api-url }}/api/v1/organizations/${{ inputs.asset-name }}/refs/'$slug'/sarif.json' --token='${{ secrets.devguard-token }}' > sarif.json " - name: Attest SBOM - uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main-latest + uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main with: args: > sh -c " @@ -124,7 +124,7 @@ jobs: env: ARTIFACT_NAME: ${{ env.ARTIFACT_NAME }} - name: Attest VeX - uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main-latest + uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main with: args: > sh -c " @@ -137,7 +137,7 @@ jobs: env: ARTIFACT_NAME: ${{ env.ARTIFACT_NAME }} - name: Attest SAST-Results - uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main-latest + uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main with: args: > sh -c " @@ -155,7 +155,7 @@ jobs: with: name: build${{ inputs.image-suffix }}.provenance.json - name: Attest build-provenance.json - uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main-latest + uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main continue-on-error: true with: args: > diff --git a/.github/workflows/build-image.yml b/.github/workflows/build-image.yml index 488fe55..31f0815 100644 --- a/.github/workflows/build-image.yml +++ b/.github/workflows/build-image.yml @@ -63,7 +63,7 @@ jobs: persist-credentials: false - name: In-Toto Provenance record start id: in-toto-start - uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main-latest + uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main with: args: devguard-scanner intoto start --step=build --token=${{ secrets.devguard-token }} --apiUrl=${{ inputs.api-url }} --assetName=${{ inputs.asset-name }} --supplyChainId=${{ github.sha }} continue-on-error: true @@ -192,7 +192,7 @@ jobs: path: image-tag.txt - name: In-Toto Provenance record stop - uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main-latest + uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main with: args: devguard-scanner intoto stop --step=build --products=image-digest.txt --products=image-tag.txt --token=${{ secrets.devguard-token }} --apiUrl=${{ inputs.api-url }} --assetName=${{ inputs.asset-name }} --supplyChainId=${{ github.sha }} --generateSlsaProvenance continue-on-error: true diff --git a/.github/workflows/code-risk-identification.yml b/.github/workflows/code-risk-identification.yml index 8e1f663..f8b3c73 100644 --- a/.github/workflows/code-risk-identification.yml +++ b/.github/workflows/code-risk-identification.yml @@ -46,6 +46,6 @@ jobs: if: ${{ inputs.sarif-artifact-name != '' }} - name: DevGuard Code Risk Identification - uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main-latest + uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main with: args: devguard-scanner sarif ${{ inputs.sarif-file }} --assetName=${{ inputs.asset-name }} --apiUrl=${{ inputs.api-url }} --token="${{ secrets.devguard-token }}" --defaultRef=${{ github.event.repository.default_branch }} --isTag=${{ github.ref_type == 'tag' }} --ref=${{ github.ref_name }} --webUI=${{ inputs.web-ui }} \ No newline at end of file diff --git a/.github/workflows/container-scanning.yml b/.github/workflows/container-scanning.yml index e74352f..edd5f55 100644 --- a/.github/workflows/container-scanning.yml +++ b/.github/workflows/container-scanning.yml @@ -97,7 +97,7 @@ jobs: if: inputs.fetch-image-from-registry == true - name: DevGuard Container-Scanning - uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main-latest + uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main with: args: devguard-scanner container-scanning --assetName=${{ inputs.asset-name }} --apiUrl=${{ inputs.api-url }} --token="${{ secrets.devguard-token }}" --path=${{ inputs.image-path }} --defaultRef=${{ github.event.repository.default_branch }} --isTag=${{ github.ref_type == 'tag' }} --ref=${{ github.ref_name }} --failOnRisk=${{ inputs.fail-on-risk }} --failOnCVSS=${{ inputs.fail-on-cvss }} --artifactName=${{ env.ARTIFACT_NAME }} --webUI=${{ inputs.web-ui }} env: diff --git a/.github/workflows/dependency-risk-identification.yml b/.github/workflows/dependency-risk-identification.yml index 3ede3e2..19d4b8d 100644 --- a/.github/workflows/dependency-risk-identification.yml +++ b/.github/workflows/dependency-risk-identification.yml @@ -63,6 +63,6 @@ jobs: if: ${{ inputs.sbom-artifact-name != '' }} - name: DevGuard Dependency Risk Identification - uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main-latest + uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main with: args: devguard-scanner sbom ${{ inputs.sbom-file }} --assetName=${{ inputs.asset-name }} --apiUrl=${{ inputs.api-url }} --token="${{ secrets.devguard-token }}" --defaultRef=${{ github.event.repository.default_branch }} --isTag=${{ github.ref_type == 'tag' }} --ref=${{ github.ref_name }} --artifactName=${{ inputs.artifact-name }} --webUI=${{ inputs.web-ui }} --failOnRisk=${{ inputs.fail-on-risk }} --failOnCVSS=${{ inputs.fail-on-cvss }} \ No newline at end of file diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 9e76230..5fa8c2d 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -73,7 +73,7 @@ jobs: run: echo "DIGEST=$(cat image-digest.txt)" >> $GITHUB_ENV - name: In-Toto Provenance run - uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main-latest + uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main with: args: devguard-scanner intoto run --step=deploy --materials=image-tag.txt --products=image-tag.txt --products=image-digest.txt --token=${{ secrets.devguard-token }} --apiUrl=${{ inputs.api-url }} --assetName=${{ inputs.asset-name }} --supplyChainId=${{ github.sha }} --supplyChainOutputDigest="${{ env.DIGEST }}" continue-on-error: true diff --git a/.github/workflows/iac.yml b/.github/workflows/iac.yml index 230e1c8..50fed3b 100644 --- a/.github/workflows/iac.yml +++ b/.github/workflows/iac.yml @@ -39,7 +39,7 @@ jobs: persist-credentials: false fetch-depth: 0 - name: DevGuard Infrastructure as Code - uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main-latest + uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main continue-on-error: ${{ inputs.continue-on-open-code-risk }} with: args: devguard-scanner iac --assetName=${{ inputs.asset-name }} --apiUrl=${{ inputs.api-url }} --token="${{ secrets.devguard-token }}" --path=${{ inputs.path }} --defaultRef=${{ github.event.repository.default_branch }} --isTag=${{ github.ref_type == 'tag' }} --ref=${{ github.ref_name }} --webUI=${{ inputs.web-ui }} diff --git a/.github/workflows/secret-scanning.yml b/.github/workflows/secret-scanning.yml index 2951ba2..54fd76f 100644 --- a/.github/workflows/secret-scanning.yml +++ b/.github/workflows/secret-scanning.yml @@ -40,7 +40,7 @@ jobs: persist-credentials: false uses: actions/checkout@v4 - name: DevGuard Secret-Scanning - uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main-latest + uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main continue-on-error: ${{ inputs.continue-on-open-code-risk }} with: args: devguard-scanner secret-scanning --assetName=${{ inputs.asset-name }} --apiUrl=${{ inputs.api-url }} --token="${{ secrets.devguard-token }}" --path=${{ inputs.path }} --defaultRef=${{ github.event.repository.default_branch }} --isTag=${{ github.ref_type == 'tag' }} --ref=${{ github.ref_name }} --webUI=${{ inputs.web-ui }} \ No newline at end of file diff --git a/.github/workflows/sign.yml b/.github/workflows/sign.yml index eeea5b7..499bd72 100644 --- a/.github/workflows/sign.yml +++ b/.github/workflows/sign.yml @@ -58,6 +58,6 @@ jobs: run: echo "IMAGE_TAG_AND_DIGEST=$(cat image-tag.txt)@$(cat image-digest.txt)" >> $GITHUB_ENV - name: DevGuard Image-Signing - uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main-latest + uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main with: args: devguard-scanner sign -u ${{ github.actor }} -r ghcr.io -p ${{ secrets.GITHUB_TOKEN }} --token="${{ secrets.devguard-token }}" ${{ env.IMAGE_TAG_AND_DIGEST }} --apiUrl=${{ inputs.api-url }} --assetName=${{ inputs.asset-name }} \ No newline at end of file diff --git a/.github/workflows/software-composition-analysis.yml b/.github/workflows/software-composition-analysis.yml index bce5448..97f27d4 100644 --- a/.github/workflows/software-composition-analysis.yml +++ b/.github/workflows/software-composition-analysis.yml @@ -47,7 +47,7 @@ jobs: persist-credentials: true # we need the credentials to be able to use the devguard-scanner in private repositories uses: actions/checkout@v4 # Check out the repository content to the runner - name: DevGuard SCA - uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main-latest + uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main with: args: devguard-scanner sca --assetName=${{ inputs.asset-name }} --apiUrl=${{ inputs.api-url }} --token="${{ secrets.devguard-token }}" --path=${{ diff --git a/.github/workflows/static-application-security-testing.yml b/.github/workflows/static-application-security-testing.yml index c5f701c..c0a6987 100644 --- a/.github/workflows/static-application-security-testing.yml +++ b/.github/workflows/static-application-security-testing.yml @@ -39,7 +39,7 @@ jobs: fetch-depth: 0 persist-credentials: false - name: DevGuard Static application security testing - uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main-latest + uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main continue-on-error: ${{ inputs.continue-on-open-code-risk }} with: args: devguard-scanner sast --assetName=${{ inputs.asset-name }} --apiUrl=${{ inputs.api-url }} --token="${{ secrets.devguard-token }}" --path=${{ inputs.path }} --defaultRef=${{ github.event.repository.default_branch }} --isTag=${{ github.ref_type == 'tag' }} --ref=${{ github.ref_name }} --webUI=${{ inputs.web-ui }} From 0244b83cd696a536dd36d0e9d518da482e3b12f4 Mon Sep 17 00:00:00 2001 From: Tim Bastin Date: Wed, 1 Apr 2026 15:53:21 +0200 Subject: [PATCH 13/30] using main-latest scanner --- .github/workflows/attest.yml | 14 +++++++------- .github/workflows/build-image.yml | 4 ++-- .github/workflows/code-risk-identification.yml | 2 +- .github/workflows/container-scanning.yml | 2 +- .../workflows/dependency-risk-identification.yml | 2 +- .github/workflows/deploy.yml | 2 +- .github/workflows/iac.yml | 2 +- .github/workflows/secret-scanning.yml | 2 +- .github/workflows/sign.yml | 2 +- .../workflows/software-composition-analysis.yml | 2 +- .../static-application-security-testing.yml | 2 +- 11 files changed, 18 insertions(+), 18 deletions(-) diff --git a/.github/workflows/attest.yml b/.github/workflows/attest.yml index d6a68c5..06e5369 100644 --- a/.github/workflows/attest.yml +++ b/.github/workflows/attest.yml @@ -86,7 +86,7 @@ jobs: fi - name: Get SBOM - uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main + uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main-latest with: args: > sh -c " @@ -95,7 +95,7 @@ jobs: env: API_ARTIFACT_NAME: ${{ env.API_ARTIFACT_NAME }} - name: Get VeX - uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main + uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main-latest with: args: > sh -c " @@ -104,14 +104,14 @@ jobs: env: API_ARTIFACT_NAME: ${{ env.API_ARTIFACT_NAME }} - name: Get SAST-Results - uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main + uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main-latest with: args: > sh -c " slug=$(devguard-scanner slug ${{ github.ref_name }}) && devguard-scanner curl '${{ inputs.api-url }}/api/v1/organizations/${{ inputs.asset-name }}/refs/'$slug'/sarif.json' --token='${{ secrets.devguard-token }}' > sarif.json " - name: Attest SBOM - uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main + uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main-latest with: args: > sh -c " @@ -124,7 +124,7 @@ jobs: env: ARTIFACT_NAME: ${{ env.ARTIFACT_NAME }} - name: Attest VeX - uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main + uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main-latest with: args: > sh -c " @@ -137,7 +137,7 @@ jobs: env: ARTIFACT_NAME: ${{ env.ARTIFACT_NAME }} - name: Attest SAST-Results - uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main + uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main-latest with: args: > sh -c " @@ -155,7 +155,7 @@ jobs: with: name: build${{ inputs.image-suffix }}.provenance.json - name: Attest build-provenance.json - uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main + uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main-latest continue-on-error: true with: args: > diff --git a/.github/workflows/build-image.yml b/.github/workflows/build-image.yml index 31f0815..488fe55 100644 --- a/.github/workflows/build-image.yml +++ b/.github/workflows/build-image.yml @@ -63,7 +63,7 @@ jobs: persist-credentials: false - name: In-Toto Provenance record start id: in-toto-start - uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main + uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main-latest with: args: devguard-scanner intoto start --step=build --token=${{ secrets.devguard-token }} --apiUrl=${{ inputs.api-url }} --assetName=${{ inputs.asset-name }} --supplyChainId=${{ github.sha }} continue-on-error: true @@ -192,7 +192,7 @@ jobs: path: image-tag.txt - name: In-Toto Provenance record stop - uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main + uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main-latest with: args: devguard-scanner intoto stop --step=build --products=image-digest.txt --products=image-tag.txt --token=${{ secrets.devguard-token }} --apiUrl=${{ inputs.api-url }} --assetName=${{ inputs.asset-name }} --supplyChainId=${{ github.sha }} --generateSlsaProvenance continue-on-error: true diff --git a/.github/workflows/code-risk-identification.yml b/.github/workflows/code-risk-identification.yml index f8b3c73..8e1f663 100644 --- a/.github/workflows/code-risk-identification.yml +++ b/.github/workflows/code-risk-identification.yml @@ -46,6 +46,6 @@ jobs: if: ${{ inputs.sarif-artifact-name != '' }} - name: DevGuard Code Risk Identification - uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main + uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main-latest with: args: devguard-scanner sarif ${{ inputs.sarif-file }} --assetName=${{ inputs.asset-name }} --apiUrl=${{ inputs.api-url }} --token="${{ secrets.devguard-token }}" --defaultRef=${{ github.event.repository.default_branch }} --isTag=${{ github.ref_type == 'tag' }} --ref=${{ github.ref_name }} --webUI=${{ inputs.web-ui }} \ No newline at end of file diff --git a/.github/workflows/container-scanning.yml b/.github/workflows/container-scanning.yml index edd5f55..e74352f 100644 --- a/.github/workflows/container-scanning.yml +++ b/.github/workflows/container-scanning.yml @@ -97,7 +97,7 @@ jobs: if: inputs.fetch-image-from-registry == true - name: DevGuard Container-Scanning - uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main + uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main-latest with: args: devguard-scanner container-scanning --assetName=${{ inputs.asset-name }} --apiUrl=${{ inputs.api-url }} --token="${{ secrets.devguard-token }}" --path=${{ inputs.image-path }} --defaultRef=${{ github.event.repository.default_branch }} --isTag=${{ github.ref_type == 'tag' }} --ref=${{ github.ref_name }} --failOnRisk=${{ inputs.fail-on-risk }} --failOnCVSS=${{ inputs.fail-on-cvss }} --artifactName=${{ env.ARTIFACT_NAME }} --webUI=${{ inputs.web-ui }} env: diff --git a/.github/workflows/dependency-risk-identification.yml b/.github/workflows/dependency-risk-identification.yml index 19d4b8d..3ede3e2 100644 --- a/.github/workflows/dependency-risk-identification.yml +++ b/.github/workflows/dependency-risk-identification.yml @@ -63,6 +63,6 @@ jobs: if: ${{ inputs.sbom-artifact-name != '' }} - name: DevGuard Dependency Risk Identification - uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main + uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main-latest with: args: devguard-scanner sbom ${{ inputs.sbom-file }} --assetName=${{ inputs.asset-name }} --apiUrl=${{ inputs.api-url }} --token="${{ secrets.devguard-token }}" --defaultRef=${{ github.event.repository.default_branch }} --isTag=${{ github.ref_type == 'tag' }} --ref=${{ github.ref_name }} --artifactName=${{ inputs.artifact-name }} --webUI=${{ inputs.web-ui }} --failOnRisk=${{ inputs.fail-on-risk }} --failOnCVSS=${{ inputs.fail-on-cvss }} \ No newline at end of file diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 5fa8c2d..9e76230 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -73,7 +73,7 @@ jobs: run: echo "DIGEST=$(cat image-digest.txt)" >> $GITHUB_ENV - name: In-Toto Provenance run - uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main + uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main-latest with: args: devguard-scanner intoto run --step=deploy --materials=image-tag.txt --products=image-tag.txt --products=image-digest.txt --token=${{ secrets.devguard-token }} --apiUrl=${{ inputs.api-url }} --assetName=${{ inputs.asset-name }} --supplyChainId=${{ github.sha }} --supplyChainOutputDigest="${{ env.DIGEST }}" continue-on-error: true diff --git a/.github/workflows/iac.yml b/.github/workflows/iac.yml index 50fed3b..230e1c8 100644 --- a/.github/workflows/iac.yml +++ b/.github/workflows/iac.yml @@ -39,7 +39,7 @@ jobs: persist-credentials: false fetch-depth: 0 - name: DevGuard Infrastructure as Code - uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main + uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main-latest continue-on-error: ${{ inputs.continue-on-open-code-risk }} with: args: devguard-scanner iac --assetName=${{ inputs.asset-name }} --apiUrl=${{ inputs.api-url }} --token="${{ secrets.devguard-token }}" --path=${{ inputs.path }} --defaultRef=${{ github.event.repository.default_branch }} --isTag=${{ github.ref_type == 'tag' }} --ref=${{ github.ref_name }} --webUI=${{ inputs.web-ui }} diff --git a/.github/workflows/secret-scanning.yml b/.github/workflows/secret-scanning.yml index 54fd76f..2951ba2 100644 --- a/.github/workflows/secret-scanning.yml +++ b/.github/workflows/secret-scanning.yml @@ -40,7 +40,7 @@ jobs: persist-credentials: false uses: actions/checkout@v4 - name: DevGuard Secret-Scanning - uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main + uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main-latest continue-on-error: ${{ inputs.continue-on-open-code-risk }} with: args: devguard-scanner secret-scanning --assetName=${{ inputs.asset-name }} --apiUrl=${{ inputs.api-url }} --token="${{ secrets.devguard-token }}" --path=${{ inputs.path }} --defaultRef=${{ github.event.repository.default_branch }} --isTag=${{ github.ref_type == 'tag' }} --ref=${{ github.ref_name }} --webUI=${{ inputs.web-ui }} \ No newline at end of file diff --git a/.github/workflows/sign.yml b/.github/workflows/sign.yml index 499bd72..eeea5b7 100644 --- a/.github/workflows/sign.yml +++ b/.github/workflows/sign.yml @@ -58,6 +58,6 @@ jobs: run: echo "IMAGE_TAG_AND_DIGEST=$(cat image-tag.txt)@$(cat image-digest.txt)" >> $GITHUB_ENV - name: DevGuard Image-Signing - uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main + uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main-latest with: args: devguard-scanner sign -u ${{ github.actor }} -r ghcr.io -p ${{ secrets.GITHUB_TOKEN }} --token="${{ secrets.devguard-token }}" ${{ env.IMAGE_TAG_AND_DIGEST }} --apiUrl=${{ inputs.api-url }} --assetName=${{ inputs.asset-name }} \ No newline at end of file diff --git a/.github/workflows/software-composition-analysis.yml b/.github/workflows/software-composition-analysis.yml index 97f27d4..bce5448 100644 --- a/.github/workflows/software-composition-analysis.yml +++ b/.github/workflows/software-composition-analysis.yml @@ -47,7 +47,7 @@ jobs: persist-credentials: true # we need the credentials to be able to use the devguard-scanner in private repositories uses: actions/checkout@v4 # Check out the repository content to the runner - name: DevGuard SCA - uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main + uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main-latest with: args: devguard-scanner sca --assetName=${{ inputs.asset-name }} --apiUrl=${{ inputs.api-url }} --token="${{ secrets.devguard-token }}" --path=${{ diff --git a/.github/workflows/static-application-security-testing.yml b/.github/workflows/static-application-security-testing.yml index c0a6987..c5f701c 100644 --- a/.github/workflows/static-application-security-testing.yml +++ b/.github/workflows/static-application-security-testing.yml @@ -39,7 +39,7 @@ jobs: fetch-depth: 0 persist-credentials: false - name: DevGuard Static application security testing - uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main + uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main-latest continue-on-error: ${{ inputs.continue-on-open-code-risk }} with: args: devguard-scanner sast --assetName=${{ inputs.asset-name }} --apiUrl=${{ inputs.api-url }} --token="${{ secrets.devguard-token }}" --path=${{ inputs.path }} --defaultRef=${{ github.event.repository.default_branch }} --isTag=${{ github.ref_type == 'tag' }} --ref=${{ github.ref_name }} --webUI=${{ inputs.web-ui }} From 20fa726df6c36a2f44768e060a75db818ffa96d6 Mon Sep 17 00:00:00 2001 From: Tim Bastin Date: Wed, 1 Apr 2026 16:34:31 +0200 Subject: [PATCH 14/30] using main scanner --- .github/workflows/attest.yml | 14 +++++++------- .github/workflows/build-image.yml | 4 ++-- .github/workflows/code-risk-identification.yml | 2 +- .github/workflows/container-scanning.yml | 2 +- .../workflows/dependency-risk-identification.yml | 2 +- .github/workflows/deploy.yml | 2 +- .github/workflows/iac.yml | 2 +- .github/workflows/secret-scanning.yml | 2 +- .github/workflows/sign.yml | 2 +- .../workflows/software-composition-analysis.yml | 2 +- .../static-application-security-testing.yml | 2 +- 11 files changed, 18 insertions(+), 18 deletions(-) diff --git a/.github/workflows/attest.yml b/.github/workflows/attest.yml index 06e5369..d6a68c5 100644 --- a/.github/workflows/attest.yml +++ b/.github/workflows/attest.yml @@ -86,7 +86,7 @@ jobs: fi - name: Get SBOM - uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main-latest + uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main with: args: > sh -c " @@ -95,7 +95,7 @@ jobs: env: API_ARTIFACT_NAME: ${{ env.API_ARTIFACT_NAME }} - name: Get VeX - uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main-latest + uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main with: args: > sh -c " @@ -104,14 +104,14 @@ jobs: env: API_ARTIFACT_NAME: ${{ env.API_ARTIFACT_NAME }} - name: Get SAST-Results - uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main-latest + uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main with: args: > sh -c " slug=$(devguard-scanner slug ${{ github.ref_name }}) && devguard-scanner curl '${{ inputs.api-url }}/api/v1/organizations/${{ inputs.asset-name }}/refs/'$slug'/sarif.json' --token='${{ secrets.devguard-token }}' > sarif.json " - name: Attest SBOM - uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main-latest + uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main with: args: > sh -c " @@ -124,7 +124,7 @@ jobs: env: ARTIFACT_NAME: ${{ env.ARTIFACT_NAME }} - name: Attest VeX - uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main-latest + uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main with: args: > sh -c " @@ -137,7 +137,7 @@ jobs: env: ARTIFACT_NAME: ${{ env.ARTIFACT_NAME }} - name: Attest SAST-Results - uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main-latest + uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main with: args: > sh -c " @@ -155,7 +155,7 @@ jobs: with: name: build${{ inputs.image-suffix }}.provenance.json - name: Attest build-provenance.json - uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main-latest + uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main continue-on-error: true with: args: > diff --git a/.github/workflows/build-image.yml b/.github/workflows/build-image.yml index 488fe55..31f0815 100644 --- a/.github/workflows/build-image.yml +++ b/.github/workflows/build-image.yml @@ -63,7 +63,7 @@ jobs: persist-credentials: false - name: In-Toto Provenance record start id: in-toto-start - uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main-latest + uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main with: args: devguard-scanner intoto start --step=build --token=${{ secrets.devguard-token }} --apiUrl=${{ inputs.api-url }} --assetName=${{ inputs.asset-name }} --supplyChainId=${{ github.sha }} continue-on-error: true @@ -192,7 +192,7 @@ jobs: path: image-tag.txt - name: In-Toto Provenance record stop - uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main-latest + uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main with: args: devguard-scanner intoto stop --step=build --products=image-digest.txt --products=image-tag.txt --token=${{ secrets.devguard-token }} --apiUrl=${{ inputs.api-url }} --assetName=${{ inputs.asset-name }} --supplyChainId=${{ github.sha }} --generateSlsaProvenance continue-on-error: true diff --git a/.github/workflows/code-risk-identification.yml b/.github/workflows/code-risk-identification.yml index 8e1f663..f8b3c73 100644 --- a/.github/workflows/code-risk-identification.yml +++ b/.github/workflows/code-risk-identification.yml @@ -46,6 +46,6 @@ jobs: if: ${{ inputs.sarif-artifact-name != '' }} - name: DevGuard Code Risk Identification - uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main-latest + uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main with: args: devguard-scanner sarif ${{ inputs.sarif-file }} --assetName=${{ inputs.asset-name }} --apiUrl=${{ inputs.api-url }} --token="${{ secrets.devguard-token }}" --defaultRef=${{ github.event.repository.default_branch }} --isTag=${{ github.ref_type == 'tag' }} --ref=${{ github.ref_name }} --webUI=${{ inputs.web-ui }} \ No newline at end of file diff --git a/.github/workflows/container-scanning.yml b/.github/workflows/container-scanning.yml index e74352f..edd5f55 100644 --- a/.github/workflows/container-scanning.yml +++ b/.github/workflows/container-scanning.yml @@ -97,7 +97,7 @@ jobs: if: inputs.fetch-image-from-registry == true - name: DevGuard Container-Scanning - uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main-latest + uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main with: args: devguard-scanner container-scanning --assetName=${{ inputs.asset-name }} --apiUrl=${{ inputs.api-url }} --token="${{ secrets.devguard-token }}" --path=${{ inputs.image-path }} --defaultRef=${{ github.event.repository.default_branch }} --isTag=${{ github.ref_type == 'tag' }} --ref=${{ github.ref_name }} --failOnRisk=${{ inputs.fail-on-risk }} --failOnCVSS=${{ inputs.fail-on-cvss }} --artifactName=${{ env.ARTIFACT_NAME }} --webUI=${{ inputs.web-ui }} env: diff --git a/.github/workflows/dependency-risk-identification.yml b/.github/workflows/dependency-risk-identification.yml index 3ede3e2..19d4b8d 100644 --- a/.github/workflows/dependency-risk-identification.yml +++ b/.github/workflows/dependency-risk-identification.yml @@ -63,6 +63,6 @@ jobs: if: ${{ inputs.sbom-artifact-name != '' }} - name: DevGuard Dependency Risk Identification - uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main-latest + uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main with: args: devguard-scanner sbom ${{ inputs.sbom-file }} --assetName=${{ inputs.asset-name }} --apiUrl=${{ inputs.api-url }} --token="${{ secrets.devguard-token }}" --defaultRef=${{ github.event.repository.default_branch }} --isTag=${{ github.ref_type == 'tag' }} --ref=${{ github.ref_name }} --artifactName=${{ inputs.artifact-name }} --webUI=${{ inputs.web-ui }} --failOnRisk=${{ inputs.fail-on-risk }} --failOnCVSS=${{ inputs.fail-on-cvss }} \ No newline at end of file diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 9e76230..5fa8c2d 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -73,7 +73,7 @@ jobs: run: echo "DIGEST=$(cat image-digest.txt)" >> $GITHUB_ENV - name: In-Toto Provenance run - uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main-latest + uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main with: args: devguard-scanner intoto run --step=deploy --materials=image-tag.txt --products=image-tag.txt --products=image-digest.txt --token=${{ secrets.devguard-token }} --apiUrl=${{ inputs.api-url }} --assetName=${{ inputs.asset-name }} --supplyChainId=${{ github.sha }} --supplyChainOutputDigest="${{ env.DIGEST }}" continue-on-error: true diff --git a/.github/workflows/iac.yml b/.github/workflows/iac.yml index 230e1c8..50fed3b 100644 --- a/.github/workflows/iac.yml +++ b/.github/workflows/iac.yml @@ -39,7 +39,7 @@ jobs: persist-credentials: false fetch-depth: 0 - name: DevGuard Infrastructure as Code - uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main-latest + uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main continue-on-error: ${{ inputs.continue-on-open-code-risk }} with: args: devguard-scanner iac --assetName=${{ inputs.asset-name }} --apiUrl=${{ inputs.api-url }} --token="${{ secrets.devguard-token }}" --path=${{ inputs.path }} --defaultRef=${{ github.event.repository.default_branch }} --isTag=${{ github.ref_type == 'tag' }} --ref=${{ github.ref_name }} --webUI=${{ inputs.web-ui }} diff --git a/.github/workflows/secret-scanning.yml b/.github/workflows/secret-scanning.yml index 2951ba2..54fd76f 100644 --- a/.github/workflows/secret-scanning.yml +++ b/.github/workflows/secret-scanning.yml @@ -40,7 +40,7 @@ jobs: persist-credentials: false uses: actions/checkout@v4 - name: DevGuard Secret-Scanning - uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main-latest + uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main continue-on-error: ${{ inputs.continue-on-open-code-risk }} with: args: devguard-scanner secret-scanning --assetName=${{ inputs.asset-name }} --apiUrl=${{ inputs.api-url }} --token="${{ secrets.devguard-token }}" --path=${{ inputs.path }} --defaultRef=${{ github.event.repository.default_branch }} --isTag=${{ github.ref_type == 'tag' }} --ref=${{ github.ref_name }} --webUI=${{ inputs.web-ui }} \ No newline at end of file diff --git a/.github/workflows/sign.yml b/.github/workflows/sign.yml index eeea5b7..499bd72 100644 --- a/.github/workflows/sign.yml +++ b/.github/workflows/sign.yml @@ -58,6 +58,6 @@ jobs: run: echo "IMAGE_TAG_AND_DIGEST=$(cat image-tag.txt)@$(cat image-digest.txt)" >> $GITHUB_ENV - name: DevGuard Image-Signing - uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main-latest + uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main with: args: devguard-scanner sign -u ${{ github.actor }} -r ghcr.io -p ${{ secrets.GITHUB_TOKEN }} --token="${{ secrets.devguard-token }}" ${{ env.IMAGE_TAG_AND_DIGEST }} --apiUrl=${{ inputs.api-url }} --assetName=${{ inputs.asset-name }} \ No newline at end of file diff --git a/.github/workflows/software-composition-analysis.yml b/.github/workflows/software-composition-analysis.yml index bce5448..97f27d4 100644 --- a/.github/workflows/software-composition-analysis.yml +++ b/.github/workflows/software-composition-analysis.yml @@ -47,7 +47,7 @@ jobs: persist-credentials: true # we need the credentials to be able to use the devguard-scanner in private repositories uses: actions/checkout@v4 # Check out the repository content to the runner - name: DevGuard SCA - uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main-latest + uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main with: args: devguard-scanner sca --assetName=${{ inputs.asset-name }} --apiUrl=${{ inputs.api-url }} --token="${{ secrets.devguard-token }}" --path=${{ diff --git a/.github/workflows/static-application-security-testing.yml b/.github/workflows/static-application-security-testing.yml index c5f701c..c0a6987 100644 --- a/.github/workflows/static-application-security-testing.yml +++ b/.github/workflows/static-application-security-testing.yml @@ -39,7 +39,7 @@ jobs: fetch-depth: 0 persist-credentials: false - name: DevGuard Static application security testing - uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main-latest + uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main continue-on-error: ${{ inputs.continue-on-open-code-risk }} with: args: devguard-scanner sast --assetName=${{ inputs.asset-name }} --apiUrl=${{ inputs.api-url }} --token="${{ secrets.devguard-token }}" --path=${{ inputs.path }} --defaultRef=${{ github.event.repository.default_branch }} --isTag=${{ github.ref_type == 'tag' }} --ref=${{ github.ref_name }} --webUI=${{ inputs.web-ui }} From 6f824ee36e432e17d9086f5f70d364c4eebbfd19 Mon Sep 17 00:00:00 2001 From: Tim Bastin Date: Wed, 1 Apr 2026 16:37:26 +0200 Subject: [PATCH 15/30] back to main-latest --- .github/workflows/attest.yml | 14 +++++++------- .github/workflows/build-image.yml | 4 ++-- .github/workflows/code-risk-identification.yml | 2 +- .github/workflows/container-scanning.yml | 2 +- .../workflows/dependency-risk-identification.yml | 2 +- .github/workflows/deploy.yml | 2 +- .github/workflows/iac.yml | 2 +- .github/workflows/secret-scanning.yml | 2 +- .github/workflows/sign.yml | 2 +- .../workflows/software-composition-analysis.yml | 2 +- .../static-application-security-testing.yml | 2 +- 11 files changed, 18 insertions(+), 18 deletions(-) diff --git a/.github/workflows/attest.yml b/.github/workflows/attest.yml index d6a68c5..06e5369 100644 --- a/.github/workflows/attest.yml +++ b/.github/workflows/attest.yml @@ -86,7 +86,7 @@ jobs: fi - name: Get SBOM - uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main + uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main-latest with: args: > sh -c " @@ -95,7 +95,7 @@ jobs: env: API_ARTIFACT_NAME: ${{ env.API_ARTIFACT_NAME }} - name: Get VeX - uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main + uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main-latest with: args: > sh -c " @@ -104,14 +104,14 @@ jobs: env: API_ARTIFACT_NAME: ${{ env.API_ARTIFACT_NAME }} - name: Get SAST-Results - uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main + uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main-latest with: args: > sh -c " slug=$(devguard-scanner slug ${{ github.ref_name }}) && devguard-scanner curl '${{ inputs.api-url }}/api/v1/organizations/${{ inputs.asset-name }}/refs/'$slug'/sarif.json' --token='${{ secrets.devguard-token }}' > sarif.json " - name: Attest SBOM - uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main + uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main-latest with: args: > sh -c " @@ -124,7 +124,7 @@ jobs: env: ARTIFACT_NAME: ${{ env.ARTIFACT_NAME }} - name: Attest VeX - uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main + uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main-latest with: args: > sh -c " @@ -137,7 +137,7 @@ jobs: env: ARTIFACT_NAME: ${{ env.ARTIFACT_NAME }} - name: Attest SAST-Results - uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main + uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main-latest with: args: > sh -c " @@ -155,7 +155,7 @@ jobs: with: name: build${{ inputs.image-suffix }}.provenance.json - name: Attest build-provenance.json - uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main + uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main-latest continue-on-error: true with: args: > diff --git a/.github/workflows/build-image.yml b/.github/workflows/build-image.yml index 31f0815..488fe55 100644 --- a/.github/workflows/build-image.yml +++ b/.github/workflows/build-image.yml @@ -63,7 +63,7 @@ jobs: persist-credentials: false - name: In-Toto Provenance record start id: in-toto-start - uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main + uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main-latest with: args: devguard-scanner intoto start --step=build --token=${{ secrets.devguard-token }} --apiUrl=${{ inputs.api-url }} --assetName=${{ inputs.asset-name }} --supplyChainId=${{ github.sha }} continue-on-error: true @@ -192,7 +192,7 @@ jobs: path: image-tag.txt - name: In-Toto Provenance record stop - uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main + uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main-latest with: args: devguard-scanner intoto stop --step=build --products=image-digest.txt --products=image-tag.txt --token=${{ secrets.devguard-token }} --apiUrl=${{ inputs.api-url }} --assetName=${{ inputs.asset-name }} --supplyChainId=${{ github.sha }} --generateSlsaProvenance continue-on-error: true diff --git a/.github/workflows/code-risk-identification.yml b/.github/workflows/code-risk-identification.yml index f8b3c73..8e1f663 100644 --- a/.github/workflows/code-risk-identification.yml +++ b/.github/workflows/code-risk-identification.yml @@ -46,6 +46,6 @@ jobs: if: ${{ inputs.sarif-artifact-name != '' }} - name: DevGuard Code Risk Identification - uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main + uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main-latest with: args: devguard-scanner sarif ${{ inputs.sarif-file }} --assetName=${{ inputs.asset-name }} --apiUrl=${{ inputs.api-url }} --token="${{ secrets.devguard-token }}" --defaultRef=${{ github.event.repository.default_branch }} --isTag=${{ github.ref_type == 'tag' }} --ref=${{ github.ref_name }} --webUI=${{ inputs.web-ui }} \ No newline at end of file diff --git a/.github/workflows/container-scanning.yml b/.github/workflows/container-scanning.yml index edd5f55..e74352f 100644 --- a/.github/workflows/container-scanning.yml +++ b/.github/workflows/container-scanning.yml @@ -97,7 +97,7 @@ jobs: if: inputs.fetch-image-from-registry == true - name: DevGuard Container-Scanning - uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main + uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main-latest with: args: devguard-scanner container-scanning --assetName=${{ inputs.asset-name }} --apiUrl=${{ inputs.api-url }} --token="${{ secrets.devguard-token }}" --path=${{ inputs.image-path }} --defaultRef=${{ github.event.repository.default_branch }} --isTag=${{ github.ref_type == 'tag' }} --ref=${{ github.ref_name }} --failOnRisk=${{ inputs.fail-on-risk }} --failOnCVSS=${{ inputs.fail-on-cvss }} --artifactName=${{ env.ARTIFACT_NAME }} --webUI=${{ inputs.web-ui }} env: diff --git a/.github/workflows/dependency-risk-identification.yml b/.github/workflows/dependency-risk-identification.yml index 19d4b8d..3ede3e2 100644 --- a/.github/workflows/dependency-risk-identification.yml +++ b/.github/workflows/dependency-risk-identification.yml @@ -63,6 +63,6 @@ jobs: if: ${{ inputs.sbom-artifact-name != '' }} - name: DevGuard Dependency Risk Identification - uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main + uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main-latest with: args: devguard-scanner sbom ${{ inputs.sbom-file }} --assetName=${{ inputs.asset-name }} --apiUrl=${{ inputs.api-url }} --token="${{ secrets.devguard-token }}" --defaultRef=${{ github.event.repository.default_branch }} --isTag=${{ github.ref_type == 'tag' }} --ref=${{ github.ref_name }} --artifactName=${{ inputs.artifact-name }} --webUI=${{ inputs.web-ui }} --failOnRisk=${{ inputs.fail-on-risk }} --failOnCVSS=${{ inputs.fail-on-cvss }} \ No newline at end of file diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 5fa8c2d..9e76230 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -73,7 +73,7 @@ jobs: run: echo "DIGEST=$(cat image-digest.txt)" >> $GITHUB_ENV - name: In-Toto Provenance run - uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main + uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main-latest with: args: devguard-scanner intoto run --step=deploy --materials=image-tag.txt --products=image-tag.txt --products=image-digest.txt --token=${{ secrets.devguard-token }} --apiUrl=${{ inputs.api-url }} --assetName=${{ inputs.asset-name }} --supplyChainId=${{ github.sha }} --supplyChainOutputDigest="${{ env.DIGEST }}" continue-on-error: true diff --git a/.github/workflows/iac.yml b/.github/workflows/iac.yml index 50fed3b..230e1c8 100644 --- a/.github/workflows/iac.yml +++ b/.github/workflows/iac.yml @@ -39,7 +39,7 @@ jobs: persist-credentials: false fetch-depth: 0 - name: DevGuard Infrastructure as Code - uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main + uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main-latest continue-on-error: ${{ inputs.continue-on-open-code-risk }} with: args: devguard-scanner iac --assetName=${{ inputs.asset-name }} --apiUrl=${{ inputs.api-url }} --token="${{ secrets.devguard-token }}" --path=${{ inputs.path }} --defaultRef=${{ github.event.repository.default_branch }} --isTag=${{ github.ref_type == 'tag' }} --ref=${{ github.ref_name }} --webUI=${{ inputs.web-ui }} diff --git a/.github/workflows/secret-scanning.yml b/.github/workflows/secret-scanning.yml index 54fd76f..2951ba2 100644 --- a/.github/workflows/secret-scanning.yml +++ b/.github/workflows/secret-scanning.yml @@ -40,7 +40,7 @@ jobs: persist-credentials: false uses: actions/checkout@v4 - name: DevGuard Secret-Scanning - uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main + uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main-latest continue-on-error: ${{ inputs.continue-on-open-code-risk }} with: args: devguard-scanner secret-scanning --assetName=${{ inputs.asset-name }} --apiUrl=${{ inputs.api-url }} --token="${{ secrets.devguard-token }}" --path=${{ inputs.path }} --defaultRef=${{ github.event.repository.default_branch }} --isTag=${{ github.ref_type == 'tag' }} --ref=${{ github.ref_name }} --webUI=${{ inputs.web-ui }} \ No newline at end of file diff --git a/.github/workflows/sign.yml b/.github/workflows/sign.yml index 499bd72..eeea5b7 100644 --- a/.github/workflows/sign.yml +++ b/.github/workflows/sign.yml @@ -58,6 +58,6 @@ jobs: run: echo "IMAGE_TAG_AND_DIGEST=$(cat image-tag.txt)@$(cat image-digest.txt)" >> $GITHUB_ENV - name: DevGuard Image-Signing - uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main + uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main-latest with: args: devguard-scanner sign -u ${{ github.actor }} -r ghcr.io -p ${{ secrets.GITHUB_TOKEN }} --token="${{ secrets.devguard-token }}" ${{ env.IMAGE_TAG_AND_DIGEST }} --apiUrl=${{ inputs.api-url }} --assetName=${{ inputs.asset-name }} \ No newline at end of file diff --git a/.github/workflows/software-composition-analysis.yml b/.github/workflows/software-composition-analysis.yml index 97f27d4..bce5448 100644 --- a/.github/workflows/software-composition-analysis.yml +++ b/.github/workflows/software-composition-analysis.yml @@ -47,7 +47,7 @@ jobs: persist-credentials: true # we need the credentials to be able to use the devguard-scanner in private repositories uses: actions/checkout@v4 # Check out the repository content to the runner - name: DevGuard SCA - uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main + uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main-latest with: args: devguard-scanner sca --assetName=${{ inputs.asset-name }} --apiUrl=${{ inputs.api-url }} --token="${{ secrets.devguard-token }}" --path=${{ diff --git a/.github/workflows/static-application-security-testing.yml b/.github/workflows/static-application-security-testing.yml index c0a6987..c5f701c 100644 --- a/.github/workflows/static-application-security-testing.yml +++ b/.github/workflows/static-application-security-testing.yml @@ -39,7 +39,7 @@ jobs: fetch-depth: 0 persist-credentials: false - name: DevGuard Static application security testing - uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main + uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main-latest continue-on-error: ${{ inputs.continue-on-open-code-risk }} with: args: devguard-scanner sast --assetName=${{ inputs.asset-name }} --apiUrl=${{ inputs.api-url }} --token="${{ secrets.devguard-token }}" --path=${{ inputs.path }} --defaultRef=${{ github.event.repository.default_branch }} --isTag=${{ github.ref_type == 'tag' }} --ref=${{ github.ref_name }} --webUI=${{ inputs.web-ui }} From c5e842df79e668a481fa4f0e3d0d05cc37eff614 Mon Sep 17 00:00:00 2001 From: Tim Bastin Date: Wed, 1 Apr 2026 17:09:18 +0200 Subject: [PATCH 16/30] using main scanner --- .github/workflows/attest.yml | 14 +++++++------- .github/workflows/build-image.yml | 4 ++-- .github/workflows/code-risk-identification.yml | 2 +- .github/workflows/container-scanning.yml | 2 +- .../workflows/dependency-risk-identification.yml | 2 +- .github/workflows/deploy.yml | 2 +- .github/workflows/iac.yml | 2 +- .github/workflows/secret-scanning.yml | 2 +- .github/workflows/sign.yml | 2 +- .../workflows/software-composition-analysis.yml | 2 +- .../static-application-security-testing.yml | 2 +- 11 files changed, 18 insertions(+), 18 deletions(-) diff --git a/.github/workflows/attest.yml b/.github/workflows/attest.yml index 06e5369..d6a68c5 100644 --- a/.github/workflows/attest.yml +++ b/.github/workflows/attest.yml @@ -86,7 +86,7 @@ jobs: fi - name: Get SBOM - uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main-latest + uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main with: args: > sh -c " @@ -95,7 +95,7 @@ jobs: env: API_ARTIFACT_NAME: ${{ env.API_ARTIFACT_NAME }} - name: Get VeX - uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main-latest + uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main with: args: > sh -c " @@ -104,14 +104,14 @@ jobs: env: API_ARTIFACT_NAME: ${{ env.API_ARTIFACT_NAME }} - name: Get SAST-Results - uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main-latest + uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main with: args: > sh -c " slug=$(devguard-scanner slug ${{ github.ref_name }}) && devguard-scanner curl '${{ inputs.api-url }}/api/v1/organizations/${{ inputs.asset-name }}/refs/'$slug'/sarif.json' --token='${{ secrets.devguard-token }}' > sarif.json " - name: Attest SBOM - uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main-latest + uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main with: args: > sh -c " @@ -124,7 +124,7 @@ jobs: env: ARTIFACT_NAME: ${{ env.ARTIFACT_NAME }} - name: Attest VeX - uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main-latest + uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main with: args: > sh -c " @@ -137,7 +137,7 @@ jobs: env: ARTIFACT_NAME: ${{ env.ARTIFACT_NAME }} - name: Attest SAST-Results - uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main-latest + uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main with: args: > sh -c " @@ -155,7 +155,7 @@ jobs: with: name: build${{ inputs.image-suffix }}.provenance.json - name: Attest build-provenance.json - uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main-latest + uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main continue-on-error: true with: args: > diff --git a/.github/workflows/build-image.yml b/.github/workflows/build-image.yml index 488fe55..31f0815 100644 --- a/.github/workflows/build-image.yml +++ b/.github/workflows/build-image.yml @@ -63,7 +63,7 @@ jobs: persist-credentials: false - name: In-Toto Provenance record start id: in-toto-start - uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main-latest + uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main with: args: devguard-scanner intoto start --step=build --token=${{ secrets.devguard-token }} --apiUrl=${{ inputs.api-url }} --assetName=${{ inputs.asset-name }} --supplyChainId=${{ github.sha }} continue-on-error: true @@ -192,7 +192,7 @@ jobs: path: image-tag.txt - name: In-Toto Provenance record stop - uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main-latest + uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main with: args: devguard-scanner intoto stop --step=build --products=image-digest.txt --products=image-tag.txt --token=${{ secrets.devguard-token }} --apiUrl=${{ inputs.api-url }} --assetName=${{ inputs.asset-name }} --supplyChainId=${{ github.sha }} --generateSlsaProvenance continue-on-error: true diff --git a/.github/workflows/code-risk-identification.yml b/.github/workflows/code-risk-identification.yml index 8e1f663..f8b3c73 100644 --- a/.github/workflows/code-risk-identification.yml +++ b/.github/workflows/code-risk-identification.yml @@ -46,6 +46,6 @@ jobs: if: ${{ inputs.sarif-artifact-name != '' }} - name: DevGuard Code Risk Identification - uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main-latest + uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main with: args: devguard-scanner sarif ${{ inputs.sarif-file }} --assetName=${{ inputs.asset-name }} --apiUrl=${{ inputs.api-url }} --token="${{ secrets.devguard-token }}" --defaultRef=${{ github.event.repository.default_branch }} --isTag=${{ github.ref_type == 'tag' }} --ref=${{ github.ref_name }} --webUI=${{ inputs.web-ui }} \ No newline at end of file diff --git a/.github/workflows/container-scanning.yml b/.github/workflows/container-scanning.yml index e74352f..edd5f55 100644 --- a/.github/workflows/container-scanning.yml +++ b/.github/workflows/container-scanning.yml @@ -97,7 +97,7 @@ jobs: if: inputs.fetch-image-from-registry == true - name: DevGuard Container-Scanning - uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main-latest + uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main with: args: devguard-scanner container-scanning --assetName=${{ inputs.asset-name }} --apiUrl=${{ inputs.api-url }} --token="${{ secrets.devguard-token }}" --path=${{ inputs.image-path }} --defaultRef=${{ github.event.repository.default_branch }} --isTag=${{ github.ref_type == 'tag' }} --ref=${{ github.ref_name }} --failOnRisk=${{ inputs.fail-on-risk }} --failOnCVSS=${{ inputs.fail-on-cvss }} --artifactName=${{ env.ARTIFACT_NAME }} --webUI=${{ inputs.web-ui }} env: diff --git a/.github/workflows/dependency-risk-identification.yml b/.github/workflows/dependency-risk-identification.yml index 3ede3e2..19d4b8d 100644 --- a/.github/workflows/dependency-risk-identification.yml +++ b/.github/workflows/dependency-risk-identification.yml @@ -63,6 +63,6 @@ jobs: if: ${{ inputs.sbom-artifact-name != '' }} - name: DevGuard Dependency Risk Identification - uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main-latest + uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main with: args: devguard-scanner sbom ${{ inputs.sbom-file }} --assetName=${{ inputs.asset-name }} --apiUrl=${{ inputs.api-url }} --token="${{ secrets.devguard-token }}" --defaultRef=${{ github.event.repository.default_branch }} --isTag=${{ github.ref_type == 'tag' }} --ref=${{ github.ref_name }} --artifactName=${{ inputs.artifact-name }} --webUI=${{ inputs.web-ui }} --failOnRisk=${{ inputs.fail-on-risk }} --failOnCVSS=${{ inputs.fail-on-cvss }} \ No newline at end of file diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 9e76230..5fa8c2d 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -73,7 +73,7 @@ jobs: run: echo "DIGEST=$(cat image-digest.txt)" >> $GITHUB_ENV - name: In-Toto Provenance run - uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main-latest + uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main with: args: devguard-scanner intoto run --step=deploy --materials=image-tag.txt --products=image-tag.txt --products=image-digest.txt --token=${{ secrets.devguard-token }} --apiUrl=${{ inputs.api-url }} --assetName=${{ inputs.asset-name }} --supplyChainId=${{ github.sha }} --supplyChainOutputDigest="${{ env.DIGEST }}" continue-on-error: true diff --git a/.github/workflows/iac.yml b/.github/workflows/iac.yml index 230e1c8..50fed3b 100644 --- a/.github/workflows/iac.yml +++ b/.github/workflows/iac.yml @@ -39,7 +39,7 @@ jobs: persist-credentials: false fetch-depth: 0 - name: DevGuard Infrastructure as Code - uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main-latest + uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main continue-on-error: ${{ inputs.continue-on-open-code-risk }} with: args: devguard-scanner iac --assetName=${{ inputs.asset-name }} --apiUrl=${{ inputs.api-url }} --token="${{ secrets.devguard-token }}" --path=${{ inputs.path }} --defaultRef=${{ github.event.repository.default_branch }} --isTag=${{ github.ref_type == 'tag' }} --ref=${{ github.ref_name }} --webUI=${{ inputs.web-ui }} diff --git a/.github/workflows/secret-scanning.yml b/.github/workflows/secret-scanning.yml index 2951ba2..54fd76f 100644 --- a/.github/workflows/secret-scanning.yml +++ b/.github/workflows/secret-scanning.yml @@ -40,7 +40,7 @@ jobs: persist-credentials: false uses: actions/checkout@v4 - name: DevGuard Secret-Scanning - uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main-latest + uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main continue-on-error: ${{ inputs.continue-on-open-code-risk }} with: args: devguard-scanner secret-scanning --assetName=${{ inputs.asset-name }} --apiUrl=${{ inputs.api-url }} --token="${{ secrets.devguard-token }}" --path=${{ inputs.path }} --defaultRef=${{ github.event.repository.default_branch }} --isTag=${{ github.ref_type == 'tag' }} --ref=${{ github.ref_name }} --webUI=${{ inputs.web-ui }} \ No newline at end of file diff --git a/.github/workflows/sign.yml b/.github/workflows/sign.yml index eeea5b7..499bd72 100644 --- a/.github/workflows/sign.yml +++ b/.github/workflows/sign.yml @@ -58,6 +58,6 @@ jobs: run: echo "IMAGE_TAG_AND_DIGEST=$(cat image-tag.txt)@$(cat image-digest.txt)" >> $GITHUB_ENV - name: DevGuard Image-Signing - uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main-latest + uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main with: args: devguard-scanner sign -u ${{ github.actor }} -r ghcr.io -p ${{ secrets.GITHUB_TOKEN }} --token="${{ secrets.devguard-token }}" ${{ env.IMAGE_TAG_AND_DIGEST }} --apiUrl=${{ inputs.api-url }} --assetName=${{ inputs.asset-name }} \ No newline at end of file diff --git a/.github/workflows/software-composition-analysis.yml b/.github/workflows/software-composition-analysis.yml index bce5448..97f27d4 100644 --- a/.github/workflows/software-composition-analysis.yml +++ b/.github/workflows/software-composition-analysis.yml @@ -47,7 +47,7 @@ jobs: persist-credentials: true # we need the credentials to be able to use the devguard-scanner in private repositories uses: actions/checkout@v4 # Check out the repository content to the runner - name: DevGuard SCA - uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main-latest + uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main with: args: devguard-scanner sca --assetName=${{ inputs.asset-name }} --apiUrl=${{ inputs.api-url }} --token="${{ secrets.devguard-token }}" --path=${{ diff --git a/.github/workflows/static-application-security-testing.yml b/.github/workflows/static-application-security-testing.yml index c5f701c..c0a6987 100644 --- a/.github/workflows/static-application-security-testing.yml +++ b/.github/workflows/static-application-security-testing.yml @@ -39,7 +39,7 @@ jobs: fetch-depth: 0 persist-credentials: false - name: DevGuard Static application security testing - uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main-latest + uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main continue-on-error: ${{ inputs.continue-on-open-code-risk }} with: args: devguard-scanner sast --assetName=${{ inputs.asset-name }} --apiUrl=${{ inputs.api-url }} --token="${{ secrets.devguard-token }}" --path=${{ inputs.path }} --defaultRef=${{ github.event.repository.default_branch }} --isTag=${{ github.ref_type == 'tag' }} --ref=${{ github.ref_name }} --webUI=${{ inputs.web-ui }} From 2fa398ed8ab0e81d55fd3b88c4ed9ca4e825e3cf Mon Sep 17 00:00:00 2001 From: Tim Bastin Date: Thu, 2 Apr 2026 14:35:20 +0200 Subject: [PATCH 17/30] fix: saving sbom, sarif report and vex to /tmp folder --- .github/workflows/attest.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/attest.yml b/.github/workflows/attest.yml index d6a68c5..de9c5e8 100644 --- a/.github/workflows/attest.yml +++ b/.github/workflows/attest.yml @@ -90,7 +90,7 @@ jobs: with: args: > sh -c " - slug=$(devguard-scanner slug ${{ github.ref_name }}) && devguard-scanner curl '${{ inputs.api-url }}/api/v1/organizations/${{ inputs.asset-name }}/refs/'$slug'/artifacts/${{ env.API_ARTIFACT_NAME }}/sbom.json/' --token='${{ secrets.devguard-token }}' > sbom.json + slug=$(devguard-scanner slug ${{ github.ref_name }}) && devguard-scanner curl '${{ inputs.api-url }}/api/v1/organizations/${{ inputs.asset-name }}/refs/'$slug'/artifacts/${{ env.API_ARTIFACT_NAME }}/sbom.json/' --token='${{ secrets.devguard-token }}'> /tmp/sbom.json " env: API_ARTIFACT_NAME: ${{ env.API_ARTIFACT_NAME }} @@ -99,7 +99,7 @@ jobs: with: args: > sh -c " - slug=$(devguard-scanner slug ${{ github.ref_name }}) && devguard-scanner curl '${{ inputs.api-url }}/api/v1/organizations/${{ inputs.asset-name }}/refs/'$slug'/artifacts/${{ env.API_ARTIFACT_NAME }}/vex.json/' --token='${{ secrets.devguard-token }}' > vex.json + slug=$(devguard-scanner slug ${{ github.ref_name }}) && devguard-scanner curl '${{ inputs.api-url }}/api/v1/organizations/${{ inputs.asset-name }}/refs/'$slug'/artifacts/${{ env.API_ARTIFACT_NAME }}/vex.json/' --token='${{ secrets.devguard-token }}'> /tmp/vex.json " env: API_ARTIFACT_NAME: ${{ env.API_ARTIFACT_NAME }} @@ -108,7 +108,7 @@ jobs: with: args: > sh -c " - slug=$(devguard-scanner slug ${{ github.ref_name }}) && devguard-scanner curl '${{ inputs.api-url }}/api/v1/organizations/${{ inputs.asset-name }}/refs/'$slug'/sarif.json' --token='${{ secrets.devguard-token }}' > sarif.json + slug=$(devguard-scanner slug ${{ github.ref_name }}) && devguard-scanner curl '${{ inputs.api-url }}/api/v1/organizations/${{ inputs.asset-name }}/refs/'$slug'/sarif.json' --token='${{ secrets.devguard-token }}'> /tmp/sarif.json " - name: Attest SBOM uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main From 0f0c8785b5d00599d3a1751fac9b0c3457c95fe6 Mon Sep 17 00:00:00 2001 From: Tim Bastin Date: Thu, 2 Apr 2026 14:50:25 +0200 Subject: [PATCH 18/30] fix: path for json files --- .github/workflows/attest.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/attest.yml b/.github/workflows/attest.yml index de9c5e8..7327161 100644 --- a/.github/workflows/attest.yml +++ b/.github/workflows/attest.yml @@ -116,9 +116,9 @@ jobs: args: > sh -c " if [ -f image-digest.txt ]; then - devguard-scanner attest -u ${{ github.actor }} -r ghcr.io -p ${{ secrets.GITHUB_TOKEN }} sbom.json --predicateType='https://cyclonedx.org/bom' \"$(cat image-tag.txt)@$(cat image-digest.txt)\" --token='${{ secrets.devguard-token }}' --apiUrl=${{ inputs.api-url }} --assetName=${{ inputs.asset-name }} --ref=${{ github.ref_name }} --artifactName=${{ env.ARTIFACT_NAME }} + devguard-scanner attest -u ${{ github.actor }} -r ghcr.io -p ${{ secrets.GITHUB_TOKEN }} /tmp/sbom.json --predicateType='https://cyclonedx.org/bom' \"$(cat image-tag.txt)@$(cat image-digest.txt)\" --token='${{ secrets.devguard-token }}' --apiUrl=${{ inputs.api-url }} --assetName=${{ inputs.asset-name }} --ref=${{ github.ref_name }} --artifactName=${{ env.ARTIFACT_NAME }} else - devguard-scanner attest sbom.json --predicateType='https://cyclonedx.org/bom' --token='${{ secrets.devguard-token }}' --apiUrl=${{ inputs.api-url }} --assetName=${{ inputs.asset-name }} --ref=${{ github.ref_name }} --artifactName=${{ env.ARTIFACT_NAME }} + devguard-scanner attest /tmp/sbom.json --predicateType='https://cyclonedx.org/bom' --token='${{ secrets.devguard-token }}' --apiUrl=${{ inputs.api-url }} --assetName=${{ inputs.asset-name }} --ref=${{ github.ref_name }} --artifactName=${{ env.ARTIFACT_NAME }} fi " env: @@ -129,9 +129,9 @@ jobs: args: > sh -c " if [ -f image-digest.txt ]; then - devguard-scanner attest -u ${{ github.actor }} -r ghcr.io -p ${{ secrets.GITHUB_TOKEN }} vex.json \"$(cat image-tag.txt)@$(cat image-digest.txt)\" --token='${{ secrets.devguard-token }}' --predicateType='https://cyclonedx.org/vex' --apiUrl=${{ inputs.api-url }} --assetName=${{ inputs.asset-name }} --ref=${{ github.ref_name }} --artifactName=${{ env.ARTIFACT_NAME }} + devguard-scanner attest -u ${{ github.actor }} -r ghcr.io -p ${{ secrets.GITHUB_TOKEN }} /tmp/vex.json \"$(cat image-tag.txt)@$(cat image-digest.txt)\" --token='${{ secrets.devguard-token }}' --predicateType='https://cyclonedx.org/vex' --apiUrl=${{ inputs.api-url }} --assetName=${{ inputs.asset-name }} --ref=${{ github.ref_name }} --artifactName=${{ env.ARTIFACT_NAME }} else - devguard-scanner attest vex.json --predicateType='https://cyclonedx.org/vex' --token='${{ secrets.devguard-token }}' --apiUrl=${{ inputs.api-url }} --assetName=${{ inputs.asset-name }} --ref=${{ github.ref_name }} --artifactName=${{ env.ARTIFACT_NAME }} + devguard-scanner attest /tmp/vex.json --predicateType='https://cyclonedx.org/vex' --token='${{ secrets.devguard-token }}' --apiUrl=${{ inputs.api-url }} --assetName=${{ inputs.asset-name }} --ref=${{ github.ref_name }} --artifactName=${{ env.ARTIFACT_NAME }} fi " env: @@ -142,9 +142,9 @@ jobs: args: > sh -c " if [ -f image-digest.txt ]; then - devguard-scanner attest -u ${{ github.actor }} -r ghcr.io -p ${{ secrets.GITHUB_TOKEN }} sarif.json \"$(cat image-tag.txt)@$(cat image-digest.txt)\" --predicateType='https://www.schemastore.org/schemas/json/sarif-2.1.0.json' --token='${{ secrets.devguard-token }}' --apiUrl=${{ inputs.api-url }} --assetName=${{ inputs.asset-name }} --ref=${{ github.ref_name }} --artifactName=${{ env.ARTIFACT_NAME }} + devguard-scanner attest -u ${{ github.actor }} -r ghcr.io -p ${{ secrets.GITHUB_TOKEN }} /tmp/sarif.json \"$(cat image-tag.txt)@$(cat image-digest.txt)\" --predicateType='https://www.schemastore.org/schemas/json/sarif-2.1.0.json' --token='${{ secrets.devguard-token }}' --apiUrl=${{ inputs.api-url }} --assetName=${{ inputs.asset-name }} --ref=${{ github.ref_name }} --artifactName=${{ env.ARTIFACT_NAME }} else - devguard-scanner attest sarif.json --predicateType='https://www.schemastore.org/schemas/json/sarif-2.1.0.json' --token='${{ secrets.devguard-token }}' --apiUrl=${{ inputs.api-url }} --assetName=${{ inputs.asset-name }} --ref=${{ github.ref_name }} --artifactName=${{ env.ARTIFACT_NAME }} + devguard-scanner attest /tmp/sarif.json --predicateType='https://www.schemastore.org/schemas/json/sarif-2.1.0.json' --token='${{ secrets.devguard-token }}' --apiUrl=${{ inputs.api-url }} --assetName=${{ inputs.asset-name }} --ref=${{ github.ref_name }} --artifactName=${{ env.ARTIFACT_NAME }} fi " env: From b4f9917215fa4dc8e558a0d08d81ca8b782b5cbe Mon Sep 17 00:00:00 2001 From: Tim Bastin Date: Thu, 2 Apr 2026 15:09:27 +0200 Subject: [PATCH 19/30] combines get and attest steps --- .github/workflows/attest.yml | 50 ++++++++++++------------------------ 1 file changed, 16 insertions(+), 34 deletions(-) diff --git a/.github/workflows/attest.yml b/.github/workflows/attest.yml index 7327161..ccaf3d6 100644 --- a/.github/workflows/attest.yml +++ b/.github/workflows/attest.yml @@ -85,62 +85,45 @@ jobs: echo "Encoded: $API_ARTIFACT_NAME" fi - - name: Get SBOM - uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main - with: - args: > - sh -c " - slug=$(devguard-scanner slug ${{ github.ref_name }}) && devguard-scanner curl '${{ inputs.api-url }}/api/v1/organizations/${{ inputs.asset-name }}/refs/'$slug'/artifacts/${{ env.API_ARTIFACT_NAME }}/sbom.json/' --token='${{ secrets.devguard-token }}'> /tmp/sbom.json - " - env: - API_ARTIFACT_NAME: ${{ env.API_ARTIFACT_NAME }} - - name: Get VeX - uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main - with: - args: > - sh -c " - slug=$(devguard-scanner slug ${{ github.ref_name }}) && devguard-scanner curl '${{ inputs.api-url }}/api/v1/organizations/${{ inputs.asset-name }}/refs/'$slug'/artifacts/${{ env.API_ARTIFACT_NAME }}/vex.json/' --token='${{ secrets.devguard-token }}'> /tmp/vex.json - " - env: - API_ARTIFACT_NAME: ${{ env.API_ARTIFACT_NAME }} - - name: Get SAST-Results - uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main - with: - args: > - sh -c " - slug=$(devguard-scanner slug ${{ github.ref_name }}) && devguard-scanner curl '${{ inputs.api-url }}/api/v1/organizations/${{ inputs.asset-name }}/refs/'$slug'/sarif.json' --token='${{ secrets.devguard-token }}'> /tmp/sarif.json - " - - name: Attest SBOM + - name: Get and Attest SBOM uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main with: args: > sh -c " + slug=$(devguard-scanner slug ${{ github.ref_name }}) && + devguard-scanner curl '${{ inputs.api-url }}/api/v1/organizations/${{ inputs.asset-name }}/refs/'$slug'/artifacts/${{ env.API_ARTIFACT_NAME }}/sbom.json/' --token='${{ secrets.devguard-token }}' > /tmp/sbom.json && if [ -f image-digest.txt ]; then devguard-scanner attest -u ${{ github.actor }} -r ghcr.io -p ${{ secrets.GITHUB_TOKEN }} /tmp/sbom.json --predicateType='https://cyclonedx.org/bom' \"$(cat image-tag.txt)@$(cat image-digest.txt)\" --token='${{ secrets.devguard-token }}' --apiUrl=${{ inputs.api-url }} --assetName=${{ inputs.asset-name }} --ref=${{ github.ref_name }} --artifactName=${{ env.ARTIFACT_NAME }} else - devguard-scanner attest /tmp/sbom.json --predicateType='https://cyclonedx.org/bom' --token='${{ secrets.devguard-token }}' --apiUrl=${{ inputs.api-url }} --assetName=${{ inputs.asset-name }} --ref=${{ github.ref_name }} --artifactName=${{ env.ARTIFACT_NAME }} + devguard-scanner attest /tmp/sbom.json --predicateType='https://cyclonedx.org/bom' --token='${{ secrets.devguard-token }}' --apiUrl=${{ inputs.api-url }} --assetName=${{ inputs.asset-name }} --ref=${{ github.ref_name }} --artifactName=${{ env.ARTIFACT_NAME }} fi " env: - ARTIFACT_NAME: ${{ env.ARTIFACT_NAME }} - - name: Attest VeX + API_ARTIFACT_NAME: ${{ env.API_ARTIFACT_NAME }} + ARTIFACT_NAME: ${{ env.ARTIFACT_NAME }} + - name: Get and Attest VeX uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main with: args: > sh -c " + slug=$(devguard-scanner slug ${{ github.ref_name }}) && + devguard-scanner curl '${{ inputs.api-url }}/api/v1/organizations/${{ inputs.asset-name }}/refs/'$slug'/artifacts/${{ env.API_ARTIFACT_NAME }}/vex.json/' --token='${{ secrets.devguard-token }}' > /tmp/vex.json && if [ -f image-digest.txt ]; then devguard-scanner attest -u ${{ github.actor }} -r ghcr.io -p ${{ secrets.GITHUB_TOKEN }} /tmp/vex.json \"$(cat image-tag.txt)@$(cat image-digest.txt)\" --token='${{ secrets.devguard-token }}' --predicateType='https://cyclonedx.org/vex' --apiUrl=${{ inputs.api-url }} --assetName=${{ inputs.asset-name }} --ref=${{ github.ref_name }} --artifactName=${{ env.ARTIFACT_NAME }} else - devguard-scanner attest /tmp/vex.json --predicateType='https://cyclonedx.org/vex' --token='${{ secrets.devguard-token }}' --apiUrl=${{ inputs.api-url }} --assetName=${{ inputs.asset-name }} --ref=${{ github.ref_name }} --artifactName=${{ env.ARTIFACT_NAME }} + devguard-scanner attest /tmp/vex.json --predicateType='https://cyclonedx.org/vex' --token='${{ secrets.devguard-token }}' --apiUrl=${{ inputs.api-url }} --assetName=${{ inputs.asset-name }} --ref=${{ github.ref_name }} --artifactName=${{ env.ARTIFACT_NAME }} fi " env: + API_ARTIFACT_NAME: ${{ env.API_ARTIFACT_NAME }} ARTIFACT_NAME: ${{ env.ARTIFACT_NAME }} - - name: Attest SAST-Results + - name: Get and Attest SAST-Results uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main with: args: > sh -c " + slug=$(devguard-scanner slug ${{ github.ref_name }}) && + devguard-scanner curl '${{ inputs.api-url }}/api/v1/organizations/${{ inputs.asset-name }}/refs/'$slug'/sarif.json' --token='${{ secrets.devguard-token }}' > /tmp/sarif.json && if [ -f image-digest.txt ]; then devguard-scanner attest -u ${{ github.actor }} -r ghcr.io -p ${{ secrets.GITHUB_TOKEN }} /tmp/sarif.json \"$(cat image-tag.txt)@$(cat image-digest.txt)\" --predicateType='https://www.schemastore.org/schemas/json/sarif-2.1.0.json' --token='${{ secrets.devguard-token }}' --apiUrl=${{ inputs.api-url }} --assetName=${{ inputs.asset-name }} --ref=${{ github.ref_name }} --artifactName=${{ env.ARTIFACT_NAME }} else @@ -149,8 +132,7 @@ jobs: " env: ARTIFACT_NAME: ${{ env.ARTIFACT_NAME }} - # download build-provenance.json if it exists - - name: Download build-provenance.json + - name: Download and Attest build-provenance.json uses: actions/download-artifact@v4 with: name: build${{ inputs.image-suffix }}.provenance.json @@ -167,4 +149,4 @@ jobs: fi " env: - ARTIFACT_NAME: ${{ env.ARTIFACT_NAME }} + ARTIFACT_NAME: ${{ env.ARTIFACT_NAME }} From e4bbc1bf9b4633bc598d264c2c66d69be7a6f481 Mon Sep 17 00:00:00 2001 From: Tim Bastin Date: Thu, 2 Apr 2026 17:34:32 +0200 Subject: [PATCH 20/30] using generate-tag to define artifact names --- .github/workflows/build-image.yml | 48 +++++++++++---------------- .github/workflows/build-nix-image.yml | 19 +++++++---- 2 files changed, 32 insertions(+), 35 deletions(-) diff --git a/.github/workflows/build-image.yml b/.github/workflows/build-image.yml index 31f0815..797fe91 100644 --- a/.github/workflows/build-image.yml +++ b/.github/workflows/build-image.yml @@ -97,39 +97,31 @@ jobs: path: ${{ inputs.image-destination-path }} if: inputs.disable-artifact-registry-as-image-store == false - # Calculate a tag name - # If the image input is provided, use it as the tag - # If the workflow is triggered by a tag, use the tag as the tag - # Otherwise built GitOps compatible tags. Fallback to the branch name, commit hash, and timestamp. Those tags are sortable and unique. + # Calculate the image tag with the same generator used in GitLab CI. - name: Set IMAGE_TAG - run: | - if [ "${IMAGE}" != "" ]; then - IMAGE_TAG="${IMAGE}" - elif [[ "${GITHUB_REF}" == refs/tags/* ]]; then - if [ "${IMAGE_SUFFIX}" != "" ]; then - IMAGE_TAG="ghcr.io/${{ github.repository }}/${IMAGE_SUFFIX}:${GITHUB_REF#refs/tags/}" - else - IMAGE_TAG="ghcr.io/${{ github.repository }}:${GITHUB_REF#refs/tags/}" - fi - - else - branch=${GITHUB_REF##*/} - sha=${GITHUB_SHA::8} - ts=$(date +%s) - if [ "${IMAGE_SUFFIX}" != "" ]; then - IMAGE_TAG="ghcr.io/${{ github.repository }}/${IMAGE_SUFFIX}:${branch}-${sha}-${ts}" + uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main + with: + args: > + sh -c ' + if [ -n "$IMAGE" ]; then + IMAGE_TAG="$IMAGE" else - IMAGE_TAG="ghcr.io/${{ github.repository }}:${branch}-${sha}-${ts}" + if [ -n "$IMAGE_SUFFIX" ]; then + IMAGE_PATH="ghcr.io/${GITHUB_REPOSITORY}/${IMAGE_SUFFIX}" + else + IMAGE_PATH="ghcr.io/${GITHUB_REPOSITORY}" + fi + + devguard-scanner generate-tag --imagePath="$IMAGE_PATH" --ref="$GITHUB_REF_NAME" > image-tag-env.txt + IMAGE_TAG=$(grep '^IMAGE_TAG=' image-tag-env.txt | cut -d= -f2-) fi - fi - - IMAGE_TAG=$(echo "$IMAGE_TAG" | tr '[:upper:]' '[:lower:]') - echo "$IMAGE_TAG" > image-tag.txt - # necessary for the kaniko job - echo "IMAGE_TAG=$(cat image-tag.txt)" >> $GITHUB_ENV + IMAGE_TAG=$(echo "$IMAGE_TAG" | tr "[:upper:]" "[:lower:]") + echo "$IMAGE_TAG" > image-tag.txt + echo "IMAGE_TAG=$(cat image-tag.txt)" >> "$GITHUB_ENV" + ' env: - IMAGE_SUFFIX: ${{ inputs.image-suffix }} + IMAGE_SUFFIX: ${{ inputs.image-suffix }} IMAGE: ${{ inputs.image }} - name: Upload to container registry diff --git a/.github/workflows/build-nix-image.yml b/.github/workflows/build-nix-image.yml index 1101d3e..2174bb6 100644 --- a/.github/workflows/build-nix-image.yml +++ b/.github/workflows/build-nix-image.yml @@ -153,9 +153,15 @@ jobs: --architecture='${{ inputs.arch }}' \ >> image-tag-env.txt IMAGE_TAG=$(grep '^IMAGE_TAG=' image-tag-env.txt | cut -d= -f2-) + ARTIFACT_NAME=$(grep '^ARTIFACT_NAME=' image-tag-env.txt | cut -d= -f2-) + ARTIFACT_URL_ENCODED=$(grep '^ARTIFACT_URL_ENCODED=' image-tag-env.txt | cut -d= -f2-) echo "$IMAGE_TAG" > image-tag.txt + echo "$ARTIFACT_NAME" > artifact-purl.txt + echo "$ARTIFACT_URL_ENCODED" > artifact-purl-safe.txt echo "image_tag=$IMAGE_TAG" >> "$GITHUB_OUTPUT" echo "IMAGE_TAG=$IMAGE_TAG" >> "$GITHUB_ENV" + echo "ARTIFACT_NAME=$ARTIFACT_NAME" >> "$GITHUB_ENV" + echo "ARTIFACT_URL_ENCODED=$ARTIFACT_URL_ENCODED" >> "$GITHUB_ENV" - name: Upload image-tag artifact uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 - https://github.com/actions/upload-artifact/releases/tag/v4.6.2 @@ -172,13 +178,12 @@ jobs: - name: Set artifact PURL id: set-purl run: | - REGISTRY_AND_IMAGE=${IMAGE_TAG%:*} - NAME=${REGISTRY_AND_IMAGE##*/} - PURL="pkg:oci/$NAME?repository_url=$REGISTRY_AND_IMAGE" - echo "$PURL" > artifact-purl.txt - SAFE_PURL=$(echo -n "$PURL" | jq -s -R -r @uri) - echo "$SAFE_PURL" > artifact-purl-safe.txt - echo "purl=$PURL" >> $GITHUB_OUTPUT + echo "purl=$ARTIFACT_NAME" >> $GITHUB_OUTPUT + echo "$ARTIFACT_NAME" > artifact-purl.txt + echo "$ARTIFACT_URL_ENCODED" > artifact-purl-safe.txt + env: + ARTIFACT_NAME: ${{ env.ARTIFACT_NAME }} + ARTIFACT_URL_ENCODED: ${{ env.ARTIFACT_URL_ENCODED }} - name: Upload artifact-purl artifact uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 - https://github.com/actions/upload-artifact/releases/tag/v4.6.2 From f07f9f15d4d5d39cd701bd4d5a2b4610a25ba3f7 Mon Sep 17 00:00:00 2001 From: Tim Bastin Date: Fri, 3 Apr 2026 10:49:25 +0200 Subject: [PATCH 21/30] adds signing of index manifest --- .github/workflows/full-nix.yml | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/.github/workflows/full-nix.yml b/.github/workflows/full-nix.yml index 9ffdfce..89fe103 100644 --- a/.github/workflows/full-nix.yml +++ b/.github/workflows/full-nix.yml @@ -265,6 +265,38 @@ jobs: name: manifest-tag${{ inputs.artifact-name-suffix }} path: manifest-tag.txt + - name: Get manifest digest and prepare signing artifacts + run: | + MANIFEST_DIGEST=$(crane digest "$MANIFEST_TAG") + echo "$MANIFEST_TAG" > image-tag.txt + echo "$MANIFEST_DIGEST" > image-digest.txt + + - name: Upload manifest image-tag artifact + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 + with: + name: image-tag${{ inputs.artifact-name-suffix }}-manifest + path: image-tag.txt + + - name: Upload manifest image-digest artifact + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 + with: + name: image-digest${{ inputs.artifact-name-suffix }}-manifest + path: image-digest.txt + + sign-manifest: + if: ${{ inputs.should-deploy }} + needs: [create-manifest] + uses: l3montree-dev/devguard-action/.github/workflows/sign.yml@nix + permissions: + contents: read + packages: write + with: + asset-name: ${{ inputs.asset-name }} + api-url: ${{ inputs.api-url }} + image-suffix: ${{ inputs.artifact-name-suffix }}-manifest + secrets: + devguard-token: ${{ secrets.devguard-token }} + sign-amd64: if: ${{ inputs.should-deploy }} needs: [build-amd64, create-manifest] From 377976229469e72cff20fe2bf5513dfc1148f114 Mon Sep 17 00:00:00 2001 From: Tim Bastin Date: Fri, 3 Apr 2026 11:20:04 +0200 Subject: [PATCH 22/30] testing with multi line sh --- .github/workflows/attest.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/attest.yml b/.github/workflows/attest.yml index ccaf3d6..7a67cf8 100644 --- a/.github/workflows/attest.yml +++ b/.github/workflows/attest.yml @@ -88,7 +88,7 @@ jobs: - name: Get and Attest SBOM uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main with: - args: > + args: | sh -c " slug=$(devguard-scanner slug ${{ github.ref_name }}) && devguard-scanner curl '${{ inputs.api-url }}/api/v1/organizations/${{ inputs.asset-name }}/refs/'$slug'/artifacts/${{ env.API_ARTIFACT_NAME }}/sbom.json/' --token='${{ secrets.devguard-token }}' > /tmp/sbom.json && @@ -104,7 +104,7 @@ jobs: - name: Get and Attest VeX uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main with: - args: > + args: | sh -c " slug=$(devguard-scanner slug ${{ github.ref_name }}) && devguard-scanner curl '${{ inputs.api-url }}/api/v1/organizations/${{ inputs.asset-name }}/refs/'$slug'/artifacts/${{ env.API_ARTIFACT_NAME }}/vex.json/' --token='${{ secrets.devguard-token }}' > /tmp/vex.json && @@ -120,7 +120,7 @@ jobs: - name: Get and Attest SAST-Results uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main with: - args: > + args: | sh -c " slug=$(devguard-scanner slug ${{ github.ref_name }}) && devguard-scanner curl '${{ inputs.api-url }}/api/v1/organizations/${{ inputs.asset-name }}/refs/'$slug'/sarif.json' --token='${{ secrets.devguard-token }}' > /tmp/sarif.json && @@ -140,7 +140,7 @@ jobs: uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main continue-on-error: true with: - args: > + args: | sh -c " if [ -f image-digest.txt ]; then devguard-scanner attest -u ${{ github.actor }} -r ghcr.io -p ${{ secrets.GITHUB_TOKEN }} build.provenance.json \"$(cat image-tag.txt)@$(cat image-digest.txt)\" --predicateType='https://slsa.dev/provenance/v1' --token='${{ secrets.devguard-token }}' --apiUrl=${{ inputs.api-url }} --assetName=${{ inputs.asset-name }} --ref=${{ github.ref_name }} --artifactName=${{ env.ARTIFACT_NAME }} From 82f08b5302ab2095ae6a9157b43963f75b20c452 Mon Sep 17 00:00:00 2001 From: Tim Bastin Date: Fri, 3 Apr 2026 12:41:47 +0200 Subject: [PATCH 23/30] quoting artifact name --- .github/workflows/attest.yml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/attest.yml b/.github/workflows/attest.yml index 7a67cf8..c4accfa 100644 --- a/.github/workflows/attest.yml +++ b/.github/workflows/attest.yml @@ -93,9 +93,9 @@ jobs: slug=$(devguard-scanner slug ${{ github.ref_name }}) && devguard-scanner curl '${{ inputs.api-url }}/api/v1/organizations/${{ inputs.asset-name }}/refs/'$slug'/artifacts/${{ env.API_ARTIFACT_NAME }}/sbom.json/' --token='${{ secrets.devguard-token }}' > /tmp/sbom.json && if [ -f image-digest.txt ]; then - devguard-scanner attest -u ${{ github.actor }} -r ghcr.io -p ${{ secrets.GITHUB_TOKEN }} /tmp/sbom.json --predicateType='https://cyclonedx.org/bom' \"$(cat image-tag.txt)@$(cat image-digest.txt)\" --token='${{ secrets.devguard-token }}' --apiUrl=${{ inputs.api-url }} --assetName=${{ inputs.asset-name }} --ref=${{ github.ref_name }} --artifactName=${{ env.ARTIFACT_NAME }} + devguard-scanner attest -u ${{ github.actor }} -r ghcr.io -p ${{ secrets.GITHUB_TOKEN }} /tmp/sbom.json --predicateType='https://cyclonedx.org/bom' \"$(cat image-tag.txt)@$(cat image-digest.txt)\" --token='${{ secrets.devguard-token }}' --apiUrl=${{ inputs.api-url }} --assetName=${{ inputs.asset-name }} --ref=${{ github.ref_name }} --artifactName="${{ env.ARTIFACT_NAME }}" else - devguard-scanner attest /tmp/sbom.json --predicateType='https://cyclonedx.org/bom' --token='${{ secrets.devguard-token }}' --apiUrl=${{ inputs.api-url }} --assetName=${{ inputs.asset-name }} --ref=${{ github.ref_name }} --artifactName=${{ env.ARTIFACT_NAME }} + devguard-scanner attest /tmp/sbom.json --predicateType='https://cyclonedx.org/bom' --token='${{ secrets.devguard-token }}' --apiUrl=${{ inputs.api-url }} --assetName=${{ inputs.asset-name }} --ref=${{ github.ref_name }} --artifactName="${{ env.ARTIFACT_NAME }}" fi " env: @@ -109,9 +109,9 @@ jobs: slug=$(devguard-scanner slug ${{ github.ref_name }}) && devguard-scanner curl '${{ inputs.api-url }}/api/v1/organizations/${{ inputs.asset-name }}/refs/'$slug'/artifacts/${{ env.API_ARTIFACT_NAME }}/vex.json/' --token='${{ secrets.devguard-token }}' > /tmp/vex.json && if [ -f image-digest.txt ]; then - devguard-scanner attest -u ${{ github.actor }} -r ghcr.io -p ${{ secrets.GITHUB_TOKEN }} /tmp/vex.json \"$(cat image-tag.txt)@$(cat image-digest.txt)\" --token='${{ secrets.devguard-token }}' --predicateType='https://cyclonedx.org/vex' --apiUrl=${{ inputs.api-url }} --assetName=${{ inputs.asset-name }} --ref=${{ github.ref_name }} --artifactName=${{ env.ARTIFACT_NAME }} + devguard-scanner attest -u ${{ github.actor }} -r ghcr.io -p ${{ secrets.GITHUB_TOKEN }} /tmp/vex.json \"$(cat image-tag.txt)@$(cat image-digest.txt)\" --token='${{ secrets.devguard-token }}' --predicateType='https://cyclonedx.org/vex' --apiUrl=${{ inputs.api-url }} --assetName=${{ inputs.asset-name }} --ref=${{ github.ref_name }} --artifactName="${{ env.ARTIFACT_NAME }}" else - devguard-scanner attest /tmp/vex.json --predicateType='https://cyclonedx.org/vex' --token='${{ secrets.devguard-token }}' --apiUrl=${{ inputs.api-url }} --assetName=${{ inputs.asset-name }} --ref=${{ github.ref_name }} --artifactName=${{ env.ARTIFACT_NAME }} + devguard-scanner attest /tmp/vex.json --predicateType='https://cyclonedx.org/vex' --token='${{ secrets.devguard-token }}' --apiUrl=${{ inputs.api-url }} --assetName=${{ inputs.asset-name }} --ref=${{ github.ref_name }} --artifactName="${{ env.ARTIFACT_NAME }}" fi " env: @@ -125,9 +125,9 @@ jobs: slug=$(devguard-scanner slug ${{ github.ref_name }}) && devguard-scanner curl '${{ inputs.api-url }}/api/v1/organizations/${{ inputs.asset-name }}/refs/'$slug'/sarif.json' --token='${{ secrets.devguard-token }}' > /tmp/sarif.json && if [ -f image-digest.txt ]; then - devguard-scanner attest -u ${{ github.actor }} -r ghcr.io -p ${{ secrets.GITHUB_TOKEN }} /tmp/sarif.json \"$(cat image-tag.txt)@$(cat image-digest.txt)\" --predicateType='https://www.schemastore.org/schemas/json/sarif-2.1.0.json' --token='${{ secrets.devguard-token }}' --apiUrl=${{ inputs.api-url }} --assetName=${{ inputs.asset-name }} --ref=${{ github.ref_name }} --artifactName=${{ env.ARTIFACT_NAME }} + devguard-scanner attest -u ${{ github.actor }} -r ghcr.io -p ${{ secrets.GITHUB_TOKEN }} /tmp/sarif.json \"$(cat image-tag.txt)@$(cat image-digest.txt)\" --predicateType='https://www.schemastore.org/schemas/json/sarif-2.1.0.json' --token='${{ secrets.devguard-token }}' --apiUrl=${{ inputs.api-url }} --assetName=${{ inputs.asset-name }} --ref=${{ github.ref_name }} --artifactName="${{ env.ARTIFACT_NAME }}" else - devguard-scanner attest /tmp/sarif.json --predicateType='https://www.schemastore.org/schemas/json/sarif-2.1.0.json' --token='${{ secrets.devguard-token }}' --apiUrl=${{ inputs.api-url }} --assetName=${{ inputs.asset-name }} --ref=${{ github.ref_name }} --artifactName=${{ env.ARTIFACT_NAME }} + devguard-scanner attest /tmp/sarif.json --predicateType='https://www.schemastore.org/schemas/json/sarif-2.1.0.json' --token='${{ secrets.devguard-token }}' --apiUrl=${{ inputs.api-url }} --assetName=${{ inputs.asset-name }} --ref=${{ github.ref_name }} --artifactName="${{ env.ARTIFACT_NAME }}" fi " env: @@ -143,9 +143,9 @@ jobs: args: | sh -c " if [ -f image-digest.txt ]; then - devguard-scanner attest -u ${{ github.actor }} -r ghcr.io -p ${{ secrets.GITHUB_TOKEN }} build.provenance.json \"$(cat image-tag.txt)@$(cat image-digest.txt)\" --predicateType='https://slsa.dev/provenance/v1' --token='${{ secrets.devguard-token }}' --apiUrl=${{ inputs.api-url }} --assetName=${{ inputs.asset-name }} --ref=${{ github.ref_name }} --artifactName=${{ env.ARTIFACT_NAME }} + devguard-scanner attest -u ${{ github.actor }} -r ghcr.io -p ${{ secrets.GITHUB_TOKEN }} build.provenance.json \"$(cat image-tag.txt)@$(cat image-digest.txt)\" --predicateType='https://slsa.dev/provenance/v1' --token='${{ secrets.devguard-token }}' --apiUrl=${{ inputs.api-url }} --assetName=${{ inputs.asset-name }} --ref=${{ github.ref_name }} --artifactName="${{ env.ARTIFACT_NAME }}" else - devguard-scanner attest build.provenance.json --token='${{ secrets.devguard-token }}' --apiUrl=${{ inputs.api-url }} --predicateType='https://slsa.dev/provenance/v1' --assetName=${{ inputs.asset-name }} --ref=${{ github.ref_name }} --artifactName=${{ env.ARTIFACT_NAME }} + devguard-scanner attest build.provenance.json --token='${{ secrets.devguard-token }}' --apiUrl=${{ inputs.api-url }} --predicateType='https://slsa.dev/provenance/v1' --assetName=${{ inputs.asset-name }} --ref=${{ github.ref_name }} --artifactName="${{ env.ARTIFACT_NAME }}" fi " env: From a2e39ec31b09c41c69be0975af809e640a378aa5 Mon Sep 17 00:00:00 2001 From: Tim Bastin Date: Fri, 3 Apr 2026 13:12:22 +0200 Subject: [PATCH 24/30] adds nix version input --- .github/workflows/build-nix-image.yml | 9 +++++++++ .github/workflows/full-nix.yml | 7 +++++++ 2 files changed, 16 insertions(+) diff --git a/.github/workflows/build-nix-image.yml b/.github/workflows/build-nix-image.yml index 2174bb6..3508247 100644 --- a/.github/workflows/build-nix-image.yml +++ b/.github/workflows/build-nix-image.yml @@ -50,6 +50,11 @@ on: required: false type: string default: 'garage' + nix-version: + description: 'Pinned Nix version used for deterministic builds (must match other CI systems)' + required: false + type: string + default: '2.34.4' arch: description: 'Target architecture suffix appended to the generated image tag (e.g. amd64, arm64). Leave empty for single-arch builds.' required: false @@ -95,11 +100,15 @@ jobs: - uses: cachix/install-nix-action@v31 with: + install_url: ${{ format('https://releases.nixos.org/nix/nix-{0}/install', inputs.nix-version) }} extra_nix_config: | experimental-features = nix-command flakes ${{ inputs.nix-cache-substituter != '' && format('substituters = https://cache.nixos.org {0}', inputs.nix-cache-substituter) || '' }} ${{ inputs.nix-cache-public-key != '' && format('trusted-public-keys = cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY= {0}', inputs.nix-cache-public-key) || '' }} + - name: Show Nix version + run: nix --version + - name: Install crane and devguard-scanner run: nix profile install nixpkgs#crane .#devguardScanner diff --git a/.github/workflows/full-nix.yml b/.github/workflows/full-nix.yml index 89fe103..ca32a86 100644 --- a/.github/workflows/full-nix.yml +++ b/.github/workflows/full-nix.yml @@ -84,6 +84,11 @@ on: required: false type: string default: 'garage' + nix-version: + description: 'Pinned Nix version used by reusable build jobs' + required: false + type: string + default: '2.34.4' secrets: devguard-token: required: true @@ -120,6 +125,7 @@ jobs: nix-cache-s3-endpoint: ${{ inputs.nix-cache-s3-endpoint }} nix-cache-s3-bucket: ${{ inputs.nix-cache-s3-bucket }} nix-cache-region: ${{ inputs.nix-cache-region }} + nix-version: ${{ inputs.nix-version }} secrets: devguard-token: ${{ secrets.devguard-token }} nix-cache-secret-key: ${{ secrets.nix-cache-secret-key }} @@ -143,6 +149,7 @@ jobs: nix-cache-s3-endpoint: ${{ inputs.nix-cache-s3-endpoint }} nix-cache-s3-bucket: ${{ inputs.nix-cache-s3-bucket }} nix-cache-region: ${{ inputs.nix-cache-region }} + nix-version: ${{ inputs.nix-version }} secrets: devguard-token: ${{ secrets.devguard-token }} nix-cache-secret-key: ${{ secrets.nix-cache-secret-key }} From e498bbf9b3041856675b69f1296505c1a06e2f4e Mon Sep 17 00:00:00 2001 From: Tim Bastin Date: Fri, 3 Apr 2026 21:54:12 +0200 Subject: [PATCH 25/30] troubleshooting attest --- .github/workflows/attest.yml | 36 ++++++++++++++++++++++++++++-------- 1 file changed, 28 insertions(+), 8 deletions(-) diff --git a/.github/workflows/attest.yml b/.github/workflows/attest.yml index c4accfa..4f1d65c 100644 --- a/.github/workflows/attest.yml +++ b/.github/workflows/attest.yml @@ -84,6 +84,7 @@ jobs: echo "Using provided artifact name: ${{ inputs.artifact-name }}" echo "Encoded: $API_ARTIFACT_NAME" fi + echo "Resolved artifact name for attestation: ${{ inputs.artifact-name }}" - name: Get and Attest SBOM uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main @@ -91,11 +92,16 @@ jobs: args: | sh -c " slug=$(devguard-scanner slug ${{ github.ref_name }}) && + artifact_name="$ARTIFACT_NAME" && + echo 'Fetching SBOM for artifact:' '${{ env.API_ARTIFACT_NAME }}' && devguard-scanner curl '${{ inputs.api-url }}/api/v1/organizations/${{ inputs.asset-name }}/refs/'$slug'/artifacts/${{ env.API_ARTIFACT_NAME }}/sbom.json/' --token='${{ secrets.devguard-token }}' > /tmp/sbom.json && + echo 'SBOM downloaded to /tmp/sbom.json' && if [ -f image-digest.txt ]; then - devguard-scanner attest -u ${{ github.actor }} -r ghcr.io -p ${{ secrets.GITHUB_TOKEN }} /tmp/sbom.json --predicateType='https://cyclonedx.org/bom' \"$(cat image-tag.txt)@$(cat image-digest.txt)\" --token='${{ secrets.devguard-token }}' --apiUrl=${{ inputs.api-url }} --assetName=${{ inputs.asset-name }} --ref=${{ github.ref_name }} --artifactName="${{ env.ARTIFACT_NAME }}" + echo 'Attesting SBOM with image digest present' && + devguard-scanner attest -u ${{ github.actor }} -r ghcr.io -p ${{ secrets.GITHUB_TOKEN }} /tmp/sbom.json --predicateType='https://cyclonedx.org/bom' \"$(cat image-tag.txt)@$(cat image-digest.txt)\" --token='${{ secrets.devguard-token }}' --apiUrl=${{ inputs.api-url }} --assetName=${{ inputs.asset-name }} --ref=${{ github.ref_name }} --artifactName="$artifact_name" else - devguard-scanner attest /tmp/sbom.json --predicateType='https://cyclonedx.org/bom' --token='${{ secrets.devguard-token }}' --apiUrl=${{ inputs.api-url }} --assetName=${{ inputs.asset-name }} --ref=${{ github.ref_name }} --artifactName="${{ env.ARTIFACT_NAME }}" + echo 'Attesting SBOM without image digest' && + devguard-scanner attest /tmp/sbom.json --predicateType='https://cyclonedx.org/bom' --token='${{ secrets.devguard-token }}' --apiUrl=${{ inputs.api-url }} --assetName=${{ inputs.asset-name }} --ref=${{ github.ref_name }} --artifactName="$artifact_name" fi " env: @@ -107,11 +113,16 @@ jobs: args: | sh -c " slug=$(devguard-scanner slug ${{ github.ref_name }}) && + artifact_name="$ARTIFACT_NAME" && + echo 'Fetching VeX for artifact:' '${{ env.API_ARTIFACT_NAME }}' && devguard-scanner curl '${{ inputs.api-url }}/api/v1/organizations/${{ inputs.asset-name }}/refs/'$slug'/artifacts/${{ env.API_ARTIFACT_NAME }}/vex.json/' --token='${{ secrets.devguard-token }}' > /tmp/vex.json && + echo 'VeX downloaded to /tmp/vex.json' && if [ -f image-digest.txt ]; then - devguard-scanner attest -u ${{ github.actor }} -r ghcr.io -p ${{ secrets.GITHUB_TOKEN }} /tmp/vex.json \"$(cat image-tag.txt)@$(cat image-digest.txt)\" --token='${{ secrets.devguard-token }}' --predicateType='https://cyclonedx.org/vex' --apiUrl=${{ inputs.api-url }} --assetName=${{ inputs.asset-name }} --ref=${{ github.ref_name }} --artifactName="${{ env.ARTIFACT_NAME }}" + echo 'Attesting VeX with image digest present' && + devguard-scanner attest -u ${{ github.actor }} -r ghcr.io -p ${{ secrets.GITHUB_TOKEN }} /tmp/vex.json \"$(cat image-tag.txt)@$(cat image-digest.txt)\" --token='${{ secrets.devguard-token }}' --predicateType='https://cyclonedx.org/vex' --apiUrl=${{ inputs.api-url }} --assetName=${{ inputs.asset-name }} --ref=${{ github.ref_name }} --artifactName="$artifact_name" else - devguard-scanner attest /tmp/vex.json --predicateType='https://cyclonedx.org/vex' --token='${{ secrets.devguard-token }}' --apiUrl=${{ inputs.api-url }} --assetName=${{ inputs.asset-name }} --ref=${{ github.ref_name }} --artifactName="${{ env.ARTIFACT_NAME }}" + echo 'Attesting VeX without image digest' && + devguard-scanner attest /tmp/vex.json --predicateType='https://cyclonedx.org/vex' --token='${{ secrets.devguard-token }}' --apiUrl=${{ inputs.api-url }} --assetName=${{ inputs.asset-name }} --ref=${{ github.ref_name }} --artifactName="$artifact_name" fi " env: @@ -123,11 +134,16 @@ jobs: args: | sh -c " slug=$(devguard-scanner slug ${{ github.ref_name }}) && + artifact_name="$ARTIFACT_NAME" && + echo 'Fetching SAST results for artifact:' '${{ env.ARTIFACT_NAME }}' && devguard-scanner curl '${{ inputs.api-url }}/api/v1/organizations/${{ inputs.asset-name }}/refs/'$slug'/sarif.json' --token='${{ secrets.devguard-token }}' > /tmp/sarif.json && + echo 'SAST results downloaded to /tmp/sarif.json' && if [ -f image-digest.txt ]; then - devguard-scanner attest -u ${{ github.actor }} -r ghcr.io -p ${{ secrets.GITHUB_TOKEN }} /tmp/sarif.json \"$(cat image-tag.txt)@$(cat image-digest.txt)\" --predicateType='https://www.schemastore.org/schemas/json/sarif-2.1.0.json' --token='${{ secrets.devguard-token }}' --apiUrl=${{ inputs.api-url }} --assetName=${{ inputs.asset-name }} --ref=${{ github.ref_name }} --artifactName="${{ env.ARTIFACT_NAME }}" + echo 'Attesting SAST results with image digest present' && + devguard-scanner attest -u ${{ github.actor }} -r ghcr.io -p ${{ secrets.GITHUB_TOKEN }} /tmp/sarif.json \"$(cat image-tag.txt)@$(cat image-digest.txt)\" --predicateType='https://www.schemastore.org/schemas/json/sarif-2.1.0.json' --token='${{ secrets.devguard-token }}' --apiUrl=${{ inputs.api-url }} --assetName=${{ inputs.asset-name }} --ref=${{ github.ref_name }} --artifactName="$artifact_name" else - devguard-scanner attest /tmp/sarif.json --predicateType='https://www.schemastore.org/schemas/json/sarif-2.1.0.json' --token='${{ secrets.devguard-token }}' --apiUrl=${{ inputs.api-url }} --assetName=${{ inputs.asset-name }} --ref=${{ github.ref_name }} --artifactName="${{ env.ARTIFACT_NAME }}" + echo 'Attesting SAST results without image digest' && + devguard-scanner attest /tmp/sarif.json --predicateType='https://www.schemastore.org/schemas/json/sarif-2.1.0.json' --token='${{ secrets.devguard-token }}' --apiUrl=${{ inputs.api-url }} --assetName=${{ inputs.asset-name }} --ref=${{ github.ref_name }} --artifactName="$artifact_name" fi " env: @@ -142,10 +158,14 @@ jobs: with: args: | sh -c " + artifact_name="$ARTIFACT_NAME" && + echo 'Building provenance attestation for artifact:' '${{ env.ARTIFACT_NAME }}' && if [ -f image-digest.txt ]; then - devguard-scanner attest -u ${{ github.actor }} -r ghcr.io -p ${{ secrets.GITHUB_TOKEN }} build.provenance.json \"$(cat image-tag.txt)@$(cat image-digest.txt)\" --predicateType='https://slsa.dev/provenance/v1' --token='${{ secrets.devguard-token }}' --apiUrl=${{ inputs.api-url }} --assetName=${{ inputs.asset-name }} --ref=${{ github.ref_name }} --artifactName="${{ env.ARTIFACT_NAME }}" + echo 'Attesting provenance with image digest present' && + devguard-scanner attest -u ${{ github.actor }} -r ghcr.io -p ${{ secrets.GITHUB_TOKEN }} build.provenance.json \"$(cat image-tag.txt)@$(cat image-digest.txt)\" --predicateType='https://slsa.dev/provenance/v1' --token='${{ secrets.devguard-token }}' --apiUrl=${{ inputs.api-url }} --assetName=${{ inputs.asset-name }} --ref=${{ github.ref_name }} --artifactName="$artifact_name" else - devguard-scanner attest build.provenance.json --token='${{ secrets.devguard-token }}' --apiUrl=${{ inputs.api-url }} --predicateType='https://slsa.dev/provenance/v1' --assetName=${{ inputs.asset-name }} --ref=${{ github.ref_name }} --artifactName="${{ env.ARTIFACT_NAME }}" + echo 'Attesting provenance without image digest' && + devguard-scanner attest build.provenance.json --token='${{ secrets.devguard-token }}' --apiUrl=${{ inputs.api-url }} --predicateType='https://slsa.dev/provenance/v1' --assetName=${{ inputs.asset-name }} --ref=${{ github.ref_name }} --artifactName="$artifact_name" fi " env: From 82fa4ce5c3ed5594ab53227b2fe826b91da44c49 Mon Sep 17 00:00:00 2001 From: Tim Bastin Date: Mon, 6 Apr 2026 15:18:31 +0200 Subject: [PATCH 26/30] using devguardScanner from github rather than local flake --- .github/workflows/build-nix-image.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-nix-image.yml b/.github/workflows/build-nix-image.yml index 3508247..3359809 100644 --- a/.github/workflows/build-nix-image.yml +++ b/.github/workflows/build-nix-image.yml @@ -110,7 +110,7 @@ jobs: run: nix --version - name: Install crane and devguard-scanner - run: nix profile install nixpkgs#crane .#devguardScanner + run: nix profile install nixpkgs#crane github:l3montree-dev/devguard#devguardScanner - name: In-Toto Provenance record start run: devguard-scanner intoto start --step=build --token=${{ secrets.devguard-token }} --apiUrl=${{ inputs.api-url }} --assetName=${{ inputs.asset-name }} --supplyChainId=${{ github.sha }} From 606df5605490e09ab904d66b84de4734ccaf9432 Mon Sep 17 00:00:00 2001 From: Tim Bastin Date: Wed, 8 Apr 2026 15:13:45 +0200 Subject: [PATCH 27/30] troubleshooting build-image --- .github/workflows/build-image.yml | 110 +++++++++++++++--------------- 1 file changed, 55 insertions(+), 55 deletions(-) diff --git a/.github/workflows/build-image.yml b/.github/workflows/build-image.yml index 797fe91..a8b98e8 100644 --- a/.github/workflows/build-image.yml +++ b/.github/workflows/build-image.yml @@ -23,7 +23,7 @@ on: type: string required: false default: '' - description: "The name of the artifact you are building. This is useful when a single pipeline builds more than a single artifact like a container with a shell inside and one without. If you build a single artifact - leave it empty." + description: "The name of the artifact you are building. This is useful when a single pipeline builds more than a single artifact like a container with a shell inside and one without. If you build a single artifact - leave it empty." disable-artifact-registry-as-image-store: required: false default: false @@ -34,6 +34,11 @@ on: type: string required: false default: '' + nix-version: + description: 'Pinned Nix version used for deterministic builds (must match other CI systems)' + required: false + type: string + default: '2.34.4' secrets: devguard-token: description: 'DevGuard API token' @@ -55,22 +60,27 @@ jobs: fi echo "BUILD_ARGS=$BUILD_ARGS --no-push --tarPath /github/workspace/tmp-image.tar" >> $GITHUB_ENV - + - name: Checkout code uses: actions/checkout@v4 with: submodules: recursive persist-credentials: false + + - uses: cachix/install-nix-action@v31 + with: + install_url: ${{ format('https://releases.nixos.org/nix/nix-{0}/install', inputs.nix-version) }} + extra_nix_config: | + experimental-features = nix-command flakes + + - name: Install crane and devguard-scanner + run: nix profile install nixpkgs#crane github:l3montree-dev/devguard#devguardScanner + - name: In-Toto Provenance record start id: in-toto-start - uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main - with: - args: devguard-scanner intoto start --step=build --token=${{ secrets.devguard-token }} --apiUrl=${{ inputs.api-url }} --assetName=${{ inputs.asset-name }} --supplyChainId=${{ github.sha }} + run: devguard-scanner intoto start --step=build --token=${{ secrets.devguard-token }} --apiUrl=${{ inputs.api-url }} --assetName=${{ inputs.asset-name }} --supplyChainId=${{ github.sha }} continue-on-error: true - - name: Setup crane - uses: imjasonh/setup-crane@v0.1 - - name: Build Docker image with Kaniko # Building the Docker image using Kaniko id: build_image @@ -82,7 +92,7 @@ jobs: run: mv tmp-image.tar "${IMAGE_DESTINATION_PATH}" env: IMAGE_DESTINATION_PATH: ${{ inputs.image-destination-path }} - + - name: Use crane to get the digest run: | crane digest --tarball="${IMAGE_DESTINATION_PATH}" > image-digest.txt @@ -97,29 +107,31 @@ jobs: path: ${{ inputs.image-destination-path }} if: inputs.disable-artifact-registry-as-image-store == false - # Calculate the image tag with the same generator used in GitLab CI. - - name: Set IMAGE_TAG - uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main - with: - args: > - sh -c ' - if [ -n "$IMAGE" ]; then - IMAGE_TAG="$IMAGE" - else - if [ -n "$IMAGE_SUFFIX" ]; then - IMAGE_PATH="ghcr.io/${GITHUB_REPOSITORY}/${IMAGE_SUFFIX}" - else - IMAGE_PATH="ghcr.io/${GITHUB_REPOSITORY}" - fi - - devguard-scanner generate-tag --imagePath="$IMAGE_PATH" --ref="$GITHUB_REF_NAME" > image-tag-env.txt - IMAGE_TAG=$(grep '^IMAGE_TAG=' image-tag-env.txt | cut -d= -f2-) - fi - - IMAGE_TAG=$(echo "$IMAGE_TAG" | tr "[:upper:]" "[:lower:]") - echo "$IMAGE_TAG" > image-tag.txt - echo "IMAGE_TAG=$(cat image-tag.txt)" >> "$GITHUB_ENV" - ' + - name: Set image tag + id: set-image-tag + run: | + if [ -n "$IMAGE" ]; then + IMAGE_TAG="$IMAGE" + echo "$IMAGE_TAG" > image-tag.txt + echo "IMAGE_TAG=$IMAGE_TAG" >> "$GITHUB_ENV" + else + if [ -n "$IMAGE_SUFFIX" ]; then + IMAGE_PATH="ghcr.io/${GITHUB_REPOSITORY}/${IMAGE_SUFFIX}" + else + IMAGE_PATH="ghcr.io/${GITHUB_REPOSITORY}" + fi + devguard-scanner generate-tag \ + --imagePath="$IMAGE_PATH" \ + --ref="$GITHUB_REF_NAME" \ + >> image-tag-env.txt + IMAGE_TAG=$(grep '^IMAGE_TAG=' image-tag-env.txt | cut -d= -f2-) + ARTIFACT_NAME=$(grep '^ARTIFACT_NAME=' image-tag-env.txt | cut -d= -f2-) + ARTIFACT_URL_ENCODED=$(grep '^ARTIFACT_URL_ENCODED=' image-tag-env.txt | cut -d= -f2-) + echo "$IMAGE_TAG" > image-tag.txt + echo "IMAGE_TAG=$IMAGE_TAG" >> "$GITHUB_ENV" + echo "ARTIFACT_NAME=$ARTIFACT_NAME" >> "$GITHUB_ENV" + echo "ARTIFACT_URL_ENCODED=$ARTIFACT_URL_ENCODED" >> "$GITHUB_ENV" + fi env: IMAGE_SUFFIX: ${{ inputs.image-suffix }} IMAGE: ${{ inputs.image }} @@ -138,25 +150,21 @@ jobs: name: image-digest${{ inputs.image-suffix }} path: image-digest.txt - - name: Set Artifact purl + - name: Set artifact PURL run: | - if [ -n "$ARTIFACT_NAME" ]; then - PURL="$ARTIFACT_NAME" + if [ -n "$ARTIFACT_NAME_INPUT" ]; then + PURL="$ARTIFACT_NAME_INPUT" + SAFE_PURL=$(echo -n "$PURL" | jq -s -R -r @uri) else - IMAGE_TAG=$(cat image-tag.txt) - REGISTRY_AND_IMAGE=${IMAGE_TAG%:*} - VERSION=${IMAGE_TAG##*:} - NAMESPACE_AND_NAME=${REGISTRY_AND_IMAGE#*/} - NAME=${NAMESPACE_AND_NAME##*/} - REPOSITORY_URL="$REGISTRY_AND_IMAGE" - PURL="pkg:oci/$NAME?repository_url=$REPOSITORY_URL" + PURL="$ARTIFACT_NAME" + SAFE_PURL="$ARTIFACT_URL_ENCODED" fi - echo "$PURL" > artifact-purl.txt + echo "$SAFE_PURL" > artifact-purl-safe.txt echo "PURL=$PURL" >> $GITHUB_ENV echo "Using artifact name: $PURL" env: - ARTIFACT_NAME: ${{ inputs.artifact-name }} + ARTIFACT_NAME_INPUT: ${{ inputs.artifact-name }} - name: Upload artifact purl uses: actions/upload-artifact@v4 @@ -164,17 +172,11 @@ jobs: name: artifact-purl${{ inputs.image-suffix }} path: artifact-purl.txt - - name: create safe purl - run: | - SAFE_PURL=$(echo -n "$PURL" | jq -s -R -r @uri) - echo "$SAFE_PURL" > artifact-purl-safe.txt - echo "Safe artifact name: $SAFE_PURL" - - name: Upload safe artifact purl uses: actions/upload-artifact@v4 with: name: artifact-purl-safe${{ inputs.image-suffix }} - path: artifact-purl-safe.txt + path: artifact-purl-safe.txt # Upload the calculated image tag as an artifact - name: Upload image tag @@ -184,11 +186,9 @@ jobs: path: image-tag.txt - name: In-Toto Provenance record stop - uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main - with: - args: devguard-scanner intoto stop --step=build --products=image-digest.txt --products=image-tag.txt --token=${{ secrets.devguard-token }} --apiUrl=${{ inputs.api-url }} --assetName=${{ inputs.asset-name }} --supplyChainId=${{ github.sha }} --generateSlsaProvenance + run: devguard-scanner intoto stop --step=build --products=image-digest.txt --products=image-tag.txt --token=${{ secrets.devguard-token }} --apiUrl=${{ inputs.api-url }} --assetName=${{ inputs.asset-name }} --supplyChainId=${{ github.sha }} --generateSlsaProvenance continue-on-error: true - + - name: Upload SLSA Provenance uses: actions/upload-artifact@v4 with: From 116bcf5bf1530ddda1836f77d3b44caee2fb06b7 Mon Sep 17 00:00:00 2001 From: Tim Bastin Date: Wed, 8 Apr 2026 15:55:08 +0200 Subject: [PATCH 28/30] using generate-tag in build image --- .github/workflows/build-image.yml | 54 +++++++++++++++++-------------- 1 file changed, 29 insertions(+), 25 deletions(-) diff --git a/.github/workflows/build-image.yml b/.github/workflows/build-image.yml index a8b98e8..aeaf2f8 100644 --- a/.github/workflows/build-image.yml +++ b/.github/workflows/build-image.yml @@ -34,11 +34,6 @@ on: type: string required: false default: '' - nix-version: - description: 'Pinned Nix version used for deterministic builds (must match other CI systems)' - required: false - type: string - default: '2.34.4' secrets: devguard-token: description: 'DevGuard API token' @@ -67,18 +62,11 @@ jobs: submodules: recursive persist-credentials: false - - uses: cachix/install-nix-action@v31 - with: - install_url: ${{ format('https://releases.nixos.org/nix/nix-{0}/install', inputs.nix-version) }} - extra_nix_config: | - experimental-features = nix-command flakes - - - name: Install crane and devguard-scanner - run: nix profile install nixpkgs#crane github:l3montree-dev/devguard#devguardScanner - - name: In-Toto Provenance record start id: in-toto-start - run: devguard-scanner intoto start --step=build --token=${{ secrets.devguard-token }} --apiUrl=${{ inputs.api-url }} --assetName=${{ inputs.asset-name }} --supplyChainId=${{ github.sha }} + uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main + with: + args: devguard-scanner intoto start --step=build --token=${{ secrets.devguard-token }} --apiUrl=${{ inputs.api-url }} --assetName=${{ inputs.asset-name }} --supplyChainId=${{ github.sha }} continue-on-error: true - name: Build Docker image with Kaniko @@ -95,7 +83,11 @@ jobs: - name: Use crane to get the digest run: | - crane digest --tarball="${IMAGE_DESTINATION_PATH}" > image-digest.txt + docker run --rm \ + -v "$GITHUB_WORKSPACE:/workspace" \ + -w /workspace \ + ghcr.io/l3montree-dev/devguard/scanner:main \ + crane digest --tarball="${IMAGE_DESTINATION_PATH}" > image-digest.txt env: IMAGE_DESTINATION_PATH: ${{ inputs.image-destination-path }} @@ -109,6 +101,9 @@ jobs: - name: Set image tag id: set-image-tag + env: + IMAGE_SUFFIX: ${{ inputs.image-suffix }} + IMAGE: ${{ inputs.image }} run: | if [ -n "$IMAGE" ]; then IMAGE_TAG="$IMAGE" @@ -120,10 +115,14 @@ jobs: else IMAGE_PATH="ghcr.io/${GITHUB_REPOSITORY}" fi - devguard-scanner generate-tag \ - --imagePath="$IMAGE_PATH" \ - --ref="$GITHUB_REF_NAME" \ - >> image-tag-env.txt + docker run --rm \ + -e IMAGE_PATH \ + -e GITHUB_REF_NAME \ + ghcr.io/l3montree-dev/devguard/scanner:main \ + devguard-scanner generate-tag \ + --imagePath="$IMAGE_PATH" \ + --ref="$GITHUB_REF_NAME" \ + >> image-tag-env.txt IMAGE_TAG=$(grep '^IMAGE_TAG=' image-tag-env.txt | cut -d= -f2-) ARTIFACT_NAME=$(grep '^ARTIFACT_NAME=' image-tag-env.txt | cut -d= -f2-) ARTIFACT_URL_ENCODED=$(grep '^ARTIFACT_URL_ENCODED=' image-tag-env.txt | cut -d= -f2-) @@ -132,13 +131,16 @@ jobs: echo "ARTIFACT_NAME=$ARTIFACT_NAME" >> "$GITHUB_ENV" echo "ARTIFACT_URL_ENCODED=$ARTIFACT_URL_ENCODED" >> "$GITHUB_ENV" fi - env: - IMAGE_SUFFIX: ${{ inputs.image-suffix }} - IMAGE: ${{ inputs.image }} - name: Upload to container registry run: | - crane push "${IMAGE_DESTINATION_PATH}" $(cat image-tag.txt) + docker run --rm \ + -v "$GITHUB_WORKSPACE:/workspace" \ + -w /workspace \ + -v "$DOCKER_CONFIG:/root/.docker:ro" \ + -e DOCKER_CONFIG=/root/.docker \ + ghcr.io/l3montree-dev/devguard/scanner:main \ + crane push "${IMAGE_DESTINATION_PATH}" "$(cat image-tag.txt)" env: IMAGE_DESTINATION_PATH: ${{ inputs.image-destination-path }} if: inputs.disable-artifact-registry-as-image-store == true @@ -186,7 +188,9 @@ jobs: path: image-tag.txt - name: In-Toto Provenance record stop - run: devguard-scanner intoto stop --step=build --products=image-digest.txt --products=image-tag.txt --token=${{ secrets.devguard-token }} --apiUrl=${{ inputs.api-url }} --assetName=${{ inputs.asset-name }} --supplyChainId=${{ github.sha }} --generateSlsaProvenance + uses: docker://ghcr.io/l3montree-dev/devguard/scanner:main + with: + args: devguard-scanner intoto stop --step=build --products=image-digest.txt --products=image-tag.txt --token=${{ secrets.devguard-token }} --apiUrl=${{ inputs.api-url }} --assetName=${{ inputs.asset-name }} --supplyChainId=${{ github.sha }} --generateSlsaProvenance continue-on-error: true - name: Upload SLSA Provenance From 7e678c19e45d453d4f93d9de3d31f8e5f321b419 Mon Sep 17 00:00:00 2001 From: Tim Bastin Date: Wed, 8 Apr 2026 16:34:53 +0200 Subject: [PATCH 29/30] troubleshooting DOCKER_CONFIG variable --- .github/workflows/build-image.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/build-image.yml b/.github/workflows/build-image.yml index aeaf2f8..99d9815 100644 --- a/.github/workflows/build-image.yml +++ b/.github/workflows/build-image.yml @@ -137,8 +137,7 @@ jobs: docker run --rm \ -v "$GITHUB_WORKSPACE:/workspace" \ -w /workspace \ - -v "$DOCKER_CONFIG:/root/.docker:ro" \ - -e DOCKER_CONFIG=/root/.docker \ + -v "${HOME}/.docker:/tmp/.docker:ro" \ ghcr.io/l3montree-dev/devguard/scanner:main \ crane push "${IMAGE_DESTINATION_PATH}" "$(cat image-tag.txt)" env: From caf9e63a7d356efdc227c6de23b5bc44b2e44c67 Mon Sep 17 00:00:00 2001 From: Tim Bastin Date: Wed, 8 Apr 2026 17:37:59 +0200 Subject: [PATCH 30/30] adds crane auth login --- .github/workflows/build-image.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.github/workflows/build-image.yml b/.github/workflows/build-image.yml index 99d9815..ce43d98 100644 --- a/.github/workflows/build-image.yml +++ b/.github/workflows/build-image.yml @@ -132,6 +132,14 @@ jobs: echo "ARTIFACT_URL_ENCODED=$ARTIFACT_URL_ENCODED" >> "$GITHUB_ENV" fi + - name: Log in to ghcr.io + run: | + docker run --rm \ + -v "${HOME}/.docker:/tmp/.docker" \ + ghcr.io/l3montree-dev/devguard/scanner:main \ + crane auth login ghcr.io -u ${{ github.actor }} -p ${{ github.token }} + if: inputs.disable-artifact-registry-as-image-store == true + - name: Upload to container registry run: | docker run --rm \