Autenticación en Kubernetes con GitHub OAuth y Dex

Te presento el tutorial para generar acceso al clúster de Kubernetes usando Dex, dex-k8s-authenticator y GitHub.

imagen

Meme local del chat en ruso Kubernetes en Telegram

Introduccion


Utilizamos Kubernetes para crear entornos dinámicos para el equipo de desarrollo y el control de calidad. Por lo tanto, queremos darles acceso al clúster tanto para paneles como para kubectl. A diferencia de OpenShift, Vanilla Kubernetes no tiene autenticación nativa, por lo que utilizamos herramientas de terceros para esto.

En esta configuración, utilizamos:

  • dex-k8s-authenticator : aplicación web para generar la configuración de kubectl
  • Dex - Proveedor de OpenID Connect
  • GitHub: simplemente porque usamos GitHub en nuestra empresa

Intentamos usar Google OIDC, pero desafortunadamente no pudimos agruparlos, por lo que la integración con GitHub estuvo bien con nosotros. Sin la asignación de grupo, no puede crear políticas RBAC basadas en grupo.

Entonces, ¿cómo funciona nuestro proceso de autorización en Kubernetes en una representación visual?

imagen
Proceso de autorización

Un poco más de detalle y puntos:

  1. El usuario inicia sesión en dex-k8s-authenticator ( login.k8s.example.com )
  2. dex-k8s-authenticator redirige la solicitud a Dex ( dex.k8s.example.com )
  3. Dex redirige a la página de inicio de sesión de GitHub
  4. GitHub genera la información de autorización necesaria y la devuelve a Dex
  5. Dex pasa la información recibida a dex-k8s-authenticator
  6. El usuario obtiene el token OIDC de GitHub
  7. dex-k8s-authenticator agrega un token a kubeconfig
  8. kubectl pasa el token a KubeAPIServer
  9. KubeAPIServer basado en el token transferido devuelve accesos en kubectl
  10. El usuario obtiene acceso desde kubectl

Actividades preparatorias


Por supuesto, ya tenemos instalado un clúster de k8s.example.com ( k8s.example.com ), así como HELM. También tenemos una organización en GitHub (superorganización).
Si no tiene HELM, es muy fácil de instalar.

Primero necesitamos configurar GitHub.

Vaya a la página de configuración de la organización ( https://github.com/organizations/super-org/settings/applications ) y cree una nueva aplicación (Aplicación OAuth autorizada):
imagen
Crear una nueva aplicación en GitHub

Complete los campos con las URL necesarias, por ejemplo:

  • URL de la página de inicio: https://dex.k8s.example.com
  • URL de devolución de llamada de autorización: https://dex.k8s.example.com/callback

Tenga cuidado con los enlaces, es importante no perder barras.

En respuesta al formulario completado, GitHub generará la Client ID del Client ID y el Client secret , los guardará en un lugar seguro, nos serán útiles (por ejemplo, usamos Vault para almacenar secretos):

 Client ID: 1ab2c3d4e5f6g7h8 Client secret: 98z76y54x32w1 

Prepare registros DNS para los subdominios login.k8s.example.com y dex.k8s.example.com , así como certificados SSL para entradas.

Crear certificados 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 

Ya debería existir un ClusterIssuer con el nombre le-clusterissuer , si no, créelo usando 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: k8s-admin@example.com privateKeySecretRef: name: le-clusterissuer http01: {} EOF 

Configuración de KubeAPIServer


Para que kubeAPIServer funcione, debe configurar OIDC y actualizar el clúster:

 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 

Usamos kops para implementar clústeres, pero funciona igual para otros administradores de clústeres .

Configuración de autenticación dex y dex-k8s


Para que Dex funcione, debe tener un certificado y una clave del maestro de Kubernetes, extrayéndolo desde allí:

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

Clone el repositorio dex-k8s-authenticator:

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

Mediante el uso de archivos de valores, podemos establecer variables de manera flexible para nuestros gráficos HELM .

Describamos la configuración para 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 

Y para 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 

Instale Dex y 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 

Verifiquemos la capacidad de servicio de los servicios (Dex debería devolver el código 400 y dex-k8s-authenticator, el código 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 

Configuración RBAC


Creamos ClusterRole para el grupo, en nuestro caso con accesos de solo lectura:

 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 

Cree una configuración para 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 

Ahora estamos listos para probar.

Pruebas


Vamos a la página de inicio de sesión ( https://login.k8s.example.com ) e iniciamos sesión con la cuenta de GitHub:

imagen
Página de inicio de sesión

imagen
Página de inicio de sesión redirigida a GitHub

imagen
Siga las instrucciones generadas para acceder

Después de copiar y pegar desde la página web, podemos usar kubectl para administrar los recursos de nuestro clúster:

 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 "amet@example.com" cannot delete pods in the namespace "default" 

Y funciona, todos los usuarios de GitHub en nuestra organización pueden ver recursos e ingresar pods, pero no tienen el derecho de cambiarlos.

Source: https://habr.com/ru/post/es436238/


All Articles