Skip to content

feat(cloud-rbac): cluster-scoped read for Cloud tiers (+ opt-in node-ops)#986

Open
nadaverell wants to merge 1 commit into
mainfrom
feat/cloud-cluster-read-rbac
Open

feat(cloud-rbac): cluster-scoped read for Cloud tiers (+ opt-in node-ops)#986
nadaverell wants to merge 1 commit into
mainfrom
feat/cloud-cluster-read-rbac

Conversation

@nadaverell

@nadaverell nadaverell commented Jun 23, 2026

Copy link
Copy Markdown
Contributor

Fixes the reported bug: Cloud owners/viewers can't see Nodes/PVs/StorageClasses because the tier groups bind to built-in admin/edit/view, which exclude cluster-scoped resources.

Approach — explicit additive bindings (NOT aggregation)

Aggregating into built-in view/edit would widen those shared roles cluster-wide for every other subject bound to them (verified: kyverno/event-exporter SAs bind view on our clusters). Instead, mirror the existing radar-helm add-on: explicit ClusterRoleBindings to the cloud:* groups.

  • radar-cluster-readget/list/watch on nodes, persistentvolumes, storageclasses, ingressclasses, priorityclasses (+ metrics nodes when rbac.metrics). No Secrets, no RBAC objects, no namespaces (built-in view already grants namespaces). Bound to viewer+member+owner.
  • radar-node-opspatch nodes + list pods + create pods/eviction (exact pkg/k8score/node_ops.go verbs). Owner-only. Cluster-write, default OFF (cloud.defaultRbac.nodeOps).

Gating (verified via helm template matrix)

Cluster-read is a per-tier axis (cloud.defaultRbac.clusterScopedRead.{viewer,member,owner}, each default true), independent of the namespaced ClusterRole a tier binds to. Each binding renders when (a) the tier is enabled AND (b) its clusterScopedRead flag is true. Swapping a tier's namespaced *ClusterRole no longer disables infra-read (separate bindings) — set the flag false for namespaced-only (e.g. clusterScopedRead.viewer: false). Verified via helm template: defaults (3 tiers), viewer:false (member+owner only), all-false (empty), custom viewerClusterRole (viewer keeps read — decoupled), tier-disabled (absent), OSS-mode (empty). Schema rejects the old bool shape + typo keys.

Notes

  • Default-on widening (founder decision): all tiers gain cluster-scoped read on chart upgrade, with per-tier opt-out (clusterScopedRead.<tier>: false) for security-conscious orgs (e.g. namespaced-only viewer). Prominent in values + docs (radar-docs#24).
  • Covers core cluster-scoped kinds; cluster-scoped CRDs (NodePool/GatewayClass/…) are not included (documented).
  • No Chart.yaml change: release.yml stamps chart version/appVersion from the release tag at publish time, so this PR adds templates only; the next v* tag ships them. Helm lint error pre-exists on cloud-rbac.yaml (CI Helm check is the gate).
  • Docs: radar-docs#24. Hold reviewed; do not merge ahead of me.

Note

Medium Risk
Default-on cluster-scoped read widens Cloud tier permissions on chart upgrade; optional nodeOps adds cluster-scoped write for owners when enabled.

Overview
Fixes Cloud users bound to built-in admin/edit/view being unable to see Nodes, PVs, StorageClasses, and related cluster-scoped kinds in Radar.

The chart now emits a radar-cluster-read ClusterRole (get/list/watch on nodes, persistentvolumes, storageclasses, ingressclasses, priorityclasses; optional metrics.k8s.io nodes) with explicit ClusterRoleBindings to cloud:viewer, cloud:member, and cloud:owner—not aggregate-to-view, so shared built-in roles are not widened for other cluster subjects. Per-tier opt-out via cloud.defaultRbac.clusterScopedRead.{viewer,member,owner} (each defaults on).

An optional radar-node-ops add-on (cloud.defaultRbac.nodeOps, default off) grants owners patch nodes, list pods, and create pods/eviction for Radar cordon/drain. Values, JSON schema, and docs/authentication.md document the new axes.

Reviewed by Cursor Bugbot for commit 9c8e47a. Bugbot is set up for automated code reviews on this repo. Configure here.

@nadaverell nadaverell requested a review from hisco as a code owner June 23, 2026 23:01
@nadaverell nadaverell force-pushed the feat/cloud-cluster-read-rbac branch 2 times, most recently from 1eee2d9 to f87d64b Compare June 29, 2026 20:46
…ops)

Built-in admin/edit/view exclude cluster-scoped resources, so Cloud owners/viewers
couldn't see Nodes/PVs/StorageClasses. Add explicit additive ClusterRoleBindings
(the radar-helm pattern, NOT aggregate-to-view which would widen shared built-in
roles cluster-wide):
- radar-cluster-read: get/list/watch on nodes, PVs, storageclasses, ingressclasses,
  priorityclasses (+ metrics nodes when rbac.metrics). No Secrets, no RBAC. Bound to
  viewer+member+owner. Cluster-scoped read is its own per-tier axis
  (clusterScopedRead.{viewer,member,owner}, each default true) — independent of the
  namespaced ClusterRole a tier binds to, so a custom *ClusterRole no longer silently
  disables infra read. Set a tier false for namespaced-only (e.g. viewer).
- radar-node-ops: patch nodes + list pods + create pods/eviction (exact node_ops.go
  verbs; PDBs enforced by eviction API). Owner-only. Cluster-write, default OFF.
  patch nodes can't be field-scoped by RBAC, so it also permits relabel/taint.

Docs: cloud/rbac.mdx (radar-docs) + docs/authentication.md cover the per-tier toggle
and security-conscious lockdown recipes.
@nadaverell nadaverell force-pushed the feat/cloud-cluster-read-rbac branch from f87d64b to 9c8e47a Compare June 29, 2026 21:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant