Support runtime.wasmcloud.dev apiGroup RBAC to be namespaced vs Cluster#5208
Merged
Merged
Conversation
Signed-off-by: Jeremy Fleitz <jeremy@cosmonic.com>
Contributor
|
We'll want to call out this change in release notes. Chart upgrade in scoped mode replaces cluster-scoped …-workload-namespace and …-endpointslice ClusterRoles with same-named namespaced Roles. Helm should just handle this but plenty of operators don't use helm for the install. Upgrade note should include that operators should verify no orphaned ClusterRoles remain post-upgrade |
ricochet
approved these changes
May 27, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Support
runtime.wasmcloud.devRBAC as Namespaced vs ClusterSummary
When the operator is configured to watch a fixed set of namespaces
(
operator.watchNamespaces), it no longer needs — and should not be granted —cluster-wide access to the
runtime.wasmcloud.devapiGroup resources. This PRmakes the operator's workload-side RBAC follow the watch scope: cluster-wide
when watching all namespaces, namespaced when
watchNamespacesis set.Concretely, when
operator.watchNamespacesis non-empty, access toartifacts,workloads,workloadreplicasets, andworkloaddeployments(plus their
/statusand/finalizerssubresources) is granted via a Role +RoleBinding in each watched namespace instead of a cluster-wide
ClusterRole.The shared core resources (
configmaps/secrets/services/events) andendpointslicesare converted to the same per-namespace pattern.Motivation
Previously the main operator
ClusterRolealways granted theruntime.wasmcloud.devCRD verbs cluster-wide, regardless ofwatchNamespaces.For a
watchNamespacesinstall that is broader than the operator actually uses:the workload-side informer cache is already scoped to the watched namespaces via
cacheOpts.DefaultNamespaces(runtime-operator/cmd/main.go), so thecontrollers only ever read/write these resources within those namespaces.
Granting them per-namespace:
in the namespaces it manages;
workload resources rather than cluster-admin.
What changed
All changes are in the
runtime-operatorHelm chart; no operator code orgenerated manifests changed.
watchNamespacesset)clusterrole.yamlnot .Values.operator.watchNamespaces— omitted entirely in scoped modeclusterrolebinding.yamlnot .Values.operator.watchNamespaces— omitted in scoped modeworkload-crd-role.yaml(new)Role+RoleBindingper watched namespace forartifacts/workloads/workloadreplicasets/workloaddeployments+/status+/finalizersworkload-namespace-role.yamlClusterRole+ per-nsRoleBindingRole+RoleBindingper watched namespace (configmaps/secrets/services/events+services/finalizers)endpointslice-role.yamlClusterRole+ per-nsRoleBindingRole+RoleBindingper watched namespace (endpointslices)Resulting RBAC
watchNamespaces: [](watch all — default, unchanged behavior):ClusterRole+ClusterRoleBindingcarrying theruntime.wasmcloud.devCRD rules and the cluster-wide core/discovery rules.watchNamespaces: [team-a, team-b]:ClusterRole/ClusterRoleBinding;…-workload-crd,…-workload-namespace,…-endpointsliceRole+RoleBinding;…-leader-electionRoleremains in the operator's own namespace.HostCRDs are unaffected — they always live in the operator's own namespace andcontinue to be granted by the namespaced Role in
role.yaml.Why it's safe
The workload-side informer cache is scoped to
watchNamespacesviacacheOpts.DefaultNamespaces, so the controllers never list/watch theseresources cluster-wide. Namespaced RBAC is therefore sufficient for all
list/watch/CRUD the controllers perform, including stamping owner references with
blockOwnerDeletion=true(the GC admission plugin'supdateon<owner>/finalizerscheck is satisfied within each namespace).No RBAC drift
This is a chart-only change that relocates where permissions are bound; it does
not add or remove any permission from the set declared by the
+kubebuilder:rbacmarkers.
runtime-operator/config/rbac/role.yaml(generated bycontroller-gen)is unchanged, so the
make manifestsdrift guard continues to pass. Theper-namespace scoping is a Helm-only concern that
controller-gencannotexpress, so it intentionally lives only in the chart.
Testing
Verified all with a local Kind cluster install:
helm lintpasses.helm templaterendered withwatchNamespacesempty and withwatchNamespaces={team-a,team-b}, verifying:ClusterRole/ClusterRoleBindingpresent with CRD rules;ClusterRole/ClusterRoleBindingabsent;Role+RoleBindingpresent in each watched namespace with the full CRD rules(incl.
/statusand/finalizers).Out of scope / follow-ups
gateway.enabled, defaulttrue) (deprecated) grants cluster-widehosts/workloads; could be converted to per-namespace Roles in a follow-up.metrics-auth/metrics-reader) usetokenreviews,subjectaccessreviews, andnonResourceURLs— inherently cluster-scoped APIsthat cannot be namespaced; they could only be gated behind a values flag.
Signed-off-by: Jeremy Fleitz jeremy@cosmonic.com