Skip to main content

Kubernetes authorization evidence/v1alpha1

Specified; runtime pending

Rendered from adapters/kubernetes/contracts/auth/v1alpha1/semantics.md by connectors-docs; the source owns every rule on this page.

Status: proposed native binding, not implemented. Implements auth.evidence/v1alpha1. The exact ResourceAttributes target, namespace mode, public target projection and auth-validation POST belong to Kubernetes. The generic evidence lifetime, current-admission, fan-out and publication rules remain shared obligations.

Activation selects SelfSubjectReview for identity validation. Ordinary business reads cannot invent this probe. Per-operation permission checks use the exact SelfSubjectAccessReview binding below. The original extraction evidence is ../connectors/docs/design/10-local-kubernetes-context-and-resource-discovery.md:50-116.

An exec credential plugin's token is validated by the same SelfSubjectReview probe as a configured token. Which plugin may run, with what arguments, environment and bounds, and how long its token is reused, is the implemented pinned binding in reads, Exec-plugin credentials.

4.4 Exact authorization targets and fan-out budget (F08)​

After host admission and configuration allowlist checks, build the complete bounded authorization target set from the operation and selected input before provider work. For Kubernetes a resource target is the exact (verb, api_group, api_version, resource, namespace, name, subresource) tuple. Empty group means core; empty subresource means none. Empty name is the selected collection-wide name attribute for list, not permission to substitute get/delete on arbitrary names. Namespace meaning depends on the declared resource and operation: a namespaced list carries its actual namespace; an explicitly selected all-namespaces list carries empty namespace; a cluster-scoped resource also carries empty namespace but is a different resource tuple. These distinctions follow Kubernetes ResourceAttributes and cannot be inferred from a public null field or an empty result. A proxy forward has get, core/v1, services, the fixed namespace and Service name, and proxy. Exact configured kinds multiply finite per-namespace targets. Deduplicate identical tuples within the same checking binding and order them lexicographically by the seven fields in the order above, using their reviewed canonical UTF-8 representation. A required multi-target read with an empty normalized set is invalid_input; omitted selectors may expand only under an explicitly bounded configured selection. Neither grouping namespaces nor a list result grants permission to get another resource/name/subresource.

The first Service discovery profile preserves the explicitly configured all-namespaces mode: an admitted empty configured namespace list selects exactly (list,"","v1","services","","",""), one SSAR target and one cluster-wide collection partition. It is mutually exclusive with the finite per-namespace mode. A missing/invalid configuration, denied namespace, empty provider result or caller-supplied empty selector cannot activate this mode or fall back to it. An all-namespaces allow cannot be substituted for a per-namespace target in this exact-evidence profile, nor can several namespace allows synthesize the all-namespaces allow. Switching modes changes the selection/scope and requires fresh admission/evidence. All provider pages share the same scan object/call/byte/deadline ceilings; one target does not grant an unbounded cluster scan. The scope's private checking/profile/configuration coordinates preserve the selected resource semantics. This fixes the earlier overbroad claim that every empty namespace meant a cluster-scoped resource; it does not add wildcard matching or impersonation.

Target equality for evidence reuse additionally includes the checking instance, connection, profile, provider authority, immutable credential generation, current binding/configuration revision and host admission scope. A mediated check uses the parent checking binding and fixed child route/observation revision. This first Kubernetes profile forbids impersonation and caller-supplied Impersonate-* headers; any future supported impersonation context must become an explicit reviewed evidence/admission coordinate. A safe public target description is not that private cache key. Reuse requires unchanged bindings and unexpired evidence at both admission and dispatch: at most 300 s for reads, 60 s for mutation authorization, or the smaller provider/profile deadline. Known revocation, replacement, policy withdrawal or evidence invalidation wins over age. Permission evidence never crosses a generation change. Denied evidence may be reused only under the same bounds and never becomes success; caching cannot replace current host authorization.

