From b50dd6386ecb9391cecc1a4a3b110d9f45a2fbf0 Mon Sep 17 00:00:00 2001 From: devitway Date: Wed, 18 Mar 2026 09:49:45 +0000 Subject: [PATCH] security: pin Docker base images by SHA, cosign signing in release, branch protection - Pin alpine:3.20 by SHA digest in all Dockerfiles (Pinned-Dependencies) - Add cosign keyless signing for Docker images and binary (Signed-Releases) - Enable branch protection: strict status checks, linear history, no force push - Add .sig and .pem to GitHub Release assets --- .github/workflows/release.yml | 23 ++++++++++++++++++++++- Dockerfile | 2 +- Dockerfile.astra | 2 +- Dockerfile.redos | 2 +- 4 files changed, 25 insertions(+), 4 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 857bd34..385415f 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -18,6 +18,7 @@ jobs: permissions: contents: read packages: write + id-token: write # Sigstore cosign keyless signing steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 @@ -130,6 +131,17 @@ jobs: cache-to: type=registry,ref=${{ env.NORA }}/${{ env.IMAGE_NAME }}-cache:astra,mode=max # ── Smoke test ────────────────────────────────────────────────────────── + - name: Install cosign + uses: sigstore/cosign-installer@dc72c7d5c4d10cd6bcb8cf6e3fd1d5ad67616c25 # v3 + + - name: Sign Docker images (keyless Sigstore) + run: | + TAGS=($(echo "${{ steps.meta-alpine.outputs.tags }}" | tr "\n" " ")) + for tag in "${TAGS[@]}"; do + [[ "$tag" == *"localhost"* ]] && continue + cosign sign --yes "$tag" + done + - name: Smoke test — verify alpine image starts and responds run: | docker rm -f nora-smoke 2>/dev/null || true @@ -189,7 +201,8 @@ jobs: needs: [build, scan] permissions: contents: write - packages: read + id-token: write # Sigstore cosign keyless signing + packages: write # cosign needs push for signatures steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 @@ -226,6 +239,12 @@ jobs: format: cyclonedx-json output-file: nora-${{ github.ref_name }}.sbom.cdx.json + - name: Install cosign + uses: sigstore/cosign-installer@dc72c7d5c4d10cd6bcb8cf6e3fd1d5ad67616c25 # v3 + + - name: Sign binary with cosign (keyless Sigstore) + run: cosign sign-blob --yes --output-signature nora-linux-amd64.sig --output-certificate nora-linux-amd64.pem ./nora-linux-amd64 + - name: Create Release uses: softprops/action-gh-release@153bb8e04406b158c6c84fc1615b65b24149a1fe # v2 with: @@ -233,6 +252,8 @@ jobs: files: | nora-linux-amd64 nora-linux-amd64.sha256 + nora-linux-amd64.sig + nora-linux-amd64.pem nora-${{ github.ref_name }}.sbom.spdx.json nora-${{ github.ref_name }}.sbom.cdx.json body: | diff --git a/Dockerfile b/Dockerfile index 282d2dc..566c071 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,6 +1,6 @@ # syntax=docker/dockerfile:1.4 # Binary is pre-built by CI (cargo build --release) and passed via context -FROM alpine:3.20 +FROM alpine:3.20@sha256:a4f4213abb84c497377b8544c81b3564f313746700372ec4fe84653e4fb03805 RUN apk add --no-cache ca-certificates && mkdir -p /data diff --git a/Dockerfile.astra b/Dockerfile.astra index bfd7627..d3c04f3 100644 --- a/Dockerfile.astra +++ b/Dockerfile.astra @@ -5,7 +5,7 @@ # FROM registry.astralinux.ru/library/alse:latest # RUN apt-get update && apt-get install -y --no-install-recommends ca-certificates && rm -rf /var/lib/apt/lists/* -FROM alpine:3.20 AS certs +FROM alpine:3.20@sha256:a4f4213abb84c497377b8544c81b3564f313746700372ec4fe84653e4fb03805 AS certs RUN apk add --no-cache ca-certificates FROM scratch diff --git a/Dockerfile.redos b/Dockerfile.redos index 4010bf9..c70d62b 100644 --- a/Dockerfile.redos +++ b/Dockerfile.redos @@ -5,7 +5,7 @@ # FROM registry.red-soft.ru/redos/redos:8 # RUN dnf install -y ca-certificates && dnf clean all -FROM alpine:3.20 AS certs +FROM alpine:3.20@sha256:a4f4213abb84c497377b8544c81b3564f313746700372ec4fe84653e4fb03805 AS certs RUN apk add --no-cache ca-certificates FROM scratch