⚠️ (helm/v2-plugin): enhance RBAC support with namespace-scoped deployments, multi-namespace configuration, and dynamic Role/ClusterRole rendering (rename rbacHelpers to rbac.helpers)#5579
Conversation
|
@Allex1 could you please give a hand on this one? |
30eb9a4 to
9dfc400
Compare
|
Hi @sam-mcbr could you please help us to validate this one. |
e313e68 to
da20941
Compare
|
Hi @camilamacedo86! I think this PR looks good. I tested with our deployment and I do see when I remove cluster-scoped RBAC scaffolding it generates a correct I do see this doesn't solve the issue I opened (#5546) where we need both cluster-scoped RBAC and namespace-scoped RBAC (but that seems intended since you didn't mark it as fixed in the description. I only mention this because when both kinds of scaffolds are included, the Thanks for the fast improvements to the chart generation! |
|
Hi @sam-mcbr Thank you a lot for the fast review and for raise this one 🎉 So, we do not need to duplicate the roles. We do that conditionally.
WDYT? Does not this solve the scenario? |
|
@camilamacedo86 maybe I'm missing something about the changes. To clarify, our use-case is: We have an operator that monitors CustomResources across a cluster, and then uses those to create/reconcile a single
Please correct me if I'm misunderstanding the changes in your PR, but to me it looks like the chart only supports either a |
|
That is true. So, now I understand better your case. Let me think more about |
|
Hi @sam-mcbr Your issue scenario has no relation with this PR. Then that would either work with this one, because the goal here is allow the cluster-admin/consumer of the chart install only using namespaced scoped instead of cluster scoped options. But I am changing this PR to either cover this specific scenario. |
da20941 to
8bfe8dd
Compare
rbacHelpers to rbac.helpers)
8bfe8dd to
5efe81a
Compare
pkg/plugins/optional/helm/v2alpha/scaffolds/internal/kustomize/helm_templater.go
Outdated
Show resolved
Hide resolved
pkg/plugins/optional/helm/v2alpha/scaffolds/internal/kustomize/helm_templater.go
Outdated
Show resolved
Hide resolved
eceeaf2 to
c3c91be
Compare
pkg/plugins/optional/helm/v2alpha/scaffolds/internal/templates/values_basic.go
Show resolved
Hide resolved
pkg/plugins/optional/helm/v2alpha/scaffolds/internal/templates/values_basic.go
Show resolved
Hide resolved
pkg/plugins/optional/helm/v2alpha/scaffolds/internal/templates/values_basic.go
Show resolved
Hide resolved
c3c91be to
83939ab
Compare
pkg/plugins/optional/helm/v2alpha/scaffolds/internal/kustomize/helm_templater.go
Show resolved
Hide resolved
pkg/plugins/optional/helm/v2alpha/scaffolds/internal/kustomize/helm_templater.go
Show resolved
Hide resolved
rbacHelpers to rbac.helpers)rbacHelpers to rbac.helpers)
83939ab to
585d9fd
Compare
585d9fd to
b01bb7a
Compare
pkg/plugins/optional/helm/v2alpha/scaffolds/internal/kustomize/helm_templater.go
Outdated
Show resolved
Hide resolved
pkg/plugins/optional/helm/v2alpha/scaffolds/internal/kustomize/helm_templater.go
Outdated
Show resolved
Hide resolved
pkg/plugins/optional/helm/v2alpha/scaffolds/internal/kustomize/helm_templater.go
Show resolved
Hide resolved
pkg/plugins/optional/helm/v2alpha/scaffolds/internal/templates/values_basic_test.go
Outdated
Show resolved
Hide resolved
|
/lgtm thanks for this |
|
@Allex1: changing LGTM is restricted to collaborators DetailsIn response to this:
Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository. |
|
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: Allex1, camilamacedo86 The full list of commands accepted by this bot can be found here. The pull request process is described here DetailsNeeds approval from an approver in each of these files:
Approvers can indicate their approval by writing |
| detectedPrefix: "test-project", | ||
| chartName: "test-project", | ||
| managerNamespace: "user", // Short namespace that appears as substring | ||
| roleNamespaces: make(map[string]string), |
There was a problem hiding this comment.
Wouldn't a nil map work too?
| // Exclude metrics-auth-role which is always cluster-scoped | ||
| if !strings.Contains(name, "metrics") { |
There was a problem hiding this comment.
The comment does not seem to match the code.
| chartConverter := kustomize.NewChartConverter(resources, namePrefix, chartName, s.outputDir) | ||
|
|
||
| // Detect multi-namespace RBAC scenarios. | ||
| // Extract manager namespace first to identify which namespaces are "specific" |
| } | ||
| } | ||
|
|
||
| // Collect Roles and RoleBindings that deploy to specific namespaces (not manager namespace) |
There was a problem hiding this comment.
Ah, not manager ns. Perhaps move this definition up?
…loyments, multi-namespace configuration, and dynamic Role/ClusterRole rendering Generated-by: Claude
| func (t *HelmTemplater) handleRBACConditionalWrappers(yamlContent, kind, name string) string { | ||
| // Distinguish between essential RBAC and helper RBAC | ||
| isHelper := strings.Contains(name, "admin-role") || strings.Contains(name, "editor-role") || | ||
| strings.Contains(name, "viewer-role") | ||
|
|
||
| // Check for specific Kubebuilder-scaffolded metrics RBAC resources | ||
| isMetricsAuthRole := strings.Contains(name, "metrics-auth-role") | ||
| isMetricsAuthBinding := strings.Contains(name, "metrics-auth-rolebinding") |
There was a problem hiding this comment.
handleRBACConditionalWrappers classifies RBAC resources as “metrics-related” via strings.Contains(name, "metrics"). Because RBAC resource names include the project prefix, a project whose name/prefix contains metrics (e.g. metrics-operator-manager-role) will be misclassified and wrapped by the metrics conditionals, potentially preventing essential RBAC from being rendered when metrics is disabled. Prefer matching specific known metrics RBAC resource suffixes (e.g., -metrics-auth-role, -metrics-reader, -metrics-auth-rolebinding) or otherwise using a delimiter/suffix-based match rather than a broad substring check.
| func (t *HelmTemplater) handleCertificateConditionalWrappers(yamlContent, name string) string { | ||
| // Handle different certificate types | ||
| isMetricsCert := strings.Contains(name, "metrics-cert") || strings.Contains(name, "metrics") | ||
| if isMetricsCert { | ||
| // Metrics certificates need certManager, metrics enabled, AND secure metrics (TLS) | ||
| // When metrics.secure=false, metrics use HTTP so TLS certs are not needed | ||
| return fmt.Sprintf( | ||
| "{{- if and .Values.certManager.enable .Values.metrics.enable .Values.metrics.secure }}\n%s{{- end }}\n", | ||
| yamlContent) | ||
| } | ||
| // Other certificates (webhook serving certs) only need certManager enabled | ||
| return fmt.Sprintf("{{- if .Values.certManager.enable }}\n%s{{- end }}", yamlContent) | ||
| } | ||
|
|
||
| // handleServiceConditionalWrappers handles conditional logic for Service resources | ||
| func (t *HelmTemplater) handleServiceConditionalWrappers(yamlContent, name string) string { | ||
| // Services need conditional logic based on their purpose | ||
| if strings.Contains(name, "metrics") { | ||
| // Metrics services need metrics enabled | ||
| return fmt.Sprintf("{{- if .Values.metrics.enable }}\n%s{{- end }}\n", yamlContent) | ||
| } | ||
| if strings.Contains(name, "webhook") { | ||
| // Webhook services need webhook enabled | ||
| return fmt.Sprintf("{{- if .Values.webhook.enable }}\n%s{{- end }}\n", yamlContent) | ||
| } |
There was a problem hiding this comment.
handleCertificateConditionalWrappers / handleServiceConditionalWrappers use broad substring checks like strings.Contains(name, "metrics") (and "webhook") to decide conditional wrappers. Since resource names are typically prefixed with the project name, this can misclassify unrelated resources when the project prefix contains those substrings (e.g., metrics-operator-webhook-service would be treated as a metrics Service). Consider switching to suffix- or pattern-based matching for the well-known resource names you intend to target (metrics service, metrics certs, webhook service, etc.).
| // Check if project has cluster-scoped RBAC (ClusterRole resources for business logic). | ||
| // By default, Kubebuilder scaffolds metrics-auth-role (for TokenReview/SubjectAccessReview APIs) | ||
| // and metrics-reader (for /metrics nonResourceURLs). Both must always remain ClusterRoles as they | ||
| // access cluster-scoped APIs. This check identifies whether the project has additional ClusterRoles | ||
| // for business logic (e.g., controller permissions), which can optionally be converted to namespace-scoped | ||
| // Roles via the rbac.namespaced toggle. | ||
| hasClusterScopedRBAC := false | ||
| for _, cr := range resources.ClusterRoles { | ||
| name := cr.GetName() | ||
| // Exclude the specific Kubebuilder-scaffolded metrics roles which are always cluster-scoped | ||
| if strings.Contains(name, "metrics-auth-role") || strings.Contains(name, "metrics-reader") { |
There was a problem hiding this comment.
hasClusterScopedRBAC detection excludes any ClusterRole whose name contains "metrics". Because ClusterRole names include the project prefix, projects with metrics in their name/prefix will incorrectly be treated as having no cluster-scoped RBAC, which can suppress emitting the rbac.namespaced value/docs. Consider excluding only the specific metrics ClusterRoles (e.g., metrics-auth-role/metrics-reader) using suffix/pattern matches rather than a generic substring.
This PR introduces two new RBAC configuration options to the Helm v2-alpha plugin.
1. rbac.namespaced — Namespace-scoped operator deployments
Allows switching between cluster-wide and namespace-scoped RBAC.
Example values:
Example install:
helm install my-operator ./dist/chart --set rbac.namespaced=true2. rbac.roleNamespaces — Multi-namespace RBAC
Enables deploying Roles and RoleBindings into specific namespaces using kubebuilder annotations.
Example annotations:
Generated values:
Override at install:
Breaking Change
RBAC values structure has changed:
Before:
After:
Closes:
Partially: #5517