Skip to content

rekor-monitor

rekor-monitor #184

Workflow file for this run

# SPDX-License-Identifier: AGPL-3.0-only
# Copyright (C) 2026 RS-Key contributors
# Rekor transparency-log identity monitor — a supply-chain tripwire.
#
# Our releases sign keyless inside release-build.yml: cosign over SHA256SUMS
# plus the SLSA build-provenance attestation, both recorded in the PUBLIC Rekor
# transparency log (docs/supply-chain.md). That log is tamper-EVIDENT, not
# tamper-proof — it only helps if someone actually watches it.
#
# Every hour this asks sigstore/rekor-monitor "did anything sign as an RS-Key
# GitHub-Actions identity?" and files a GitHub issue with whatever it finds.
# Every legitimate release adds entries from release-build.yml, so a couple of
# EXPECTED issues per release are normal — confirm and close them. The signal
# that matters is an entry you do NOT recognise: that would mean our signing
# identity was used by something we did not run (a compromised GitHub-OIDC
# token, repo, or Actions runner) — the one thing that could forge provenance
# the SLSA Build L3 attestation otherwise vouches for.
#
# We watch the WHOLE …/RS-Key/.github/workflows/ namespace, not just
# release-build.yml: only release-build.yml ever signs legitimately, so a
# signature from any other workflow path in this repo is itself the alarm.
#
# rekor-monitor ships no tags/releases, so the reusable workflow is pinned to a
# main commit; Dependabot's weekly github-actions group keeps the pin fresh.
name: rekor-monitor
on:
schedule:
- cron: "23 * * * *" # hourly at :23 — upstream-recommended cadence (off the top of the hour, which GitHub heavily contends)
workflow_dispatch:
# Deny everything at the top; the job below grants exactly what the reusable
# workflow needs and nothing more.
permissions: {}
concurrency:
group: rekor-monitor
cancel-in-progress: false # never abort a run mid-checkpoint
jobs:
# Self-heal the "death spiral". rekor-monitor persists its log position as a
# `checkpoint` GH artifact. If a run is cancelled by the reusable workflow's
# 60-min job timeout BEFORE it uploads a fresh checkpoint, the stale one is
# reused forever and every later run re-scans an ever-growing slice of the
# (~1.75-billion-entry, +400k/hr) Rekor log → another timeout → the monitor is
# wedged until the artifact is deleted by hand (happened 2026-06-20). This caps
# the damage at ONE cancelled run: if the previous run did not finish, drop the
# stuck checkpoint so the monitor below re-seeds to the current log size. The
# step is best-effort and always exits 0 — it must never block the monitor.
preflight:
runs-on: ubuntu-latest
permissions:
actions: write # read run conclusions + delete the stuck checkpoint artifact
steps:
- name: Reset a stuck checkpoint after a cancelled run
env:
GH_TOKEN: ${{ github.token }}
REPO: ${{ github.repository }}
run: |
last=$(gh api "repos/$REPO/actions/workflows/rekor-monitor.yml/runs?status=completed&per_page=1" \
--jq '.workflow_runs[0].conclusion // "none"' 2>/dev/null || echo "none")
echo "previous completed rekor-monitor run: $last"
case "$last" in
cancelled | timed_out)
echo "::warning::previous run did not finish — deleting the stuck checkpoint so the monitor re-seeds"
gh api "repos/$REPO/actions/artifacts?name=checkpoint&per_page=100" \
--jq '.artifacts[].id' 2>/dev/null |
while read -r id; do
gh api -X DELETE "repos/$REPO/actions/artifacts/$id" 2>/dev/null &&
echo "deleted checkpoint artifact $id"
done
;;
*)
echo "checkpoint healthy — nothing to reset"
;;
esac
exit 0
monitor:
needs: preflight
permissions:
contents: read # checkout the reusable workflow
issues: write # file an issue when a watched identity appears
id-token: write # detect the running repo/ref for the reusable workflow
uses: sigstore/rekor-monitor/.github/workflows/reusable_monitoring.yml@50847dce81efa8d76093c64e08ba48d2c21399c3 # main @ 2026-06-18
with:
file_issue: true
once: true
config: |
monitoredValues:
certIdentities:
- certSubject: '^https://github\.com/TheMaxMur/RS-Key/\.github/workflows/.*$'
issuers:
- '^https://token\.actions\.githubusercontent\.com$'