Skip to content

🐛 Fix namespace-scoped RBAC Role name conflicts with kustomize#1329

Closed
camilamacedo86 wants to merge 1 commit intokubernetes-sigs:mainfrom
camilamacedo86:roles-names-fix
Closed

🐛 Fix namespace-scoped RBAC Role name conflicts with kustomize#1329
camilamacedo86 wants to merge 1 commit intokubernetes-sigs:mainfrom
camilamacedo86:roles-names-fix

Conversation

@camilamacedo86
Copy link
Member

@camilamacedo86 camilamacedo86 commented Jan 28, 2026

When using namespace-scoped RBAC markers with different namespaces, controller-gen would generate multiple Roles with the same name in different namespaces. This caused kustomize to fail with "namespace transformation produces ID conflict" when applying a global namespace transformation, as both Roles would end up in the same namespace with identical names. More info: kubernetes-sigs/kubebuilder#5148 (comment)

Changes:

  • Append namespace to Role name for namespace-scoped Roles (e.g., "manager-role-infrastructure" for namespace "infrastructure")
  • ClusterRoles maintain original name without suffix
  • Updated documentation to clarify the naming behavior
  • Added test scenario covering the reported issue with different resource types in different namespaces (apps/deployments in infrastructure namespace, core/secrets in users namespace)

This ensures uniqueness when kustomize transforms namespaces, preventing the ID conflict error.

When using namespace-scoped RBAC markers with different namespaces,
controller-gen would generate multiple Roles with the same name in
different namespaces. This caused kustomize to fail with "namespace
transformation produces ID conflict" when applying a global namespace
transformation, as both Roles would end up in the same namespace with
identical names.

Changes:
- Append namespace to Role name for namespace-scoped Roles
  (e.g., "manager-role-infrastructure" for namespace "infrastructure")
- ClusterRoles maintain original name without suffix
- Updated documentation to clarify the naming behavior
- Added test scenario covering the reported issue with different
  resource types in different namespaces (apps/deployments in
  infrastructure namespace, core/secrets in users namespace)

This ensures uniqueness when kustomize transforms namespaces, preventing
the ID conflict error.
@k8s-ci-robot
Copy link
Contributor

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: camilamacedo86
Once this PR has been reviewed and has the lgtm label, please assign vincepri for approval. For more information see the Code Review Process.

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@k8s-ci-robot k8s-ci-robot added cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. size/M Denotes a PR that changes 30-99 lines, ignoring generated files. labels Jan 28, 2026
@camilamacedo86
Copy link
Member Author

camilamacedo86 commented Jan 28, 2026

@sbueringer @JoelSpeed
Could you please give a help/hand for we get this small fix merged?

@JoelSpeed
Copy link
Contributor

This feels like it could be breaking to me. Existing users will suddenly get a different RBAC file name, which if they blindly apply, means they'll end up with 2 roles per namespace now, with one redundant. Will the rolebindings get updated automatically? I'm guessing not, so then they'd be stuck on an older role that is no longer being updated/maintained.

Is it possible to add a name parameter to the RBAC generation? That way, folks would instead be able to choose their own names, rather than relying on generated names, and then they can control this themselves, deliberately, rather than us deciding to add a namespace to the name?

@camilamacedo86
Copy link
Member Author

Hi @JoelSpeed

If the user use namespace we have a duplication and that does not work well with kustomize

See:

The Problem

When using namespace-scoped RBAC markers with different namespaces, controller-gen generated multiple Roles with duplicate names in different namespaces. This caused kustomize to fail with a "namespace transformation produces ID conflict" error.

Test Scenario

Using these RBAC markers in a controller:

// +kubebuilder:rbac:groups=apps,namespace=infrastructure,resources=deployments,verbs=get;list;watch;update;patch
// +kubebuilder:rbac:groups="",namespace=users,resources=secrets,verbs=get;list;watch

BEFORE Fix: Duplicate Role Names ❌

Generated YAML

---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: manager-role        # ← DUPLICATE NAME
  namespace: infrastructure
rules:
- apiGroups:
  - apps
  resources:
  - deployments
  verbs:
  - get
  - list
  - patch
  - update
  - watch
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: manager-role        # ← DUPLICATE NAME
  namespace: users
rules:
- apiGroups:
  - ""
  resources:
  - secrets
  verbs:
  - get
  - list
  - watch

After Kustomize Namespace Transformation

When using kustomize with a global namespace transformation:

# config/default/kustomization.yaml
namespace: myproject-system

Result: CONFLICT! ❌

---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: manager-role          # ← SAME NAME
  namespace: myproject-system # ← SAME NAMESPACE
rules:
- apiGroups:
  - apps
  resources:
  - deployments
  verbs: [get, list, patch, update, watch]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: manager-role          # ← SAME NAME
  namespace: myproject-system # ← SAME NAMESPACE
rules:
- apiGroups: [""]
  resources: [secrets]
  verbs: [get, list, watch]

Kustomize Error

Error: namespace transformation produces ID conflict: 
[{"apiVersion":"rbac.authorization.k8s.io/v1","kind":"Role","metadata":{"name":"manager-role","namespace":"myproject-system"}...}
 {"apiVersion":"rbac.authorization.k8s.io/v1","kind":"Role","metadata":{"name":"manager-role","namespace":"myproject-system"}...}]

Two Roles with identical (kind, name, namespace) = CONFLICT!


AFTER Fix: Unique Role Names ✅

Generated YAML

---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: manager-role-infrastructure  # ← UNIQUE NAME (namespace suffix)
  namespace: infrastructure
