Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -405,6 +405,8 @@ Or use the groups flag to assign cluster role to a group of users.
kubectl create clusterrolebinding all-developers-tigera-ui-user --group=<group> --clusterrole=tigera-ui-user
```

To create scoped roles in the web console and bind them to the groups in your LDAP directory, see [Grant access with custom roles and IdP groups](manage-roles.mdx).

### (Optional) Allow $[prodname] URIs in your IdP

Most IdPs require redirect URIs to be allowed to redirect users at the end of the OAuth flow to the $[prodname] web console or to Kibana. Consult your IdP documentation for authorizing your domain for the respective origins and destinations.
Expand All @@ -427,5 +429,6 @@ Most IdPs require redirect URIs to be allowed to redirect users at the end of th
## Additional resources

- [Configure user roles and permissions](roles-and-permissions.mdx)
- [Grant access with custom roles and IdP groups](manage-roles.mdx)
- [Configure RBAC for tiered policies](../../network-policy/policy-tiers/rbac-tiered-policies.mdx)
- [Configure RBAC for Elasticsearch](../../observability/elastic/rbac-elasticsearch.mdx)
190 changes: 190 additions & 0 deletions calico-enterprise/operations/cnx/manage-roles.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,190 @@
---
description: Grant scoped access to Calico Enterprise by creating custom roles in the web console and binding them to groups from your identity provider, instead of writing Kubernetes RBAC manifests by hand.
---

import IconUser from '/img/icons/user-icon.svg';

# Grant access with custom roles and IdP groups

## Big picture

Create and scope $[prodname] roles from the **Manage Team** page in the web console, and bind them to groups from your identity provider, instead of writing Kubernetes RBAC manifests by hand.

## Value

Giving a team access to one tier, one namespace, or one web console feature normally means hand-writing `ClusterRole` and `ClusterRoleBinding` manifests, and knowing which $[prodname] API resources each feature reads. **Manage Team** turns that into a list of named permissions: you pick what a role can view or modify and where it applies, and $[prodname] writes and reconciles the underlying Kubernetes RBAC for you.

## Concepts

### 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.

Behind each role, $[prodname] writes the Kubernetes RBAC that grants its permissions — `ClusterRoleBindings`, or `RoleBindings` where you scoped a permission to a namespace — labeled `app.kubernetes.io/managed-by=calico-ui-rbac`. These are the console's to manage; you do not edit them by hand.

The console does not create or invite users. The **Users** tab is read-only, and lists the subjects it finds on those bindings and in any bound identity provider groups, with the roles in effect for each.

### Role management is per cluster

Role management is off by default and is turned on one cluster at a time, including each managed cluster in a multi-cluster deployment. A role belongs to the cluster it was created on and is not synchronized to other clusters; use **Export YAML** to copy it.

On a managed cluster, a role's log and Kibana permissions are held on the management cluster, because that is where the logs and Kibana live. The console writes and removes them with the rest of the role, so you manage the role from the managed cluster as usual. For this to work, role management must also be turned on in the management cluster.

## Before you begin

**Required**

- [Access to the web console](access-the-manager.mdx) as a user bound to `tigera-network-admin`

**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.

Check failure on line 42 in calico-enterprise/operations/cnx/manage-roles.mdx

View workflow job for this annotation

GitHub Actions / runner / vale

[vale] reported by reviewdog 🐶 [Vale.Spelling] Did you really mean 'Okta'? Raw Output: {"message":"[Vale.Spelling] Did you really mean 'Okta'?","location":{"path":"calico-enterprise/operations/cnx/manage-roles.mdx","range":{"start":{"line":42,"column":86},"end":{"line":42,"column":90}}},"severity":"ERROR","code":{"value":"Vale.Spelling"}}
- Role management cannot be turned on for a multi-tenant management cluster.

## How to

- [Turn on role management](#turn-on-role-management)
- [Connect an identity provider directory](#connect-an-identity-provider-directory)
- [Create a role](#create-a-role)
- [See who has access](#see-who-has-access)
- [Copy roles to another cluster](#copy-roles-to-another-cluster)

### Turn on role management

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**.

$[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.

```bash
kubectl get configmap rbac-ui-config -n calico-system -o json \
| jq '.data["rbac-ui-enabled"] = "false"' \
| kubectl replace -f -
```

`kubectl patch` fails here: `tigera-network-admin` holds `get` and `update` on this ConfigMap, not `patch`.

### Connect an identity provider directory

Connecting your directory lets roles bind to groups that already exist in it, so membership stays managed in your identity provider and users pick their roles up at the next sign-in.

This requires the cluster to authenticate users with [LDAP](configure-identity-provider.mdx), on port 389 or 636. The directory is read on the management cluster only, so create the secret there and turn role management on there too, even when the role applies to a managed cluster.

A user gets a directory group's role only if their sign-in carries the group, so check the LDAP settings in the `Authentication` resource:

- `spec.ldap.groupSearch` must be set. Without it, users sign in with no groups.
- `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>`.

```yaml
apiVersion: v1
kind: Secret
metadata:
name: tigera-idp-ldap-config
namespace: calico-system
stringData:
url: ldaps://ad.example.com:636
bindDN: cn=admin,dc=example,dc=com
bindPassword: <password>
baseDN: ou=groups,dc=example,dc=com
```

The URL must be a full `ldap://` or `ldaps://` URL whose host matches `Authentication.spec.ldap.host`. $[prodname] can connect only to that host, so a URL pointing anywhere else is accepted but no groups are found. If the directory runs in the cluster, write `Authentication.spec.ldap.host` as `<service>.<namespace>.svc`, for example `openldap.ldap.svc:389`. $[prodname] picks up the secret, searches the directory with these credentials, and offers the groups it finds when you create a role. It searches again every five minutes by default.

