Les presento un tutorial para generar accesos a un clúster de Kubernetes utilizando Dex, dex-k8s-authenticator y GitHub.

Un meme local del chat de Kubernetes en ruso
Introducción
Usamos Kubernetes para crear entornos dinámicos para el equipo de desarrolladores y QA. De esta manera, queremos proporcionarles acceso al clúster tanto para el panel como para kubectl. A diferencia de OpenShift, Kubernetes 'vanilla' no tiene autenticación nativa, por lo que utilizamos herramientas de terceros para esto.
En esta configuración usamos:
- — una aplicación web para generar la configuración de kubectl
- — proveedor OpenID Connect
- GitHub — simplemente porque usamos GitHub en nuestra empresa
Intentamos usar Google OIDC, pero desafortunadamente no configurarlos con grupos, por lo que la integración con GitHub nos satisfizo. Sin el mapeo de grupos no es posible crear políticas RBAC basadas en grupos.
Entonces, ¿cómo funciona nuestro proceso de autorización en Kubernetes de manera visual?

Proceso de autorización
Un poco más de detalles, punto por punto:
- 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 autorización en GitHub
- GitHub genera la información necesaria sobre la autorización y la devuelve a Dex
- Dex pasa la información obtenida a dex-k8s-authenticator
- El usuario recibe un token OIDC de GitHub
- dex-k8s-authenticator añade el token al kubeconfig
- kubectl envía el token a KubeAPIServer
- KubeAPIServer, basándose en el token enviado, devuelve accesos a kubectl
- El usuario recibe accesos de kubectl
Acciones preparatorias
Por supuesto, ya tenemos un clúster de Kubernetes (k8s.example.com), así como HELM preinstalado. También tenemos una organización en GitHub (super-org).
Si no tiene HELM, se instala .
Primero necesitamos configurar GitHub.
Vamos a la página de configuración de la organización, (https://github.com/organizations/super-org/settings/applications) y creamos una nueva aplicación (Aplicación OAuth Autorizada):

Creación de una nueva aplicación en GitHub
Completemos los campos con las URL necesarias, por ejemplo:
- Homepage URL:
https://dex.k8s.example.com - Authorization callback URL:
https://dex.k8s.example.com/callback
Tenga cuidado con los enlaces, es importante no perder las barras.
En respuesta al formulario completo, GitHub generará Client ID y Client secret, guárdelos en un lugar seguro, los necesitaremos (por ejemplo, usamos para el almacenamiento de secretos):
Client ID: 1ab2c3d4e5f6g7h8
Client secret: 98z76y54x32w1 Prepara los registros DNS para los subdominios login.k8s.example.com y dex.k8s.example.com, así como los certificados SSL para los ingresos.
Crearemos los 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 El ClusterIssuer con el nombre le-clusterissuer debe existir ya, si no existe, lo crearemos 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: {}
EOFConfiguración de KubeAPIServer
Para que kubeAPIServer funcione, es necesario 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 --yesUtilizamos para el despliegue de clústeres, pero esto funciona de manera similar para .
Configuración de Dex y dex-k8s-authenticator
Para que Dex funcione, es necesario tener un certificado y una clave del maestro de Kubernetes, lo extraeremos de allí:
sudo cat /srv/kubernetes/ca.{crt,key}
-----BEGIN CERTIFICATE-----
AAAAAAAAAAABBBBBBBBBBCCCCCC
-----END CERTIFICATE-----
-----BEGIN RSA PRIVATE KEY-----
DDDDDDDDDDDEEEEEEEEEEFFFFFF
-----END RSA PRIVATE KEY-----Clonaremos el repositorio dex-k8s-authenticator:
git clone git@github.com:mintel/dex-k8s-authenticator.git
cd dex-k8s-authenticator/Con los archivos values podemos ajustar de manera flexible las variables para nuestros .
Describiremos la configuración para Dex:
cat < 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 < 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
EOFInstalemos 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-authenticatorVerifiquemos el funcionamiento de los servicios (Dex debería devolver el código 400, mientras que dex-k8s-authenticator debería devolver 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 200Configuración de RBAC
Creamos un ClusterRole para el grupo, en nuestro caso con accesos de solo lectura:
cat << EOF | kubectl create -f -
apiversión: 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"]
EOFVamos a crear una configuración para ClusterRoleBinding:
cat <<EOF | kubectl create -f -
apiversión: 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"
EOFAhora estamos listos para probar.
Pruebas
Vamos a la página de inicio de sesión (https://login.k8s.example.com) y nos autenticamos con la cuenta de GitHub:

Página de autenticación

Página de autenticación redirigida a GitHub

Sigamos las instrucciones generadas para obtener los accesos
Después de copiar y pegar desde la página web, podemos usar kubectl para gestionar los recursos de nuestro clúster:
kubectl get po
NOMBRE LISTO ESTADO REINICIOS EDAD
mypod 1/1 Corriendo 0 3d
kubectl delete po mypod
Error del servidor (Prohibido): pods "mypod" está prohibido: El usuario "amet@example.com" no puede eliminar pods en el namespace "default" Y eso funciona, todos los usuarios de GitHub en nuestra organización pueden ver los recursos y entrar en los pods, sin embargo, no tienen derechos para modificarlos.
Fuente: habr.com
