Conectando la autorización de Active Directory a Kubernetes mediante Keycloak

Este artículo está escrito con el propósito de ampliar ya existente, pero habla sobre las particularidades de la integración específicamente con Microsoft Active Directory, además de complementarla.

En este artículo, explicaré cómo instalar y configurar:

  • Keycloak es un proyecto de código abierto que proporciona un único punto de entrada para aplicaciones. Funciona con muchos protocolos, incluidos LDAP y OpenID, los cuales son de nuestro interés.
  • Keycloak gatekeeper es una aplicación de proxy inverso que permite integrar la autorización a través de Keycloak.
  • Gangway es una aplicación que genera la configuración para kubectl mediante la cual se puede autorizar e ingresar al API de Kubernetes a través de OpenID.

Cómo funcionan los derechos en Kubernetes.

Podemos gestionar los derechos de usuario/grupos mediante RBAC; ya se han creado muchos artículos sobre esto, así que no me detendré en detalles. El problema es que, si bien puede usar RBAC para restringir los derechos del usuario, Kubernetes no sabe nada acerca de los usuarios. Por lo tanto, se necesita un mecanismo para introducir al usuario en Kubernetes. Para ello, agregaremos un proveedor OpenID a Kubernetes, que confirmará que el usuario efectivamente existe, y los derechos serán otorgados por Kubernetes mismo.

Preparación

  • Necesitará un clúster de Kubernetes o minikube
  • Active Directory
  • Dominios:
    keycloak.example.org
    kubernetes-dashboard.example.org
    gangway.example.org
  • Certificado para los dominios o un certificado autofirmado

No me detendré en cómo crear un certificado autofirmado, pero necesitará crear 2 certificados: uno raíz (centro de certificación) y uno wildcard para el dominio *.example.org

Una vez que obtenga/emita los certificados, debe agregar el certificado del cliente a Kubernetes, para eso creamos un secret:

kubectl create secret tls tls-keycloak --cert=example.org.crt --key=example.org.pem

A continuación, lo utilizaremos para nuestro controlador de Ingress

Instalación de Keycloak

Decidí que lo más sencillo era usar soluciones ya preparadas, específicamente charts de helm.

Instalamos el repositorio y lo actualizamos:

helm repo add codecentric https://codecentric.github.io/helm-charts
helm repo update

Creamos el archivo keycloak.yml con el siguiente contenido:

keycloak.yml

keycloak:
  # Nombre del administrador
  username: "test_admin"
  # Contraseña del administrador
  password: "admin"
  # Estas flags son necesarias para permitir cargar scripts en Keycloak directamente a través de la interfaz web. Esto nos
  servirá para solucionar un error que se describe a continuación.
  extraArgs: "-Dkeycloak.profile.feature.script=enabled -Dkeycloak.profile.feature.upload_scripts=enabled"
  # Activamos el ingreso, especificamos el nombre del host y el certificado que guardamos previamente en los secretos
  ingress:
    enabled: true 
    path: \/
    annotations:
      kubernetes.io\/ingress.class: nginx
      ingress.kubernetes.io\/affinity: cookie
    hosts:
      - keycloak.example.org
    tls:
    - hosts:
        - keycloak.example.org
      secretName: tls-keycloak
  # Keycloak requiere una base de datos para su funcionamiento, para propósitos de prueba estoy desplegando Postgresql directamente en Kubernetes, en producción no es recomendable hacer esto!
  persistence:
    deployPostgres: true
    dbVendor: postgres

postgresql:
  postgresUser: keycloak
  postgresPassword: ""
  postgresDatabase: keycloak
  persistence:
    enabled: true

Configuración de la federación

A continuación, accedemos a la interfaz web keycloak.example.org

En la esquina izquierda, hacemos clic en Añadir reino

Clave
Value

Nombre
kubernetes

Nombre para mostrar
Kubernetes

Deshabilitamos la verificación del correo electrónico del usuario:
Client scopes —> Email —> Mappers —> Email verified (Eliminar)

Configuramos la federación para importar usuarios desde ActiveDirectory; dejaré a continuación capturas de pantalla, creo que será más claro.

User federation —> Añadir proveedor… —> ldap

Configuración de la federaciónConectando la autorización de Active Directory a Kubernetes mediante Keycloak
Conectando la autorización de Active Directory a Kubernetes mediante Keycloak

Si todo está bien, después de presionar el botón Sincronizar todos los usuarios verá un mensaje de importación exitosa de usuarios.

A continuación, necesitamos mapear nuestros grupos

User federation —> ldap_localhost —> Mappers —> Crear

Creación de un mapeadorConectando la autorización de Active Directory a Kubernetes mediante Keycloak

Configuración del cliente

Debemos crear un cliente, en los términos de Keycloak esto es una aplicación que se autenticará con él. Resaltaré los puntos importantes en la captura de pantalla en rojo.

Clients —> Crear

Configuración del clienteConectando la autorización de Active Directory a Kubernetes mediante Keycloak

Crearemos un scope para los grupos:

Client Scopes —> Crear