Optionally add `groupFilter` (default `(objectClass=groupOfNames)`), `nameAttribute` (default `cn`; Active Directory typically uses `sAMAccountName`), `caBundle` for a private certificate authority, and `refreshIntervalSeconds` (default 300, clamped to 60–86400).

When a group leaves the directory, or stops matching `baseDN`, `groupFilter` or `nameAttribute`, $[prodname] removes the roles bound to it, so changing these settings can remove many roles at once. If the directory cannot be reached, nothing is removed.

A `tigera-network-admin` user can create the secret but cannot read, change or delete it, so changing the settings later needs a cluster administrator.

### Create a role

A role's name is a group, so choosing the name decides who gets it. There are two ways to set it:

- **Bind an IdP group** takes the name from a group in your [connected directory](#connect-an-identity-provider-directory), so everyone already in that group has the role. Membership stays managed in your identity provider, and there is nothing to do outside the console. This is the usual choice.
- **Manual group binding** lets you type the group name yourself, for a group the directory sync does not offer.

1. Click the user icon <IconUser width="20"/> > **Manage Team** > **Roles** > **Create Role**.
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:
- For an IdP group, **IdP Group** is fixed to the group you picked. **Role Display Name** is cosmetic: it is what the **Roles** list shows, so you can make it readable without changing who holds the role.
- 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.
- **Namespace** — for namespaced permissions. Leave it as **any namespace** to apply the permission cluster-wide.
1. Click **Add Permission** for each further permission, then click **Save**. A role must carry at least one permission.

#### What some permissions include

- **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)**.
- **Policy** permissions include Kubernetes network policies only when they cover the `default` tier, where $[prodname] enforces them.
- **Alerts and Security Events Settings** is the alert configuration. **View** also reads the security events, and **Modify** also reads the logs its alerts query, because an alert copies what it finds into the events it raises. To grant the security events alone, use **View Alerts**.
- **View IP Pools** and **View L2 Networks** list pods in every namespace.
- **Tiers** and **Policy Recommendations** are offered as **Modify** only, and **Kibana**, **IP Pools**, **L2 Networks** and the log permissions as **View** only.

Click a role in the **Roles** list to see what each of its permissions includes.

