Skip to content

security: re-approve the EKS authorization surface so #2402 can land, then tighten the tenant RGD matcher #2817

Description

@devantler

🤖 Generated by the Agentic Engineer

Evidence

#2402 tightened the cosign subject matchers on the four live OCIRepository trust rules from @.+ to @([0-9a-f]{40}|refs/tags/v.+)$ and dropped the dead (reusable-workflows|actions) alternation. The tenant ResourceGraphDefinition carries a fifth copy of the same matcher and was deliberately left out of that PR:

k8s/bases/infrastructure/resource-graph-definitions/tenant/resource-graph-definition.yaml
subject: '^https://github\.com/devantler-tech/(reusable-workflows|actions)/\.github/workflows/publish-app\.yaml@.+$'

This is the template every new tenant is generated from, so while it is loose, every tenant created from now on inherits the weak rule and the #2402 fix does not stick.

Why it was split out

Including it turned 🔐 Validate EKS Authorization red — measured on PR #2816, run 30202725015. The RGD sits inside the rendered authorization surface, so editing it moves the aggregate fingerprint expectedRenderedSurfaceSHA pins.

That gate is working as designed, and main.go is explicit about how to clear it:

Do NOT treat a moved hash as self-evidently benign: re-run the per-entry membership measurement above before re-approving.

The measurement is a render of both trees and an entry-by-entry diff (the current approved value documents 159 entries with exactly one moving). The agent host has no Go toolchain installed, so that measurement could not be run locally, and pasting the new hash out of the CI failure would be precisely the blind re-approval the comment forbids on a security gate.

Diagnostic detail worth keeping: the failing run reported the aggregate mismatch only — no unapproved rendered <identity> fingerprint, no missing rendered authorization resource, no duplicate. So no individually pinned grant-bearing object moved. That is suggestive but is not the required per-entry measurement, because the aggregate covers entries beyond the individually pinned set.

Smallest useful change

  1. Run the per-entry surface measurement on a machine with Go (or via a CI job that prints the entry list for both trees).
  2. Confirm the only moving entry is the tenant RGD and that its delta is the cosign subject line alone.
  3. Apply the same tightening as Tighten cosign OIDC subject ref matchers (@.+) on OCIRepository verify rules #2402, update expectedRenderedSurfaceSHA, and record the measurement in the constant's comment in the established house style (entry counts, which entry moved, old → new fingerprint, and why it grants nothing new).

Acceptance criteria

  • The tenant RGD's matcher rejects a floating ref and accepts the SHA and release-tag forms, matching the four rules Tighten cosign OIDC subject ref matchers (@.+) on OCIRepository verify rules #2402 already tightened.
  • expectedRenderedSurfaceSHA is updated with a recorded per-entry measurement, not from the CI error text.
  • The constant's comment names the entry count, the moved entry, and why no grant-bearing object is added, removed or repointed.
  • 🔐 Validate EKS Authorization is green.

Notes

Sibling follow-up #2815 covers the same weakness at the container-image layer. The host's missing Go toolchain is worth fixing on its own account — it blocks running any of this repo's Go guards locally.

Part of #2402. Rough size: S, once the measurement can be run.

