From 404b17d194d8fc9b1a69d7846b91fc64c0457616 Mon Sep 17 00:00:00 2001 From: jwbron <8340608+jwbron@users.noreply.github.com> Date: Wed, 13 May 2026 04:41:43 +0000 Subject: [PATCH 1/2] docs: update RBAC model for topology-reader roles --- docs/architecture/kubernetes-migration.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/docs/architecture/kubernetes-migration.md b/docs/architecture/kubernetes-migration.md index ffc7cd3d49..de25ab771c 100644 --- a/docs/architecture/kubernetes-migration.md +++ b/docs/architecture/kubernetes-migration.md @@ -249,10 +249,12 @@ Agent Jobs are built programmatically by ``KubernetesClient.create_container`` ## RBAC Model -The orchestrator uses a ServiceAccount (`egg-orchestrator` in `egg-system`) with two levels of permissions: +The orchestrator uses a ServiceAccount (`egg-orchestrator` in `egg-system`) with four RBAC bindings: -1. **ClusterRole** (`egg-orchestrator`): Broad permissions for cross-namespace operations (Jobs, Pods, ConfigMaps) +1. **ClusterRole** (`egg-orchestrator`): Broad permissions for cross-namespace operations (Jobs, Pods, ConfigMaps, Deployments) 2. **Role** (`egg-agent-manager` in `egg-agents`): Fine-grained permissions scoped to the agent namespace +3. **ClusterRole** (`egg-cluster-topology-reader`): Read-only `nodes` access for `_detect_k3s` / cluster topology probes +4. **Role** (`egg-kube-system-topology-reader` in `kube-system`): DaemonSet reads for `_detect_cni` (least-privilege scoped to kube-system) ```yaml # Namespace-scoped Role in egg-agents @@ -276,7 +278,7 @@ rules: verbs: ["create"] ``` -This replaces the Docker socket mount with a principle-of-least-privilege API access model. The orchestrator can manage Jobs and Pods in `egg-agents` but has no access to other namespaces' workloads. +This replaces the Docker socket mount with a principle-of-least-privilege API access model. The orchestrator can manage Jobs and Pods in `egg-agents`; the topology-reader roles are scoped minimally so `validate_network_isolation` and `get_deployment_context` can detect CNI and k3s state without cluster-wide DaemonSet access. ## Developer Workflow Changes From 77983b16aca94f48eaf7f4ab337e2781d029babe Mon Sep 17 00:00:00 2001 From: "egg-reviewer[bot]" <261018737+egg-reviewer[bot]@users.noreply.github.com> Date: Wed, 13 May 2026 04:59:57 +0000 Subject: [PATCH 2/2] docs(rbac): correct RBAC bindings to match k8s/base/rbac.yaml MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Address review feedback on #2696: the previous version of the doc described a fabricated `ClusterRole egg-orchestrator` that does not exist in `k8s/base/rbac.yaml`. The PR carried that fiction forward and made it worse by adding "Deployments" to the fake entry. Replace it with the four real bindings on the `egg-orchestrator` SA: - Role egg-agent-manager (egg-agents) — jobs + pods + pods/log + pods/exec - Role egg-service-log-reader (egg-system) — deployments + pods + pods/log - ClusterRole egg-cluster-topology-reader — nodes (the only cluster grant) - Role egg-kube-system-topology-reader (kube-system) — daemonsets Also: - Attribute the kube-system DaemonSet read to _detect_cni AND _detect_k3s's image-name fallback (orchestrator/routes/deployment.py lines 209-225), not _detect_cni alone. - Drop the spurious `create` verb from the inline `pods` rules block; rbac.yaml:25-27 only grants delete/get/list/watch (Jobs create pods on the SA's behalf). Authored-by: egg --- docs/architecture/kubernetes-migration.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/architecture/kubernetes-migration.md b/docs/architecture/kubernetes-migration.md index de25ab771c..08f09d55a6 100644 --- a/docs/architecture/kubernetes-migration.md +++ b/docs/architecture/kubernetes-migration.md @@ -249,12 +249,12 @@ Agent Jobs are built programmatically by ``KubernetesClient.create_container`` ## RBAC Model -The orchestrator uses a ServiceAccount (`egg-orchestrator` in `egg-system`) with four RBAC bindings: +The orchestrator uses a ServiceAccount (`egg-orchestrator` in `egg-system`) bound to four namespace- or cluster-scoped roles. There is no broad `egg-orchestrator` ClusterRole — every grant is least-privilege. -1. **ClusterRole** (`egg-orchestrator`): Broad permissions for cross-namespace operations (Jobs, Pods, ConfigMaps, Deployments) -2. **Role** (`egg-agent-manager` in `egg-agents`): Fine-grained permissions scoped to the agent namespace -3. **ClusterRole** (`egg-cluster-topology-reader`): Read-only `nodes` access for `_detect_k3s` / cluster topology probes -4. **Role** (`egg-kube-system-topology-reader` in `kube-system`): DaemonSet reads for `_detect_cni` (least-privilege scoped to kube-system) +1. **Role** (`egg-agent-manager` in `egg-agents`): manage agent Jobs/Pods (`jobs`: create/delete/get/list/watch/patch; `pods`: delete/get/list/watch; `pods/log`: get; `pods/exec`: create). Jobs create their pods on the SA's behalf, so the SA does not need `pods: create`. +2. **Role** (`egg-service-log-reader` in `egg-system`): read the orchestrator's own Deployments and Pod logs (`deployments`: get/list — `list` added in #2648 for `_collect_egg_image_tags`; `pods`: get/list; `pods/log`: get). +3. **ClusterRole** (`egg-cluster-topology-reader`): cluster-scoped `nodes: get/list` for `_detect_k3s`'s kubelet-version probe — the only grant that genuinely needs cluster scope. +4. **Role** (`egg-kube-system-topology-reader` in `kube-system`): `apps/daemonsets: get/list` for `_detect_cni` and `_detect_k3s`'s image-name fallback. Scoped to kube-system to keep cluster-wide DaemonSet reads off the SA (least-privilege per #2658 review). ```yaml # Namespace-scoped Role in egg-agents @@ -269,7 +269,7 @@ rules: verbs: ["create", "delete", "get", "list", "watch", "patch"] - apiGroups: [""] resources: ["pods"] - verbs: ["create", "delete", "get", "list", "watch"] + verbs: ["delete", "get", "list", "watch"] - apiGroups: [""] resources: ["pods/log"] verbs: ["get"]