ProxyAuthK8S

Exposer un cluster

Ajouter un cluster Kubernetes derrière ProxyAuthK8S avec une ressource ProxyKubeApi

Chaque cluster exposé par ProxyAuthK8S est décrit par une ressource ProxyKubeApi (weebo.si.rs/v1) créée dans le cluster hôte. Le controller la valide, vérifie que l'apiserver cible répond, puis publie le cluster sous /clusters/<namespace>/<nom>.

Le générateur ProxyKubeApi construit le manifeste depuis le schéma de la CRD, et la référence CRD décrit chaque champ.

1. Où est l'apiserver ? (service)

Exactement une des trois variantes :

# Un apiserver joignable par URL (autre cluster, load balancer, VIP…)
service:
  ExternalService:
    url: https://api.my-cluster.example.com:6443
# Une Service Kubernetes du cluster hôte (ex. le cluster hôte lui-même)
service:
  KubernetesService:
    name: kubernetes
    namespace: default   # défaut : namespace du ProxyKubeApi
    port: 443            # ou port_name
# Un apiserver que le proxy ne peut pas joindre : un agent ouvre le tunnel
service:
  Agent:
    bootstrap: { ServiceAccountToken: { … } }

La troisième est décrite dans Cluster derrière un agent.

Préférez toujours https : selon le mode d'authentification, le jeton de l'utilisateur est transmis à cette URL. Voir Cible upstream (SSRF).

2. Comment faire confiance à son certificat ? (cert)

Le CA qui a signé le certificat de l'apiserver. Exactement une variante :

cert:
  ConfigMap: { name: kube-root-ca.crt, key: ca.crt }   # ConfigMap du namespace du CR
# cert:
#   Secret: { name: my-cluster-ca, key: ca.crt }
# cert:
#   Cert: LS0tLS1CRUdJTi...                             # PEM encodé en base64
# cert:
#   SystemRoots: true                                   # magasin de confiance système, pas de CA dédié

Insecure: true est l'ancien nom, déprécié, de SystemRoots. Malgré son nom, il n'a jamais désactivé la vérification TLS : le cluster cible est vérifié avec le magasin de confiance système. Il reste accepté pour les ressources existantes (le controller log un avertissement) ; renommez-le en SystemRoots: true.

Le Secret/ConfigMap est lu dans le namespace du ProxyKubeApi. Un champ namespace différent est refusé, sauf si PROXYAUTH_ALLOW_CROSS_NS_CERT=true (voir mTLS vers le cluster cible). Ce CA est aussi celui qu'on retrouve dans les kubeconfigs générés par le dashboard.

Si l'apiserver exige un certificat client du proxy, ajoutez client_cert (même forme que cert, avec cert et key).

3. Comment authentifier les utilisateurs ? (auth_config)

Le proxy relaie le jeton Bearer du client tel quel à l'apiserver. Il le valide d'abord lui-même (pour appliquer bannissement, groupes, liste de ressources et audit), mais c'est bien l'apiserver cible qui décide in fine des droits (RBAC).

SSO via un provider OIDC

auth_config:
  validate_against: OidcProvider
  oidc_provider:
    enabled: true
    issuer_url: https://auth.example.com
    client_id: my-cluster
    client_secret: "…"
    audience: my-cluster           # défaut : client_id
    extra_scope: "openid groups profile email"
  • Le dashboard et le plugin kubectl déroulent alors un login OIDC propre à ce cluster ; le client OIDC doit autoriser les redirect URIs <dashboard>/auth/callback/<ns>/<nom> et http://localhost:18000/auth/callback/<ns>/<nom>.
  • Côté cluster cible, l'apiserver doit accepter ces jetons : configurez son authentification OIDC (--oidc-issuer-url/--oidc-client-id ou une AuthenticationConfiguration) avec le même issuer et le même client, et créez les RoleBinding/ClusterRoleBinding pour les utilisateurs ou groupes.
  • expose_oauth_authorization_server: true publie en plus un serveur OAuth médié (RFC 8414 + PKCE) : voir la section OAuth Authorization Server médiée de Sécurité du proxy. oc login --web fonctionne contre lui à condition de viser un host qui ne sert pas le dashboard : oc sonde la racine du host et abandonne sur une page HTML. Posez ingress.apiHost (chart), puis oc login --web https://<apiHost>/clusters/<ns>/<nom>. Le client OIDC doit autoriser <host public>/clusters/<ns>/<nom>/oauth/callback ; chez Dex, déclarer des redirectURIs sur un client public lui retire les redirections localhost du plugin : utilisez un client dédié au serveur médié, accepté aussi par l'apiserver (audience).