The first profile admits at most 64 distinct targets and 64 provider authorization calls per business invocation, with at most one call per uncached target, at most four concurrent authorization queries, and no automatic retries, redirects or nested checks. A deployment/operation may lower target/call/concurrency ceilings (including a zero-call cache-only policy), never raise them without a revised profile. Cached targets still count toward the target ceiling. Reserve the whole missing-evidence call budget before starting any check; a target-set overflow is invalid_input and an insufficient remaining call budget is unavailable, both before any provider request. Every attempted call consumes one slot even on timeout or ambiguous response. Concurrency counts all in-flight authorization queries across nested work; zero remaining deadline grants no send. Stop scheduling on failure/deadline, and cancel or await already in-flight checks without issuing more. Provider pagination and parent forwarding share the original invocation budget and deadline; a subrequest does not reset it. Evidence checks and business reads share the provider deadline. An ordinary call cannot invent identity/verify probes to consume spare slots.

All required checks finish before the first business resource request. Only a well-formed definite allow authorizes; missing/malformed/contradictory status or a provider evaluation error is unavailable, never denial or success. Any unavailable, timed-out, unknown, not_run or stale required result refuses the invocation as unavailable, with zero business reads; completed checks may remain cached only under the original bounds. This conservative first profile does not return a successful checked prefix after budget exhaustion. A definitive authorization denial is separate: for an explicitly declared multi-target read supporting authorization coverage, skip denied targets and read only allowed targets. If all are denied, return forbidden, never a successful empty page. Single-target operations and mutations refuse denied permission with forbidden; a Kubernetes route maps exact parent permission denial to route_refused. A required result expiring or becoming invalid before dispatch cannot be reused; if earlier allowed resource reads already ran, discard their partial payload and return the applicable refusal (those read requests are not undone). no unchecked request or implicit extra check is permitted.

The multi-target read payload must declare authorization: {complete: boolean, targets: [{target: {verb, api_group, api_version, resource, namespace, name, subresource}, result: "allowed" | "denied"}]} as a closed safe projection. Every requested distinct target appears exactly once under disclosure admission, in canonical target order. The array has at most 64 entries and each coordinate at most 256 UTF-8 bytes (smaller provider-specific limits still apply). Coverage and provider items together must fit the selected result byte limit; if truthful coverage cannot fit, refuse unavailable without silently dropping targets. Here authorization.complete is true only if all requested targets are allowed; any denial forces both authorization.complete and the overall result's complete to false, even when all allowed-target pages have been read. A permitted target returning zero records is distinct from a denied target. Pagination/cursors bind the original target set, denial/coverage observation and all normal configuration/authority constraints; continuation re-evaluates current admission and exact evidence. A permission/coverage change invalidates the continuation (stale_cursor), requiring a fresh read, and never silently changes the represented target set. No cursor is fabricated solely to retry a denied target. A payload reader without this coverage field cannot advertise this partial-read profile; the existing strict Page is unchanged. A discovery consumer must not call an incomplete view complete: denied/incomplete partitions provide no absence evidence. An independently complete, comparable partition may establish absence only within its exact scope even when another partition makes the overall view partial, under resource discovery §4.2. Authorization coverage alone never proves provider exhaustion. Prior terminal withdrawn rows remain withdrawn; other unobserved history may become stale. Coverage discloses only admitted target coordinates, never credential generations or hidden route locators. It is authorization coverage, not proof that a discovery observation was withdrawn or that a provider collection was exhaustive.

Kubernetes SelfSubjectAccessReview is an explicitly admitted auth-validation POST for this check, despite the business read's GET-only capability. A private check-specific capability fixes its endpoint and bounded ResourceAttributes body; it cannot be used by provider business code to POST arbitrary resources. Count its evaluation as provider work under this budget, without misclassifying it as an approved business mutation. Exact request/response interpretation and a supporting capability implementation are advertisement prerequisites; the generic read capability grants no such POST authority.