docs(adr): ADR-0011 — owner-issued grant for remoteControl.tls credentials - #328
Closed
thc1006 wants to merge 2 commits into
Closed
docs(adr): ADR-0011 — owner-issued grant for remoteControl.tls credentials#328thc1006 wants to merge 2 commits into
thc1006 wants to merge 2 commits into
Conversation
…tials Three gaps remain on main after #219, #251/#300, #296, #297, #309 and #313. They look separate but share one shape: the Secret's owner cannot express, revocably, what their credential may be used for. 1. #309's ValidatingAdmissionPolicy is evaluated at ADMISSION only — ADR-0009's own amendment says stored objects are not re-validated, so withdrawing an author's RBAC afterwards does not re-evaluate the CRs they already created. 2. --remote-control-allowed-endpoint-hosts is ADMIN-GLOBAL. Verified against main: there is no per-Secret endpoint binding anywhere in the tree, so any labelled Secret can be paired with any allow-listed endpoint. 3. Secrets are get-only by design (an informer would need cluster-wide list/watch, rejected in #298), so withdrawing consent is invisible until the next real push — measured at 166s on a live 1.36.3 cluster, driven by the referenced SatelliteEphemeris's heartbeat rather than any per-cell retry. A grant is an OBJECT rather than a check, which is what buys all three: it can be deleted (revocable), it can be watched and indexed so revocation enqueues the affected NTNCellConfigs, and it has somewhere to put allowedEndpoints and allowedModes. Partly supersedes ADR-0009. Its recommendation to prefer a SubjectAccessReview over a ReferenceGrant-style CRD was sound for the requirement as stated there — deciding who may create the reference — but does not survive two requirements that were not on the table: revocability (a SAR is point-in-time on a write) and endpoint binding (a SAR cannot express a destination). So a grant is not a heavier way to do the same job; it does three jobs. ADR-0009 now carries a forward pointer so a reader cannot act on the superseded bullet. #309 is explicitly NOT replaced — it stays the cheap default tier (no CRD, no controller, one declarative policy). Enforcement is admin-gated and default-off behind --require-credential-grant; the "enforce whenever a grant exists" variant is rejected in the ADR because an attacker simply would not create one. Deliberately candid about the limit: rotating a Secret's CONTENTS touches no grant and fires no watch, so that path keeps the ~3-minute bound. The optional credentialRevision field is an opt-in escape hatch, not a Secret watch, and this ADR does not close #298. Proposed only — no CRD, controller or flag ships here.
thc1006
force-pushed
the
docs/adr-0010-credential-grant
branch
from
July 31, 2026 06:26
de07d2b to
b1addac
Compare
…to one current decision Resolves the ADR-0010 number collision: the concurrent secure-by-default transport decision (#330) takes 0010, this grant takes 0011, following the layering 0009 threat model -> 0010 transport -> 0011 continuous authorization. Flips the grant's numbering note and its transport-enum dependency refs, the ADR-0009 forward-pointer, and the CHANGELOG entry. Also flattens ADR-0009 per the review: a single "Net current state" block up front states the three composing tiers (endpoint allow-list / #309 admission policy / ADR-0011 grant) and marks the original "prefer SAR, defer authz" bullet superseded; the original two-part decision and both amendments are kept below as history. Signed-off-by: thc1006 <hctsai@linux.com>
This was referenced Jul 31, 2026
thc1006
added a commit
that referenced
this pull request
Jul 31, 2026
Replace docs/adr/ with the maintainer's SHA256-verified authoritative bundle. This folds in the review's remaining corrections and supersedes the piecemeal edits in PRs #328/#330/#338. - rename 0001 -> nr-mobility-measurement-scope, 0008 -> constellation-pool- availability, 0009 -> remote-control-credential-boundary (old slugs removed); - 0010 = v1alpha2 secure-by-default transport + refreshInterval duration admission validation; - 0011 = owner-issued credential grant (resolves the two-ADR-0010 collision); - add 0012 = evidence-based ground-station antenna health; - every ADR now carries YAML front matter (adr/status/supersedes/superseded_by/ implementation/tracking/last_verified) per ADR_STYLE_GUIDE.md. Governance: checks/check_adr_metadata.py (front matter + numbering) and hack/check-adr-index.sh (index membership + repo-internal link/anchor resolution) both run via `make adr-lint` and the ADR lint CI job. SOURCES.md and REVIEW_FINDINGS.md record verification provenance. Signed-off-by: thc1006 <hctsai@linux.com>
Owner
Author
|
Superseded by #337 (authoritative consolidated ADR set, now on main). The owner-issued credential grant lives at |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Proposed — no CRD, controller or flag ships here. This records a design and corrects part of an earlier one.
Why now
Three gaps remain on
mainafter #219, #251/#300, #296, #297, #309 and #313. I checked each againstmain @ 93c47f3rather than assuming. They look separate but share one shape: the Secret's owner cannot express, revocably, what their credential may be used for.mainValidatingAdmissionPolicyis evaluated at admission only — ADR-0009's own amendment says stored objects are not re-validated. Withdrawing an author's RBAC does not re-evaluate the CRs they already created.--remote-control-allowed-endpoint-hostsis admin-global. Grepped the tree: zero per-Secret endpoint binding. Any labelled Secret can be paired with any allow-listed endpoint.get-only by design (an informer needs cluster-widelist/watch, rejected in #298). Withdrawn consent is unseen until the next real push — measured at 166 s on a live 1.36.3 cluster, driven by the referencedSatelliteEphemeris's heartbeat, not by any per-cell retry.A failing push is already fine —
RemoteEndpointRejected,RemoteControlCredentialUnavailableandRemoteControlEndpointNotAllowedall self-heal on the 5-minute poll. The gap is the healthy cell, where the dedup early-return sits ahead ofresolveRemoteControlTLS, so nothing re-reads the credential at all.The design
RemoteControlCredentialGrant, namespaced, created by the Secret's owner in the Secret's namespace:secretRef,allowedConfigs(name + optional uid),allowedEndpoints,allowedModes.Being an object rather than a check is what buys all three properties at once — it can be deleted (revocable), it can be watched and field-indexed so revocation enqueues the affected
NTNCellConfigs instead of waiting on an unrelated heartbeat, and it has somewhere to put an endpoint and a mode.Enforcement is admin-gated and default-off behind
--require-credential-grant. The tempting "enforce whenever a grant exists for that Secret" variant is rejected in the ADR: an attacker simply would not create one, so the feature would do nothing precisely when it matters.It corrects ADR-0009, and says which part
ADR-0009 recommended SAR-at-admission over a grant CRD, calling the latter "heavier than the problem warrants". That was sound for the requirement as stated there — deciding who may create the reference. It does not survive two requirements that were not on the table:
So a grant is not a heavier way to do the same job; it does three jobs, which is what changes the calculus. ADR-0009 now carries a forward pointer in its header so nobody lands on it and acts on the superseded bullet.
#309 is explicitly not replaced. It stays the cheap default tier — no CRD, no controller, one declarative policy — and stops the confused deputy at write time. The grant is the opt-in stronger tier for multi-tenant namespaces. #300's allow-list remains the admin's outer bound on destinations.
What the ADR refuses to claim
credentialRevisionfield is an opt-in escape hatch that depends on the owner remembering to bump it — not a Secret watch, and the ADR says so.patch-capable principal in the Secret's namespace can still write a grant they should not; namespace RBAC remains the ceiling.Cost, stated up front
A fifth CRD means
make manifests bundle nephio-syncacross four copies plusdocs/api-reference.md, chart RBAC and samples. The controller gainslist/watchon the new CRD but not on Secrets — that is the point: consent becomes watchable without widening Secret access, which is the trade #298 rejected an informer for.Follow-up, deliberately not bundled
Automated E2E for the credentialed push. The chain is verified manually and shipped as a sample (#326), but no test in
test/e2e/exercises wss/mTLS, so a regression would ship green. Tracked separately — it is independent of this design decision.