BKE Bahriya Kubernetes Engine Start a 14-day trial

Cluster login

Read this page before you plan cluster authentication, not while you are configuring it. One limitation below decides whether your identity provider can be used at all, and one section decides when you do this rather than how.

The two halves

Authorisation. BKE creates four ClusterRoleBindings from auth.rbac.* in your config.yaml, binding your groups to Kubernetes’ built-in roles:

config.yaml Kubernetes role Grants
clusterAdminGroups cluster-admin everything
adminGroups admin full control within a namespace
editGroups edit create and modify workloads, not RBAC
viewGroups view read-only

These are created even when auth.enabled is false, which is deliberate: the bindings can exist harmlessly, binding groups nobody can present yet, so that turning authentication on later is one change rather than two.

Authentication. With auth.enabled: true, BKE configures your API server to trust your identity provider. Your people then log in as themselves, and the bindings above decide what they can do.

Setting auth.enabled is a decision about the API server, not a preference. What it changes, exactly:

  enabled: false enabled: true
the four ClusterRoleBindings created created
your API server untouched started with --authentication-config
who can log in nobody, through OIDC anyone your provider authenticates
creating the cluster six kubeadm flags, as always a configuration file BKE renders

On a new cluster it costs nothing extra, because the API server is being started for the first time anyway. If you know you want cluster login, set it before you run install.sh --role master and there is no second event.

On a cluster that already exists, turning it on restarts the API server. That belongs in a maintenance window. Turning it on for a cluster that already exists below is the procedure; read Break-glass first, not afterwards.

The limitation that may rule out your provider

BKE grants all cluster access through group membership. There is no mechanism to grant a role to an individual user — auth.rbac.* takes group names and nothing else.

So an identity provider that cannot emit a groups claim is unsupported. A user would authenticate successfully against it and then be able to do nothing at all, because no group means no binding means no permission.

BKE refuses a configuration like that outright:

auth.oidc[0] sets no groupsClaim, and BKE cannot support an identity provider that does not emit groups. All cluster access is granted through group membership (auth.rbac.*), so a login with no groups would authenticate and then be able to do nothing.

Check now, before anything else on this page matters:

  1. Can your provider emit a groups claim in an ID token? Entra ID, Okta, Google Workspace and Keycloak all can. Some smaller or embedded providers cannot.
  2. Does it emit groups without needing a second call? Kubernetes reads claims from the token. A provider that requires a /userinfo lookup to reveal group membership will not work.
  3. Are the groups stable identifiers? If your provider emits group names that an administrator can rename, your bindings break when someone renames a group. Object IDs are safer, if less readable.

If the answer to the first is no, cluster login is not available for that provider in this BKE version, and no amount of configuration will change it.

Configuring it

auth:
  enabled: true
  oidc:
    - issuerUrl: https://login.example.com/v2.0
      clientId: bke-prod
      usernameClaim: email
      groupsClaim: groups
      groupsPrefix: "oidc:"
  rbac:
    clusterAdminGroups:
      - oidc:platform-admins
    adminGroups:
      - oidc:team-leads
    editGroups:
      - oidc:developers
    viewGroups: []

oidc is a list even with one issuer. Kubernetes supports several, and the shape does not change when you add a second.

groupsPrefix is worth setting. It prefixes every group from this issuer, so a group called admins at your provider becomes oidc:admins in Kubernetes and cannot collide with a name from anywhere else. Whatever you choose, the names in auth.rbac.* must include it — oidc:platform-admins, not platform-admins.

usernameClaim decides what shows up in audit logs. email is readable; sub is stable but opaque. Pick for whoever will read those logs.

usernamePrefix is optional and defaults to none. It does for usernames what groupsPrefix does for groups. Leaving it unset is normal; set it if you have more than one issuer and their usernames could collide.

issuerUrl must be https://. Kubernetes refuses anything else, and it refuses it when the API server starts — which on a new cluster is after kubeadm has already created it. BKE refuses it earlier, where it costs you a re-run.

What happens on the node

On a new cluster, install.sh --role master asks the API how this cluster should be created, before it changes anything on the machine:

  • with auth.enabled: false it is told there is nothing to do, and the cluster is created exactly as it always was;
  • with auth.enabled: true it is handed a kubeadm configuration file and an authentication configuration, writes the second to /etc/kubernetes/bke/authentication-config.yaml, and runs kubeadm init --config.

