feat(helm): make cluster-scoped RBAC optional - #3459
Conversation
|
All contributors have signed the DCO ✍️ ✅ |
c5c9173 to
e876b74
Compare
|
I have read the DCO document and I hereby sign the DCO. |
|
recheck |
purp
left a comment
There was a problem hiding this comment.
gator-agent
PR Review Status
This PR implements the accepted cluster-scoped RBAC split in #3043, and the initial code review found no blocking defects. The default and legacy-values paths remain enabled, the custom-name and service-account cases are covered, and the operator-facing Helm and Kubernetes documentation is updated.
Blocking findings:
- No blocking findings remain
Carried findings:
- None
Non-blocking suggestions:
- None
Gator metadata
- Validation: Implements accepted issue #3043 with a focused Helm packaging and RBAC change
- Docs: Fern Kubernetes setup documentation and chart documentation are updated
- Checks: Current baseline branch, Helm lint, Trivy, and DCO checks are green; required Kubernetes E2E dispatch is pending
- E2E:
test:e2e-kubernetesrequired for the Helm Kubernetes RBAC topology change - Head SHA:
e876b74eb9a83ecda9d1b1e349981cfea84c6cef - Base SHA:
4b2cb7f007da2f701422daf394643b0fd9d4daef - Merge base SHA:
4b2cb7f007da2f701422daf394643b0fd9d4daef - Patch ID:
b3b39191943f12e797db7e99d09a9bff104c0f06 - Gator payload:
9 - Review mode:
initial - Previous reviewed SHA: none
- Review budget exhausted: no
- Maintainer decision required: no
- Next state:
gator:in-reviewuntil the required Kubernetes E2E workflow is confirmed queued
|
Label |
|
Label |
Maintainer Review NudgeThis PR has been in @NVIDIA/openshell-maintainers @NVIDIA/openshell-codeowners @mrunalp @sjenning @derekwaynecarr, can someone review and either approve, request changes, or close this out? |
|
Will approve. Slated for v0.1.1 next week. Do not merge until then. |
409361b to
6802f19
Compare
The gateway chart always rendered the ClusterRole and ClusterRoleBinding, so
every install and upgrade required cluster-admin even when only namespaced
objects were needed. Installers that are namespace-admin GitOps or platform
controllers could not run the release at all, and clusters where cluster-scoped
RBAC is owned by a separate team had no supported way to split the install.
Add an rbac values block so a cluster-admin can apply the cluster-scoped objects
once and a namespace-admin can install and upgrade the release without
cluster-scoped permissions:
rbac:
create: true
clusterScoped:
create: true
clusterRoleName: ""
clusterRoleBindingName: ""
rbac.clusterScoped.create gates the ClusterRole and ClusterRoleBinding, and is
independent of the workspace mode. rbac.create additionally gates the namespaced
sandbox Role and RoleBinding, which matters because Kubernetes escalation
prevention stops an installer holding only the built-in admin role from creating
a Role that grants agents.x-k8s.io verbs it does not itself hold. The certgen
hook and credential driver RBAC keep their existing flags.
Both flags default to true, so current installs are unchanged. The helpers treat
a missing rbac block as enabled so upgrades with --reuse-values do not drop RBAC,
matching the existing workspaceResources pattern. The ClusterRoleBinding roleRef
follows clusterRoleName so a separately applied ClusterRole can carry a name the
cluster-admin chooses.
Document the migration for a release that already owns the cluster-scoped
objects: Helm deletes objects that leave the manifest, so annotate them with
helm.sh/resource-policy=keep before setting the flag, otherwise the gateway
loses TokenReview until a cluster-admin re-applies them.
Signed-off-by: ansjindal <ansjindal@nvidia.com>
6802f19 to
93278a3
Compare
Summary
Makes the gateway chart's cluster-scoped RBAC optional so a cluster-admin can apply the
ClusterRoleandClusterRoleBindingonce and a namespace-admin can install and upgrade the OpenShell release without cluster-scoped permissions. Both new flags default totrue, so existing installs are unchanged.Related Issue
Fixes #3043
Changes
rbacvalues block following the shape proposed on the issue:rbac.create,rbac.clusterScoped.create,rbac.clusterScoped.clusterRoleName,rbac.clusterScoped.clusterRoleBindingName.clusterrole.yamlandclusterrolebinding.yamlonrbac.clusterScoped.create, independent ofserver.drivers.kubernetes.workspaceMode.role.yaml/rolebinding.yamland the gatewaypeer-role.yaml— onrbac.create. This is not merely a parent switch: insharedmode, Kubernetes escalation prevention stops an installer holding only the built-inadminClusterRole from creating a Role that grantsagents.x-k8s.ioverbs it does not itself hold, so such an installer needsrbac.create=falsewith all gateway RBAC applied out of band. The certgen hook and credential driver RBAC keep their existing flags.rbacblock as enabled, sohelm upgrade --reuse-valuesfrom a pre-change release does not drop RBAC — the same pattern asopenshell.workspaceResourcesEnabled.ClusterRoleBindingroleReffromclusterRoleNameso a separately applied ClusterRole can carry a cluster-admin-chosen name.ci/values-namespace-admin.yaml, picked up automatically by thehelm:lintoverlay loop.docs/kubernetes/setup.mdx. This also corrects the documented ClusterRole name, which isopenshell-node-reader-<namespace>.deploy/helm/test-split-ownership.shto assert arbac.clusterScoped.create=falserender emits no cluster-scoped objects while keeping the gateway ServiceAccount.Notes for reviewers
Migration. Helm deletes objects that leave a release manifest, so setting the flag on a release that already owns the cluster-scoped objects deletes them, and the gateway loses TokenReview until a cluster-admin re-applies them. The docs prescribe annotating them with
helm.sh/resource-policy=keepfirst; this was tested and hands ownership over with no gap.peer-role.yaml. HA gateway rebalancing (#1868) landed while this PR was open and added an ungated namespaced Role/RoleBinding bound to the gateway ServiceAccount. Leaving it ungated would makerbac.create's contract false, so it is gated here too. It never blocked an install — the peer Role grants onlypods get, which a built-inadmininstaller can create — so this is a contract fix, not a runtime one.Rebase. Rebased onto current
main, which required honoring two upstream changes to the same files: the reduced gateway Secret privileges (#3616, assertion deleted rather than updated) and the removed NetworkPolicy acknowledgement (#3677, dropped from the documented commands).Testing
mise run pre-commitpassesmise run pre-commit(fmt + lint) exits 0 andfmtproduces no diff. Thelinthalf covers all 15 subtasks, includinghelm:lintacross all CI overlays,helm:docs:check,helm:test,license:check, clippy, and markdown/mermaid.Unit tests — new cases in
clusterrole_test.yaml,clusterrolebinding_test.yaml, and a newrbac_test.yaml: default still renders every object; each flag omits the right ones; omission is independent of workspace mode; name overrides land inmetadata.nameandroleRef;serviceAccount.create=falsestill yields a correct binding subject; and legacy values with norbackey still create RBAC. Gateway suite is 203 tests / 17 suites, workspace 6 / 1, plustest-split-ownership.sh, whose new assertion was negative-controlled by flipping the flag to confirm it fails.Live cluster (k3d, agent-sandbox v1.0.2, gateway image pinned to the per-commit build for
mainHEAD,--kube-as-userimpersonation of an identity holding only the built-inadminClusterRole in one namespace, asserted unable to get or create ClusterRoles/ClusterRoleBindings). Three suites, all green:clusterroles ... is forbidden ... at the cluster scope). Withrbac.clusterScoped.create=false, a cluster-admin applies the two cluster-scoped objects and the namespace-admin installs and upgrades; the release still owns the namespaced RBAC; the pre-created binding matches the release's ServiceAccount, which can create TokenReviews. Withrbac.create=false, the installer needs no RBAC write permission at all andhelm get manifestconfirms the release claims no RBAC.serviceAccount.create=falsewith a pre-created ServiceAccount resolves correctly in the ClusterRoleBinding subject, RoleBinding subject, and podserviceAccountName. Gateway logs are clean.mainand upgrades it with this branch: default upgrade,--reuse-values, a pre-change values file,--set-json rbac=null,helm rollbackto the pre-change revision, and uninstall leaving no cluster-scoped residue. Cluster-scoped objects survive and stay release-owned in every case.managedandoperatorinstall and upgrade as a namespace-admin withrbac.clusterScoped.create=false, roll out, and log no permission errors. Mode-specific ClusterRole grants were verified to land (managedgets namespace create/delete, cluster-wide sandboxes, serviceaccount create;operatorgets cluster-wide sandboxes but not namespace create), with livekubectl auth can-ion the gateway SA matching per mode. Insharedmode both documented remedies were verified, and the plain-adminfailure it is documented against was reproduced.Cluster-scope audit — every CI overlay plus defaults was scanned against 16 cluster-scoped kinds (SCC, ClusterIssuer, GatewayClass, CRD, PV, StorageClass, webhooks, and others). Each renders exactly
ClusterRole+ClusterRoleBindingand nothing else, and zero with the flag off, confirming the object inventory the docs publish.Not covered: OpenShift SCC admission and Route behavior on a real OpenShift cluster. The three OpenShift overlays pass render-level checks and lint, but the live path needs an OpenShift cluster;
test:e2e-kubernetesmay be worth applying.Checklist
architecture/doc covers chart RBAC topology