Authentification dans Kubernetes avec Dex: attachez LDAP

Aujourd'hui, je vais passer en revue les détails de la configuration de l'authentification dans Kubernetes à l'aide de Dex en conjonction avec LDAP, et montrer également comment vous pouvez ajouter des utilisateurs statiques à Dex. 

Dans cet article, je ne m'attarderai pas sur les principes de base de Dex, mais je procéderai immédiatement à l'installation et à la configuration de LDAP. Vous pouvez vous familiariser avec les principes de Dex dans cet article .

Qu'est-ce qu'on fait:

  1. Installez OpenLDAP et configurez-y le support STARTTLS. 
  2. Nous décrivons la structure de l'annuaire LDAP de notre organisation .
  3. Activez la prise en charge OIDC (OpenID Connect) sur les serveurs kube-api .
  4. Obtenez le certificat SAN pour les domaines que Dex utilisera .
  5. Installez Dex et Dex-auth, où nous décrivons l'annuaire LDAP et les utilisateurs statiques
  6. Nous générerons kubeconfig de notre utilisateur pour travailler avec le cluster .
  7. Configurez l'authentification RBAC pour les groupes et les utilisateurs du cluster .

Alors allons-y.



Je vais vous montrer un exemple d'un cluster Kubernetes prêt à l'emploi avec Helm version 3 et Ingress, ainsi que trois noms de domaine.

Installer et configurer le serveur OpenLDAP


Nous utiliserons OpenLDAP comme LDAP sur la distribution Ubuntu 18.04. 
Le nom de notre serveur: openldap.dtln.cloud. 

  1. Nous sommes connectés au serveur et nous commençons l'installation d'OpenLDAP. Lors de l'installation, nous serons invités à définir un mot de passe:

    sudo apt update 
    sudo apt install slapd ldap-utils
    

  2. Reconfiguration d'OpenLDAP pour notre domaine:

    sudo dpkg-reconfigure slapd 
    

  3. Choisissez Non :


  4. Entrez le nom de domaine:


  5. Entrez le nom de l'organisation:


  6. Répétez la saisie du mot de passe:


  7. Nous incluons le support pour STARTTLS. Nous mettons les packages nécessaires:

    sudo apt install gnutls-bin ssl-cert
    

  8. CA-:

    sudo sh -c "certtool --generate-privkey > /etc/ssl/private/cakey.pem"
    

  9. /etc/ssl/ca.info:

    cn = DTLN Company
    ca
    cert_signing_key
    

  10. CA-a , :

    sudo certtool --generate-self-signed --load-privkey /etc/ssl/private/cakey.pem --template /etc/ssl/ca.info --outfile /etc/ssl/certs/cacert.pem
    sudo certtool --generate-privkey --bits 1024 --outfile /etc/ssl/private/openldap_key.pem
    

  11. /etc/ssl/openldap.info:

    organization = DTLN Company
    cn = openldap.dtln.cloud
    tls_www_server
    encryption_key
    signing_key
    expiration_days = 3650
    

  12. :

    sudo certtool --generate-certificate --load-privkey /etc/ssl/private/openldap_key.pem --load-ca-certificate /etc/ssl/certs/cacert.pem --load-ca-privkey /etc/ssl/private/cakey.pem --template /etc/ssl/openldap.info --outfile /etc/ssl/certs/openldap.pem
    

  13. OpenLDAP STARTTLS. certinfo.dif:

    dn: cn=config
    add: olcTLSCACertificateFile
    olcTLSCACertificateFile: /etc/ssl/certs/cacert.pem
    -
    add: olcTLSCertificateFile
    olcTLSCertificateFile: /etc/ssl/certs/openldap.pem
    -
    add: olcTLSCertificateKeyFile
    olcTLSCertificateKeyFile: /etc/ssl/private/openldap_key.pem
    

  14. :

    sudo ldapmodify -Y EXTERNAL -H ldapi:/// -f certinfo.dif
    

  15. :

    sudo chgrp openldap /etc/ssl/private/openldap_key.pem
    sudo chmod 0640 /etc/ssl/private/openldap_key.pem
    sudo gpasswd -a openldap ssl-cert
    sudo systemctl restart slapd.service
    

  16. , /etc/ldap/ldap.conf :

    TLS_CACERT /etc/ssl/certs/cacert.pem
    

  17. STARTTLS:

    ldapwhoami -H ldap://openldap.dtln.cloud -x -ZZ
    

    :



    :


