Integrujemy autoryzację ActiveDirectory z Kubernetes przy użyciu Keycloak

Artykuł ten został napisany w celu rozszerzenia istniejącej konfiguracji, ale opisuje szczegóły integracji z Microsoft Active Directory oraz ją uzupełnia.

W tym artykule opowiem, jak zainstalować i skonfigurować:

  • Keycloak — to projekt o otwartym kodzie źródłowym, który zapewnia jednolity punkt wejścia dla aplikacji. Działa z wieloma protokołami, w tym z LDAP i OpenID, które nas interesują.
  • Keycloak gatekeeper — to aplikacja działająca jako reverse proxy, umożliwiająca integrację autoryzacji przez Keycloak.
  • Gangway — aplikacja, która generuje konfigurację dla kubectl, dzięki której można się autoryzować przez OpenID i podłączyć do API Kubernetes.

Jak działają uprawnienia w Kubernetes.

Zarządzać uprawnieniami użytkowników/grup możemy za pomocą RBAC; na ten temat istnieje już wiele artykułów, więc nie będę się na tym szczegółowo skupiać. Problem polega na tym, że możemy użyć RBAC do ograniczania uprawnień użytkowników, ale Kubernetes nic nie wie o użytkownikach. W związku z tym potrzebny jest mechanizm dostarczania informacji o użytkownikach do Kubernetes. W tym celu dodamy do Kubernetes dostawcę OpenID, który potwierdzi, że dany użytkownik rzeczywiście istnieje, a uprawnienia przyzna sam Kubernetes.

Przygotowanie

  • Będziesz potrzebować klastra Kubernetes lub minikube
  • Active Directory
  • Domeny:
    keycloak.example.org
    kubernetes-dashboard.example.org
    gangway.example.org
  • Certyfikat dla domen lub certyfikat samopodpisany

Nie będę szczegółowo omawiać, jak tworzyć certyfikaty samopodpisane; należy stworzyć 2 certyfikaty: główny (Centrum Certyfikacji) oraz wildcard dla domeny *.example.org.

Po uzyskaniu/wypisaniu certyfikatów, certyfikat klienta należy dodać do Kubernetes; w tym celu tworzymy jego secret:

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

Następnie będziemy go używać dla naszego kontrolera Ingress.

Instalacja Keycloak

Postanowiłem, że najłatwiej będzie wykorzystać gotowe rozwiązania, a dokładniej helm chart-y.

Dodajemy repozytorium i aktualizujemy je:

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

Tworzymy plik keycloak.yml z następującą zawartością:

keycloak.yml

keycloak:
  # Nazwa administratora
  username: "test_admin"
  # Hasło administratora  
  password: "admin"
  # Te flagi są potrzebne, aby umożliwić ładowanie skryptów do Keycloak bezpośrednio przez interfejs webowy. Będzie to 
  potrzebne, aby naprawić pewien błąd, o którym mowa poniżej.
  extraArgs: "-Dkeycloak.profile.feature.script=enabled -Dkeycloak.profile.feature.upload_scripts=enabled" 
  # Włączamy ingress, podajemy nazwę hosta i certyfikat, który wcześniej zapisaliśmy w secrets
  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 wymaga bazy danych do swojej pracy, w celach testowych uruchamiam Postgresql bezpośrednio w Kubernets, w produkcji lepiej tego nie robić!
  persistence:
    deployPostgres: true
    dbVendor: postgres

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

Konfigurowanie federacji

Następnie logujemy się do interfejsu webowego keycloak.example.org

W lewym rogu klikamy Dodaj realm

Klucz
@Value

Nazwa
kubernetes

Nazwa wyświetlana
Kubernetes

Wyłączamy weryfikację potwierdzenia e-maila użytkownika:
Client scopes —> Email —> Mappers —> Email verified (Usuń)

Konfigurujemy federację do importu użytkowników z Active Directory, poniżej umieszczę zrzuty ekranu, myślę że tak będzie jaśniej.

User federation —> Dodaj dostawcę… —> ldap

Konfigurowanie federacjiIntegrujemy autoryzację ActiveDirectory z Kubernetes przy użyciu Keycloak
Integrujemy autoryzację ActiveDirectory z Kubernetes przy użyciu Keycloak

Jeśli wszystko pójdzie dobrze, po naciśnięciu przycisku Synchronizuj wszystkich użytkowników zobaczysz komunikat o pomyślnym imporcie użytkowników.

Następnie musimy zamapować nasze grupy

User federation —> ldap_localhost —> Mappers —> Utwórz

