Skip to content

[DOCS#EV-6436]: Document the RBAC management UI for Calico Enterprise - #3035

Open
dimitri-nicolo wants to merge 8 commits into
tigera:mainfrom
dimitri-nicolo:dimitri-EV-6436
Open

dimitri-nicolo wants to merge 8 commits into
tigera:mainfrom
dimitri-nicolo:dimitri-EV-6436

Conversation

@dimitri-nicolo

@dimitri-nicolo dimitri-nicolo commented Sep 21, 2026 •

Copy link
Copy Markdown
Contributor

Product Version(s): Calico Enterprise 3.24 (next) only.

Issue: EV-6436 — epic EV-6431 / PMREQ-824

Link to docs preview:

(Use the calico-docs-preview-next preview — the tigera preview builds released versions only, so it redirects away from next.)

SME review:

  • An SME has approved this change.

DOCS review:

  • A member of the docs team has approved this change.

Additional information:

One new page, Grant access with custom roles and IdP groups, under Operations > Calico Enterprise Manager UI, plus its sidebar entry and cross-links from Configure user roles and permissions and Configure an external identity provider.

  • calico-enterprise/operations/cnx/manage-roles.mdx (new)
  • sidebars-calico-enterprise.js
  • calico-enterprise/operations/cnx/roles-and-permissions.mdx (one link)
  • calico-enterprise/operations/cnx/configure-identity-provider.mdx (two links)

The page covers turning role management on and off, connecting an LDAP directory so roles can bind to its groups, creating and scoping a role, seeing who has access, and copying roles to another cluster. It is written around the console. kubectl appears only where the console has no equivalent: turning the feature off, creating the directory secret, and applying an export.

Each statement was checked against master: ui-apis, rbacsync in kube-controllers, the operator, and the console in ui-modules. These are the parts SMEs may want to look at most closely:

  • The Authentication settings a directory role depends on: spec.ldap.groupSearch, a nameAttribute that matches the directory secret's, and no groupsPrefix.
  • What happens to existing roles when role management is turned off.
  • Which export directions work, and the four values to change when copying a managed cluster's roles to another managed cluster.
  • What some permissions include, which lists access that a permission's name does not suggest.

Merge checklist:

  • Deploy preview inspected wherever changes were made
  • Build completed successfully
  • Test have passed

@netlify

netlify Bot commented Sep 21, 2026 •

Copy link
Copy Markdown

✅ Deploy Preview for calico-docs-preview-next ready!

Name Link
🔨 Latest commit b9847c2
🔍 Latest deploy log https://app.netlify.com/projects/calico-docs-preview-next/deploys/6ac96c8710e5ac000835e701
😎 Deploy Preview https://deploy-preview-3035--calico-docs-preview-next.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
🤖 Make changes Run an agent on this branch

To edit notification comments on pull requests, go to your Netlify project configuration.

@netlify

netlify Bot commented Sep 21, 2026 •

Copy link
Copy Markdown

❌ Deploy Preview for tigera failed. Why did it fail? →

Built without sensitive environment variables

Name Link
🔨 Latest commit b9847c2
🔍 Latest deploy log https://app.netlify.com/projects/tigera/deploys/6ac96c874698390008ec80f7

@dimitri-nicolo
dimitri-nicolo force-pushed the dimitri-EV-6436 branch 14 times, most recently from 8cd84c1 to e366482 Compare September 22, 2026 22:06
Add "Manage roles in the web console" under Operations > Calico Enterprise
Manager UI, covering what the feature needs to be usable: turning it on,
creating and scoping a role, granting it to a subject, binding it to an
identity provider group, reviewing who holds what, and exporting roles to
another cluster.

Scoped to Calico Enterprise 3.24 (next) only, plus its sidebar entry and a
cross-link from "Configure user roles and permissions".

Behaviour the page is deliberate about, since each is easy to get wrong:

- Role names take any non-empty string up to 253 characters, matching
  ValidateIdentity. Spaces, '@' and non-ASCII are all valid and necessary, since
  the name has to equal the group claim the IdP sends.
- Turning the feature off uses get | jq | kubectl replace, because
  tigera-network-admin holds get and update on rbac-ui-config, not patch.
- Subjects added by hand go on the ClusterRoleBindings. Those are what
  FindExistingMemberSubjects reads back, so a subject added only to a namespaced
  RoleBinding is dropped the next time the role is edited in the console.
- IdP group binding is LDAP-only and single-homed on the management cluster:
  the manager's egress opens 389/636 only when Authentication.spec.ldap is set
  and scopes the destination to spec.ldap.host, and the /team/idp-groups routes
  always target the management cluster. The directory-sync secret is a second
  secret, distinct from tigera-ldap-credentials.
- Export carries bindings, not the ClusterRoles they reference, so the target
  cluster needs role management on and the same tiers and namespaces.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@dimitri-nicolo
dimitri-nicolo marked this pull request as ready for review September 22, 2026 22:34
@dimitri-nicolo
dimitri-nicolo requested a review from a team as a code owner September 22, 2026 22:34
@dimitri-nicolo

Copy link
Copy Markdown
Contributor Author

@Dean-Coakley @ctauchen could I please get a review?

The console has no form for the LDAP directory connection in this release,
so the section now leads with creating tigera-idp-ldap-config and explains
the URL and host requirement after the example. Drop the note about the bind
password not being shown again, which only applied to the API, and the
remark that the console cannot turn role management off.
Copilot AI balanced review requested due to automatic review settings October 2, 2026 21:27

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot review overview

🟡 Changes recommended

The audit command omits namespace RoleBindings, and credential examples expose secrets through command arguments.

Review effort: Balanced
Findings: 1 Medium severity · 2 Low severity

Open (3)
What changed in this PR

Documents Calico Enterprise’s new UI-based RBAC role management workflow.

Changes:

  • Adds guidance for managing custom roles and IdP groups.
  • Adds sidebar navigation and a cross-link from existing RBAC documentation.
  • Covers multi-cluster role export and access auditing.
File Description
sidebars-calico-enterprise.js Adds the new page to navigation.
calico-enterprise/​operations/​cnx/​roles-and-permissions.mdx Links to the new workflow.
calico-enterprise/​operations/​cnx/​manage-roles.mdx Adds the role-management guide.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread calico-enterprise/operations/cnx/manage-roles.mdx Outdated
Comment on lines +81 to +85
kubectl create secret generic tigera-idp-ldap-config -n calico-system \
--from-literal=url=ldaps://ad.example.com:636 \
--from-literal=bindDN='cn=admin,dc=example,dc=com' \
--from-literal=bindPassword='<password>' \
--from-literal=baseDN='ou=groups,dc=example,dc=com'
Comment thread calico-enterprise/operations/cnx/manage-roles.mdx Outdated
Replace the curl to /ui-apis/team/export?target= with the edits it makes:
in the bindings labeled rbac.tigera.io/managed-cluster, the source cluster's
name appears in the label, the annotation, the end of metadata.name and the
end of roleRef.name. Changing those four values to the target cluster gives
the same file the API would return. Every other binding in the export does
not name a cluster and applies unchanged.
Copilot AI balanced review requested due to automatic review settings October 2, 2026 21:41

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot review overview

🔵 Needs a closer look

The LDAP setup command risks exposing the directory bind password through shell history and process arguments.

Review effort: Balanced
Findings: 1 Medium severity · 1 Low severity

Open (2)
Resolved since last review (1)

Fixes found by checking each statement against ui-apis, rbacsync, the
operator and ui-modules:

- Tier has no default; all tiers has to be chosen.
- The permission is Modify Alerts and Security Events Settings, and its
  notes show in the expanded role, not in the picker. View also reads the
  security events.
- Not every permission comes as View and Modify; list the one-variant ones.
- A managed cluster's roles also need role management on the management
  cluster.
- Turning role management off freezes roles: all tiers stops following new
  tiers and directory removals stop revoking.
- Exports copy between standalone and management clusters, or between
  managed clusters. A missing tier is rejected for tigera-network-admin.
- Drop the audit command, which missed RoleBindings and listed hidden
  bindings.
- Name the Authentication settings an IdP role depends on: groupSearch, a
  matching nameAttribute, and no groupsPrefix. Manual role names must match
  the token's group, prefix included.
- Renaming a manual role changes only its display name.
- Directory removals revoke roles, and tigera-network-admin cannot change the
  directory secret after creating it.
- Create the directory secret from a manifest, keeping the password off the
  command line.
- Drop the minimum version line.

Link the page from the identity provider page.
Copilot AI balanced review requested due to automatic review settings October 2, 2026 22:14

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot review overview

🔵 Needs a closer look

The LDAP setup instructions do not provide a valid secret location for supported standalone deployments.

Review effort: Balanced
Findings: 1 Low severity

Open (1)
Resolved since last review (1)
Previously missed (1)

In code that hasn't changed since last review

Low severity Support standalone clusters without requiring a management cluster

calico-enterprise/​operations/​cnx/​manage-roles.mdx:83

This setup assumes that every deployment has a management cluster, but the page explicitly supports standalone clusters later (line 152). A standalone user therefore has no valid location for the directory secret. Distinguish standalone from multi-cluster deployments here and in the secret instruction.

The directory sync runs in calico-kube-controllers, not the web console, so
say "Calico Enterprise can connect only to that host". An in-cluster
directory is reachable only when Authentication.spec.ldap.host names it as
<service>.<namespace>.svc, so say that too.
Copilot AI balanced review requested due to automatic review settings October 3, 2026 00:05

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot review overview

🔵 Needs a closer look

The detailed RBAC and multi-cluster behavior still requires the pending SME review.

Review effort: Balanced
Findings: 1 Low severity

Open (1)

@ctauchen ctauchen left a comment •

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Withdrawn. Review to follow.

@ctauchen ctauchen left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I tested this on a CE v3.24.0-3.0 management cluster as a tigera-network-admin user. I turned on role management, then created, edited, exported and deleted a role, and turned the feature off with the kubectl command on the page. The labels, the bindings, the export and the disable command all match the page.

I couldn't test LDAP group binding, copying roles between managed clusters, or what happens to roles after the feature is turned off.

The first three comments need an answer before merge. The rest are small.


### A role is a named set of permissions

A role in the console is a set of permissions under a name, and that name is a Kubernetes **group**. Membership in the group is what grants the role: anyone whose login carries the group has it. Nothing else decides who holds a role.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

The Roles tab says roles "are bound to users, service accounts, and groups with kubectl, outside this console." This line says a role is a group and nothing else decides who holds it. Which is right? If users and service accounts can be bound too, this section and line 25 need to say so.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I've removed: "Nothing else decides who holds a role."

Will ask that the comment is removed from the UI, it looks like it's referring to Kubernetes roles, not what we define here to be a role.

- `spec.ldap.groupSearch.nameAttribute` must be the same attribute as `nameAttribute` in the secret below (`cn` unless you set it), so that both give a group the same name.
- `spec.groupsPrefix` must not be set. Roles are bound to the group name as the directory has it, without a prefix.

On the management cluster, create the `tigera-idp-ldap-config` secret in the `calico-system` namespace with the directory's URL, a bind DN and password, and the base DN to search for groups. This secret is separate from the `tigera-ldap-credentials` secret that authentication uses. Save the manifest to a file and create the secret with `kubectl create -f <file>`.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

A standalone cluster has no management cluster. Can this say "On the standalone or management cluster"? Line 75 has the same gap.


- **Logs** are granted per log type (**View Flow Logs**, **View DNS Logs**, **View Audit Logs (Timeline)** and so on, or **View All Logs**) and apply to the cluster the role is on.
- **View Kibana** signs the user in to Kibana, which is a single instance on the management cluster shared by all clusters. What they see there comes only from their log permissions, cluster by cluster.
- **Policy** permissions do not include audit logs. To see a policy's change history on the policy board, add **View Audit Logs (Timeline)**.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

In testing, View Policies also bound calico-ui-policies-logs, which grants read access to flow logs for the whole cluster. Can this list say so?


$[prodname] sets `rbac-ui-enabled` to `true` in the `rbac-ui-config` ConfigMap in the `calico-system` namespace, then builds the catalogue of permissions. This takes a few seconds, after which the **Roles** and **Users** tabs appear.

To turn role management off again, set the flag back to `false`. Roles you already created keep granting what they did, but are no longer manageable from the console, and $[prodname] stops keeping them up to date: a role scoped to **all tiers** does not cover tiers created afterwards, and a role bound to a directory group keeps its access after the group is removed from the directory.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

The command works as written. Can we say plainly that the console has no off switch, and list jq as a requirement?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

The section now opens with "The console has no control to turn role management off," and jq is listed under Required in Before you begin.

- For a manual role, **Role Name** is the group itself, exactly as users' sign-in carries it, including any `groupsPrefix` set in the `Authentication` resource. Microsoft Entra ID, for example, sends a group's object ID rather than its name unless you configure it otherwise. Any non-empty value up to 253 characters is accepted, spaces and `@` included.
1. Choose a permission from the list. Permissions are per feature area — policies, network sets, dashboards, service graph, packet captures, egress gateways and so on — most of them offered as both **View** and **Modify**.
1. Scope the permission, where it supports it:
- **Tier** — for policy permissions. Choose **all tiers** to apply the permission to every tier.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

A tier is required for policy permissions. The form won't save without one. Suggest: "Tier: required for policy permissions. Choose all tiers to apply the permission to every tier."

**Limitations**

- Roles do not synchronize between clusters. Exported roles are a copy, not a link.
- Directory groups come from LDAP only. With an OIDC-only identity provider, such as Okta or Microsoft Entra ID, **Bind an IdP group** is not offered; use **Manual group binding** instead.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Can this link to the Entra ID note in the Create a role step? Readers need to know Entra sends group IDs, not names, before they type a role name.


1. In the web console, select the cluster you want to manage roles on.
1. Click the user icon <IconUser width="20"/> > **Manage Team**.
1. Click **Enable RBAC management**.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

With no directory connected, Manage Team shows a banner saying no identity provider is connected. Worth a sentence here so readers know it's expected.

1. Choose what the role binds to, then click **Next**. With no directory connected this step does not appear and the role form opens straight away.
- **Bind an IdP group** is selected by default. Pick a group from the list; a group can back only one role, so any that already do are shown as unavailable.
- **Manual group binding** opens the form with an empty name for you to fill in.
1. Name the role:

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

The form also has an optional Description field, which shows in the Roles list. Worth a line here.

1. Click the user icon <IconUser width="20"/> > **Manage Team**.
1. Click **Enable RBAC management**.

$[prodname] sets `rbac-ui-enabled` to `true` in the `rbac-ui-config` ConfigMap in the `calico-system` namespace, then builds the catalogue of permissions. This takes a few seconds, after which the **Roles** and **Users** tabs appear.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

"catalog" for US spelling. Same on line 150.


## Additional resources

- [Grant access with custom roles and IdP groups](manage-roles.mdx) — create and scope roles in the web console, without writing RBAC manifests.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

The other links here have no description. Suggest dropping the text after the dash and moving this link into the list below "For RBAC details".

@ctauchen

ctauchen commented Oct 8, 2026

Copy link
Copy Markdown
Collaborator

@dimitri-nicolo One UI thing, not for this PR: the Create Role form shows "Name is required." as soon as it opens, before anything is typed. Can you pass it to the console team?

- Drop "Nothing else decides who holds a role."
- The directory secret goes on the standalone or management cluster.
- Policy permissions also grant flow logs; Dashboards and Service Graph
  grant the logs their pages show.
- Say the console has no off switch, and list jq as a requirement.
- Tier is required for policy permissions.
- Expanding a role shows its permissions and where each applies.
- Apply every binding in an export; the console finds and manages roles
  through the bindings' labels and annotations.
- Link the OIDC limitation to the Create a role step, and say Entra ID sends
  group IDs.
- Mention the no-identity-provider banner and the Description field.
- US spelling: catalog.
- Move the link on the roles page into the list, without a description.
- Drop the sentences on IdP role subjects not being editable and on a
  deleted IdP role's group staying in the directory.
@dimitri-nicolo

Copy link
Copy Markdown
Contributor Author

@dimitri-nicolo One UI thing, not for this PR: the Create Role form shows "Name is required." as soon as it opens, before anything is typed. Can you pass it to the console team?

Save stays disabled until the name is filled in, so showing the message straight away looks intentional: it points to the field that's blocking Save. I'll check with @Dean-Coakley before raising it with the team.

Calico Enterprise now allows the directory sync to reach the host and port in
the secret's URL, so the URL no longer has to match
Authentication.spec.ldap.host. An in-cluster directory still has to be named
<service>.<namespace>.svc to be reachable.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants