OpenShift
About 1225 wordsAbout 4 min
2026-07-11
kush works with OpenShift and needs no OpenShift-specific setup. Because it copies your kubeconfig's cluster, context, and user blocks verbatim into the throwaway kubeconfig, whatever authenticates you against an OpenShift cluster today keeps working inside a kush shell: OAuth bearer tokens, the cluster CA, oc's exec credential plugins, and OIDC all carry over untouched. And since kush only pins KUBECONFIG and forks your shell, oc honors it exactly like kubectl.
This guide walks through the everyday loop, then the one real gotcha (token expiry) and how to run long sessions without tripping over it.
The loop: log in, enter, work, exit
Authenticate the way you always do. oc login writes the context into ~/.kube/config; then you hand that context to kush:
$ oc login https://api.mycluster.example.com:6443
# populates ~/.kube/config as usual
$ kush default/api-mycluster-example-com:6443/kube:admin
# subshell pinned to that context, via a private kubeconfig
$ oc get pods
$ oc get routes
$ exit
# temp kubeconfig deleted, ~/.kube/config never touchedEverything between entering and exit runs against that one cluster and nothing else. As with kubectl, you never pass a --context flag to anything: oc, odo, helm, and k9s all read the same pinned KUBECONFIG.
OpenShift's default context names are long, like default/api-mycluster-example-com:6443/kube:admin, so most people run kush with no argument and pick from the list instead of typing one out:
$ kush
# opens the picker (fzf if installed, otherwise the built-in TUI)Projects are namespaces
An OpenShift project is a Kubernetes namespace with extra metadata, so kush's namespace handling applies directly. Inside a kush shell you can re-pin with either tool:
kush ns billing # kush's own re-pin
oc project billing # oc's equivalent; both edit the same temp kubeconfigBoth edit the current context in the temp kubeconfig, so the change stays isolated to this shell and is thrown away on exit, exactly like a namespace switch. Your (kush:…) prompt marker reads the namespace live from the kubeconfig file, so it updates whichever command you use. See Switch namespaces for the full picture.
Multi-tenant clusters
OpenShift does multi-tenancy on the cluster: projects are the boundary, and RBAC decides what your identity can reach. kush knows nothing about any of that. It never calls the API, so it neither enforces tenant scoping nor understands it. What it does give you is the layer underneath: a shell whose view can't drift onto the wrong tenant.
In practice a tenant is a set of projects on a cluster. You oc login once, then move between that tenant's projects with kush ns <project> or oc project <project>, the same way you'd switch any namespace. The payoff shows up when you work several tenants at once: open one kush shell per tenant, and because no shared current-context exists to fall out of sync, a command meant for one tenant physically can't land on another's cluster or project from the other shell. When tenants need different identities, each is its own user block, and kush keeps them apart per shell.
One thing to know: since kush reads only your local kubeconfig, the context picker lists what you've already logged into, and kush ns takes free text rather than enumerating projects. To see which projects a tenant identity can actually reach, ask the cluster with oc projects from inside the shell; kush won't list them for you. That's the cost of staying a single static binary that makes no cluster round-trips.
The one gotcha: token expiry in long sessions
If you authenticate with a username and password (oc login -u … -p …), OpenShift issues a static OAuth bearer token, usually valid for about 24 hours, and bakes it into your kubeconfig's user block. kush snapshots that token into the temp kubeconfig when you enter the shell. Two things follow from that:
- A kush shell you leave open long enough starts returning
401 Unauthorizedonce the token expires. - Refreshing the token in another terminal (a fresh
oc loginthere) does not reach back into this shell's snapshot.
The fix is easy. Run oc login again from inside the kush shell. oc respects the pinned KUBECONFIG, so it rewrites the temp file in place; your session refreshes and stays just as isolated and disposable as it was before.
$ oc get pods
error: You must be logged in to the server (Unauthorized)
$ oc login https://api.mycluster.example.com:6443
# rewrites the temp kubeconfig for THIS shell only
$ oc get pods
NAME READY STATUS RESTARTS AGE
web-7d9f8b6c5-x2z9k 1/1 Running 0 3hRefresh auth before entering
If you do not want to remember a manual oc login before opening a kush shell, use a pre-exec hook. It runs after kush knows the target context, but before kush extracts the isolated kubeconfig. After the hook succeeds, kush reloads kubeconfig, so any auth state refreshed by oc is included in the throwaway kubeconfig.
For a single OpenShift context, configure the hook under that context name:
# ~/.config/kush/config.yaml
contexts:
default/api-mycluster-example-com:6443/kube:admin:
pre_exec_hook: "oc whoami >/dev/null 2>&1 || oc login https://api.mycluster.example.com:6443"For a setup where the auth command can derive everything from the selected context, use the global hook and KUSH_CONTEXT:
pre_exec_hook: "oc whoami --context \"$KUSH_CONTEXT\" >/dev/null 2>&1 || oc login https://api.mycluster.example.com:6443"If the hook exits non-zero, kush stops instead of opening a shell with stale credentials. This is still local-only behavior: kush does not call the OpenShift API itself; it just runs your configured command before creating the isolated kubeconfig.
Long sessions: use a refreshing credential
You can sidestep expiry entirely by authenticating with a credential that refreshes on demand instead of a static token. Configure OIDC against your cluster's OAuth server through an oc/kubectl exec credential plugin such as kubelogin or oc-oidc. Your user block then becomes an exec: stanza rather than a hard-coded token:
users:
- name: oidc/api-mycluster-example-com:6443
user:
exec:
apiVersion: client.authentication.k8s.io/v1
command: kubectl
args: ["oidc-login", "get-token", "--oidc-issuer-url=…", "--oidc-client-id=…"]kush copies exec stanzas verbatim, so every kush shell you open mints fresh tokens on its own with no re-login step. This is a cluster and kubeconfig setup choice; it needs no kush configuration, and it's the setup to prefer if you keep pinned shells open for hours.
The exec plugin config lives in the temp kubeconfig with the same 0600/0700 permissions kush applies to everything else, so your credentials are no more exposed than in your real kubeconfig (see How isolation works).
Recap
kush needs no OpenShift-specific setup: oc login, then kush <context>, then use oc normally. Projects are just namespaces, so kush ns and oc project do the same isolated thing. The only wrinkle is that static OAuth tokens expire; re-run oc login inside the shell to refresh in place, use a pre-exec hook to refresh before entering, or move to an OIDC exec credential and stop thinking about it.