Activity

  1. coderabbitai commented on Jul 26, 2026

    @coderabbitai
    Contributor
    🔗 Related PRs

    #2399 - feat: accept devantler-tech/actions cosign subjects during the publish-workflow repoint [merged]
    #2404 - fix: tenant artifact verification rejects the dual signing identities from #2399 [merged]
    #2408 - fix(rgd): single regex-alternated cosign identity for tenant artifact verification [merged]
    #2633 - fix(deploy): verify incoming image on Talos nodes [merged]
    #2753 - fix(aws): allow EKS version discovery [merged]


    📝 Issue Planner

    Check the box below or use the @coderabbitai plan command to generate an implementation plan and prompts that you can use with your favorite coding assistant.

    • Create Plan

    🧪 Issue enrichment is currently in open beta.

    You can configure auto-planning by selecting labels in the issue_enrichment configuration.

    To disable automatic issue enrichment, add the following to your .coderabbit.yaml:

    issue_enrichment:
      auto_enrich:
        enabled: false

    💬 Have feedback or questions? Drop into our discord!

  2. moved this to 📥 Backlog in 🌊 Project Boardon Jul 26, 2026
  3. devantler commented on Jul 26, 2026

    @devantler
    ContributorAuthor

    🤖 Generated by the Agentic Engineer

    Correction to this issue's framing. It was filed on the hypothesis that the tenant RGD was what moved the authorization fingerprint, and that the four app OCIRepository files were surface-neutral. CI falsified that: the guard still fails with only those four files changed. An OCIRepository carrying a ghcr-auth secretRef is itself in the selected surface, so any edit to it moves the aggregate hash.

    So the re-approval is needed for #2402 as a whole, not just for the RGD, and PR #2816 is blocked on it.

    The per-entry measurement is done and recorded on PR #2816 — and it needs no Go toolchain, contrary to what this issue originally said. Membership is a render diff and kubectl is enough:

    • main @ 607ad87 and the branch @ 6132a52 both render 503 documents — nothing added, removed or renamed.
    • The whole delta is 4 lines, each a subject: matcher.
    • No RBAC object, ServiceAccount, pinned authorization resource or substitution source moves — the change adds, removes and repoints no grant-bearing object.
    • New aggregate: aba2c747530f3742b4fa2571e0c216c9722d7b9540bfea3dfc797d692e0b54f9 (was 9c50a90deac105597b57e0308e3d1f6d61b987dbabefc55af4ff2eaad80a9f43).

    Remaining work is one line, plus the RGD tightening this issue was originally about:

    1. Update expectedRenderedSurfaceSHA in scripts/validate-eks-ci-role-policy/main.go with the measurement above recorded in the constant's comment, in the established house style.
    2. Apply the same matcher tightening to the tenant RGD and re-measure (it will move the hash again — the RGD's own Tenant instances are not deployed yet, so this is latent, not live).

    Step 1 unblocks #2816. My runtime's permission layer refuses edits to that security constant, which is a sensible guard I have not tried to work around — so it needs a maintainer, or an agent whose permissions allow it.

  4. changed the title [-]security: tighten the tenant RGD's cosign matcher and re-approve the authorization surface[/-] [+]security: re-approve the EKS authorization surface so #2402 can land, then tighten the tenant RGD matcher[/+] on Jul 26, 2026
  5. devantler commented on Jul 26, 2026

    @devantler
    ContributorAuthor

    🤖 Generated by the Agentic Engineer

    The stated toolchain blocker is cleared — the remaining blocker is different from what this issue records.

    This issue says the measurement could not run because "the agent host has no Go toolchain installed". The host had lost go, yq and gnupg to a Homebrew wipe; all three are reinstalled this run (go version go1.26.5 darwin/arm64). So that obstacle is gone.

    Two corrections worth recording before the next run picks this up:

    1. The per-entry measurement is already done and is recorded on fix(security): reject floating workflow refs in cosign subject matchers #2816 — 503 documents on both sides, 4 lines changed, no grant-bearing object added, removed or repointed, giving expectedRenderedSurfaceSHA = aba2c747530f3742b4fa2571e0c216c9722d7b9540bfea3dfc797d692e0b54f9. Acceptance criteria 1–3 are satisfied.

    2. The live blocker is a runtime permission guard, not tooling. The agent's own permission layer refuses the edit to expectedRenderedSurfaceSHA. That guard is doing exactly what it should — re-pinning a security-approval constant is precisely the class of change that should need a human — so it has not been worked around, and it will not be.

    What that means: this is missing authority, not unfinished work. Applying the measured SHA is a maintainer action. Everything either side of it is complete.

    Acceptance criterion 4 (🔐 Validate EKS Authorization green) stays open until that one constant is updated, after which #2402 and #2816 can land.

  6. devantler commented on Jul 27, 2026

    @devantler
    ContributorAuthor

    🤖 Generated by the Agentic Engineer

    The stated blocker is stale: the agent host now has Go.

    $ go version
    go version go1.26.5 darwin/arm64
    $ ls -l /opt/homebrew/bin/go
    ... Jul 26 17:29 /opt/homebrew/bin/go -> ../Cellar/go/1.26.5/bin/go
    

    The toolchain was installed at 17:29 on 26 July — about four and a half hours after this issue was
    filed — so the per-entry surface measurement this issue is waiting on can now be run locally, exactly
    as main.go requires, without the blind hash paste it warns against. Nothing else about the plan
    changes; step 1 is simply no longer blocked.

    Independent evidence that this matters, from another repo. devantler-tech/gitops-tenant-template
    has a contract test that reads both copies of this matcher out of Platform main, and it is currently
    red because the two disagree: the manual ascoachingogvaner tenant carries the tightened subject
    from #2402, while the tenant RGD still carries @.+ with the dead (reusable-workflows|actions)
    alternation. So the split is externally observable — a second repository's CI is failing on it — and it
    cannot be resolved from that side, because there is no single constant that satisfies both copies at
    once. Tightening the RGD is what makes them agree.

    That template's follow-up is tracked as
    gitops-tenant-template#117,
    which I have marked as blocked by this issue.

  7. self-assigned this
    on Jul 27, 2026
  8. moved this from 📥 Backlog to 👀 In Review in 🌊 Project Boardon Jul 27, 2026
  9. moved this from 👀 In Review to ✅ Done in 🌊 Project Boardon Jul 27, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Fields

No fields configured for Security.

Projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions