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 nogroupsClaim, 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:
- 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.
- Does it emit groups without needing a second call? Kubernetes reads claims
from the token. A provider that requires a
/userinfolookup to reveal group membership will not work. - 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: falseit is told there is nothing to do, and the cluster is created exactly as it always was; - with
auth.enabled: trueit is handed akubeadmconfiguration file and an authentication configuration, writes the second to/etc/kubernetes/bke/authentication-config.yaml, and runskubeadm 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
kubeadmon the node is from the Kubernetes minor the cluster is running, becausekubeadmis what writes the API server’s configuration and one from another release writes that release’s; - asks us for your cluster’s own
kubeadmconfiguration 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.