Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .github/allowed_signers
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# SSH allowed-signers for verifying commit signatures in CI (the commit-signing
# job in ci.yaml points gpg.ssh.allowedSignersFile here). One line per trusted
# maintainer signing key: "<committer-email> namespaces=\"git\" <key>".
# Add a contributor's *signing* key here when they start signing commits.
malte.kiefer@mailbox.org namespaces="git" ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGbTRZn7tO3Zpw9491nXQICExYHG1J5aJEO5AfvjKaJI pr0ph37
18 changes: 11 additions & 7 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ jobs:
persist-credentials: false # AUDIT 4.3.1.18
- uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0
with:
go-version: '1.26.3'
go-version: '1.26.5'
cache: true

- name: vet
Expand Down Expand Up @@ -62,7 +62,7 @@ jobs:
persist-credentials: false # AUDIT 4.3.1.18
- uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0
with:
go-version: '1.26.3'
go-version: '1.26.5'
# AUDIT 4.3.1.13: pin govulncheck to a specific tag rather than @latest
# so a malicious or accidental upstream tag move can't silently land in
# CI. Annual review: bump to current latest on each scheduled audit pass
Expand All @@ -85,7 +85,7 @@ jobs:
persist-credentials: false # AUDIT 4.3.1.18
- uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0
with:
go-version: '1.26.3'
go-version: '1.26.5'
cache: false # golangci-lint-action manages its own caches
- uses: golangci/golangci-lint-action@1e7e51e771db61008b38414a730f564565cf7c20 # v9.2.0
with:
Expand All @@ -99,7 +99,7 @@ jobs:
persist-credentials: false # AUDIT 4.3.1.18
- uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0
with:
go-version: '1.26.3'
go-version: '1.26.5'
# AUDIT 4.3.1.12: severity floor lowered from "high" to "medium" so we
# don't silently miss medium-severity findings. Any newly-surfaced
# medium false positive must be added to -exclude with an inline
Expand Down Expand Up @@ -242,7 +242,7 @@ jobs:
persist-credentials: false # AUDIT 4.3.1.18
- uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0
with:
go-version: '1.26.3'
go-version: '1.26.5'
cache: true
- name: test-migrations
run: make test-migrations
Expand All @@ -263,7 +263,7 @@ jobs:
persist-credentials: false # AUDIT 4.3.1.18
- uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0
with:
go-version: '1.26.3'
go-version: '1.26.5'
cache: true
- name: regenerate spec
run: |
Expand Down Expand Up @@ -300,12 +300,16 @@ jobs:
- name: verify signatures
run: |
set -euo pipefail
# AUDIT-2026-07-16: %G? can only return G/U for SSH-signed commits
# when git has an allowed-signers file; point it at the committed
# maintainer key list so signatures actually verify on the runner.
git config gpg.ssh.allowedSignersFile "${GITHUB_WORKSPACE}/.github/allowed_signers"
base="${{ github.event.pull_request.base.sha }}"
head="${{ github.event.pull_request.head.sha }}"
unsigned=$(git log "$base..$head" --pretty=format:'%H %G?' \
| awk '$2 != "G" && $2 != "U" { print $1 }')
if [ -n "$unsigned" ]; then
echo "::error::Unsigned commits found:"
echo "::error::Unsigned or unverifiable commits found:"
echo "$unsigned"
exit 1
fi
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/fuzz.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ jobs:
persist-credentials: false
- uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0
with:
go-version: '1.26.3'
go-version: '1.26.5'
cache: true
- name: run fuzz target
id: fuzz
Expand Down
52 changes: 41 additions & 11 deletions .github/workflows/release.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,11 @@ concurrency:
group: release-${{ github.ref }}
cancel-in-progress: false

# AUDIT-2026-07-16 L2: least privilege. The default token is read-only; only
# the jobs that push a tag (auto-tag) or upload release assets (publish) get
# contents: write, and the container job scopes its own extra permissions.
permissions:
contents: write
contents: read

# NOTE: Go patch pin (4.3.1.19) — keep go-version in lockstep with go.mod's
# `go <X.Y.Z>` line. Bump procedure: update go.mod, then sweep this file for
Expand All @@ -58,6 +61,8 @@ jobs:
# created the tag. No `repository_dispatch` or PAT plumbing required.
auto-tag:
runs-on: ubuntu-latest
permissions:
contents: write # pushes the bumped version tag
outputs:
version: ${{ steps.tag.outputs.version }}
channel: ${{ steps.tag.outputs.channel }}
Expand Down Expand Up @@ -108,7 +113,7 @@ jobs:
ref: ${{ needs.auto-tag.outputs.version }}
- uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0
with:
go-version: '1.26.3'
go-version: '1.26.5'
cache: true