A role bound to a directory group appears in the list as **Custom - IdP**. Its membership is owned by your identity provider, so its subjects cannot be edited from the console.

To change a role later, select **Actions** > **Edit Permissions**. Editing a manual role's **Role Name** changes only the name shown in the list; the group it binds is fixed when the role is created. **Delete Role** removes the role and its bindings from this cluster; subjects bound to it lose the access it granted. For a role bound to a directory group, the group stays in the directory and can be bound to a new role.

### See who has access

Click the user icon <IconUser width="20"/> > **Manage Team** > **Users** to review which subjects hold which roles, and when each last signed in. Click a subject to expand the permissions its roles carry.

The tab is read-only, and lists the subjects on the roles' bindings plus the members of any bound identity provider groups. A directory group's members appear once they have signed in to the web console at least once; until then the group's role applies to them, but they are not listed. Effective permissions are the union of these roles and anything bound to the subject outside the console, which this view does not show.

### Copy roles to another cluster

Roles apply only to the cluster they were created on. To reuse them elsewhere, export them and apply them to a cluster that also has role management turned on. The export carries each role's bindings, not the permissions they point at, and those exist only where the console has built its catalogue.

Copy roles between standalone and management clusters, or from one managed cluster to another. A role copied between a managed cluster and any other kind of cluster loses its log and Kibana permissions.

1. Select the source cluster, then click the user icon <IconUser width="20"/> > **Manage Team** > **Roles** > **Export YAML**.
1. Apply the file:
- For a standalone or management cluster, apply it to the target cluster.

```bash
kubectl apply -f <exported-file>
```

- For a managed cluster, the file also holds the bindings kept on the management cluster, labeled `rbac.tigera.io/managed-cluster`. Apply each part to its cluster.

```bash
kubectl --context <managed-cluster> apply -f <exported-file> -l '!rbac.tigera.io/managed-cluster'
kubectl --context <management-cluster> apply -f <exported-file> -l rbac.tigera.io/managed-cluster
```

The file is written for the cluster it was exported from. To copy a managed cluster's roles to a different managed cluster, edit the bindings labeled `rbac.tigera.io/managed-cluster` before you apply them, replacing the source cluster's name with the target's in four places: the label, the annotation with the same key, the end of `metadata.name`, and the end of `roleRef.name`. The rest of the file does not name a cluster and applies as it is.

```yaml
metadata:
name: calico-ui-<hash>-<target-cluster>
labels:
rbac.tigera.io/managed-cluster: <target-cluster>
annotations:
rbac.tigera.io/managed-cluster: <target-cluster>
roleRef:
name: calico-ui-logs-view-flows-<target-cluster>
```

Check first that the target cluster has the tiers and namespaces the roles were scoped to. A binding into a namespace that does not exist is rejected. A binding that names a missing tier is rejected when a `tigera-network-admin` user applies it; applied by a cluster administrator, it is accepted but grants nothing until the tier exists.

The roles are independent copies: later changes on the source cluster are not propagated.

## Additional resources

- [Configure user roles and permissions](roles-and-permissions.mdx)
- [Configure an external identity provider](configure-identity-provider.mdx)
- [Configure RBAC for tiered policies](../../network-policy/policy-tiers/rbac-tiered-policies.mdx)
2 changes: 2 additions & 0 deletions calico-enterprise/operations/cnx/roles-and-permissions.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ $[prodname] provides the following predefined roles and permissions:

## 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.

For RBAC details on any given feature, see the feature. For example:

- [Tiered policy RBAC](../../network-policy/policy-tiers/rbac-tiered-policies.mdx)
Expand Down
1 change: 1 addition & 0 deletions sidebars-calico-enterprise.js
Original file line number Diff line number Diff line change
Expand Up @@ -549,6 +549,7 @@ module.exports = {
'operations/cnx/authentication-quickstart',
'operations/cnx/configure-identity-provider',
'operations/cnx/roles-and-permissions',
'operations/cnx/manage-roles',
],
},
'operations/comms/index',
Expand Down
Loading