Интеграция IAM с Kubernetes строится вокруг OIDC. kube-apiserver получает от провайдера идентификации (Keycloak, Dex или Azure AD) подписанный JWT, проверяет подпись по discovery-документу, достаёт из claims имя пользователя и группы, а привязки RBAC превращают эти группы в права. Пользователь входит в кластер через kubelogin, CI/CD-пайплайн работает через сервисный аккаунт с минимальным набором прав.
Результат настройки: вход по корпоративной учётной записи с MFA, отзыв доступа через деактивацию в IdP, автоматическая выдача прав по группам AD, ротация токенов без ручных действий. Базовый сценарий с одним IdP и одним кластером закрывается за несколько часов: флаги API-сервера, kubeconfig, две RBAC-привязки, один ServiceAccount для пайплайна.
Порядок разбора: выбор провайдера, флаги kube-apiserver, настройка kubelogin, привязка прав, сервисные аккаунты для CI/CD, диагностика ошибок 401 и 403, ротация учётных данных, подключение LDAP и Active Directory. Примеры конфигураций рассчитаны на копирование с адаптацией под свои realm, группы и namespace.
Зачем интегрировать IAM с Kubernetes: проблемы встроенной аутентификации
Встроенные механизмы Kubernetes рассчитаны на небольшой круг доверенных администраторов. Как только кластером пользуются три команды, а состав инженеров меняется, сертификаты и статические токены начинают создавать операционные проблемы.
Ограничения сертификатов и статических токенов
kubeadm по умолчанию выдаёт клиентские сертификаты сроком на 1 год. Имя пользователя берётся из CN, группы из поля O. Сертификат нельзя отозвать: kube-apiserver не проверяет CRL для клиентских сертификатов. Закрыть доступ уволенному сотруднику можно только перевыпуском CA и раздачей новых kubeconfig всем, у кого есть доступ. На практике это означает, что сертификат живёт до конца года.
Статические токены задаются флагом --token-auth-file. Файл формата token,user,uid,"group1,group2" читается один раз при старте API-сервера, токен действует бессрочно, а правка списка требует перезапуска kube-apiserver. Bootstrap-токены решают другую задачу: они нужны для подключения нод, а не людей.
Итог: нет централизованного отзыва, нет привязки к корпоративным группам, аудит входов ограничен логами API-сервера. При ротации команды каждый новый инженер получает персональный сертификат, а уволенный сохраняет рабочий доступ.
Преимущества OIDC: единая точка входа и автоматическая ротация
OIDC переносит аутентификацию в IdP. Сотрудник вводит пароль и второй фактор на стороне провайдера и получает id_token (JWT со сроком жизни обычно 5-60 минут) плюс refresh token. kube-apiserver проверяет подпись токена по публичным ключам из discovery-документа, сверяет audience с --oidc-client-id и берёт имя пользователя и группы из claims.
Права привязываются к группам IdP, а не к отдельным людям. Новый сотрудник получает доступ в день добавления в группу. Увольнение блокирует вход после истечения текущего id_token, а в Keycloak сессию можно отозвать принудительно. Все входы фиксируются в IdP и в audit-логах API-сервера.
Kubernetes поддерживает такую схему нативно через флаги --oidc-*. В версиях 1.30 и новее доступна структурированная конфигурация аутентификации (--authentication-config) с JWT authenticators: несколько провайдеров одновременно, CEL-правила проверки claims, гибкий маппинг имени и групп. Классические флаги при этом продолжают работать.
Выбор провайдера идентификации: Keycloak, Dex или Azure AD
Все три решения выдают совместимые OIDC-токены. Разница в том, где хранятся пользователи и сколько ресурсов уходит на сопровождение IdP.
Keycloak: функциональность и сложность настройки
Keycloak работает на Java (Quarkus) и требует примерно 1-2 ГБ RAM на инстанс плюс PostgreSQL для хранения конфигурации и сессий. Он подключается к LDAP и Active Directory через User Federation, умеет объединять несколько источников пользователей (identity brokering), поддерживает OIDC и SAML, тонко настраивает маппинг claims через mappers.
Плата за гибкость: больше сущностей в админ-консоли, обновления, бэкапы базы, контроль кеша федерации. Keycloak выбирают, когда компания строит единый SSO для внутренних сервисов, а Kubernetes становится одним из потребителей.
Dex: легковесный OIDC-провайдер для Kubernetes
Dex написан на Go, собирается в один бинарник, не хранит пользователей и пароли. Ему достаточно config.yaml с описанием connectors: LDAP, GitHub, GitLab, SAML, Microsoft, другой OIDC. В кластере Dex занимает Deployment с 50-100 МБ памяти, а из хранилища ему нужен только бэкенд для refresh-токенов (etcd или CRD Kubernetes).
Ограничения: нет админ-панели для управления пользователями, нет самостоятельной регистрации, пароли через Dex не меняются. Провайдер выступает мостом между корпоративным каталогом и Kubernetes, что закрывает задачу доступа к кластеру с минимальными затратами.
Azure AD: интеграция для организаций Microsoft
Azure AD (сейчас Microsoft Entra ID) подходит компаниям на Microsoft 365. Настройка начинается с App registration: вы получаете client ID, добавляете redirect URI для kubelogin (http://localhost:8000 и http://localhost:18000), включаете группы в Token configuration.
Нюанс с группами: при большом количестве групп claim groups может превысить лимит и превратиться в ссылку на Microsoft Graph (group overage). Решение: выбирать в Token configuration только группы, назначенные приложению, или использовать app roles. Условный доступ и MFA настраиваются на стороне Entra ID без доработок в кластере.
| Критерий | Keycloak | Dex | Azure AD (Entra ID) |
|---|---|---|---|
| Развёртывание | Своё: контейнер и PostgreSQL, 1-2 ГБ RAM | Один бинарник или Deployment, 50-100 МБ RAM, без базы пользователей | Облачный сервис, разворачивать нечего |
| Хранение пользователей | Локальная БД плюс федерация LDAP/AD | Только upstream-каталог | Облачный каталог Microsoft |
| Подключение LDAP/AD | User Federation из коробки | LDAP connector | Через Entra Connect или cloud sync |
| Управление группами | Маппинг групп LDAP, локальные группы, mappers | Группы читаются из каталога при входе | Groups claim, app roles, назначение приложению |
| Стоимость | Бесплатно, оплата ресурсами и временем | Бесплатно, минимум ресурсов | Зависит от лицензий Microsoft 365 |
| Когда выбирать | Разнородная инфраструктура, несколько источников пользователей, SSO для сервисов | Есть upstream IdP, нужен только OIDC-мостик для кластера | Компания уже использует Microsoft 365 и Entra ID |
Для команды из 5-20 человек с одним AD разумный старт: Dex и один config.yaml. Keycloak берут, когда нужны SSO для внутренних сервисов, несколько источников пользователей и тонкие политики. Azure AD оптимален, если компания уже платит за Microsoft 365 и не хочет держать собственный IdP.
Для стенда, где можно безопасно ломать конфигурацию, подойдёт managed Kubernetes в облаке, например Timeweb Cloud: серверы, VDS/VPS, базы данных и Kubernetes с оплатой за фактические ресурсы. Стенд для проверки OIDC и RBAC поднимается за минуты и так же быстро удаляется.
Настройка OIDC-аутентификации в kube-apiserver
API-сервер принимает токены, если issuer и audience заданы точно. URL в --oidc-issuer-url должен совпадать с полем issuer из discovery-документа посимвольно: лишний слэш, другой регистр или схема http вместо https ломают аутентификацию целиком.
Обязательные флаги kube-apiserver для OIDC
| Флаг | Назначение | Пример |
|---|---|---|
--oidc-issuer-url | URL issuer, должен совпадать со значением issuer в discovery-документе | https://keycloak.example.com/realms/prod |
--oidc-client-id | Ожидаемый audience токена | kubernetes |
--oidc-username-claim | Claim с именем пользователя | email или preferred_username |
--oidc-username-prefix | Префикс, защищающий от подмены системных имён | oidc: |
--oidc-groups-claim | Claim со списком групп | groups |
--oidc-groups-prefix | Префикс для групп | oidc: |
--oidc-ca-file | CA-сертификат для проверки TLS issuer | /etc/kubernetes/pki/oidc-ca.crt |
--oidc-signing-algs | Разрешённые алгоритмы подписи | RS256 |
Пример блока command для kube-apiserver в кластере, установленном через kubeadm (файл /etc/kubernetes/manifests/kube-apiserver.yaml):
spec:
containers:
- command:
- kube-apiserver
- --oidc-issuer-url=https://keycloak.example.com/realms/prod
- --oidc-client-id=kubernetes
- --oidc-username-claim=email
- --oidc-username-prefix=oidc:
- --oidc-groups-claim=groups
- --oidc-groups-prefix=oidc:
- --oidc-ca-file=/etc/kubernetes/pki/oidc-ca.crt
volumeMounts:
- name: oidc-ca
mountPath: /etc/kubernetes/pki/oidc-ca.crt
readOnly: true
volumes:
- name: oidc-ca
hostPath:
path: /etc/kubernetes/pki/oidc-ca.crt
type: File
Префиксы oidc: указывайте явно. Без них токен с именем system:admin или группой system:masters, если такие значения допустимы в IdP, совпадёт со встроенными привязками кластера и получит права администратора. С префиксом появляется пользователь oidc:system:admin, который с системными привязками не пересекается.
В версиях 1.30 и новее набор флагов заменяется структурированной конфигурацией, файл подключается флагом --authentication-config:
apiVersion: apiserver.config.k8s.io/v1beta1
kind: AuthenticationConfiguration
jwt:
- issuer:
url: https://keycloak.example.com/realms/prod
audiences:
- kubernetes
certificateAuthority: |
-----BEGIN CERTIFICATE-----
MIIC...
-----END CERTIFICATE-----
claimValidationRules:
- expression: claims.email_verified == true
claimMappings:
username:
claim: email
prefix: "oidc:"
groups:
claim: groups
prefix: "oidc:"
Даёт три вещи: несколько JWT authenticators в одном файле, валидацию claims выражениями CEL, отдельные правила для каждого провайдера. Оба способа одновременно не применяют: выберите либо флаги, либо структурированный конфиг.
Проверка конфигурации и типичные ошибки на этом этапе
Проверьте discovery-документ с той машины, где работает kube-apiserver:
curl -s https://keycloak.example.com/realms/prod/.well-known/openid-configuration | jq -r .issuer
Ответ должен совпадать с --oidc-issuer-url посимвольно. Логи API-сервера показывают проблемы с OIDC:
kubectl -n kube-system logs kube-apiserver-cp01 | grep -i oidc
Если API-сервер не поднялся после правки манифеста, логи смотрите на самой ноде через crictl logs или journalctl -u kubelet. Статический pod перезапускается автоматически после изменения файла, поэтому сохраните копию до правки: cp /etc/kubernetes/manifests/kube-apiserver.yaml /root/kube-apiserver.yaml.bak.
Частые ошибки этапа: issuer URL недоступен из control plane (DNS, firewall, прокси), self-signed сертификат без --oidc-ca-file, client ID не совпадает с audience токена, префиксы не указаны. Устройство control plane и роль статических подов разобрано в статье Kubernetes: архитектура кластера и ключевые объекты API.
Получение доступа к кластеру через kubelogin
kubelogin (плагин kubectl oidc-login) выполняет authorization code flow с PKCE, открывает браузер, получает id_token и refresh token, после чего подставляет id_token в запросы kubectl. Обновление токена происходит автоматически.
Установка и настройка kubelogin
kubectl krew install oidc-login
brew install int128/kubelogin/kubelogin
Плагин также ставится из бинарных релизов проекта: скопируйте файл в ~/.kube/plugins/ или в каталог из PATH. Проверка: kubectl oidc-login --help.
Генерация конфигурации командой setup:
kubectl oidc-login setup \
--oidc-issuer-url=https://keycloak.example.com/realms/prod \
--oidc-client-id=kubernetes
Утилита выведет готовый фрагмент kubeconfig и проверит discovery-документ. Ручной вариант фрагмента для ~/.kube/config:
users:
- name: oidc
user:
exec:
apiVersion: client.authentication.k8s.io/v1beta1
command: kubectl
args:
- oidc-login
- get-token
- --oidc-issuer-url=https://keycloak.example.com/realms/prod
- --oidc-client-id=kubernetes
interactiveMode: IfAvailable
provideClusterInfo: false
Для публичного клиента с PKCE секрет не нужен. Если IdP требует confidential client, добавьте --oidc-client-secret=..., но учитывайте: секрет хранится в kubeconfig открытым текстом. Для CLI безопаснее публичный клиент, а секреты применяйте там, где файл защищён.
Процесс входа и обновление токенов
Первый же запрос открывает браузер: kubectl get pods перебрасывает на страницу входа IdP, после аутентификации и второго фактора браузер возвращается на http://localhost:8000, и kubectl выполняет команду.
Токены кэшируются в ~/.kube/cache/oidc-login/. Когда id_token истекает (обычно через 5-15 минут), kubelogin обновляет его по refresh token без открытия браузера. Время жизни refresh token задаётся в IdP: в Keycloak это параметры SSO Session Idle и SSO Session Max, для получения refresh token клиенту нужен scope offline_access.
На серверах без графического окружения используйте device code flow: --grant-type=device-code. kubelogin выведет ссылку и код, которые нужно ввести на другом устройстве. Второй вариант: перенести кэш ~/.kube/cache/oidc-login с рабочей машины, если политика безопасности это допускает. Сценарии с обязательным вторым фактором и защитой веб-интерфейсов разобраны в статье Защита Kubernetes с двухфакторной аутентификацией.
Привязка прав через RBAC: ClusterRoleBinding и RoleBinding
После аутентификации Kubernetes знает имя пользователя и группы из claims. Дальше работает стандартный RBAC: привязка связывает субъект (User или Group) с ролью. Для групп из OIDC используйте kind: Group, а имя указывайте с префиксом, если он задан в kube-apiserver: группа devops превращается в oidc:devops.
ClusterRoleBinding: права на уровне всего кластера
ClusterRoleBinding выдаёт права на все namespace и кластерные ресурсы. Пример выдачи группе devops полных административных прав:
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: oidc-devops-cluster-admin
subjects:
- kind: Group
name: oidc:devops
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: cluster-admin
apiGroup: rbac.authorization.k8s.io
cluster-admin уместен для платформенной команды из 2-5 человек. Остальным группам выдавайте view или edit: они покрывают чтение и изменение рабочих нагрузок без доступа к RBAC и секретам кластера.
RoleBinding: ограничение прав в пределах namespace
RoleBinding не выходит за границы одного namespace. Пример: группа developers получает роль edit в namespace staging.
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: developers-edit
namespace: staging
subjects:
- kind: Group
name: oidc:developers
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: edit
apiGroup: rbac.authorization.k8s.io
В roleRef допустимо ссылаться на ClusterRole: роль описана один раз, а действие ограничено namespace привязки. Такой приём экономит манифесты, когда одинаковый набор прав нужен в десяти namespace.
Проверка прав и аудит доступа
kubectl auth can-i list pods --as=oidc:ivan@example.com
kubectl auth can-i create deployments --as-group=oidc:developers -n staging
kubectl auth can-i --list --as=oidc:ivan@example.com
kubectl auth reconcile -f rbac.yaml применит манифесты и приведёт существующие привязки к нужному состоянию. Полный список привязок с субъектами выгружается командой kubectl get clusterrolebindings,rolebindings -A -o json. Практика разбора опасных конфигураций RBAC и автоматизации проверок описана в статье RBAC в Kubernetes 2026: практическое управление доступом.
Сервисные аккаунты для CI/CD: создание и управление
CI/CD-система не может входить через браузер, поэтому для неё создаётся ServiceAccount. С версии Kubernetes 1.24 Secret с токеном больше не создаётся автоматически: токен либо запрашивают через TokenRequest, либо явно создают Secret старого типа.
Создание ServiceAccount и генерация токена
kubectl create serviceaccount ci-deployer -n staging
Долгоживущий токен, совместимый с любыми версиями CI:
apiVersion: v1
kind: Secret
metadata:
name: ci-deployer-token
namespace: staging
annotations:
kubernetes.io/service-account.name: ci-deployer
type: kubernetes.io/service-account-token
kubectl -n staging get secret ci-deployer-token -o jsonpath='{.data.token}' | base64 -d
Современный вариант: короткоживущий токен через TokenRequest. Команда kubectl create token ci-deployer -n staging --duration=8h выдаёт токен с заданным сроком (по умолчанию 1 час, верхняя граница задаётся флагом kube-apiserver --service-account-max-token-expiration). Отозвать такой токен нельзя, зато он сам истекает, что снижает ценность утечки.
Формирование kubeconfig для CI/CD-системы
apiVersion: v1
kind: Config
clusters:
- name: prod
cluster:
server: https://api.k8s.example.com:6443
certificate-authority-data: LS0tLS1CRUdJTi...
users:
- name: ci-deployer
user:
token: eyJhbGciOiJSUzI1NiIs...
contexts:
- name: prod
context:
cluster: prod
user: ci-deployer
namespace: staging
current-context: prod
Файл передаётся в CI как защищённая переменная: в GitLab CI это File-переменная с KUBECONFIG, в Jenkins credentials типа Secret file, в GitHub Actions secret с base64. Проверка: kubectl --kubeconfig=ci.kubeconfig -n staging get pods.
Ограничение прав ServiceAccount через RBAC
Сервисному аккаунту нужны только те действия, которые выполняет пайплайн. Пример роли для деплоя в один namespace:
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: deployer
namespace: staging
rules:
- apiGroups: ["apps"]
resources: ["deployments"]
verbs: ["get", "list", "watch", "patch", "update"]
- apiGroups: [""]
resources: ["pods", "pods/log"]
verbs: ["get", "list", "watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: ci-deployer
namespace: staging
subjects:
- kind: ServiceAccount
name: ci-deployer
namespace: staging
roleRef:
kind: Role
name: deployer
apiGroup: rbac.authorization.k8s.io
Проверьте права до запуска пайплайна: kubectl auth can-i patch deployments --as=system:serviceaccount:staging:ci-deployer -n staging. Отдельный ServiceAccount на каждую систему (GitLab, Jenkins, Argo CD) упрощает аудит: в логах видно, кто именно менял ресурсы.
Типичные ошибки конфигурации IAM и способы их устранения
Проблемы делятся на три группы: токен не проходит аутентификацию (401), токен принят, но прав нет (403), инфраструктурные сбои с сертификатами или сетью. Диагностика начинается с логов kube-apiserver и проверки claims в токене.
Ошибки аутентификации: токены и issuer URL
- 401 Unauthorized, «token expired»: истёк id_token и не сработал refresh. Очистите кэш
~/.kube/cache/oidc-login/, выполните вход заново, проверьте срок жизни refresh token в IdP. - 401, «invalid issuer»: значение
--oidc-issuer-urlне совпадает с issuer в discovery-документе. Сравните строки посимвольно, включая слэш на конце. - 401, «audience mismatch»: audience токена не равен
--oidc-client-id. В Keycloak проверьте Client ID, в Azure AD Application ID. - 401 при живом токене: рассинхрон часов между control plane и IdP ломает проверку
expиiat. Держите NTP на всех нодах и на хосте IdP.
Полезный приём: декодировать payload токена локально, не отправляя его на сервер.
kubectl oidc-login get-token --oidc-issuer-url=https://keycloak.example.com/realms/prod --oidc-client-id=kubernetes > token.json
python3 -c "import base64,json,sys; t=sys.stdin.read().strip().split('.')[1]; t+='='*(-len(t)%4); print(json.dumps(json.loads(base64.urlsafe_b64decode(t)), indent=2, ensure_ascii=False))" < token.jwt
В payload смотрите поля iss, aud, email или preferred_username, groups, exp.
Ошибки авторизации: RBAC и claims
- 403 Forbidden сразу после входа: для группы нет RBAC-привязок. Проверьте:
kubectl auth can-i --list --as=oidc:ivan@example.com. - Группа не совпадает: в RoleBinding указано
devops, а kube-apiserver добавил префикс, поэтому субъект называетсяoidc:devops. Имена чувствительны к регистру. - Пустой список групп в токене: в IdP не настроен маппер групп или клиент не запрашивает нужный scope. В Keycloak добавьте mapper типа Group Membership, в Azure AD включите groups claim.
- Неверный username claim:
subдаёт непредсказуемое имя видаf3a9c1e0-..., а привязки написаны на email. Приведите claim и привязки к одному формату.
Проблемы с сертификатами и сетевой доступностью
- «x509: certificate signed by unknown authority»: kube-apiserver не доверяет сертификату issuer. Добавьте
--oidc-ca-fileс CA-сертификатом и перезапустите API-сервер. - Issuer недоступен: control plane не может открыть discovery-документ из-за firewall, DNS или прокси. Проверьте
curlс той же ноды, где работает kube-apiserver, а не с ноутбука. - Ошибки после обновления IdP: сменился сертификат или путь realm, а флаги остались прежними. Храните конфигурацию API-сервера в Git и сверяйте после каждого обновления IdP.
Разбирать большие выгрузки логов удобнее автоматически. Единый API к 200+ моделям (GPT, Gemini, Claude) с оплатой в рублях и управлением бюджетами предоставляет AiTunnel: интерфейс совместим с библиотеками OpenAI, VPN не требуется. Скрипт на 20 строк находит все события 401 и 403 по конкретному пользователю за нужный период.
Регулярная проверка конфигурации до инцидента экономит ночные часы. Готовые команды для аудита Docker и Kubernetes собраны в статье Практическое руководство по аудиту безопасности контейнеров и Kubernetes.
Безопасность и ротация учетных данных
Долгоживущие токены и широкие права - две главные причины инцидентов с доступом к кластеру. Целевая модель: короткие сроки жизни, минимальные права, полный аудит.
Ротация токенов ServiceAccount
Bound-токены из TokenRequest живут ограниченное время. Если токен подключается к поду через projected volume, kubelet обновляет его автоматически: новый токен запрашивается, когда остаётся меньше 20% срока, и ротация проходит без перезапуска пода. Аудитория токена ограничивается параметром audience, поэтому токен для внутреннего сервиса не примет сторонний API.
apiVersion: v1
kind: Pod
metadata:
name: app
spec:
serviceAccountName: app-sa
containers:
- name: app
image: example/app:1.0
volumeMounts:
- name: token
mountPath: /var/run/secrets/tokens
readOnly: true
volumes:
- name: token
projected:
sources:
- serviceAccountToken:
path: token
expirationSeconds: 3600
audience: internal-api
Для CI/CD ротация выглядит иначе: токен выпускается на время сборки. Вариант с минимальными правами: отдельный bootstrap-ServiceAccount с Role, которая разрешает только создание токенов для нужных аккаунтов.
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: token-issuer
namespace: staging
rules:
- apiGroups: [""]
resources: ["serviceaccounts/token"]
verbs: ["create"]
resourceNames: ["ci-deployer"]
Если без постоянного токена обойтись нельзя, ограничьте его срок, права и заведите календарное напоминание на перевыпуск раз в 90 дней.
Аудит доступа и мониторинг
Включите audit policy в kube-apiserver: уровень Metadata для обычных запросов и RequestResponse для операций с RBAC, Secret и ServiceAccount. Записи складывайте в файл или webhook и отправляйте в SIEM. Минимальный набор для отслеживания: создание и изменение привязок, запросы токенов, попытки доступа от system:anonymous.
Метрики apiserver_request_total с кодами 401 и 403 показывают всплески неудачной аутентификации. Алерт на рост 401 в 5 раз за 10 минут ловит и ошибки конфигурации после обновления, и перебор токенов. Отдельно настройте алерт на изменение ClusterRoleBinding с ролью cluster-admin: таких событий в норме быть не должно.
Развёрнутый чек-лист проверок кластера, включая RBAC, ServiceAccount и control plane, приведён в статье Аудит безопасности Kubernetes-кластера: базовые проверки.
Интеграция с корпоративными каталогами: LDAP и Active Directory
Компании редко переносят пользователей в новый каталог. Рабочая схема: Keycloak или Dex подключается к существующим LDAP/AD, а Kubernetes доверяет токенам этого IdP.
Настройка Keycloak с LDAP/Active Directory
Порядок действий в админ-консоли Keycloak: User Federation, затем Add LDAP provider. Параметры для Active Directory:
- Connection URL:
ldaps://dc01.example.com:636 - Bind DN:
CN=svc-keycloak,OU=Service,DC=example,DC=com - Edit Mode:
READ_ONLY - Users DN:
OU=Users,DC=example,DC=com, Username Attribute:sAMAccountName, UUID Attribute:objectGUID - Group mapper: Groups DN
OU=Groups,DC=example,DC=com, Group Name Attributecn, Membership Attributemember
После сохранения запустите Sync all users и проверьте, что группы появились в разделе Groups. Затем добавьте mapper группы в клиент Kubernetes: тип Group Membership, Token Claim Name groups, Add to ID token = On. Заблокированная в AD учётная запись не войдёт заново, потому что пароль проверяется в каталоге, а активные сессии Keycloak живут до истечения SSO Session Idle.
Настройка Dex с LDAP
connectors:
- type: ldap
name: OpenLDAP
id: ldap
config:
host: ldap.example.com:636
insecureNoSSL: false
bindDN: cn=dex,ou=service,dc=example,dc=com
bindPW: "<пароль>"
usernamePrompt: LDAP Username
userSearch:
baseDN: ou=people,dc=example,dc=com
filter: "(objectClass=person)"
username: uid
idAttr: uid
emailAttr: mail
nameAttr: cn
groupSearch:
baseDN: ou=groups,dc=example,dc=com
filter: "(objectClass=groupOfNames)"
userMatchers:
- userAttr: DN
groupAttr: member
nameAttr: cn
Dex передаёт найденные группы в claim groups, который читает kube-apiserver. Dex не хранит пользователей: данные берутся из каталога при каждом входе, поэтому блокировка в AD сразу запрещает новый вход, а выданный ранее токен действует до истечения срока. Срок жизни токена задаётся параметром expiry в конфигурации Dex (по умолчанию 24 часа), для кластера разумно снизить его до 1-2 часов в связке с refresh token.
Итоговая схема для большинства компаний: AD остаётся источником истины для учётных записей, Dex или Keycloak транслирует группы в OIDC-claims, kube-apiserver проверяет токены, RBAC-привязки выдают права группам, а CI/CD работает через отдельные ServiceAccount с токенами на время сборки. Такая конфигурация выдерживает рост команды и проходит проверку безопасности без переделки.