Skip to content

Install kubelogin

kubelogin is a kubectl credential plugin that runs the OIDC browser flow against Keycloak, caches the token, and feeds it to the Kestrel kube-apiserver. The upstream project is int128/kubelogin. There is an unrelated binary also called kubelogin maintained by Microsoft for Azure AD — that is not what Kestrel uses. If your package manager offers both, pick the int128/kubelogin build.

For the mental model of how kubelogin sits between Keycloak, the kube-apiserver, and Capsule, see Identity chain.

The recommended path on macOS is Homebrew:

Terminal window
brew install kubelogin

If Homebrew is not available, download the kubelogin_darwin_arm64.zip or kubelogin_darwin_amd64.zip archive from the upstream release page, extract it, and put the kubelogin binary on your PATH.

Paste the following block into ~/.kube/config (merge with any existing config carefully — or use KUBECONFIG=~/.kube/config-kestrel kubectl ... to keep it isolated while you test).

apiVersion: v1
kind: Config
clusters:
- name: kestrel
cluster:
server: https://proxy.kestrel.arbutus.cloud
contexts:
- name: kestrel
context:
cluster: kestrel
user: kestrel-oidc
current-context: kestrel
users:
- name: kestrel-oidc
user:
exec:
apiVersion: client.authentication.k8s.io/v1
command: kubectl
args:
- oidc-login
- get-token
- --oidc-issuer-url=https://keycloak.arbutus.alliancecan.ca/realms/atmosphere
- --oidc-client-id=kubernetes
- --token-cache-storage=keyring
interactiveMode: IfAvailable
provideClusterInfo: false

Run any read-only kubectl command that hits the apiserver. The simplest is:

Terminal window
kubectl auth whoami

On the first command:

  1. kubelogin opens your default browser to the Keycloak login page.
  2. Log in with your Alliance CCDB username and password — the same ones you use at ccdb.alliancecan.ca.
  3. Keycloak redirects the browser back to localhost:8000, where kubelogin is listening. Once the page says login is complete, you can close the tab.
  4. kubelogin caches the token under ~/.kube/cache/oidc-login/ and hands it to kubectl, and the command completes:
❯ kubectl auth whoami
ATTRIBUTE VALUE
Username testuser
Groups [oidc:def-testuser system:authenticated]

The oidc: group is your tenant name — your Cloud RAP’s Alliance LDAP group name, one of def-profname, crg-profname-xx, or cpp-profname-xx (ask your PI if you don’t know yours). This group claim in the token is what grants you access to your tenant — nothing in your kubeconfig names it. See Identity chain for how the pieces connect.

Subsequent kubectl commands reuse the cached token until it expires, at which point kubelogin silently refreshes it against Keycloak without prompting you again.

Symptom: browser shows “Unable to connect” after the Keycloak login page; kubelogin in the terminal hangs.

Cause: kubelogin listens on localhost:8000 and automatically falls back to localhost:18000 if 8000 is taken. This symptom therefore means both default ports are already bound — dev servers, previous kubelogin sessions, Docker port publishes — or the fallback port is blocked.

Fix: free up one of the two default ports, or override the listen address with --listen-address=localhost:18000 in the kubeconfig exec.args (the flag can be repeated to list multiple candidate ports). RCS has registered multiple candidate ports with Keycloak, so the alternate port is accepted as a redirect target.

Symptom: browser reaches the Keycloak login page but returns an error page after you authenticate (“State does not match” or a similar OIDC state-mismatch message).

Cause: stale OIDC state in the local cache — usually from a previous aborted login, or a duplicate browser tab that followed an old callback link.

Fix: clear the cache and retry:

Terminal window
kubectl oidc-login clean
kubectl auth whoami

If it persists, open a fresh browser window (or an incognito session) so the Keycloak session cookie is new.

Browser does not open, or opens but the login never completes

Section titled “Browser does not open, or opens but the login never completes”

Symptom: kubectl auth whoami hangs with no browser window, or a browser opens but errors out before or after the Keycloak login page.

Cause: kubelogin launches whatever the OS reports as the default browser. This fails when there is no GUI at all (WSL2, tmux, remote SSH sessions) and can misbehave with sandboxed browser installs (Flatpak/Snap browsers on Linux are a known culprit) or a stale default-browser registration.

Fix (local machine): add --skip-open-browser to the exec.args in your kubeconfig. Instead of launching a browser, kubelogin prints the login URL — copy it into any working browser on the same machine and complete the login. No tunnelling or SSH is involved: the URL points at localhost:8000, where kubelogin is already listening.

Fix (remote shell — WSL2, SSH, tmux): same --skip-open-browser, but because the browser runs on a different machine than kubelogin, forward the callback port first:

Terminal window
ssh -L 8000:localhost:8000 <user>@<remote-host>

<remote-host> is the machine you run kubectl on — not a Kestrel or Keycloak address. The browser on your local workstation then reaches localhost:8000 through the tunnel and hands the authorization code back to the kubelogin process on the remote host.

kubectl auth whoami is missing your tenant group

Section titled “kubectl auth whoami is missing your tenant group”

Symptom: the OIDC browser flow completes and kubelogin writes a token cache successfully, but the Groups row in kubectl auth whoami only shows system:authenticated — no oidc:<your-tenant> entry.

(An empty kubectl get ns is not this failure — a fresh tenant has no namespaces until you create one. If whoami shows your oidc: tenant group, login is working; carry on to Your first deployment.)

Cause: you have successfully authenticated to Keycloak and the kube-apiserver has accepted your identity, but the groups claim in your OIDC id_token does not contain any tenant group that maps to a Capsule Tenant on Kestrel. The two common reasons:

  1. You have not been added to the tenant’s group yet. Tenant membership is currently managed by RCS staff in Keycloak — sponsorship in CCDB alone does not grant access. This is the single most common failure mode on first login. Ask your PI to confirm the add-user request to RCS was made and completed — see Managing membership.
  2. Your CCDB account is brand-new. Keycloak’s user store federates from the Alliance (CCDB) LDAP; a just-created account can take a sync cycle before RCS can add it to the tenant group.

Fix: once RCS has confirmed the add, clear the cached token and force a fresh login:

Terminal window
# You own this — clears the stale OIDC cache so the next kubectl triggers a fresh login
kubectl oidc-login clean
kubectl auth whoami

If the tenant group is still missing after a fresh token, the problem is upstream of Keycloak. See Requesting access for the end-to-end CCDB flow, and contact accounts@tech.alliancecan.ca for CCDB-level issues.