-
Notifications
You must be signed in to change notification settings - Fork 90
feat(ci): Rekor v2 identity monitoring for the release signer #1727
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -53,17 +53,71 @@ failure during the first 60s after tag publish. Re-run the workflow. | |
|
|
||
| The `Rekor Monitor` workflow (`.github/workflows/rekor-monitor.yaml`) runs | ||
| hourly and calls the upstream `sigstore/rekor-monitor` reusable workflow. It | ||
| watches the public-good Rekor transparency log for two things: that the log | ||
| stays append-only (consistency), and that no entry appears under AICR's release | ||
| signing identity that a release did not produce (identity). On either failure it | ||
| opens an issue. | ||
| watches the **Rekor v2** transparency log (where AICR release signing writes | ||
| since [#1650](https://github.com/NVIDIA/aicr/issues/1650)) for two things, both | ||
| in one job: that the log stays append-only (consistency), and that no entry | ||
| appears under AICR's release signing identity that a release did not produce | ||
| (identity). On either failure it opens an issue. | ||
|
|
||
| This protects the trust root every AICR consumer depends on: the release | ||
| binaries, the signed recipe catalog, and the container images all chain to that | ||
| one identity. When the workflow files an issue, follow the triage steps in the | ||
| workflow file's header comment; an unrecognized identity hit should be treated | ||
| as potential OIDC/key compromise. | ||
|
|
||
| ### Why v2, and why identity monitoring is feasible now | ||
|
|
||
| Identity monitoring is a linear scan of every entry added to the log since the | ||
| last checkpoint, because Rekor's index cannot be queried by certificate SAN and | ||
| AICR's keyless release identity has no email or fixed public key to search on. | ||
| On the Rekor **v1** firehose that scan runs roughly 50x slower than the log | ||
| grows, so it can never keep up inside a bounded CI job: the earlier v1 | ||
| identity config timed out on every run and never completed a single scan | ||
| ([#1623](https://github.com/NVIDIA/aicr/issues/1623)). Rekor **v2** is | ||
| tile-based: bulk 256-entry reads let a single worker outpace the log, so the | ||
| identity scan is a cheap job that always finishes. This is why the whole design | ||
| is a single unbounded scan again rather than sharded paging. | ||
|
|
||
| ### Shard selection (automatic, no manual re-tune) | ||
|
|
||
| The monitor selects Rekor v2 by pointing its `url` at a v2 shard listed in the | ||
| Sigstore `SigningConfig`; a match on a v2 service switches it to v2, after which | ||
| it auto-discovers the **full** shard set from TUF and refreshes it every run. | ||
|
|
||
| The shard URL is **not hardcoded**. The `resolve-v2-shard` job computes it at run | ||
| time from the same TUF-distributed signing config that release signing resolves, | ||
| then feeds it to the monitor: | ||
|
|
||
| ```bash | ||
| # Same command the resolve-v2-shard job runs (works from a fresh checkout). | ||
| go run ./cmd/aicr trust update --emit-signing-config signing-config.json | ||
| jq -er '[.rekorTlogUrls[] | select(.majorApiVersion == 2)] | sort_by(.validFor.start) | last | .url' signing-config.json | ||
| ``` | ||
|
|
||
| Because it reads the signing config directly, the monitor provably watches where | ||
| releases actually write, and yearly shard rotation (`log2025-1` -> `log2026-1` | ||
| -> ...) needs no change to this workflow. If the resolve job ever fails (for | ||
| example the TUF CDN is unreachable), the monitor job is skipped for that run and | ||
| retries on the next hourly tick. | ||
|
|
||
| ### First run after switching from v1: reset the checkpoint | ||
|
|
||
| The `checkpoint` artifact persists a **v1** checkpoint from the prior config; a | ||
| v2 run cannot parse it and will fail. After merging a change that moves this | ||
| workflow to v2, delete the stale artifact once so the first v2 run establishes a | ||
| fresh v2 baseline (it saves the current v2 tree head and scans forward from | ||
| there): | ||
|
|
||
| ```bash | ||
| gh api "repos/NVIDIA/aicr/actions/artifacts?name=checkpoint" \ | ||
| --jq '.artifacts[].id' \ | ||
| | xargs -I{} gh api -X DELETE "repos/NVIDIA/aicr/actions/artifacts/{}" | ||
| ``` | ||
|
Comment on lines
+111
to
+115
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win 🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -euo pipefail
printf '\n## docs/contributor/maintaining.md (around lines 111-115)\n'
nl -ba docs/contributor/maintaining.md | sed -n '100,125p'
printf '\n## Search for related artifact cleanup guidance\n'
rg -n "actions/artifacts|checkpoint cleanup|checkpoint" docs .github -g '!**/node_modules/**' || trueRepository: NVIDIA/aicr Length of output: 248 🌐 Web query:
💡 Result: The GitHub REST API endpoints for listing artifacts support pagination via the Citations:
🏁 Script executed: #!/bin/bash
set -euo pipefail
python3 - <<'PY'
from pathlib import Path
p = Path("docs/contributor/maintaining.md")
for i, line in enumerate(p.read_text().splitlines(), 1):
if 100 <= i <= 125:
print(f"{i:4d}: {line}")
PY
printf '\n## Related mentions\n'
python3 - <<'PY'
from pathlib import Path
import re
for path in [Path("docs/contributor/maintaining.md")]:
text = path.read_text()
for m in re.finditer(r'checkpoint|artifact|gh api', text, re.I):
line = text.count("\n", 0, m.start()) + 1
print(f"{path}:{line}")
PYRepository: NVIDIA/aicr Length of output: 1897 🌐 Web query:
💡 Result: The GitHub Actions artifacts API endpoints (e.g., Citations:
Paginate the checkpoint cleanup. 🤖 Prompt for AI Agents |
||
|
|
||
| The first v2 run then watches forward from the current head; historical entries | ||
| predating the baseline are covered by release-time verification (the `aicr | ||
| verify` path), not by this monitor. | ||
|
Comment on lines
+117
to
+119
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🔒 Security & Privacy | 🟠 Major | 🏗️ Heavy lift 🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -euo pipefail
# Inspect the referenced doc section with line numbers
sed -n '100,140p' docs/contributor/maintaining.md | cat -n
# Find references to the v2 run / checkpoint / verify wording
rg -n "v2 run|checkpoint|aicr verify|Rekor|identity scan|historical" docs pkg cmd .github -S
# Map likely verification-related files before reading
fd -a "verify" docs pkg cmd tools | sed -n '1,200p'Repository: NVIDIA/aicr Length of output: 50369 🏁 Script executed: #!/bin/bash
set -euo pipefail
# Read the user-facing verification docs around the relevant claims
sed -n '160,190p' docs/user/artifact-verification.md | cat -n
sed -n '2550,2635p' docs/user/cli-reference.md | cat -n
sed -n '1,90p' docs/integrator/supply-chain-verification.md | cat -n
# Inspect the verifier implementation for any Rekor history scanning
ast-grep outline pkg/bundler/attestation/verifying.go --view expanded
ast-grep outline pkg/evidence/verifier/verify.go --view expanded
# Search for code paths that query Rekor entries by identity, history, or monitor-style scanning
rg -n "history|historical|identity scan|certificate SAN|Rekor.*search|rekor.*search|entries.*identity|query.*Rekor|scan forward|baseline" pkg docs -SRepository: NVIDIA/aicr Length of output: 29801 🏁 Script executed: #!/bin/bash
set -euo pipefail
# Read the surrounding maintenance guidance, including the historical audit section
sed -n '288,325p' docs/contributor/maintaining.md | cat -n
# Inspect the verifier implementation paths for any identity-history scan behavior
sed -n '1,220p' pkg/bundler/attestation/verifying.go | cat -n
sed -n '1,280p' pkg/evidence/verifier/verify.go | cat -n
# Look for any Rekor search-by-identity or history scan code
rg -n "search.*identity|identity.*search|SAN|history scan|historical scan|Rekor.*UUID|rekor-cli search|search --sha|search --email|certificate identity" pkg docs -SRepository: NVIDIA/aicr Length of output: 29915 Add a one-time Rekor history audit before dropping the v1 checkpoint. The v2 monitor only advances from the new head, and 🤖 Prompt for AI Agents |
||
|
|
||
| ## Reviewing Recipe Contributions | ||
|
|
||
| A recipe PR touches `recipes/overlays/`, `recipes/mixins/`, | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.