Authentification Kubernetes avec GitHub OAuth et Dex

Je présente à votre attention un tutoriel pour générer un accès à un cluster Kubernetes en utilisant Dex, dex-k8s-authenticator et GitHub.

Authentification Kubernetes avec GitHub OAuth et Dex
Mème local du chat Kubernetes en russe dans Telegram

introduction

Nous utilisons Kubernetes pour créer des environnements dynamiques pour l'équipe de développement et l'AQ. Nous voulons donc leur donner accès au cluster à la fois pour le tableau de bord et kubectl. Contrairement au même OpenShift, vanilla Kubernetes n'a pas d'authentification native, nous utilisons donc des outils tiers pour cela.

Dans cette configuration nous utilisons :

  • authentificateur dex-k8s  - application web pour générer la configuration kubectl
  • Dex - Fournisseur OpenID Connect
  • GitHub - simplement parce que nous utilisons GitHub dans notre entreprise

Nous avons essayé d'utiliser Google OIDC, mais malheureusement nous manqué pour les démarrer avec des groupes, donc l'intégration avec GitHub nous convenait parfaitement. Sans mappage de groupe, il ne sera pas possible de créer des stratégies RBAC basées sur des groupes.

Alors, comment fonctionne notre processus d'autorisation Kubernetes dans une représentation visuelle :

Authentification Kubernetes avec GitHub OAuth et Dex
Processus d'autorisation

Un peu plus de détails et point par point :

  1. L'utilisateur se connecte à dex-k8s-authenticator (login.k8s.example.com)
  2. dex-k8s-authenticator redirige la requête vers Dex (dex.k8s.example.com)
  3. Dex redirige vers la page de connexion GitHub
  4. GitHub génère les informations d'autorisation requises et les renvoie à Dex
  5. Dex transmet les informations reçues à dex-k8s-authenticator
  6. L'utilisateur obtient le jeton OIDC de GitHub
  7. dex-k8s-authenticator ajoute un jeton à kubeconfig
  8. kubectl transmet le jeton à KubeAPIServer
  9. KubeAPIServer basé sur le jeton transmis renvoie l'accès à kubectl
  10. Accès utilisateur depuis kubectl

Actions préparatoires

Bien sûr, nous avons déjà installé un cluster Kubernetes (k8s.example.com), ainsi que HELM préinstallé. Nous avons également une organisation sur GitHub (super-org).
Si vous n'avez pas HELM, installez-le très simple.

Nous devons d'abord configurer GitHub.

Accédez à la page des paramètres de l'organisation, (https://github.com/organizations/super-org/settings/applications) et créez une nouvelle application (application OAuth autorisée) :
Authentification Kubernetes avec GitHub OAuth et Dex
Créer une nouvelle application sur GitHub

Remplissez les champs avec les URL requises, par exemple :

  • Page d'accueil URL: https://dex.k8s.example.com
  • URL de rappel d'autorisation : https://dex.k8s.example.com/callback

Attention aux liens, il est important de ne pas perdre les slashs.

En réponse au formulaire rempli, GitHub générera Client ID и Client secret, conservez-les en lieu sûr, elles nous seront utiles (par exemple, nous utilisons Voûte pour garder des secrets):

Client ID: 1ab2c3d4e5f6g7h8
Client secret: 98z76y54x32w1

Préparer les enregistrements DNS pour les sous-domaines login.k8s.example.com и dex.k8s.example.com, ainsi que des certificats SSL pour les entrées.

Créons des certificats SSL :

cat <<EOF | kubectl create -f -
apiVersion: certmanager.k8s.io/v1alpha1
kind: Certificate
metadata:
  name: cert-auth-dex
  namespace: kube-system
spec:
  secretName: cert-auth-dex
  dnsNames:
    - dex.k8s.example.com
  acme:
    config:
    - http01:
        ingressClass: nginx
      domains:
      - dex.k8s.example.com
  issuerRef:
    name: le-clusterissuer
    kind: ClusterIssuer
---
apiVersion: certmanager.k8s.io/v1alpha1
kind: Certificate
metadata:
  name: cert-auth-login
  namespace: kube-system
spec:
  secretName: cert-auth-login
  dnsNames:
    - login.k8s.example.com
  acme:
    config:
    - http01:
        ingressClass: nginx
      domains:
      - login.k8s.example.com
  issuerRef:
    name: le-clusterissuer
    kind: ClusterIssuer