Jetons Kubernetes (ServiceAccount, kubeadm, cloud…)

auth_config:
  validate_against: Kubernetes   # défaut

Le proxy valide le jeton par un SelfSubjectReview sur le cluster cible. C'est le mode adapté aux clusters sans SSO : le dashboard affiche alors un kubeconfig à compléter avec son propre jeton.

disable_validation: true désactive toute validation : le proxy relaie sans savoir qui appelle. Combiné à un groupe requis, le cluster renvoie systématiquement 403.

4. Qui peut le voir et l'utiliser ?

expose_via_dashboard: true        # visible dans le dashboard et `kubectl proxyauth get`
dashboard_group: team-a-viewers   # défaut : dashboard-<namespace>-<nom>
proxy_group: team-a-operators     # défaut : dashboard_group si exposé, sinon aucun
enabled: true                     # false : le cluster est désactivé sans être supprimé

Les groupes viennent du claim groups (userinfo) en mode OidcProvider, et des groupes renvoyés par le SelfSubjectReview en mode Kubernetes. Détails : Autorisation par cluster.

5. Durcir l'accès (optionnel)

security_config ajoute bannissement après échecs de login, liste blanche de chemins ou de ressources (y compris par namespace et par port : port-forward, sous-ressource proxy, nodes/proxy) et quotas. Tout est décrit dans Sécurité du proxy. virtual_apis permet d'émuler des API absentes du cluster (ex. les Projects OpenShift) : voir API virtuelles.

6. Appliquer et vérifier

kubectl apply -f my-cluster.yaml
kubectl wait --for=condition=Ready proxykubeapi/my-cluster -n team-a
kubectl get proxykubeapi -n team-a my-cluster -o jsonpath='{.status}'

La condition Ready, ses codes de raison et les Events que kubectl describe affiche sont détaillés dans Statut et Events.

statusSignification
exposed: true, path: /clusters/team-a/my-clusterLe cluster est joignable et servi par le proxy
error: Failed to validate proxy configuration: …auth_config ou security_config incohérent
error: Failed to check if target service is reachable: …Échec avant même l'appel (ex. cert introuvable, namespace refusé)
error: Target service is not reachableL'apiserver ne répond pas (URL, réseau, NetworkPolicy, CA)
warnings: ["rule N covers …"]Une règle que la restriction de ports prive de ports ou de nodes/proxy (appliquée quand même)

Le controller réessaie régulièrement (30 s, puis jusqu'à 5 min) : corrigez la ressource ou le réseau, le statut se met à jour seul. Avec la NetworkPolicy de la chart activée, pensez à autoriser l'egress vers l'apiserver cible (networkPolicy.egress).

Exemple complet

apiVersion: weebo.si.rs/v1
kind: ProxyKubeApi
metadata:
  name: my-cluster
  namespace: team-a
spec:
  expose_via_dashboard: true
  dashboard_group: team-a
  service:
    ExternalService:
      url: https://api.my-cluster.example.com:6443
  cert:
    Secret: { name: my-cluster-ca, key: ca.crt }
  auth_config:
    validate_against: OidcProvider
    oidc_provider:
      enabled: true
      issuer_url: https://auth.example.com
      client_id: my-cluster
      client_secret: "…"
      extra_scope: "openid groups profile email"
  security_config:
    enabled: true
    fail2login_equal_ban:
      enabled: true
      max_failed_logins: 5
      ban_duration: 300
    allowed_resources:
      # Lire et suivre les pods de team-a…
      - Crd:
          group: ""
          version: v1
          kind: Pod
          plural: pods
          namespace: { enabled: true, rule_kind: { AllowedNamespaces: ["team-a"] } }
          # …et n'ouvrir que leur port 8080 (port-forward et pods/x:8080/proxy).
          allowed_ports: ["8080"]

Avec allowed_ports, une règle qui n'en porte pas n'accorde aucun port, et nodes/proxy est refusé : voir Ports autorisés.

D'autres exemples sont disponibles dans deploy/example/.

On this page