Прикручуємо ActiveDirectory авторизацію до Kubernetes за допомогою Keycloak

Ця стаття написана з метою розширити вже існуючу, але розповідає про особливості зв'язки саме з Microsoft ActiveDirectory, а також доповнює її.

У цій статті я розповім як встановити та налаштувати:

  • Плащ-ключ - Це проект з відкритим вихідним кодом. Який забезпечує єдину точку входу додатків. Працює з безліччю протоколів, у тому числі з LDAP та OpenID які нас цікавлять.
  • Keycloak gatekeeper — реверс проксі-програми, що дозволяє інтегрувати авторизацію через Keycloak.
  • Gangway - Додаток которе генерує конфіг для kubectl за допомогою якого через OpenID можна авторизуватися та підключитися до Kubernetes API.

Як працюють права у Kubernetes.

Управляти правами користувача/груп ми можемо за допомогою RBAC, про це вже створено купу статей, не буду докладно на цьому зупинятися. Проблема в тому, що ви можете використовуючи RBAC для того, щоб обмежити права користувача, але Kubernetes не чого не знає про користувачів. Виходить, що потрібен механізм доставки користувача в Kubernetes. Для цього ми додамо в Kuberntes OpenID провайдера, який і буде говорити про те, що такий користувач дійсно існує, а права йому вже видасть сам Kubernetes.

Підготовка

  • Вам знадобиться кластер Kubernetes або minikube
  • Active Directory
  • Домени:
    keycloak.example.org
    kubernetes-dashboard.example.org
    gangway.example.org
  • Сертифікат для доменів або самопідписаний сертифікат

Детально зупинятися на тому, як створювати самопідписані сертифікат я не буду, треба створити 2 сертифікати, це кореневий(Центр сертифікації) і wildcard клієнтський для домену *.example.org

Після того як ви отримаєте/випишіть сертифікати, клієнтську треба додати в Kubernetes, для цього створюємо для нього secret:

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

Далі ми будемо його використовувати для нашого Ingress контролера

Установка Keycloak

Я вирішив що найпростіше використовувати готові рішення для цього, а саме helm chart-и.

Встановлюємо репозиторій та оновлюємо його:

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

Створюємо файл keycloak.yml з таким вмістом:

keycloak.yml

keycloak:
  # Имя администратора
  username: "test_admin"
  # Пароль администратор  
  password: "admin"
  # Эти флаги нужны что бы позволить загружать в Keycloak скрипты прямо через web морду. Это нам 
  понадобиться что бы починить один баг, о котором ниже.
  extraArgs: "-Dkeycloak.profile.feature.script=enabled -Dkeycloak.profile.feature.upload_scripts=enabled" 
  # Включаем ingress, указываем имя хоста и сертификат который мы предварительно сохранили в 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 для своей работы требует базу данных, в тестовых целях я разворачиваю Postgresql прямо в Kuberntes, в продакшене так лучше не делать!
  persistence:
    deployPostgres: true
    dbVendor: postgres

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

Налаштування федерації

Далі заходимо до веб-інтерфейсу keycloak.example.org

У лівому кутку натискаємо Add realm

ключ
значення

ІМ'Я
кубернети

Показати ім'я
Кубернетес

Вимикаємо перевірку підтвердження email користувача:
Client scopes -> Email -> Mappers -> Email verified (Delete)

Налаштовуємо федерацію для імпорту користувачів з ActiveDirectory, я залишу нижче скріншоти думаю так буде зрозуміліше.

User federation -> Add provider ... -> ldap

Налаштування федераціїПрикручуємо ActiveDirectory авторизацію до Kubernetes за допомогою Keycloak
Прикручуємо ActiveDirectory авторизацію до Kubernetes за допомогою Keycloak

Якщо все добре, то після натискання кнопки Synchronize all users Ви введіть повідомлення про успішний імпорт користувачів.

Далі треба замапити наші групи

User federation -> ldap_localhost -> Mappers -> Create