EOF
kubectl describe certificates cert-auth-dex -n kube-system
kubectl describe certificates cert-auth-login -n kube-system

ClusterIssuer avec titre le-clusterissuer devrait déjà exister, sinon, créez-le en utilisant HELM :

helm install --namespace kube-system -n cert-manager stable/cert-manager
cat << EOF | kubectl create -f -
apiVersion: certmanager.k8s.io/v1alpha1
kind: ClusterIssuer
metadata:
  name: le-clusterissuer
  namespace: kube-system
spec:
  acme:
    server: https://acme-v02.api.letsencrypt.org/directory
    email: [email protected]
    privateKeySecretRef:
      name: le-clusterissuer
    http01: {}
EOF

Configuration de KubeAPIServer

Pour que kubeAPIServer fonctionne, vous devez configurer OIDC et mettre à niveau le cluster :

kops edit cluster
...
  kubeAPIServer:
    anonymousAuth: false
    authorizationMode: RBAC
    oidcClientID: dex-k8s-authenticator
    oidcGroupsClaim: groups
    oidcIssuerURL: https://dex.k8s.example.com/
    oidcUsernameClaim: email
kops update cluster --yes
kops rolling-update cluster --yes

Nous utilisons puisque pour étendre les clusters, mais cela fonctionne de la même manière pour autres gestionnaires de cluster.

Configuration Dex et authentificateur dex-k8s

Pour que Dex fonctionne, vous devez disposer d'un certificat et d'une clé du maître Kubernetes, nous allons l'extraire de là :

sudo cat /srv/kubernetes/ca.{crt,key}
-----BEGIN CERTIFICATE-----
AAAAAAAAAAABBBBBBBBBBCCCCCC
-----END CERTIFICATE-----
-----BEGIN RSA PRIVATE KEY-----
DDDDDDDDDDDEEEEEEEEEEFFFFFF
-----END RSA PRIVATE KEY-----

Clonez le dépôt dex-k8s-authenticator :

git clone [email protected]:mintel/dex-k8s-authenticator.git
cd dex-k8s-authenticator/

Avec l'aide de fichiers de valeurs, nous pouvons configurer de manière flexible des variables pour notre Cartes HELM.

Décrivons la configuration de Dex :

cat << EOF > values-dex.yml
global:
  deployEnv: prod
tls:
  certificate: |-
    -----BEGIN CERTIFICATE-----
    AAAAAAAAAAABBBBBBBBBBCCCCCC
    -----END CERTIFICATE-----
  key: |-
    -----BEGIN RSA PRIVATE KEY-----
    DDDDDDDDDDDEEEEEEEEEEFFFFFF
    -----END RSA PRIVATE KEY-----
ingress:
  enabled: true
  annotations:
    kubernetes.io/ingress.class: nginx
    kubernetes.io/tls-acme: "true"
  path: /
  hosts:
    - dex.k8s.example.com
  tls:
    - secretName: cert-auth-dex
      hosts:
        - dex.k8s.example.com
serviceAccount:
  create: true
  name: dex-auth-sa
config: |
  issuer: https://dex.k8s.example.com/
  storage: # https://github.com/dexidp/dex/issues/798
    type: sqlite3
    config:
      file: /var/dex.db
  web:
    http: 0.0.0.0:5556
  frontend:
    theme: "coreos"
    issuer: "Example Co"
    issuerUrl: "https://example.com"
    logoUrl: https://example.com/images/logo-250x25.png
  expiry:
    signingKeys: "6h"
    idTokens: "24h"
  logger:
    level: debug
    format: json
  oauth2:
    responseTypes: ["code", "token", "id_token"]
    skipApprovalScreen: true
  connectors:
  - type: github
    id: github
    name: GitHub
    config:
      clientID: $GITHUB_CLIENT_ID
      clientSecret: $GITHUB_CLIENT_SECRET
      redirectURI: https://dex.k8s.example.com/callback
      orgs:
      - name: super-org
        teams:
        - team-red
  staticClients:
  - id: dex-k8s-authenticator
    name: dex-k8s-authenticator
    secret: generatedLongRandomPhrase
    redirectURIs:
      - https://login.k8s.example.com/callback/