LDAP-


  1. , x , Kubernetes. content.ldif:

    dn: ou=People,dc=openldap,dc=dtln,dc=cloud
    objectClass: organizationalUnit
    ou: People
    dn: cn=jane,ou=People,dc=openldap,dc=dtln,dc=cloud
    objectClass: person
    objectClass: inetOrgPerson
    sn: doe
    cn: jane
    mail: janedoe@openldap.dtln.cloud
    userpassword: foo_password
    
    dn: cn=john,ou=People,dc=openldap,dc=dtln,dc=cloud
    objectClass: person
    objectClass: inetOrgPerson
    sn: doe
    cn: john
    mail: johndoe@openldap.dtln.cloud
    userpassword: bar_password
    
    # Group definitions.
    
    dn: ou=Groups,dc=openldap,dc=dtln,dc=cloud
    objectClass: organizationalUnit
    ou: Groups
    
    dn: cn=admins,ou=Groups,dc=openldap,dc=dtln,dc=cloud
    objectClass: groupOfNames
    cn: admins
    member: cn=jane,ou=People,dc=openldap,dc=dtln,dc=cloud
    
    dn: cn=developers,ou=Groups,dc=openldap,dc=dtln,dc=cloud
    objectClass: groupOfNames
    cn: developers
    member: cn=jane,ou=People,dc=openldap,dc=dtln,dc=cloud
    member: cn=john,ou=People,dc=openldap,dc=dtln,dc=cloud
    

  2. Développez la structure décrite avec la commande:

    ldapadd -x -D cn=admin,dc=openldap,dc=dtln,dc=cloud -W -f content.ldif
    

  3. Assurez-vous que nos utilisateurs sont dans l'annuaire:

    ldapwhoami -vvv -h openldap.dtln.cloud -p 389 -D cn=john,ou=People,dc=openldap,dc=dtln,dc=cloud -x -w bar_password -ZZ
    ldapwhoami -vvv -h openldap.dtln.cloud -p 389 -D cn=jane,ou=People,dc=openldap,dc=dtln,dc=cloud -x -w foo_password -ZZ
    

Nous connectons le support pour OpenID Connect


Passons à la configuration du cluster Kubernetes. 

Nous utilisons le domaine dex.ash.dtln.cloud pour accéder au serveur API Dex et login.ash.dtln.cloud pour accéder au cluster.

Nous avons déployé le cluster sans les installateurs kubeadm ou kops, de sorte que la configuration OIDC peut être immédiatement ajoutée à l'unité systemd. Dans d'autres cas, la configuration est mieux effectuée à l'aide de ces utilitaires.

  1. Nous éditons l'unité /etc/systemd/system/kube-apiserver.service et ajoutons les paramètres de démarrage à la section ExecStart :

    --oidc-client-id=dex-k8s-authenticator \
    --oidc-groups-claim=groups \
    --oidc-username-claim=email \
    --oidc-issuer-url=https://dex.ash.dtln.cloud/ \
    
  2. Nous redémarrons nos API, vérifions qu'elles ont augmenté:

    sudo systemctl daemon-reload
    sudo systemctl restart kube-apiserver
    sudo systemctl status kube-apiserver
    

Créer un certificat multi-domaine