rules:
- apiGroups:
  - apps
  resources:
  - deployments
  verbs:
  - get
  - list
  - patch
  - update
  - watch
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: manager-role-users           # ← UNIQUE NAME (namespace suffix)
  namespace: users
rules:
- apiGroups:
  - ""
  resources:
  - secrets
  verbs:
  - get
  - list
  - watch

After Kustomize Namespace Transformation

With the same global namespace transformation:

# config/default/kustomization.yaml
namespace: myproject-system

Result: NO CONFLICT! ✅

---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: manager-role-infrastructure  # ← UNIQUE NAME
  namespace: myproject-system
rules:
- apiGroups:
  - apps
  resources:
  - deployments
  verbs: [get, list, patch, update, watch]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: manager-role-users           # ← UNIQUE NAME
  namespace: myproject-system
rules:
- apiGroups: [""]
  resources: [secrets]
  verbs: [get, list, watch]

Kustomize Success

$ kustomize build config/default | kubectl apply -f -
role.rbac.authorization.k8s.io/manager-role-infrastructure created
role.rbac.authorization.k8s.io/manager-role-users created

Each Role has a unique name - no conflict!

// The generated Role name will be suffixed with the namespace (e.g., "manager-role-namespace")
// to ensure uniqueness when multiple namespace-scoped Roles are generated. This suffix is
// ONLY applied to namespace-scoped Roles, not to ClusterRoles.
Namespace string `marker:",optional"`
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Won't this break everyone using this part of controller-gen today?

Copy link
Member Author

@camilamacedo86 camilamacedo86 Jan 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The change shouldn’t break anything functionally. The RBAC files will still be re-generated; the only delta is the Role name. If someone is currently using namespace-scoped RBAC, the generated Role will now include a namespace suffix.

Honestly, I think this is a very rare use case. If the marker-based namespace RBAC generation were common, we likely would have seen this reported earlier—this is the first time it’s come up. ( it cannot work with kustomize/kubebuilder and nobody raised the issue before )

In this case we’re only changing the resource name. The main way this could “break” someone is if they have external tooling or scripts that reference the old Role name by string (e.g., CI checks, dashboards, custom automation). Otherwise, I think it should be very unlikely to cause issues.

Copy link
Member

@sbueringer sbueringer Jan 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wouldn't it lead to duplicate objects if folks still have roles with the old name around and now the name changes?

I'm not sure if we can assume that the files generated by controller-gen are always consumed by kustomize

Generally speaking Roles are usually referenced by name by RoleBindings

Copy link
Member Author

@camilamacedo86 camilamacedo86 Jan 29, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree we can’t assume controller-gen output is always consumed by Kustomize. That said, I think the most common adoption path is still Kubebuilder/Operator SDK + Kustomize, where controller-gen is part of the standard workflow.

Also, I don’t think the namespace= RBAC marker is used very often (which may explain why this wasn’t caught earlier). GitHub search suggests ~1.7k usages of namespace= vs ~48.1k total RBAC marker usages:

Given that context, expecting generated resources to have unique names seems reasonable. The key question for me is:

1. How do we ensure controller-gen never generates two resources with the same name here?
2. IMO, generating duplicate resource names is a bug.

What’s your suggested fix?
If a breaking change isn’t acceptable even to fix a bug, what alternative do you propose? Should we introduce a new marker resource name? What would to be acceptable?

PS: There are 23k+ refs using the latest Kubebuilder layouts (which promote controller-gen) based on go.kubebuilder.io references:
https://github.com/search?q=go.kubebuilder.io&type=code

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've opened an alternative PR that addresses the breaking change concerns raised here: #1334

Instead of automatically appending namespace suffixes, my approach adds an optional roleName parameter to the RBAC marker:

// +kubebuilder:rbac:groups=apps,namespace=infrastructure,roleName=infra-manager,resources=deployments,verbs=get;list
// +kubebuilder:rbac:groups="",namespace=users,roleName=user-secrets,resources=secrets,verbs=get

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense. Thx for looking into how this can be done without a breaking change

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the review!

AlirezaPourchali added a commit to AlirezaPourchali/controller-tools that referenced this pull request Feb 11, 2026
Allows users to specify custom role names per marker to avoid
name conflicts when using namespace-scoped RBAC across multiple
namespaces.

Key features:
- Optional roleName parameter in RBAC marker
- Non-breaking: defaults to --roleName flag if not specified
- Useful for avoiding kustomize namespace transformation conflicts
- Multiple markers with same roleName in same namespace are merged

Example usage:
  // +kubebuilder:rbac:groups=apps,namespace=infrastructure,roleName=infra-manager,resources=deployments,verbs=get;list
  // +kubebuilder:rbac:groups="",namespace=users,roleName=user-secrets,resources=secrets,verbs=get

This addresses the issue raised in kubernetes-sigs/kubebuilder#5148
where namespace-scoped Roles with the same name in different
namespaces cause kustomize namespace transformation ID conflict errors.

Unlike PR kubernetes-sigs#1329 (automatic namespace suffix), this approach:
- Is opt-in (non-breaking for existing users)
- Gives users explicit control over Role names
- Works for any use case, not just kustomize
- Avoids breaking changes and migration issues
@sbueringer
Copy link
Member

#1334 has been merged, I think we can close this one?

@k8s-ci-robot k8s-ci-robot added the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Feb 13, 2026
@k8s-ci-robot
Copy link
Contributor

PR needs rebase.

Details

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.

@camilamacedo86
Copy link
Member Author

Closing in favour of the PR that adds the roleName

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. size/M Denotes a PR that changes 30-99 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants