-
Notifications
You must be signed in to change notification settings - Fork 1.6k
π (helm/v2-alpha): Fix cross-namespace RBAC file naming and namespace handling #5360
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. Weβll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
π (helm/v2-alpha): Fix cross-namespace RBAC file naming and namespace handling #5360
Conversation
|
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: 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 |
|
Could you help us in the review? |
096e67d to
bb65586
Compare
|
/test pull-kubebuilder-e2e-k8s-1-34-0 |
| namespace := resource.GetNamespace() | ||
| if namespace != "" && (kind == "Role" || kind == "RoleBinding") { | ||
| fileName = fmt.Sprintf("%s-%s", fileName, namespace) | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
/hold
Requires changes
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The filename collision fix is good.
The logic for cross-namespace RBAC filenames makes sense
bb65586 to
56dbecf
Compare
56dbecf to
015443b
Compare
|
/hold cancel |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for working on this fix! I really appreciate you addressing issue #5354.
The filename collision prevention logic in chart_writer.go (lines 165-174) looks great - appending the namespace suffix should properly distinguish cross-namespace roles.
I tested the new changes on my project to generate the helm chart and i found an interesting bug.
if the CRD name contains the namespace name, we will have this in the ClusterRole manifest:
....
resources:
- {{ .Release.Namespace }}s/finalizers
verbs:
- update
- apiGroups:
- identity.me.cloud
resources:
- {{ .Release.Namespace }}s/status
verbs:
- get
- patch
- update
you can see my inline comment for more details.
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_test.go
Show resolved
Hide resolved
8238663 to
efddbe6
Compare
efddbe6 to
a2448be
Compare
|
Thank you for all your reviews. Could you please check it now? |
Fixes handling of namespace-scoped RBAC resources (Role, RoleBinding) in cross-namespace scenarios for leader election and cross-namespace permissions. Changes: - Extract manager namespace from Deployment resource - Append namespace suffix only for cross-namespace RBAC files - Template only manager namespace refs, preserve cross-namespace values Result: - manager-role.yaml (manager NS, templated) - manager-role-infrastructure.yaml (cross-NS, preserved) Assisted-by: Cursor
a2448be to
69a9cc8
Compare
What This Fixes
This PR fixes how the Helm plugin (v2-alpha) handles namespaces when converting your Kustomize project to a Helm chart.
Problems Before This Fix
β Missing RBAC Resources
If you used namespace-scoped Roles (like for leader election or cross-namespace permissions), they were ignored. Only ClusterRole was converted. Your Helm-deployed operator would fail with permission errors.
β Broken Resource Names
If your namespace was
userand you had a resource calledusers, it would break:users{{ .Release.Namespace }}sπ±β Incomplete DNS Replacement
Only
.svcDNS names worked. Other patterns like.pod,.svc.cluster.local, or.endpointswere left with hardcoded namespaces.β File Name Collisions
Multiple Roles with the same name in different namespaces would overwrite each other.
β Hardcoded Annotations
Things like
cert-manager.io/inject-ca-from: my-namespace/certstayed hardcoded.What This Fixes
β All RBAC Resources Converted
Both ClusterRole AND namespace-scoped Roles/RoleBindings are now converted to Helm templates.
β Safe Namespace Replacement
Resource names like
users,deployments,podsare never touched. Only actual namespace fields are replaced.β All Kubernetes DNS Patterns
Every DNS format works:
.svc,.svc.cluster.local,.pod,.endpoints, with ports, with paths, everything.β Smart Cross-Namespace Handling
myapp-system) β{{ .Release.Namespace }}infrastructure,production) β kept as-isβ No More File Collisions
Files get unique names:
leader-election-role.yamlvsmanager-role-infrastructure.yamlβ Complete Templating
Annotations, DNS names, resource references - everything that should be templated is templated.
How It Works (Simple Explanation)
When you run
kubebuilder edit --plugins=helm/v2-alpha, the plugin reads your Kustomize output and converts it to Helm templates.The Smart Rules
{{ .Release.Namespace }}Example: Your Namespace
When someone installs your chart:
It becomes:
namespace: productionβExample: External Namespace
This is for cross-namespace permissions that must use a specific namespace.
Real-World Examples
Example 1: Leader Election Role
What you write (RBAC marker):
//+kubebuilder:rbac:groups=coordination.k8s.io,resources=leases,verbs=get;list;watch;create;update;patch;deleteWhat Kustomize generates:
What the Helm plugin generates:
dist/chart/templates/rbac/leader-election-role.yamlWhy this is important: Your operator can now be installed in ANY namespace:
Example 2: Cross-Namespace Permissions
What you write (RBAC marker with explicit namespace):
//+kubebuilder:rbac:groups=apps,namespace=infrastructure,resources=deployments,verbs=get;list;watchWhat Kustomize generates:
What the Helm plugin generates:
dist/chart/templates/rbac/manager-role-infrastructure.yaml(note the-infrastructuresuffix!)Why this is important: You can have permissions in specific namespaces:
Example 3: ConfigMap with Service URLs
What Kustomize generates:
What the Helm plugin generates:
Why this is important: Your service URLs automatically work in any namespace:
Example 4: The Substring Bug Fix
Scenario: Your namespace is
userand you have a resource type calledusers.Before this fix (BROKEN β):
After this fix (CORRECT β ):
How it works: The code uses smart patterns that only match actual namespaces:
namespace: userβ Hasnamespace:field, replace itusersβ Just a word, no namespace field, keep itWhat Gets Templated vs Preserved
β Gets Templated (Manager Namespace β
{{ .Release.Namespace }})namespace: myapp-systemnamespace: {{ .Release.Namespace }}api.myapp-system.svcapi.{{ .Release.Namespace }}.svcapi.myapp-system.svc.cluster.localapi.{{ .Release.Namespace }}.svc.cluster.localapi.myapp-system.svc:8080api.{{ .Release.Namespace }}.svc:8080pod.myapp-system.pod.cluster.localpod.{{ .Release.Namespace }}.pod.cluster.localmyapp-system/my-cert{{ .Release.Namespace }}/my-certconfigMapRef: myapp-system/configconfigMapRef: {{ .Release.Namespace }}/configβ Gets Preserved (External Namespaces)
namespace: infrastructure.monitoring-system.svcexternal-namespace/resourceβ Never Touched (Resource Names)
users,deployments,podsapp: frontendmy-applicationFile Organization
RBAC Files Go to
rbac/DirectoryAll RBAC resources are organized in
dist/chart/templates/rbac/:Note: They're never in
extras/, even custom ServiceAccounts.Filename Rules
manager-role.yamlleader-election-role.yamlmanager-role-infrastructure.yamlleader-election-rolebinding.yamlmanager-rolebinding-infrastructure.yamlThe
-<namespace>suffix prevents file collisions when you have multiple Roles with the same name in different namespaces.Before vs After Comparison
Before This Fix
After This Fix
Technical Details (For the Curious)
Why Regex Instead of YAML Parsing?
Short answer: The content has Helm templates mixed with YAML, which breaks YAML parsers.
Long answer: By the time we need to replace namespaces, the content looks like this:
If we try to parse this as YAML:
So we use smart regex patterns that only match what we want:
namespace: myapp-system(only if it's on its own line).myapp-system.svc(only if there are dots on both sides)myapp-system/cert(only if followed by/)Safety Guarantees
Each pattern is designed to prevent false matches:
(?m)^(\s*)namespace:\s+<value>\s*$namespace: myapp-systemmessage: "namespace: myapp-system"(in string)\b<value>/myapp-system/certhttps://example.com/myapp-system/docs(URL)\.<value>\..myapp-system.svcusers(no dots),app=myapp-system(no dots on both sides)Closes: #5354