- name: derive version
Expand Down Expand Up @@ -136,6 +141,18 @@ jobs:
-X github.com/MalteKiefer/MonSys/internal/shared/version.Version=${VERSION} \
-X github.com/MalteKiefer/MonSys/internal/shared/version.Commit=${COMMIT} \
-X github.com/MalteKiefer/MonSys/internal/shared/version.Date=${DATE}"
# AUDIT-2026-07-16 C1: embed the minisign public key so the agent's
# self-updater has an out-of-band trust anchor. The key lives in
# deploy/release.pub (line 2 of a minisign .pub is the base64 key).
# Without it the agent falls back to placeholder and self-update
# fails closed (never SHA-256-only), so a missing key degrades to
# "no auto-update", not "unsigned auto-update".
if [ -f deploy/release.pub ]; then
PUBKEY="$(tail -n1 deploy/release.pub)"
LDFLAGS="$LDFLAGS -X github.com/MalteKiefer/MonSys/internal/agent/updater.PublicKey=${PUBKEY}"
else
echo "::warning title=agent update key::deploy/release.pub absent; mon-agent self-update will be disabled (fail-closed) in this build."
fi
go build -trimpath -ldflags="$LDFLAGS" -o "out/mon-agent-linux-${GOARCH}" ./cmd/mon-agent
go build -trimpath -ldflags="$LDFLAGS" -o "out/mon-server-linux-${GOARCH}" ./cmd/mon-server

Expand Down Expand Up @@ -173,12 +190,12 @@ jobs:
- name: stage SBOMs alongside binaries
run: mv SBOM-*.cdx.json out/

# AUDIT-401: detached minisign signatures alongside each binary. The
# agent updater pulls these from the same release URL and verifies
# them against the public key compiled into the binary. We skip
# signing (with a warning, not a failure) when either secret is
# unset so the very first run after introducing this step doesn't
# break the release pipeline before secrets have been added.
# AUDIT-401 / AUDIT-2026-07-16 C1: detached minisign signatures
# alongside each binary. The agent updater pulls these from the same
# release URL and verifies them against the public key compiled into
# the binary. Signing is REQUIRED — if the secrets are missing the job
# fails rather than publishing unsigned artifacts, because the agent
# fleet auto-updates from these binaries as root.
- name: sign artifacts (minisign)
working-directory: out
env:
Expand All @@ -187,9 +204,12 @@ jobs:
MINISIGN_PASSWORD: ${{ secrets.MONSYS_MINISIGN_PASSWORD }}
run: |
set -euo pipefail
if [ -z "${MINISIGN_SECRET_KEY:-}" ] || [ -z "${MINISIGN_PASSWORD:-}" ]; then
echo "::warning title=minisign skipped::MONSYS_MINISIGN_SECRET_KEY and/or MONSYS_MINISIGN_PASSWORD not set; release will publish without signatures."
exit 0
# AUDIT-2026-07-16 C1: signing is required. The secret key is an
# UNENCRYPTED minisign key (matching deploy/release.pub); minisign -S
# signs it non-interactively, so no password is needed in CI.
if [ -z "${MINISIGN_SECRET_KEY:-}" ]; then
echo "::error title=minisign secret missing::set the MONSYS_MINISIGN_SECRET_KEY secret (unencrypted key matching deploy/release.pub); refusing to publish unsigned release artifacts."
exit 1
fi
# AUDIT 4.3.1.14: pin minisign by SHA256 instead of apt-get. The
# distro package may lag on security fixes and is unverified
Expand Down Expand Up @@ -255,6 +275,10 @@ jobs:
container:
needs: [auto-tag, build]
runs-on: ubuntu-latest
# AUDIT-2026-07-16 M5: gate artifact publishing behind a protected
# environment. Configure Settings > Environments > "release" with required
# reviewers so an unreviewed push to main cannot auto-ship to the fleet.
environment: release
# AUDIT 4.3.1.8: scoped permissions for this job only — id-token: write
# enables cosign keyless OIDC signing against the public sigstore Fulcio
# instance; packages: write enables GHCR push.
Expand Down Expand Up @@ -361,6 +385,12 @@ jobs:
publish:
needs: [auto-tag, build, sbom-source, container]
runs-on: ubuntu-latest
# AUDIT-2026-07-16 M5: same protected "release" environment gate as the
# container job — requires the configured reviewers to approve before
# binaries/release assets are published.
environment: release
permissions:
contents: write # creates releases and uploads release assets
steps:
# NOTE: this checkout intentionally does NOT set persist-credentials:
# false because the `release (latest)` step below uses `gh release
Expand Down
2 changes: 1 addition & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ repos:
hooks:
- id: gitleaks
- repo: https://github.com/golangci/golangci-lint
rev: v1.62.2
rev: v2.11.4
hooks:
- id: golangci-lint
- repo: https://github.com/pre-commit/pre-commit-hooks
Expand Down
Loading
Loading