Colleghiamo l'autenticazione ActiveDirectory a Kubernetes tramite Keycloak

Quest'articolo è scritto con l'obiettivo di espandere già esistente, ma tratta delle peculiarità del collegamento con Microsoft Active Directory, e la integra.

In questo articolo spiegherò come installare e configurare:

  • Keycloak Keycloak è un progetto open source. Che fornisce un punto di accesso unico per le applicazioni. Supporta vari protocolli, tra cui LDAP e OpenID, che ci interessano.
  • Keycloak gatekeeper è un'applicazione reverse proxy che consente di integrare l'autorizzazione tramite Keycloak.
  • Gangway è un'applicazione che genera una configurazione per kubectl tramite la quale è possibile autenticarsi e collegarsi all'API di Kubernetes usando OpenID.

Come funzionano i permessi in Kubernetes.

Possiamo gestire i permessi per utenti/gruppi tramite RBAC, di cui sono già stati scritti molti articoli, quindi non mi fermerò qui a discutere in dettaglio. Il problema è che puoi usare RBAC per limitare i permessi di un utente, ma Kubernetes non ha informazioni sugli utenti. Risulta quindi necessario un meccanismo per portare l'utente in Kubernetes. A questo scopo, aggiungeremo a Kubernetes un provider OpenID che confermerà che tale utente esiste realmente, mentre i permessi saranno gestiti direttamente da Kubernetes.

Preparazione

  • Avrai bisogno di un cluster Kubernetes o di minikube.
  • Active Directory
  • Domini:
    keycloak.example.org
    kubernetes-dashboard.example.org
    gangway.example.org
  • Certificato per i domini o un certificato autofirmato

Non mi soffermerò su come creare certificati autofirmati, è necessario generare 2 certificati: uno radice (Centro di certificazione) e uno wildcard client per il dominio *.example.org.

Dopo aver ottenuto/i certificati, il certificato client deve essere aggiunto a Kubernetes, per questo creiamo un secret:

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

Successivamente lo utilizzeremo per il nostro controller Ingress.

Installazione di Keycloak

Ho deciso che fosse più semplice utilizzare soluzioni pronte all'uso, come i chart helm.

Aggiungiamo il repository e lo aggiorniamo:

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

Creiamo un file keycloak.yml con il seguente contenuto:

keycloak.yml

keycloak:
  # Nome dell'amministratore
  username: "test_admin"
  # Password dell'amministratore  
  password: "admin"
  # Questi flag sono necessari per consentire il caricamento di script su Keycloak tramite l'interfaccia web. Questo ci
  servirà per risolvere un bug, di cui parlerò di seguito.
  extraArgs: "-Dkeycloak.profile.feature.script=enabled -Dkeycloak.profile.feature.upload_scripts=enabled" 
  # Abilitare ingress, specificando il nome host e il certificato che abbiamo precedentemente salvato nei segreti
  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 richiede un database per funzionare, per scopi di test installo Postgresql direttamente in Kubernetes, in produzione non è consigliato farlo!
  persistence:
    deployPostgres: true
    dbVendor: postgres

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

Configurazione della federazione

Successivamente accediamo all'interfaccia web. keycloak.example.org

In alto a sinistra clicchiamo su Aggiungi realm

Chiave
Valore

Name
kubernetes

Nome visualizzato
Kubernetes

Disabilitiamo la verifica dell'email per gli utenti:
Client scopes —> Email —> Mappers —> Email verified (Elimina)

Configuriamo la federazione per importare utenti da Active Directory, lascerò di seguito degli screenshot per una maggiore chiarezza.

User federation —> Aggiungi provider… —> ldap

Configurazione della federazioneColleghiamo l'autenticazione ActiveDirectory a Kubernetes tramite Keycloak
Colleghiamo l'autenticazione ActiveDirectory a Kubernetes tramite Keycloak

Se va tutto bene, dopo aver premuto il bottone Sincronizza tutti gli utenti vedrai un messaggio di importazione riuscita degli utenti.

Ora dobbiamo mappare i nostri gruppi.

User federation —> ldap_localhost —> Mappers —> Crea

Creazione di un mapperColleghiamo l'autenticazione ActiveDirectory a Kubernetes tramite Keycloak

Configurazione del client