Creación de un scopeConectando la autorización de Active Directory a Kubernetes mediante Keycloak

Y configuraremos un mapeador para ellos:

Client Scopes —> groups —> Mappers —> Crear

MapperConectando la autorización de Active Directory a Kubernetes mediante Keycloak

Añadimos el mapeo de nuestros grupos en los Default Client Scopes:

Clients —> kubernetes —> Client Scopes —> Default Client Scopes
Seleccionamos groups en Client Scopes Disponibles, hacemos clic en Añadir seleccionados

Obtenemos el secret (y lo anotamos en algún lugar) que utilizaremos para la autenticación en Keycloak:

Clients —> kubernetes —> Credentials —> Secret
Con esto, la configuración ha terminado, pero tuve un error cuando después de una autenticación exitosa recibí un error 403. Informe de errores.

Solución:

Client Scopes —> roles —> Mappers —> Crear

MapperConectando la autorización de Active Directory a Kubernetes mediante Keycloak

Código del script

// add current client-id to token audience
token.addAudience(token.getIssuedFor());

// return token issuer as dummy result assigned to iss again
token.getIssuer();

Configuración de Kubernetes

Debemos indicar dónde se encuentra nuestro certificado raíz del sitio y dónde se encuentra el proveedor OIDC.
Para esto, editamos el archivo \/etc\/kubernetes\/manifests\/kube-apiserver.yaml

kube-apiserver.yaml


...
spec:
  containers:
  - command:
    - kube-apiserver
...
    - --oidc-ca-file=/var/lib/minikube/certs/My_Root.crt
    - --oidc-client-id=kubernetes
    - --oidc-groups-claim=groups
    - --oidc-issuer-url=https://keycloak.example.org/auth/realms/kubernetes
    - --oidc-username-claim=email
...

Actualizamos la configuración de kubeadm en el clúster:

kubeadm config

kubectl edit -n kube-system configmaps kubeadm-config


...
data:
  ClusterConfiguration: |
    apiServer:
      extraArgs:
        oidc-ca-file: /var/lib/minikube/certs/My_Root.crt
        oidc-client-id: kubernetes
        oidc-groups-claim: groups
        oidc-issuer-url: https://keycloak.example.org/auth/realms/kubernetes
        oidc-username-claim: email
...

Configuración del auth-proxy

Para proteger su aplicación web, se puede utilizar keycloak gatekeeper. Además de que este proxy inverso autorizará al usuario antes de mostrar la página, también pasará la información sobre usted a la aplicación final en las cabeceras. De este modo, si su aplicación soporta OpenID, el usuario se autenticará de inmediato. Veremos esto con el ejemplo de Kubernetes Dashboard.

Instalación de Kubernetes Dashboard


helm install stable/kubernetes-dashboard --name dashboard -f values_dashboard.yaml

values_dashboard.yaml

enableInsecureLogin: true
service:
  externalPort: 80
rbac:
  clusterAdminRole: true
  create: true
serviceAccount:
  create: true
  name: 'dashboard-test'

Configuración de permisos:

Crearemos un ClusterRoleBinding que otorgará permisos de administrador de clúster (ClusterRole estándar cluster-admin) a los usuarios que estén en el grupo DataOPS.


kubectl apply -f rbac.yaml

rbac.yaml


apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: dataops_group
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: cluster-admin
subjects:
- apiGroup: rbac.authorization.k8s.io
  kind: Group
  name: DataOPS

Instalación de keycloak gatekeeper:


helm repo add gabibbo97 https://gabibbo97.github.io/charts/
helm repo update
helm install gabibbo97/keycloak-gatekeeper --version 2.1.0 --name keycloak-gatekeeper -f values_proxy.yaml

values_proxy.yaml



# Включаем ingress
ingress:
  enabled: true
  annotations:
    kubernetes.io/ingress.class: nginx
  path: /
  hosts:
    - kubernetes-dashboard.example.org
  tls:
   - secretName: tls-keycloak
     hosts:
       - kubernetes-dashboard.example.org

# Говорим где мы будем авторизовываться у OIDC провайдера
discoveryURL: "https://keycloak.example.org/auth/realms/kubernetes"
# Имя клиента которого мы создали в Keycloak
ClientID: "kubernetes"
# Secret который я просил записать
ClientSecret: "c6ec03b8-d0b8-4cb6-97a0-03becba1d727"
# Куда перенаправить в случае успешной авторизации. Формат <SCHEMA>://<SERVICE_NAME>.><NAMESAPCE>.<CLUSTER_NAME>
upstreamURL: "http://dashboard-kubernetes-dashboard.default.svc.cluster.local"
# Пропускаем проверку сертификата, если у нас самоподписанный
skipOpenidProviderTlsVerify: true
# Настройка прав доступа, пускаем на все path если мы в группе DataOPS
rules:
  - "uri=/*|groups=DataOPS"

Después de esto, al intentar acceder a kubernetes-dashboard.example.org, será redirigido a Keycloak y, en caso de una autenticación exitosa, accederemos al Dashboard ya autenticado.