Accédez maintenant au cluster Kubernetes. 

  1. Nous installons cert-manager à l'aide de Helm: 

    helm repo add jetstack https://charts.jetstack.io
    helm repo update
    helm install cert-manager --namespace kube-system jetstack/cert-manager --version v0.13.0
    

  2. Nous décrivons la demande de certificat SAN pour nos domaines dans cert.yml:

    ---
    apiVersion: cert-manager.io/v1alpha2
    kind: ClusterIssuer
    metadata:
      name: letsencrypt-dex
    spec:
      acme:
        email: kubernetes@dataline.ru
        server: https://acme-v02.api.letsencrypt.org/directory
        privateKeySecretRef:
          name: letsencrypt-key-dex
        solvers:
        - http01:
            ingress:
              class: nginx
    ---
    apiVersion: cert-manager.io/v1alpha2
    kind: Certificate
    metadata:
      name: auth-dex
      namespace: kube-system
    spec:
      secretName: cert-auth-dex
      issuerRef:
        kind: ClusterIssuer
        name: letsencrypt-dex
      commonName: dex.ash.dtln.cloud
      dnsNames:
      - dex.ash.dtln.cloud
      - login.ash.dtln.cloud
    

  3. Nous exécutons la commande:

    kubectl apply -f cert.yaml
    

  4. Maintenant, nous regardons l'état de notre demande de certificat avec les commandes suivantes: 

    kubectl get certificates --all-namespaces
    kubectl get challenges --all-namespaces
    

  5. Nous attendons une confirmation, le processus peut prendre un certain temps:



Installer Dex


Pour Dex, nous avons besoin de ca.crt, ca.key du serveur maître. Habituellement, ils se trouvent dans le répertoire / etc / kubernetes / pki /.
Nous avons également besoin du certificat CA précédent avec OpenLDAP que nous avons généré, situé le long du chemin /etc/ssl/certs/cacert.pem

  1. Téléchargez les sources dex-authentifier et accédez au répertoire:

    git clone git@github.com:mintel/dex-k8s-authenticator.git
    cd dex-k8s-authenticator/
    

  2. Nous préparons la configuration pour Dex-auth, collons le contenu du ca.crt précédemment copié, il est important de respecter l'indentation:

    ---
    global:
      deployEnv: prod
    dexK8sAuthenticator:
      clusters:
        - name: 'ash.dtln.cloud'
          short_description: "k8s cluster"
          description: "Kubernetes cluster"
          issuer: https://dex.ash.dtln.cloud/
          k8s_master_uri: https://kubernetes.dtln.cloud:6443 # url or ip
          client_id: dex-k8s-authenticator
          static_context_name: false
          client_secret: acDEgDEcIg7RX0U7A9hlW2pGGraHDuMAZ4qFEKg2fUHHxr8
          redirect_uri: https://login.ash.dtln.cloud/callback
          k8s_ca_pem: |
            -----BEGIN CERTIFICATE-----
            #   ca.crt
            -----END CERTIFICATE-----
    ingress:
      enabled: true
      annotations:
        kubernetes.io/ingress.class: nginx
        kubernetes.io/tls-acme: "true"
      path: /
      hosts:
        - login.ash.dtln.cloud
      tls:
        - secretName: cert-auth-dex
          hosts:
            - login.ash.dtln.cloud
    
    

  3. Nous traduisons le contenu de cacert.pem en base64 pour l'ajouter à la configuration:

    cacert.pem | base64
    

  4. Dex, . staticPasswords bcrypt:

    ---
    global:
      deployEnv: prod
    tls:
      certificate: |-
        -----BEGIN CERTIFICATE-----
        # ca.crt
        -----END CERTIFICATE-----
      key: |-
        -----BEGIN RSA PRIVATE KEY-----
        # ca.key
        -----END RSA PRIVATE KEY-----
    ingress:
      enabled: true
      annotations:
        kubernetes.io/ingress.class: nginx
        kubernetes.io/tls-acme: "true"
      path: /
      hosts:
        - dex.ash.dtln.cloud
      tls:
        - secretName: cert-auth-dex
          hosts:
            - dex.ash.dtln.cloud
    serviceAccount:
      create: true
      name: dex-auth-sa
    config:
      issuer: https://dex.ash.dtln.cloud/
      storage:
        type: kubernetes
        config:
          inCluster: true
      web:
        http: 0.0.0.0:5556
      frontend:
        theme: "coreos"
        issuer: "kube-dtln"
        issuerUrl: "https://login.ash.dtln.cloud"
      expiry:
        signingKeys: "6h"
        idTokens: "24h"
      logger:
        level: debug
        format: json
      oauth2:
        responseTypes: ["code", "token", "id_token"]
        skipApprovalScreen: true
    
      connectors:
      - type: ldap
        id: ldap
        name: LDAP
        config:
          insecureNoSSL: false
          insecureSkipVerify: false
          startTLS: true #   
          rootCAData: |-
            # cacert.pem  base64 
            # 
         
          host: openldap.dtln.cloud:389
          usernamePrompt: Email Address
          userSearch:
            baseDN: ou=People,dc=openldap,dc=dtln,dc=cloud
            filter: "(objectClass=person)"
            username: mail
            idAttr: DN
            emailAttr: mail
            nameAttr: cn
          groupSearch:
            baseDN: ou=Groups,dc=openldap,dc=dtln,dc=cloud
            filter: "(objectClass=groupOfNames)"
    
            userMatchers:
            - userAttr: DN
              groupAttr: member
    
            nameAttr: cn
    
      staticClients:
      - id: dex-k8s-authenticator
        name: Kubernetes Dev Cluster
        secret: 'acDEgDEcIg7RX0U7A9hlW2pGGraHDuMAZ4qFEKg2fUHHxr8'
        redirectURIs:
          - https://login.ash.dtln.cloud/callback
    
      enablePasswordDB: True
    
      staticPasswords:
        #       base64
      - email: "admin@dtln.cloud"
        # bcrypt hash of the string "password"
        hash: "$2a$10$2b2cU8CPhOTaGrs1HRQuAueS7JTT5ZHsHSzYiFPm1leZck7Mc8T4W"
        username: "admin"
        userID: "08a8684b-db88-4b73-90a9-3cd1661f5466"
    
    

  5. dex dex-auth- :

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