Devi creare un client, nel contesto di Keycloak, questo rappresenta l'applicazione che sarà autorizzata. Sottolineerò i punti importanti nello screenshot in rosso.

Clients —> Crea

Configurazione del clientColleghiamo l'autenticazione ActiveDirectory a Kubernetes tramite Keycloak

Creiamo un scope per i gruppi:

Client Scopes —> Crea

Creazione di uno scopeColleghiamo l'autenticazione ActiveDirectory a Kubernetes tramite Keycloak

E configureremo il mapper per essi:

Client Scopes —> groups —> Mappers —> Crea

MapperColleghiamo l'autenticazione ActiveDirectory a Kubernetes tramite Keycloak

Aggiungiamo il mapping dei nostri gruppi negli Default Client Scopes:

Clients —> kubernetes —> Client Scopes —> Default Client Scopes
Selezioniamo groups in Scope client disponibili, facciamo clic su Aggiungi selezionati

Otteniamo il segreto (e lo annotiamo da qualche parte) che useremo per l'autenticazione in Keycloak:

Clients —> kubernetes —> Credentials —> Secret
A questo punto la configurazione è completa, ma ho riscontrato un errore quando, dopo un'autenticazione riuscita, ricevevo un errore 403. Rapporto del bug.

Correzione:

Client Scopes —> roles —> Mappers —> Crea

MapperColleghiamo l'autenticazione ActiveDirectory a Kubernetes tramite Keycloak

Codice dello script

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

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

Configurazione di Kubernetes

Dobbiamo specificare dove si trova il nostro certificato radice del sito e dove si trova il provider OIDC.
Per questo, modifichiamo il file /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
...

Aggiorniamo la configurazione di kubeadm nel cluster:

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
...

Configurazione auth-proxy

Per proteggere la tua applicazione web, puoi utilizzare Keycloak Gatekeeper. Oltre a svolgere la funzione di reverse proxy che autorizza l'utente prima di mostrare la pagina, trasferisce anche le informazioni riguardo a te nell'intestazione all'applicazione finale. In questo modo, se la tua applicazione supporta OpenID, l'utente verrà autenticato immediatamente. Consideriamo l'esempio del Kubernetes Dashboard.

Installazione del 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'

Configurazione dei permessi di accesso:

Creiamo un ClusterRoleBinding che concederà i diritti di amministratore del cluster (la ClusterRole standard cluster-admin) per gli utenti che appartengono al gruppo 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

Installazione di 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"

Dopo questo, quando tentiamo di accedere a kubernetes-dashboard.example.org, ci sarà un reindirizzamento a Keycloak e, in caso di autorizzazione riuscita, arriveremo al Dashboard già autenticati.

Installazione di Gangway

Per comodità, possiamo aggiungere Gangway, che genererà un file di configurazione per kubectl, attraverso il quale potremo accedere a Kubernetes con il nostro utente.


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

values_gangway.yaml


gangway:
  # Nome del cluster personalizzato
  clusterName: "my-k8s"
  # Dove si trova il nostro provider 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"
  # Teoricamente qui possiamo aggiungere i gruppi che abbiamo mappato
  scopes: ["openid", "profile", "email", "offline_access"]
  redirectURL: "https://gangway.example.org/callback"
  # Nome del client
  clientID: "kubernetes"
  # Segreto
  clientSecret: "c6ec03b8-d0b8-4cb6-97a0-03becba1d727"
  # Se lasciato il valore predefinito, il nome utente verrà preso da <b>Nome di battesimo</b> <b>Cognome</b>, e con "sub" il suo nome utente
  usernameClaim: "sub"
  # Nome di dominio o indirizzo IP del server API
  apiServerURL: "https://192.168.99.111:8443"

# Attiviamo l'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

# Se utilizziamo un certificato autofirmato, è necessario specificare il certificato radice pubblico.
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-----

Sembra più o meno così. Permette sia di scaricare immediatamente il file di configurazione sia di generarlo utilizzando un insieme di comandi:

Colleghiamo l'autenticazione ActiveDirectory a Kubernetes tramite Keycloak

Fonte: habr.com

Acquista hosting affidabile per siti web con protezione DDoS, VPS VDS server 🔥 Acquista hosting affidabile per siti web con protezione DDoS, VPS VDS server | ProHoster