Instalación de gangway

Para mayor comodidad, se puede añadir gangway, que generará un archivo de configuración para kubectl, con el cual ya bajo nuestro usuario accederemos a Kubernetes.


helm install --name gangway stable/gangway -f values_gangway.yaml

values_gangway.yaml


gangway:
  # Nombre del clúster
  clusterName: "my-k8s"
  # Donde se encuentra nuestro proveedor OIDC
  authorizeURL: "https://keycloak.example.org/auth/realms/kubernetes/protocol/openid-connect/auth"
  tokenURL: "https://keycloak.example.org/auth/realms/kubernetes/protocol/openid-connect/token"
  audience: "https://keycloak.example.org/auth/realms/kubernetes/protocol/openid-connect/userinfo"
  # Teóricamente, aquí se pueden agregar grupos que hemos asignado
  scopes: ["openid", "profile", "email", "offline_access"]
  redirectURL: "https://gangway.example.org/callback"
  # Nombre del cliente
  clientID: "kubernetes"
  # Secreto
  clientSecret: "c6ec03b8-d0b8-4cb6-97a0-03becba1d727"
  # Si se deja el valor predeterminado, el nombre de usuario será utilizado <b>Primer nombre</b> <b>Segundo nombre</b>, y en "sub" su inicio de sesión
  usernameClaim: "sub"
  # Nombre de dominio o dirección IP del servidor API
  apiServerURL: "https://192.168.99.111:8443"

# Activamos Ingress
ingress:
  enabled: true
  annotations:
    kubernetes.io/ingress.class: nginx
    nginx.ingress.kubernetes.io/proxy-buffer-size: "64k"
  path: / 
  hosts:
  - gangway.example.org
  tls:
  - secretName: tls-keycloak
    hosts:
      - gangway.example.org

# Si utilizamos un certificado autofirmado, debe especificarse el certificado raíz (público).
trustedCACert: |-
 -----BEGIN CERTIFICATE-----
 MIIDVzCCAj+gAwIBAgIBATANBgkqhkiG9w0BAQsFADA1MQswCQYDVQQGEwJVUzEQMA4GA1UEChMHRGF0YU9QUzEUMBIGA1UEAxMLbXkgcm9vdCBrZXkwHhcNMjAwMjE0MDkxODAwWhcNMzAwMjE0MDkxODAwWjA1MQswCQYDVQQGEwJVUzEQMA4GA1UEChMHRGF0YU9QUzEUMBIGA1UEAxMLbXkgcm9vdCBrZXkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDyP749PqqIRwNSqaK6qr0Zsi03G4PTCUlgaYTPZuMrwUVPK8xX2dWWs9MPRMOdXpgr8aSTZnVfmelIlVz4D7o2vK5rfmAe9GPcK0WbwKwXyhFU0flS9sU/g46ogHFrk03SZxQAeJhMLfEmAJm8LF5HghtGDs3t4uwGsB95o+lqPLiBvxRB8ZS3jSpYpvPgXAuZWKdZUQ3UUZf0X3hGLp7uIcIwJ7i4MduOGaQEO4cePeEJy9aDAO6qV78YmHbyh9kaW+1DL/Sgq8NmTgHGV6UOnAPKHTnMKXl6KkyUz8uLBGIdVhPxrlzG1EzXresJbJenSZ+FZqm3oLqZbw54Yp5hAgMBAAGjcjBwMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFHISTOU/6BQqqnOZj+1xJfxpjiG0MAsGA1UdDwQEAwIBBjARBglghkgBhvhCAQEEBAMCAAcwHgYJYIZIAYb4QgENBBEWD3hjYSBjZXJ0aWZpY2F0ZTANBgkqhkiG9w0BAQsFAAOCAQEAj7HC8ObibwOLT4ZYmISJZwub9lcE0AZ5cWkPW39j/syhdbbqjK/6jy2D3WUEbR+s1Vson5Ov7JhN5In2yfZ/ByDvBnoj7CP8Q/ZMjTJgwN7j0rgmEb3CTZvnDPAz8Ijw3FP0cjxfoZ1Z0V2F44Ry7gtLJWr06+MztXVyto3aIz1/XbMQnXYlzc3c3B5yUQIy44Ce5aLRVsAjmXNqVRmDJ2QPNLicvrhnUJsO0zFWI+zZ2hc4Ge1RotCrjfOc9hQY63jZJ17myCZ6QCD7yzMzAob4vrgmkD4q7tpGrhPY/gDcE+lUNhC7DO3l0oPy2wsnT2TEn87eyWmDiTFG9zWDew==
 -----END CERTIFICATE-----

Se ve algo así. Permite tanto descargar el archivo de configuración como generarlo utilizando un conjunto de comandos:

Conectando la autorización de Active Directory a Kubernetes mediante Keycloak

Fuente: habr.com

Compra un hosting fiable para sitios web con protección contra DDoS, servidores VPS VDS 🔥 Compra un hosting fiable para sitios web con protección contra DDoS, servidores VPS VDS | ProHoster