kubeconfig


  1. , pod’. login.ash.dtln.cloud. , mail- . 

    static- mail:


  2.  Dex-auth. C kubeconfig-. :


  3. Essayez maintenant d'accéder au cluster et obtenez une erreur. C'est vrai, notre utilisateur n'a pas de droits, alors passons à la configuration de RBAC.



Nous configurons l'autorisation RBAC


  1. Par exemple, nous affectons l'utilisateur statique au rôle système d' administration de cluster et les utilisateurs du groupe de développeurs au rôle d'affichage, qui autorise uniquement l'affichage des ressources. Le contenu du fichier crb.yml devrait alors ressembler à ceci:

    ---
    apiVersion: rbac.authorization.k8s.io/v1beta1
    kind: ClusterRoleBinding
    metadata:
      name: dex-admin
      namespace: kube-system
    roleRef:
      apiGroup: rbac.authorization.k8s.io
      kind: ClusterRole
      name: cluster-admin
    subjects:
    - kind: User
      name: "admin@dtln.cloud"
    
    ---
    apiVersion: rbac.authorization.k8s.io/v1beta1
    kind: ClusterRoleBinding
    metadata:
      name: dex-developers
      namespace: kube-system
    roleRef:
      apiGroup: rbac.authorization.k8s.io
      kind: ClusterRole
      name: view
    subjects:
    - kind: Group
      name: "developers"
    

  2. Basculez vers le contexte principal et appliquez le fichier yaml créé au cluster:

    kubectl config set-context default
    kubectl apply -f crb.yml
    

  3. Nous regardons les contextes disponibles et revenons à notre utilisateur:

    kubectl config get-contexts
    kubectl config set-context johndoe-ash.dtln.cloud
    

Ceci termine la configuration de Dex en conjonction avec OpenLDAP.

Quelques conseils pour la fin:

  • Si des problèmes surviennent, la première chose à vérifier est le formatage des fichiers yaml et faites attention à l'indentation. 
  • Les barres obliques dans les adresses doivent correspondre aux exemples. 
  • pod’ Dex, Dex-auth, kube-api .

All Articles