Kubernetes Protected Execution

Audience: operators governing Kubernetes remediation with ADK — #1310 Phase 4. This is the Kubernetes instance of the domain-neutral Protected Execution Boundary model, and the proof that Phase 4 is not a robotics-only feature: the same manifest contract that isolates a ROS actuator path isolates a cluster mutation.

Remediation proposer            ADK              Governed executor         Kubernetes API
 (read/proposal-only SA)  ──▶  authorizes   ──▶  (mutation-capable SA)  ──▶  (deployments/scale)

The proposer can propose a scale; only the governed executor service account can perform it. The boundary proves the proposer has no RBAC path to mutate the resource directly.

Validate-only

The builtin.kubernetes_rbac provider never talks to the Kubernetes API, creates RoleBindings, or mints tokens (§26 — ADK is a governance runtime, not a policy controller). It evaluates a deterministic RBAC model you export from your cluster: a snapshot of which subjects hold which verbs on which resources in which namespaces.

Step 1 — Export the effective RBAC model

Produce a JSON snapshot of the effective permissions for the principals involved (from your RBAC tooling / kubectl auth can-i --list per subject):

{
  "subjects": [
    { "name": "system:serviceaccount:autonomyops:remediation-proposer",
      "rules": [ { "verbs": ["get","list","watch"], "resources": ["deployments","deployments/scale"], "namespaces": ["production"] } ] },
    { "name": "system:serviceaccount:autonomyops:governed-enforcer",
      "rules": [ { "verbs": ["patch","update"], "resources": ["deployments/scale"], "namespaces": ["production"] } ] }
  ]
}

"*" in a verb, resource, or namespace list is a wildcard. Keep this snapshot current — the boundary is only as good as the model it validates; re-export and re-attest after RBAC changes.

Step 2 — Declare the boundary (deployment manifest, schema v1.8)

schema_version: "1.8"
execution_boundaries:
  - id: production_scaling
    action_kinds: [tool.k8s.scale]
    adapter:
      id: governed_k8s_executor
      identity: system:serviceaccount:autonomyops:governed-enforcer
    target:
      kind: kubernetes.api
      resource: deployments/scale
      namespace: production
    protection:
      provider: builtin.kubernetes_rbac
      provider_version: "1"
      configuration:
        enforcement_service_account: system:serviceaccount:autonomyops:governed-enforcer
        proposer_service_account: system:serviceaccount:autonomyops:remediation-proposer
        namespace: production
        rbac_model_path: /etc/adk/rbac-model.json
        # governed_verbs defaults to [patch, update, delete, create]
    requirements:
      exclusive_enforcement_principal: true
      proposer_has_no_direct_access: true
      preflight_validation: required

Step 3 — Verify (activation is the gate)

At runtime start / release activation, the provider checks the model, fail-closed:

  • the proposer cannot patch/update/delete/create the governed resource in the namespace (proposer_has_direct_access), and no wildcard grant lets it (wildcard_grant);

  • the enforcer can (adapter_not_authorized if not);

  • no other principal can mutate the resource (extra_mutator);

  • the enforcer and proposer are distinct identities (shared_identity).

If any fails, the bundle refuses to activate with an execution-boundary: reason and the prior bundle stays live, e.g.:

activation: execution boundary "production_scaling" [execution-boundary: bypass_detected]:
  proposer has a direct execution path (proposer_has_direct_access: the proposer
  "system:serviceaccount:autonomyops:remediation-proposer" can mutate "deployments/scale" directly, bypassing ADK)

Failure modes

Symptom

Cause

Fix

bypass_detected (proposer_has_direct_access)

The proposer SA can mutate the governed resource.

Remove the proposer’s mutation Role/RoleBinding.

bypass_detected (wildcard_grant)

A verbs: ["*"] / resources: ["*"] grant reaches the proposer.

Scope the role; remove the wildcard.

bypass_detected (extra_mutator)

A third principal can also mutate the resource.

Revoke its grant, or intentionally exclude it from the boundary.

identity_mismatch (adapter_not_authorized)

The enforcer SA has no mutation grant.

Grant the enforcer the governed verbs on the resource.

invalid (shared_identity)

Enforcer and proposer are the same SA.

Run the enforcer under a distinct SA.

invalid (rbac_model_unreadable)

rbac_model_path missing/unparsable.

Re-export the RBAC model to the path.