Plugin kubectl
Utiliser ProxyAuthK8S depuis kubectl
Le plugin kubectl proxyauth est le pendant client de ProxyAuthK8S : il gère la connexion
OIDC, stocke les identifiants dans le trousseau du système, et sert de credential plugin
kubectl pour que kubectl parle à n'importe quel cluster exposé.
Installation
Via mise
mise use -g github:batleforc/ProxyAuthK8Smise télécharge l'archive de la
release GitHub correspondant à l'OS et à l'architecture, et met kubectl-proxyauth dans le
PATH. Pour figer une version : mise use -g github:batleforc/ProxyAuthK8S@v0.2.1.
Le plugin n'est pas publié sur l'index krew pour le moment. Le manifeste krew reste rendu à chaque tag et attaché à la release GitHub.
Depuis une release
VERSION=v0.2.1
curl -sSL -o kubectl-proxyauth.tar.gz \
"https://github.com/batleforc/proxyauthK8s/releases/download/${VERSION}/kubectl-proxyauth_${VERSION}_linux_amd64.tar.gz"
tar xzf kubectl-proxyauth.tar.gz
install -m 0755 kubectl-proxyauth ~/.local/bin/Le binaire doit s'appeler kubectl-proxyauth et être dans le PATH : c'est ce qui permet à
kubectl de l'exposer comme kubectl proxyauth.
Sur Linux, les identifiants sont stockés dans le trousseau via l'API Secret Service
(gnome-keyring, KWallet...). Si aucun Secret Service n'est joignable (machine sans
interface graphique, session SSH sans bus D-Bus), le plugin se replie sur le trousseau du
noyau (keyutils) : les tokens y sont protégés mais ne survivent pas à un redémarrage, il
faudra alors se reconnecter.
Les tokens sont rangés sous le service proxyauthk8s, par URL de serveur. Pour garder deux
profils sur le même serveur (deux comptes, deux HOME), donnez à chacun son service avec
PROXYAUTH_KEYRING_SERVICE=<nom> : sans cela, le dernier login remplace le token de l'autre.
Usage
Se connecter au serveur
kubectl proxyauth login --server-url https://proxyauthk8s.example.comSans --token, le login serveur est une connexion SSO : le plugin ouvre le navigateur sur
/api/v1/auth/login du serveur (avec --browser, PROXYAUTH_BROWSER et le collage d'URL
comme pour un cluster, voir plus bas). Après la connexion chez l'IdP du proxy, le navigateur
revient sur le listener local (http://localhost:18000/, PROXYAUTH_CALLBACK_PORT) avec un
code à usage unique, que le plugin échange (PKCE) contre la session : jeton d'accès et
refresh token, rangés dans le trousseau. Aucun jeton ne passe dans une URL.
Le jeton d'accès est renouvelé tout seul (/api/v1/auth/refresh) quand il lui reste moins
de 60 s, à l'usage (get-token, get, login <cluster>). Si la session SSO est terminée, le
plugin demande de relancer kubectl proxyauth login --server-url … ; si l'IdP est
injoignable, il le dit et il suffit de réessayer plus tard.
kubectl proxyauth login --server-url https://proxyauthk8s.example.com --token <jeton>Avec --token (scripts, CI), le jeton collé est validé auprès du serveur puis stocké tel quel,
sans renouvellement : il faut se reconnecter à son expiration.
Certificat non reconnu par le système
Si le certificat TLS de ProxyAuthK8S est auto-signé ou émis par une CA interne, le login
échoue avec certificate verify failed. Donnez au plugin le certificat de la CA (PEM) :
kubectl proxyauth login --server-url https://proxyauthk8s.example.com \
--certificate-authority ./proxyauth-ca.pemLa CA est enregistrée pour ce serveur dans ~/.kube/proxyauth_config.yaml : les commandes
suivantes (et les logins de cluster) lui font confiance sans repréciser l'option. Elle est aussi
écrite en certificate-authority-data dans les clusters du kubeconfig, pour que kubectl
lui fasse confiance. Repasser --certificate-authority la remplace.
Confiance au premier usage. Lors du premier login à un serveur https sans CA connue, le
plugin récupère le certificat présenté (la poignée de main est interrompue dès sa réception :
rien n'est envoyé à un serveur non vérifié). Si le système ne le reconnaît pas mais qu'il s'agit
d'un certificat auto-signé valide pour ce nom d'hôte (certificat du serveur lui-même, ou
racine envoyée avec la chaîne), le plugin affiche son sujet, sa validité et son empreinte
SHA-256, puis demande confirmation :
The server https://proxyauthk8s.example.com presents a self-signed certificate this system does not trust:
Subject: CN=proxyauthk8s.example.com
Valid: 2026-10-01T00:00:00Z to 2027-10-01T00:00:00Z
SHA-256: 3F:A1:…:9C
Check this fingerprint with the server's administrator before accepting.
Trust this certificate for https://proxyauthk8s.example.com? [y/N]:Vérifiez l'empreinte auprès de l'administrateur (par ex. openssl x509 -noout -fingerprint -sha256 -in cert.pem) avant d'accepter. Une réponse y l'enregistre exactement comme
--certificate-authority ; toute autre réponse arrête le login (ERR000020). Rien n'est proposé
sans terminal (scripts, CI), ni quand le certificat est expiré, émis pour un autre nom, ou
signé par une CA que le serveur n'envoie pas : passez alors la CA avec --certificate-authority.
Renouvellement du certificat. Un certificat auto-signé épinglé ne vérifie plus le serveur
dès qu'il est renouvelé avec une nouvelle clé — ce que fait cert-manager par défaut
(rotationPolicy: Always, environ tous les 60 jours). Les commandes échouent alors
(ERR000020 pour le plugin, x509: certificate signed by unknown authority pour kubectl).
Relancez kubectl proxyauth login depuis un terminal : le plugin détecte le changement et
affiche l'ancienne et la nouvelle empreinte :
WARNING: the certificate of https://proxyauthk8s.example.com has CHANGED since it was trusted.
Previously trusted SHA-256: 3F:A1:…:9C
Now presented:
Subject: CN=proxyauthk8s.example.com
Valid: 2026-12-01T00:00:00Z to 2027-12-01T00:00:00Z
SHA-256: B7:02:…:E4
This is expected after a certificate renewal, but it is also what an attacker
intercepting the connection would show. Check the new fingerprint with the
server's administrator before accepting.
Replace the trusted certificate for https://proxyauthk8s.example.com? [y/N]:Le défaut est non : un changement inattendu est exactement ce que montrerait une
interception. En acceptant, le nouveau certificat remplace l'ancien pour ce serveur et dans
tous les clusters du kubeconfig qui passent par lui, sans relogin cluster par cluster (même
chose quand --certificate-authority change la CA d'un serveur). Sans terminal, rien n'est
remplacé.
Pour un serveur utilisé dans la durée, évitez d'épingler un certificat feuille qui tourne :
servez un certificat émis par une CA (interne ou publique) et distribuez cette CA avec
--certificate-authority, ou envoyez une racine auto-signée stable avec la chaîne — seule la
rotation de cette racine demande alors une nouvelle confirmation.
Pour récupérer la CA :
-
cert-manager avec une CA interne :
kubectl get secret <secret-du-certificat> -n <ns> -o jsonpath='{.data.ca\.crt}' | base64 -d -
mkcert (dev local) :
$(mkcert -CAROOT)/rootCA.pem -
certificat auto-signé : le certificat lui-même, tel que servi par le serveur :
openssl s_client -connect proxyauthk8s.example.com:443 -servername proxyauthk8s.example.com </dev/null \ | openssl x509 > proxyauth-ca.pem
Récupérer le certificat depuis le serveur lui-même revient à lui faire confiance sur parole
(trust on first use) : vérifiez son empreinte
(openssl x509 -in proxyauth-ca.pem -noout -fingerprint -sha256) auprès de l'administrateur.
Pour une CA interne, le serveur n'envoie en général pas la racine : prenez-la à la source.
Voir où l'on est connecté
kubectl proxyauth status # tous les serveurs connus
kubectl proxyauth status -f json # même chose en json/yaml DEFAULT SERVER LOGIN USER EXPIRES CLUSTERS
* https://proxyauthk8s.example.com sso alice in 42m default/mon-clusterstatus lit uniquement l'état local (configuration et trousseau) : aucun appel réseau, et
aucun jeton n'est affiché. LOGIN vaut sso (session renouvelée à l'usage), token (jeton
collé, pas renouvelé) ou none. USER et EXPIRES sont lus dans le jeton quand c'est un JWT,
sans en vérifier la signature : c'est un affichage, pas un contrôle d'accès.
Lister les clusters visibles
kubectl proxyauth get # tous les clusters visibles
kubectl proxyauth get mon-cluster # un seul cluster
kubectl proxyauth get -f json # sortie json/yaml au lieu du tableauSeuls les clusters dont expose_via_dashboard est activé et dont le groupe dashboard
figure dans les groupes de l'utilisateur apparaissent ici.
Se connecter à un cluster
Pour un cluster dont le provider est OIDC/SSO, la connexion est interactive :
kubectl proxyauth -n default login mon-clusterLe plugin ouvre le navigateur sur le provider OIDC, récupère code/state via un callback
local (http://localhost:18000/ par défaut), échange le code auprès du serveur et stocke
l'id_token du cluster dans le trousseau.
L'URI de redirection utilisée est http://localhost:<port>/auth/callback/<ns>/<cluster> et doit
être enregistrée pour le client OIDC du cluster côté IdP. Le port par défaut est 18000 ;
changez-le avec PROXYAUTH_CALLBACK_PORT si besoin (et enregistrez l'URI correspondante).
Navigateur sur une autre machine (Eclipse Che, SSH, poste distant)
Après la connexion, le provider redirige le navigateur vers
http://localhost:<port>/auth/callback/<ns>/<cluster>?code=…&state=…. Ce localhost est celui
de la machine du navigateur : quand le plugin tourne ailleurs (workspace Eclipse Che,
session SSH, conteneur distant), la redirection ne l'atteint pas et la page ne se charge
pas. C'est attendu : depuis un terminal, le plugin accepte aussi qu'on colle l'URL de cette
page.
kubectl proxyauth login mon-cluster --browser none # n'essaie pas d'ouvrir un navigateur local- Ouvrez l'URL affichée dans le navigateur de votre poste et connectez-vous.
- Le navigateur arrive sur
http://localhost:18000/auth/callback/...et affiche une erreur de connexion : copiez l'adresse complète depuis la barre d'adresse. - Collez-la dans le terminal et validez. Le plugin termine le login (échange du code, kubeconfig).
- Le collage et le callback local sont attendus en même temps : sur un poste classique, rien ne change, le premier arrivé l'emporte.
- L'adresse complète,
?code=…&state=…oucode=…&state=…sont acceptés ; une saisie qui n'est pas une redirection est signalée et l'attente continue. Une erreur renvoyée par le provider (error=access_denied, …) arrête le login avec son détail. - Le délai d'attente passe de 3 à 10 minutes quand le collage est possible. Sans terminal (script), seul le callback local est attendu.
statereste vérifié par le serveur : coller l'URL d'un autre login échoue.
Choisir le navigateur
Par défaut, le navigateur du système est utilisé. Si le provider impose un autre navigateur
(navigateur d'entreprise, profil dédié), indiquez-le avec --browser, et ses arguments avec
--browser-arg (répétable) :
# Linux / macOS
kubectl proxyauth login mon-cluster --browser /opt/corp/browser
kubectl proxyauth login mon-cluster --browser google-chrome \
--browser-arg=--profile-directory=Work --browser-arg=--new-window
# Windows : chemin complet, sans guillemets supplémentaires à prévoir
kubectl proxyauth login mon-cluster --browser "C:\Program Files\Corp\browser.exe"- Le programme est lancé directement, sans shell : l'URL est toujours un seul argument, et un chemin avec des espaces n'a pas besoin d'échappement.
- L'URL est passée en dernier argument, sauf si un argument contient
{url}, qui est alors remplacé (ex.--browser-arg=--app={url}). - Le choix est enregistré pour le serveur (visible dans la colonne
Browserdekubectl proxyauth config get) : les logins suivants via ce serveur l'utilisent sans repréciser l'option. Il peut aussi être donné dès le login serveur. --browser nonen'ouvre rien et se contente d'afficher l'URL (poste sans navigateur, URL à ouvrir ailleurs) ;--browser defaultrevient au navigateur du système.PROXYAUTH_BROWSER=<programme>remplace le choix enregistré pour une seule exécution, sans le modifier.
Pour un cluster non-SSO (ou pour fournir un jeton directement) :
kubectl proxyauth -n default login mon-cluster --token <jeton>Dans les deux cas, le jeton est stocké dans le trousseau, puis login écrit dans le
kubeconfig (--kubeconfig, sinon $KUBECONFIG, sinon ~/.kube/config) un cluster
<ns>-<cluster>, un utilisateur <ns>-<cluster>-proxyauth et un contexte
<ns>-<cluster>-context, qui devient le contexte courant. Les autres entrées ne sont pas
modifiées, et un nouveau login met ces trois entrées à jour au lieu de les dupliquer.
Comme kubectl, le plugin accepte un $KUBECONFIG listant plusieurs fichiers (séparés par
:, ; sous Windows) : il lit leur fusion et écrit uniquement dans le premier fichier
existant (créé s'il n'en existe aucun). Ce fichier étant prioritaire lors de la fusion, ce
qui y est écrit l'emporte sur une entrée de même nom dans un fichier suivant, sans modifier ce
dernier.
L'exec de l'utilisateur appelle kubectl proxyauth get-token, qui relit le jeton dans le
trousseau à chaque commande kubectl :
kubectl proxyauth -n default login mon-cluster
kubectl get pods # passe par le proxy avec le jeton du trousseauQuand le jeton est un JWT (l'id_token d'un login OIDC, ou le jeton d'une session SSO), get-token
indique à kubectl son expiration (expirationTimestamp). kubectl relance alors get-token à
l'échéance, y compris pendant une commande longue (port-forward, exec, --watch), ce qui
renouvelle le jeton quand une session SSO le permet. Un jeton déjà expiré n'est pas transmis :
get-token échoue et indique le login à relancer, au lieu de laisser kubectl recevoir un 401.
Cluster en échange de jeton
Un cluster en upstream_auth.mode: TokenExchange (token_exchange: true dans
/api/v1/clusters) prend le jeton du serveur : login mon-cluster ne lance aucun SSO et
ne stocke aucun jeton de cluster (un --token est ignoré). Il écrit le même contexte et note
le cluster comme token_exchange dans la configuration du plugin ; get-token rend alors le
jeton du serveur, renouvelé s'il expire dans moins de 60 s.
Gérer les contextes kubectl
kubectl proxyauth context # contexte courant (alias : ctx)
kubectl proxyauth get-contexts # tous les contextes du kubeconfig
kubectl proxyauth use-context default-mon-cluster-context # change le contexte courantLes anciennes formes context --list et context --set <nom> marchent encore, avec un
avertissement : elles disparaîtront dans une prochaine version.
Se déconnecter / purger le cache
kubectl proxyauth logout mon-cluster # retire le jeton d'un cluster
kubectl proxyauth logout # déconnecte du serveur (tous ses jetons)
kubectl proxyauth cache clear # purge tous les jetons en cacheConfiguration du plugin
Le plugin garde sa configuration (serveurs connus, namespace par défaut) dans
~/.kube/proxyauth_config.yaml (surchargeable avec -p/--proxy-auth-config).
kubectl proxyauth config get # configuration courante
kubectl proxyauth config get --list # toutes les configurations
kubectl proxyauth config use-server <url> # serveur par défaut
kubectl proxyauth config set-namespace <url> <ns> # namespace par défaut d'un serveur
kubectl proxyauth config clear --server-url <url> # oublie un serveur
kubectl proxyauth config clear --allLe premier serveur auquel on se connecte devient le serveur par défaut. config set-def
(remplacée par use-server et set-namespace) marche encore, avec un avertissement.
Options globales
Une erreur s'affiche sur une ligne error: ERR0000xx: …, suivie au besoin d'une ligne hint:
qui donne la commande à lancer. Le code reste stable d'une version à l'autre.
| Option | Effet |
|---|---|
-s, --server-url <URL> | Serveur ProxyAuthK8S à utiliser (sinon le serveur par défaut) |
-n, --namespace <NS> | Namespace du cluster visé |
-k, --kubeconfig <FILE> | Kubeconfig (défaut : $KUBECONFIG puis ~/.kube/config) |
-p, --proxy-auth-config <FILE> | Configuration du plugin (défaut : ~/.kube/proxyauth_config.yaml) |
-f, --format <FORMAT> | table (défaut), json ou yaml |
-v / -vv | Logs de debug, de trace (horodatés) |
Le kubeconfig plugin
C'est ce que login écrit, et la forme téléchargeable depuis le dashboard (kubeconfig plugin) :
apiVersion: v1
kind: Config
clusters:
- name: default-mon-cluster
cluster:
server: https://proxyauthk8s.example.com/clusters/default/mon-cluster
users:
- name: default-mon-cluster-proxyauth
user:
exec:
apiVersion: client.authentication.k8s.io/v1
command: kubectl
args:
- proxyauth
- get-token
- --namespace=default
- --server-url=https://proxyauthk8s.example.com
- mon-cluster
interactiveMode: Never
contexts:
- name: default-mon-cluster-context
context:
cluster: default-mon-cluster
user: default-mon-cluster-proxyauth
current-context: default-mon-cluster-contextL'URL du serveur est celle du proxy, pas celle du cluster : c'est ProxyAuthK8S qui authentifie l'appel, applique les règles de sécurité, puis relaie vers l'apiserver.
Résolution de problèmes
| Symptôme | Cause probable |
|---|---|
401 sur toutes les requêtes | Jeton expiré : relancer kubectl proxyauth login |
the session with … is over | Session SSO du serveur terminée : relancer kubectl proxyauth login --server-url … |
the identity provider is unavailable | IdP du proxy injoignable au renouvellement : réessayer plus tard |
403 avec un message sur un groupe | L'utilisateur n'est pas dans le proxy_group du cluster |
403 avec un message sur un chemin | Le chemin n'est pas dans security_config.allowed_resources |
429 avec un en-tête Retry-After | Rate limiting, ou bannissement après des échecs d'authentification répétés |
certificate verify failed | Certificat du serveur non reconnu : voir --certificate-authority ci-dessus |
ERR000014: Unauthenticated: the login to cluster … has expired | L'id_token du cluster (ou le jeton serveur collé) a expiré : lancer la commande indiquée, par ex. kubectl proxyauth -n <ns> login <cluster> |
ERR000021: Not logged in to any ProxyAuthK8S server | Aucun serveur connu : commencer par kubectl proxyauth login --server-url https://… |
ERR000020: Server certificate not trusted | Certificat auto-signé refusé à l'invite de confiance, ou certificat renouvelé depuis qu'il a été épinglé : relancer kubectl proxyauth login depuis un terminal et accepter après vérification de l'empreinte, ou passer --certificate-authority |
x509: certificate signed by unknown authority (kubectl) | Le certificat du serveur a changé : relancer kubectl proxyauth login, qui met à jour la CA des clusters du kubeconfig |
Le cluster n'apparaît pas dans get | expose_via_dashboard est à false (défaut) ou le groupe dashboard ne correspond pas |
502 the cluster does not trust this proxy | Cluster en FrontProxy dont l'apiserver ne croit plus le proxy : se reconnecter n'y fait rien, prévenir l'opérateur (diagnostic) |
kubectl auth whoami affiche proxyauth:… | Normal en FrontProxy : l'apiserver voit le nom préfixé, c'est lui que les RoleBinding visent |