User Story
As a platform operator installing OpenShell on a shared or restricted Kubernetes cluster, I want cluster-scoped chart objects (ClusterRole and ClusterRoleBinding) to be optional, so a cluster-admin can apply those objects once and a namespace-admin can install or upgrade the OpenShell gateway chart without cluster-admin privileges.
Problem Statement
The published OpenShell Helm chart always renders cluster-scoped RBAC as part of the same release as the gateway workload.
Today deploy/helm/openshell/templates/clusterrole.yaml and clusterrolebinding.yaml have no values guard. A helm install / helm upgrade of the chart therefore always attempts to create:
ClusterRole -node-reader (TokenReview, nodes, namespaces, and additional cluster-wide rules in managed/operator workspace modes)
ClusterRoleBinding -node-reader (binds that ClusterRole to the gateway ServiceAccount)
Other chart objects already have create/enable flags (serviceAccount.create, sandboxServiceAccount.create, grpcRoute.gateway.create, credential-driver rbac.create). Cluster-scoped RBAC does not. There is no supported way to install only the namespaced gateway objects while leaving ClusterRole / ClusterRoleBinding to a separate cluster-admin step.
This is a different split from #2485 (gateway vs workspace-namespace charts). Even a gateway-only install would still include cluster-scoped RBAC.
Impact / Why This Matters
Without this feature, users must run the OpenShell Helm release as cluster-admin, even when they only need to deploy namespaced objects (Deployment/StatefulSet, Service, ServiceAccount, ConfigMaps, Secrets, and namespaced Role/RoleBinding).
That is insufficient for many customer environments:
The installer is a namespace-admin GitOps or platform controller that cannot create ClusterRole or ClusterRoleBinding.
Cluster-scoped RBAC is owned by a cluster-admin / HOM team and must not be applied by application Helm releases.
Mixing cluster-scoped and namespaced objects in one release forces a privilege escalation of the entire OpenShell install, or it fails with forbidden: User cannot create resource "clusterroles" in API group "rbac.authorization.k8s.io" at the cluster scope.
Workarounds today are all fragile: fork and patch the chart, post-process helm template output, or disable serviceAccount.create and hand-roll RBAC while still fighting the unconditional ClusterRole templates. That blocks clean adoption on enterprise and OpenShift clusters that separate cluster-admin from namespace-admin.
This matters because it is a packaging/privilege boundary, not a missing runtime capability. The gateway already works if ClusterRole/ClusterRoleBinding exist; the chart just will not let a non-admin user install it.
Proposed Design
From the operator’s point of view, installing OpenShell on a restricted cluster should be two Helm (or equivalent) steps with a clear ownership boundary:
Cluster-admin (once per cluster, or once per gateway ServiceAccount)
Apply the cluster-scoped objects the gateway needs (ClusterRole and ClusterRoleBinding whose subject is the gateway ServiceAccount in the release namespace). These may live in a separate admin chart, a documented manifest, or the same OpenShell chart with cluster objects enabled.
Namespace-admin (normal OpenShell install/upgrade)
Install the OpenShell chart with cluster-scoped objects omitted. The release creates only namespaced resources. The gateway ServiceAccount name and namespace remain stable so the pre-created ClusterRoleBinding still matches.
Observable behavior:
Default install stays as it is today: cluster-scoped RBAC is created, so existing cluster-admin installs do not change.
When the omit/disable value is set, helm template / helm install does not emit ClusterRole or ClusterRoleBinding.
Chart docs list which objects are cluster-scoped vs namespaced, and show the two-step admin / non-admin workflow (including that ClusterRoleBinding subjects must match the gateway ServiceAccount created by the namespaced release).
The flag is independent of workspace mode (shared / managed / operator). Those modes may change what the ClusterRole contains; they should not force a namespace-admin to apply it.
Exact value names and whether this is one flag or a small RBAC create block can follow existing chart conventions (serviceAccount.create, credential-driver rbac.create). The user-facing contract is: cluster-scoped objects are skippable without forking the chart.
Acceptance Criteria
- Default chart render still includes ClusterRole and ClusterRoleBinding (no behavior change for current installs).
- A documented chart value omits ClusterRole and ClusterRoleBinding from the render (helm template shows neither kind: ClusterRole nor kind: ClusterRoleBinding).
- With that value set, the remaining objects are namespaced and a namespace-admin can helm install / helm upgrade the chart without cluster-scoped RBAC permissions.
- ClusterRoleBinding, when created (default path or a separate admin install), still binds to the gateway ServiceAccount name and namespace used by the namespaced release.
- Helm README / Kubernetes setup docs describe the cluster-admin vs namespace-admin split and list the cluster-scoped objects.
- Existing serviceAccount.create=false + custom ServiceAccount workflow still works when cluster RBAC is created separately.
Alternatives Considered
- Always require cluster-admin for the OpenShell release. Simplest for the chart, but it blocks customers whose platform installer is namespace-admin only, and it mixes privilege levels that security teams keep separate.
- Disable serviceAccount.create and supply a pre-created ServiceAccount. Docs already mention this for custom RBAC, but the ClusterRole templates still render, so Helm still tries to create cluster-scoped objects. That does not solve the problem.
- Split into two published charts (gateway vs workspace) as in #2485. Useful for tenant-namespace ownership, but the gateway chart is still expected to carry cluster-scoped runtime permissions. A workspace split does not give a namespace-admin gateway install.
- Post-process helm template or maintain a forked chart. Works as a local workaround; it is not a supported, versioned interface and drifts on every upstream chart change.
A create/omit flag on cluster-scoped objects is the smallest user-facing change that preserves today’s default and unblocks the two-user (admin / non-admin) install path.
Agent Investigation
- Reviewed deploy/helm/openshell/templates/clusterrole.yaml and clusterrolebinding.yaml: neither is gated on a values flag.
- Reviewed values.yaml: serviceAccount.create, sandboxServiceAccount.create, grpcRoute.gateway.create, and server.credentialDrivers.kubernetesSecrets.rbac.create already exist; there is no equivalent for ClusterRole / ClusterRoleBinding.
- Kubernetes setup docs state the chart creates ClusterRole + ClusterRoleBinding openshell-node-reader as part of a normal install (docs).
- Related but not a duplicate:
- #2485 — split gateway vs workspace-namespace charts; gateway chart still owns cluster-scoped RBAC.
- #1018 — document RBAC requirements; does not add a skip flag.
Checklist
User Story
As a platform operator installing OpenShell on a shared or restricted Kubernetes cluster, I want cluster-scoped chart objects (ClusterRole and ClusterRoleBinding) to be optional, so a cluster-admin can apply those objects once and a namespace-admin can install or upgrade the OpenShell gateway chart without cluster-admin privileges.
Problem Statement
The published OpenShell Helm chart always renders cluster-scoped RBAC as part of the same release as the gateway workload.
Today deploy/helm/openshell/templates/clusterrole.yaml and clusterrolebinding.yaml have no values guard. A helm install / helm upgrade of the chart therefore always attempts to create:
ClusterRole -node-reader (TokenReview, nodes, namespaces, and additional cluster-wide rules in managed/operator workspace modes)
ClusterRoleBinding -node-reader (binds that ClusterRole to the gateway ServiceAccount)
Other chart objects already have create/enable flags (serviceAccount.create, sandboxServiceAccount.create, grpcRoute.gateway.create, credential-driver rbac.create). Cluster-scoped RBAC does not. There is no supported way to install only the namespaced gateway objects while leaving ClusterRole / ClusterRoleBinding to a separate cluster-admin step.
This is a different split from #2485 (gateway vs workspace-namespace charts). Even a gateway-only install would still include cluster-scoped RBAC.
Impact / Why This Matters
Without this feature, users must run the OpenShell Helm release as cluster-admin, even when they only need to deploy namespaced objects (Deployment/StatefulSet, Service, ServiceAccount, ConfigMaps, Secrets, and namespaced Role/RoleBinding).
That is insufficient for many customer environments:
The installer is a namespace-admin GitOps or platform controller that cannot create ClusterRole or ClusterRoleBinding.
Cluster-scoped RBAC is owned by a cluster-admin / HOM team and must not be applied by application Helm releases.
Mixing cluster-scoped and namespaced objects in one release forces a privilege escalation of the entire OpenShell install, or it fails with forbidden: User cannot create resource "clusterroles" in API group "rbac.authorization.k8s.io" at the cluster scope.
Workarounds today are all fragile: fork and patch the chart, post-process helm template output, or disable serviceAccount.create and hand-roll RBAC while still fighting the unconditional ClusterRole templates. That blocks clean adoption on enterprise and OpenShift clusters that separate cluster-admin from namespace-admin.
This matters because it is a packaging/privilege boundary, not a missing runtime capability. The gateway already works if ClusterRole/ClusterRoleBinding exist; the chart just will not let a non-admin user install it.
Proposed Design
From the operator’s point of view, installing OpenShell on a restricted cluster should be two Helm (or equivalent) steps with a clear ownership boundary:
Cluster-admin (once per cluster, or once per gateway ServiceAccount)
Apply the cluster-scoped objects the gateway needs (ClusterRole and ClusterRoleBinding whose subject is the gateway ServiceAccount in the release namespace). These may live in a separate admin chart, a documented manifest, or the same OpenShell chart with cluster objects enabled.
Namespace-admin (normal OpenShell install/upgrade)
Install the OpenShell chart with cluster-scoped objects omitted. The release creates only namespaced resources. The gateway ServiceAccount name and namespace remain stable so the pre-created ClusterRoleBinding still matches.
Observable behavior:
Default install stays as it is today: cluster-scoped RBAC is created, so existing cluster-admin installs do not change.
When the omit/disable value is set, helm template / helm install does not emit ClusterRole or ClusterRoleBinding.
Chart docs list which objects are cluster-scoped vs namespaced, and show the two-step admin / non-admin workflow (including that ClusterRoleBinding subjects must match the gateway ServiceAccount created by the namespaced release).
The flag is independent of workspace mode (shared / managed / operator). Those modes may change what the ClusterRole contains; they should not force a namespace-admin to apply it.
Exact value names and whether this is one flag or a small RBAC create block can follow existing chart conventions (serviceAccount.create, credential-driver rbac.create). The user-facing contract is: cluster-scoped objects are skippable without forking the chart.
Acceptance Criteria
Alternatives Considered
A create/omit flag on cluster-scoped objects is the smallest user-facing change that preserves today’s default and unblocks the two-user (admin / non-admin) install path.
Agent Investigation
Checklist