This is why the first control-plane node now needs /etc/bke/config.yaml and your licence file in place before you run install.sh. It is not guessing whether you want cluster login, and it is not reading your configuration file to find out — it asks, and it stops if it cannot.

On a cluster that already exists, the same two files are needed for the same reason, and the node sends its cluster’s own kubeadm configuration along with them: what comes back is that configuration with cluster login added, so nothing your cluster was created with is replaced by something we rendered.

check.sh checks both endpoints along with everything else, so a node that cannot reach them says so in the preflight rather than half-way through an install or a maintenance window.

Break-glass

The kubeadm administrator kubeconfig written at install time is your fallback, and it does not depend on any identity provider.

Verify it works before you reconfigure anything, not after. Enabling authentication restarts your API server, and if groups do not arrive as you expected, that certificate is the only way back in. Keep a copy somewhere that is not the cluster.

BKE checks the half of this it can check: if that kubeconfig does not authenticate against your cluster today, --enable-cluster-login refuses outright and is not overridable. It cannot check that you hold a copy somewhere else, so it asks you to say so — see below.

Canary one cluster before doing this to all of them.

Turning it on for a cluster that already exists

Run this on a control-plane node, in a maintenance window:

BKE_ACCEPT_AUTH_RISK="break-glass" \
  sh -c 'curl -sL https://bke.maml.uk/upgrade.sh | sh -s -- --enable-cluster-login --commit'

Nothing changes without --commit. Drop it and the same command performs every check, renders what it would write, shows you how your API server would differ, and stops. Do that first — days before the window if you can: it is where you find out that your break-glass kubeconfig does not authenticate, or that your API server has been edited by hand, while it is still cheap.

It takes no other option but --commit, moves no version and installs no package. Enabling cluster login restarts the API server and so does a control-plane upgrade; doing both in one run would leave two candidates for a control plane that did not come back.

Every control-plane node needs it, one at a time. The API server’s configuration is a file on each node. Wait for each node’s API server to answer before starting the next.

Before it changes anything, it:

  • checks your break-glass kubeconfig against the live API server, and refuses if it does not authenticate;
  • checks that the kubeadm on the node is from the Kubernetes minor the cluster is running, because kubeadm is what writes the API server’s configuration and one from another release writes that release’s;
  • asks us for your cluster’s own kubeadm configuration with cluster login added to it — your configuration, with two settings added and nothing else changed;
  • renders the API server configuration it would write, and compares it with the one the node is running. If anything other than cluster login differs, it prints the difference and stops.

It then writes the authentication configuration, records the change in your cluster’s own kubeadm configuration so a later upgrade keeps it, regenerates the API server, waits for it to answer, and confirms that what came back is configured for cluster login.

A copy of the API server configuration as it was is left at /etc/bke/kube-apiserver.yaml.before-cluster-login. Restoring it over /etc/kubernetes/manifests/kube-apiserver.yaml undoes the change on that node.

The two conditions it refuses on, and how to accept one

Each is named, and each is accepted by name. There is no blanket yes: accepting one is a decision about one risk rather than a decision to stop checking.

Name What it means
break-glass We cannot check that you hold a copy of the administrator kubeconfig somewhere that is not this cluster. Confirm that you do.
manifest-drift Regenerating the API server would change more than cluster login — usually because its configuration has been edited by hand since the cluster was created. The difference is printed. Read it before accepting it.
BKE_ACCEPT_AUTH_RISK="break-glass manifest-drift" \
  sh -c 'curl -sL https://bke.maml.uk/upgrade.sh | sh -s -- --enable-cluster-login --commit'

An administrator kubeconfig that does not authenticate is not in this table, and is not overridable. A fallback that does not work today will not work after the restart.

What it does not do

It does not create the access bindings — apply.sh does that, from auth.rbac.*, whether cluster login is on or off. They are already there.

It does not change any other cluster. Canary one, confirm your people can log in and have the permissions you expect, and only then do the rest.

Generating user kubeconfigs

BKE does not distribute kubeconfigs. Your users authenticate with an OIDC-capable client — kubectl oidc-login, or your provider’s own tooling — and the kubeconfig references the issuer rather than carrying a credential.

Do not hand out copies of the administrator kubeconfig as a substitute. It is a certificate that cannot be revoked short of rotating the cluster CA, and it bypasses every binding on this page.