Створення маппераПрикручуємо ActiveDirectory авторизацію до Kubernetes за допомогою Keycloak

Налаштування клієнта

Потрібно створити клієнта, в поняттях Keycloak це додаток, який у нього авторизуватиметься. Важливі пункти виокремлю на скріншоті червоним.

Clients -> Create

Налаштування клієнтаПрикручуємо ActiveDirectory авторизацію до Kubernetes за допомогою Keycloak

Створимо scoupe для груп:

Client Scopes -> Create

Створення scoupeПрикручуємо ActiveDirectory авторизацію до Kubernetes за допомогою Keycloak

І налаштуємо mapper для них:

Client Scopes -> groups -> Mappers -> Create

МаперПрикручуємо ActiveDirectory авторизацію до Kubernetes за допомогою Keycloak

Додаємо мапінг наших груп у Default Client Scopes:

Clients -> kubernetes -> Client Scopes -> Default Client Scopes
вибираємо групи в Available Client Scopes, натискаємо Додати вибране

Отримуємо secret(і записуємо його куди нитку) який ми будемо використовувати для авторизації в Keycloak:

Clients -> kubernetes -> Credentials -> Secret
На цьому налаштування закінчено, але у мене виникла помилка, коли після успішної авторизації я отримував помилку 403. Баг репорт.

Фікс:

Client Scopes -> roles -> Mappers -> Create

КартографПрикручуємо ActiveDirectory авторизацію до Kubernetes за допомогою Keycloak

Код скрипту

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

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

Налаштування Kubernetes

Нам треба вказати, де лежить наш кореневий сертифікат від сайту, і де знаходиться провайдер OIDC.
Для цього редагуємо файл /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
...

Обновляємо kubeadm конфіг у кластері:

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

Налаштування auth-proxy

Для захисту вашого веб-додаток можна використовувати keycloak gatekeeper. Крім того що даний реверс проксі авторизуватиме користувача перед тим як показати сторінку, так ще й передавати кінцевому додатку інформацію про вас в заголовках. Тим самим, якщо ваша програма підтримує OpenID, то користувач відразу авторизується. Розглянемо на прикладі Kubernetes Dashboard

Установка 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'

Налаштування прав доступу:

Створимо ClusterRoleBinding, який буде давати права адміну кластера (стандартна ClusterRole cluster-admin) для користувачів, що перебувають у групі 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

Установка 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"

Після цього при спробі зайти на kubernetes-dashboard.example.org, відбудеться перенаправлення на Keycloak і у разі успішної авторизації ми потрапимо в Dashboard вже залогіненим.

Встановлення gangway

Для зручності можна додати gangway, який буде генерувати файл конфігу для kubectl, за допомогою якого ми вже під нашим користувачем потрапимо в Kubernetes.


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

values_gangway.yaml


gangway:
  # Произвольное имя кластера
  clusterName: "my-k8s"
  # Где у нас 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"
  # Теоритически сюда можно добавить groups которые мы замапили
  scopes: ["openid", "profile", "email", "offline_access"]
  redirectURL: "https://gangway.example.org/callback"
  # Имя клиента
  clientID: "kubernetes"
  # Секрет
  clientSecret: "c6ec03b8-d0b8-4cb6-97a0-03becba1d727"
  # Если оставить дефолтное значние, то за имя пользователя будет братья <b>Frist name</b> <b>Second name</b>, а при "sub" его логин
  usernameClaim: "sub"
  # Доменное имя или IP адресс API сервера
  apiServerURL: "https://192.168.99.111:8443"

# Включаем 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

# Если используем самоподписанный сертификат, то его(открытый корневой сертификат) надо указать.
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-----

Виглядає приблизно так. Дозволяє як відразу завантажити файл конфіга так і сформувати його, використовуючи набір команд:

Прикручуємо ActiveDirectory авторизацію до Kubernetes за допомогою Keycloak

Джерело: habr.com

Додати коментар або відгук