Tworzenie mapperaIntegrujemy autoryzację ActiveDirectory z Kubernetes przy użyciu Keycloak

Konfiguracja klienta

Musimy stworzyć klienta, w pojęciu Keycloak to aplikacja, która będzie się w nim autoryzować. Ważne punkty zaznaczę na zrzucie ekranu na czerwono.

Klienci —> Utwórz

Konfiguracja klientaIntegrujemy autoryzację ActiveDirectory z Kubernetes przy użyciu Keycloak

Stworzymy scoupe dla grup:

Client Scopes —> Utwórz

Tworzenie scoupeIntegrujemy autoryzację ActiveDirectory z Kubernetes przy użyciu Keycloak

I skonfigurujemy mapper dla nich:

Client Scopes —> groups —> Mappers —> Utwórz

MapperIntegrujemy autoryzację ActiveDirectory z Kubernetes przy użyciu Keycloak

Dodajemy mapowanie naszych grup w Default Client Scopes:

Klienci —> kubernetes —> Client Scopes —> Default Client Scopes
Wybieramy groups do Dostępne zakresy klienta, klikamy Dodaj wybrane

Zyskujemy secret (i zapisujemy go gdzieś), który będziemy używać do autoryzacji w Keycloak:

Klienci —> kubernetes —> Credentials —> Secret
Na tym konfiguracja się kończy, ale napotkałem błąd, gdy po pomyślnej autoryzacji otrzymywałem błąd 403. Raport błędu.

Poprawka:

Client Scopes —> roles —> Mappers —> Utwórz

MapperIntegrujemy autoryzację ActiveDirectory z Kubernetes przy użyciu Keycloak

Kod skryptu

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

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

Konfiguracja Kubernetes

Musimy określić, gdzie znajduje się nasz certyfikat główny od witryny, i gdzie znajduje się dostawca OIDC.
W tym celu edytujemy plik \/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
...

Aktualizujemy konfigurację kubeadm w klastrze:

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

Konfiguracja auth-proxy

Aby zabezpieczyć swoją aplikację internetową, można użyć Keycloak Gatekeeper. Oprócz tego, że ten serwer proxy będzie autoryzował użytkownika przed pokazaniem strony, przekazuje również aplikacji końcowej informacje o użytkowniku w nagłówkach. Dzięki temu, jeśli twoja aplikacja obsługuje OpenID, użytkownik jest natychmiast autoryzowany. Przyjrzyjmy się temu na przykładzie Kubernetes Dashboard.

Instalacja 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'

Konfiguracja uprawnień:

Stwórzmy ClusterRoleBinding, który nada uprawnienia administratora klastra (standardowa ClusterRole cluster-admin) dla użytkowników należących do grupy 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

Instalacja 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"

Po tym, gdy spróbujesz wejść na kubernetes-dashboard.example.org, nastąpi przekierowanie do Keycloak, a po pomyślnej autoryzacji trafić w Dashboard jako zalogowany.

Instalacja gangway

Dla wygody można dodać gangway, który generuje plik konfiguracyjny dla kubectl, dzięki któremu jako nasz użytkownik wejdziemy do Kubernetes.


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

values_gangway.yaml


gangway:
  # Dowolna nazwa klastra
  clusterName: "my-k8s"
  # Gdzie znajduje się nasz dostawca 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"
  # Teoretycznie można tutaj dodać grupy, które zmapowaliśmy
  scopes: ["openid", "profile", "email", "offline_access"]
  redirectURL: "https://gangway.example.org/callback"
  # Nazwa klienta
  clientID: "kubernetes"
  # Sekret
  clientSecret: "c6ec03b8-d0b8-4cb6-97a0-03becba1d727"
  # Jeśli zostawimy domyślną wartość, to jako nazwę użytkownika weźmie "sub" <b>Imię</b> <b>Nazwisko</b>, a przy "sub" jego login
  usernameClaim: "sub"
  # Nazwa domeny lub adres IP serwera API
  apiServerURL: "https://192.168.99.111:8443"

# Włączamy 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

# Jeśli używamy certyfikatu samopodpisanego, to należy podać jego (publiczny certyfikat) korzenia.
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-----

Wygląda to mniej więcej tak. Pozwala od razu pobrać plik konfiguracyjny oraz wygenerować go z zestawem poleceń:

Integrujemy autoryzację ActiveDirectory z Kubernetes przy użyciu Keycloak

Źródło: habr.com

Kup solidny hosting stron z ochroną przed DDoS, serwery VPS VDS 🔥 Kup solidny hosting stron z ochroną przed DDoS, serwery VPS VDS | ProHoster