Te presento el tutorial para generar acceso al clúster de Kubernetes usando Dex, dex-k8s-authenticator y GitHub.
Meme local del chat en ruso Kubernetes en TelegramIntroduccion
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?
Proceso de autorizaciónUn poco más de detalle y puntos:
- El usuario inicia sesión en dex-k8s-authenticator (
login.k8s.example.com
) - dex-k8s-authenticator redirige la solicitud a Dex (
dex.k8s.example.com
) - Dex redirige a la página de inicio de sesión de GitHub
- GitHub genera la información de autorización necesaria y la devuelve a Dex
- Dex pasa la información recibida a dex-k8s-authenticator
- El usuario obtiene el token OIDC de GitHub
- dex-k8s-authenticator agrega un token a kubeconfig
- kubectl pasa el token a KubeAPIServer
- KubeAPIServer basado en el token transferido devuelve accesos en kubectl
- 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):
Crear una nueva aplicación en GitHubComplete 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:
Página de inicio de sesión
Página de inicio de sesión redirigida a GitHub
Siga las instrucciones generadas para accederDespué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.