Интеграция IAM с Kubernetes: настройка безопасного доступа к кластеру и управление сервисными аккаунтами | AdminWiki

Интеграция IAM с Kubernetes: настройка безопасного доступа к кластеру и управление сервисными аккаунтами

11 сентября 2026 16 мин. чтения
Содержание статьи

Интеграция 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 без доработок в кластере.

КритерийKeycloakDexAzure AD (Entra ID)
РазвёртываниеСвоё: контейнер и PostgreSQL, 1-2 ГБ RAMОдин бинарник или Deployment, 50-100 МБ RAM, без базы пользователейОблачный сервис, разворачивать нечего
Хранение пользователейЛокальная БД плюс федерация LDAP/ADТолько upstream-каталогОблачный каталог Microsoft
Подключение LDAP/ADUser 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-urlURL issuer, должен совпадать со значением issuer в discovery-документеhttps://keycloak.example.com/realms/prod
--oidc-client-idОжидаемый audience токенаkubernetes
--oidc-username-claimClaim с именем пользователяemail или preferred_username
--oidc-username-prefixПрефикс, защищающий от подмены системных имёнoidc:
--oidc-groups-claimClaim со списком группgroups
--oidc-groups-prefixПрефикс для группoidc:
--oidc-ca-fileCA-сертификат для проверки 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 Attribute cn, Membership Attribute member

После сохранения запустите 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 с токенами на время сборки. Такая конфигурация выдерживает рост команды и проходит проверку безопасности без переделки.

Поделиться:
Сохранить гайд? В закладки браузера