envSecrets:
  GITHUB_CLIENT_ID: "1ab2c3d4e5f6g7h8"
  GITHUB_CLIENT_SECRET: "98z76y54x32w1"
EOF

Et pour dex-k8s-authenticator :

cat << EOF > values-auth.yml
global:
  deployEnv: prod
dexK8sAuthenticator:
  clusters:
  - name: k8s.example.com
    short_description: "k8s cluster"
    description: "Kubernetes cluster"
    issuer: https://dex.k8s.example.com/
    k8s_master_uri: https://api.k8s.example.com
    client_id: dex-k8s-authenticator
    client_secret: generatedLongRandomPhrase
    redirect_uri: https://login.k8s.example.com/callback/
    k8s_ca_pem: |
      -----BEGIN CERTIFICATE-----
      AAAAAAAAAAABBBBBBBBBBCCCCCC
      -----END CERTIFICATE-----
ingress:
  enabled: true
  annotations:
    kubernetes.io/ingress.class: nginx
    kubernetes.io/tls-acme: "true"
  path: /
  hosts:
    - login.k8s.example.com
  tls:
    - secretName: cert-auth-login
      hosts:
        - login.k8s.example.com
EOF

Installez Dex et dex-k8s-authenticator :

helm install -n dex --namespace kube-system --values values-dex.yml charts/dex
helm install -n dex-auth --namespace kube-system --values values-auth.yml charts/dex-k8s-authenticator

Vérifions l'état de fonctionnement des services (Dex doit renvoyer le code 400 et dex-k8s-authenticator doit renvoyer le code 200) :

curl -sI https://dex.k8s.example.com/callback | head -1
HTTP/2 400
curl -sI https://login.k8s.example.com/ | head -1
HTTP/2 200

Configuration RBAC

Créez un ClusterRole pour le groupe, dans notre cas avec un accès en lecture seule :

cat << EOF | kubectl create -f -
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: cluster-read-all
rules:
  -
    apiGroups:
      - ""
      - apps
      - autoscaling
      - batch
      - extensions
      - policy
      - rbac.authorization.k8s.io
      - storage.k8s.io
    resources:
      - componentstatuses
      - configmaps
      - cronjobs
      - daemonsets
      - deployments
      - events
      - endpoints
      - horizontalpodautoscalers
      - ingress
      - ingresses
      - jobs
      - limitranges
      - namespaces
      - nodes
      - pods
      - pods/log
      - pods/exec
      - persistentvolumes
      - persistentvolumeclaims
      - resourcequotas
      - replicasets
      - replicationcontrollers
      - serviceaccounts
      - services
      - statefulsets
      - storageclasses
      - clusterroles
      - roles
    verbs:
      - get
      - watch
      - list
  - nonResourceURLs: ["*"]
    verbs:
      - get
      - watch
      - list
  - apiGroups: [""]
    resources: ["pods/exec"]
    verbs: ["create"]
EOF

Créons une configuration pour ClusterRoleBinding :

cat <<EOF | kubectl create -f -
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
  name: dex-cluster-auth
  namespace: kube-system
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: cluster-read-all
subjects:
  kind: Group
  name: "super-org:team-red"
EOF

Nous sommes maintenant prêts pour les tests.

Tests

Aller à la page de connexionhttps://login.k8s.example.com) et connectez-vous avec un compte GitHub :

Authentification Kubernetes avec GitHub OAuth et Dex
Page d'autorisation

Authentification Kubernetes avec GitHub OAuth et Dex
Page d'autorisation redirigée vers GitHub

Authentification Kubernetes avec GitHub OAuth et Dex
 Suivez les instructions générées pour accéder

Après avoir copié-collé depuis la page Web, nous pouvons utiliser kubectl pour gérer nos ressources de cluster :

kubectl get po
NAME                READY   STATUS    RESTARTS   AGE
mypod               1/1     Running   0          3d

kubectl delete po mypod
Error from server (Forbidden): pods "mypod" is forbidden: User "[email protected]" cannot delete pods in the namespace "default"

Et cela fonctionne, tous les utilisateurs GitHub de notre organisation peuvent voir les ressources et se connecter aux pods, mais ils n'ont pas l'autorisation de les modifier.

Source: habr.com

Ajouter un commentaire