Keycloak - open-source платформа управления идентификацией и доступом (IAM). Она закрывает единый вход (SSO) для веб-приложений и API, федерацию пользователей из Active Directory и LDAP, выдачу токенов по OIDC и SAML, многофакторную аутентификацию и аудит входов. Один сервис берет на себя то, что иначе пришлось бы писать в каждом приложении: логин-формы, сессии, роли, сброс паролей.
Развернуть рабочий контур реально за один день. Минимальный набор: контейнер Keycloak, PostgreSQL и внешний URL за обратным прокси. Production-контур добавляет две и более реплики в Kubernetes, мониторинг, бэкапы и политику обновлений.
Дальше - пошаговый маршрут: архитектура realm и clients, запуск в Docker и Kubernetes, настройка OIDC и SAML-провайдеров, тюнинг БД и JVM, чек-лист готовности к продакшену. Все примеры приведены для актуальной линейки Keycloak 26.x.
Что такое Keycloak и зачем он нужен в 2026 году
Проект развивается с 2014 года под лицензией Apache 2.0. Кодовая база выросла из Red Hat JBoss, а в 2023 году Keycloak вошел в CNCF как incubating-проект. Начиная с 18-й версии основной дистрибутив собран на Quarkus: контейнер стартует за десятки секунд и потребляет меньше памяти, чем прежний вариант на WildFly.
Из коробки доступны:
- SSO для серверных приложений, SPA и мобильных клиентов через OIDC и OAuth 2.0;
- SAML 2.0 для legacy-систем: ADFS, ERP, внутренние порталы;
- федерация пользователей с Active Directory, LDAP и Kerberos;
- MFA: TOTP, WebAuthn, recovery codes, step-up аутентификация для отдельных действий;
- identity brokering: вход через внешние IdP, включая корпоративный ADFS и социальные сервисы;
- админ-консоль, Admin REST API, CLI kcadm и событийный аудит;
- кастомные темы и SPI для собственных authenticator-ов.
В линейке 26.x hostname v2 стал основным способом задать внешний URL, появились Organizations для B2B-сценариев и поддержка multi-site контуров с внешним Infinispan. Список изменений вашей минорной версии проверяйте в release notes перед обновлением.
Ключевые возможности и сценарии использования
Задачи, которые Keycloak закрывает лучше всего:
- SSO для микросервисов. Каждый сервис регистрируется как client. Сервисы проверяют JWT локально по ключам из JWKS, похода в Keycloak на каждый запрос нет.
- Защита API. Для сценариев machine-to-machine выдается токен по client credentials с нужными ролями в claims.
- Легаси-приложения. Системы, умеющие только SAML, подключаются к тому же пулу пользователей, что и новые сервисы.
- Федерация с каталогом. Пользователи живут в Active Directory, пароли проверяются там же, а роли и MFA настраиваются в Keycloak.
- Step-up аутентификация. Просмотр отчета - обычный вход, перевод денег или смена прав - запрос OTP или WebAuthn-ключа.
Единый вход для Nginx, oauth2-proxy и внутренних порталов строится по схеме Authorization Code + PKCE. Подробный разбор брокеров и ошибок 401/403 есть в руководстве по брокерам идентификации и SSO на OAuth 2.0 и OpenID Connect.
Keycloak vs облачные IAM: когда self-hosted оправдан
Okta, Auth0 и Entra ID снимают с команды администрирование БД, кластера и обновлений, но тарифицируют по активным пользователям. При 2000-3000 сотрудников годовой счет измеряется десятками тысяч долларов, а данные о пользователях хранятся у вендора.
Self-hosted Keycloak выигрывает, когда:
- пользователей больше 500-1000 и нагрузка предсказуема;
- персональные данные должны лежать на ваших серверах или в конкретной юрисдикции;
- нужны кастомные authenticator-ы и flows, которых нет у вендоров;
- важен контроль над версиями и отсутствие vendor lock-in.
Цена self-hosted - операционная нагрузка: обновления, бэкапы, мониторинг, дежурства. Оцените, есть ли у команды на это часы. Zitadel на Go - близкая по классу альтернатива, но экосистема коннекторов и документации у Keycloak шире.
При миграции с облачного IAM пароли не переносятся: пользователи либо сбрасывают их через email, либо вы продолжаете проверять их во внешнем каталоге через федерацию.
| Критерий | Keycloak self-hosted | Облачные IAM |
|---|---|---|
| Стоимость при 2000 пользователей | Инфраструктура и время инженеров | Оплата за активных пользователей, растет линейно |
| Хранение данных | На ваших серверах | У вендора |
| Кастомизация | SPI, темы, свои authenticator-ы | Ограничена API вендора |
| Операционная нагрузка | Обновления, БД, мониторинг на вас | На вендоре |
Архитектура Keycloak: realm, client, user, role
Перед первым кликом в админке зафиксируйте ментальную модель. Realm - изолированное пространство: свой пул пользователей, свои clients, роли, ключи подписи и настройки токенов. Внутри realm живут users (субъекты), groups (иерархия для массовой выдачи ролей), realm roles и client roles (права), clients (приложения, которые запрашивают аутентификацию).
Realm "demo" |-- Users и Groups |-- Realm roles: app-user, app-admin |-- Clients | |-- app-web (OIDC, confidential) | |-- mobile (OIDC, public + PKCE) | +-- legacy-crm (SAML) |-- Client scopes и mappers +-- Identity providers (brokering)
Коды авторизации выдаются по стандартным потокам:
- Authorization Code + PKCE - браузерные приложения, SPA и мобильные клиенты; рекомендуемый вариант;
- Client Credentials - сервис-сервис без участия пользователя;
- Device Code - CLI и устройства без браузера;
- Direct Access Grant - устаревший, оставляйте только для миграционных тестов.
Времена жизни по умолчанию: access token - 5 минут, SSO-сессия - 30 минут бездействия и 10 часов максимум. Значения меняются в Realm settings -> Tokens.
Realm: изоляция и мультитенантность
Master realm существует для администрирования. Не создавайте в нем клиентов и пользователей приложений: захват админского аккаунта master даст доступ ко всей инсталляции. Рабочая схема - отдельный realm на продукт, команду или клиента.
Realm изолирует ключи подписи, настройки паролей, SMTP, темы и политики. Пользователь из одного realm не существует для другого. Для B2B-сценариев, где в одном realm нужно разделить компании-клиенты, в 26.x есть Organizations: организации группируют пользователей по доменам и подключают свои IdP. Функциональность активно развивается, проверяйте ее статус в вашей версии.
Clients, scopes и mappers
Client - приложение или сервис, запрашивающий аутентификацию. Три основных типа:
- Public - SPA и мобильные приложения: секрет хранить негде, обязателен PKCE;
- Confidential - серверные приложения: аутентификация по client secret или mTLS;
- Bearer-only - сервисы, которые только принимают и проверяют токены.
Client scopes - переиспользуемые наборы claims (profile, email, roles). Mappers добавляют в токен конкретику: audience, атрибуты пользователя, членство в группах. Без audience mapper access token часто не содержит client_id в поле aud, и строгие библиотеки валидации отклоняют такой токен.
Роли делятся на realm-роли (глобальные: app-admin, auditor) и client-роли (специфичные для приложения). В токене они приходят как realm_access.roles и resource_access.<client>.roles. Groups дают иерархию и наследование, composite roles собирают набор ролей в одну. Как выбрать между RBAC и ABAC и не утонуть в исключениях, разобрано в статье RBAC и ABAC в IAM-системах: управление доступом в Keycloak, LDAP и Kubernetes.
Установка Keycloak в Docker: быстрый старт за 5 минут
Официальные образы публикуются в реестре quay.io/keycloak/keycloak. Ниже два сценария: стенд для экспериментов и конфигурация, близкая к продакшену, с PostgreSQL и внешним URL.
Запуск в dev-режиме для тестирования
docker run --name keycloak -p 8080:8080 \ -e KC_BOOTSTRAP_ADMIN_USERNAME=admin \ -e KC_BOOTSTRAP_ADMIN_PASSWORD=admin \ quay.io/keycloak/keycloak:26.3 start-dev
Через 10-30 секунд админка доступна на http://localhost:8080/admin, вход admin/admin. Режим start-dev включает встроенную H2, отключает кластерный кэш и разрешает HTTP без TLS. Данные исчезнут вместе с контейнером, производительность не рассчитана на нагрузку. Для продакшена этот режим не подходит.
Переменные KEYCLOAK_ADMIN и KEYCLOAK_ADMIN_PASSWORD из инструкций для версий до 26 больше не работают. В 26.x стартовый администратор создается через KC_BOOTSTRAP_ADMIN_USERNAME и KC_BOOTSTRAP_ADMIN_PASSWORD.
Эти переменные нужны только при первом старте: пользователь создается один раз в базе. Повторная передача значений не меняет существующий пароль, это важно при перезапусках. В примерах используется тег 26.3; в проде фиксируйте актуальную минорную версию.
Production-конфигурация с PostgreSQL через docker-compose
Стенд, приближенный к проду: PostgreSQL 17, внешний hostname, включенные health-проверки и метрики. Сохраните как docker-compose.yml и задайте POSTGRES_PASSWORD и KEYCLOAK_ADMIN_PASSWORD в файле .env:
services:
postgres:
image: postgres:17
environment:
POSTGRES_DB: keycloak
POSTGRES_USER: keycloak
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
volumes:
- pgdata:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U keycloak -d keycloak"]
interval: 10s
timeout: 5s
retries: 5
keycloak:
image: quay.io/keycloak/keycloak:26.3
command: start
environment:
KC_DB: postgres
KC_DB_URL: jdbc:postgresql://postgres:5432/keycloak
KC_DB_USERNAME: keycloak
KC_DB_PASSWORD: ${POSTGRES_PASSWORD}
KC_HOSTNAME: https://sso.example.com
KC_HTTP_ENABLED: "true"
KC_PROXY_HEADERS: xforwarded
KC_HEALTH_ENABLED: "true"
KC_METRICS_ENABLED: "true"
KC_BOOTSTRAP_ADMIN_USERNAME: admin
KC_BOOTSTRAP_ADMIN_PASSWORD: ${KEYCLOAK_ADMIN_PASSWORD}
ports:
- "8080:8080"
- "9000:9000"
depends_on:
postgres:
condition: service_healthy
volumes:
pgdata:
Разбор ключевых параметров:
- KC_DB=postgres и KC_DB_URL переводят систему с H2 на PostgreSQL: пользователи, сессии и настройки realm уходят в СУБД;
- KC_HOSTNAME задает внешний URL и issuer токенов. Значение обязано совпадать с адресом, по которому пользователи открывают Keycloak;
- KC_HTTP_ENABLED=true + KC_PROXY_HEADERS=xforwarded: TLS завершается на прокси или балансировщике, а Keycloak доверяет заголовкам X-Forwarded-*;
- порт 9000 отдает /health/ready, /health/live и /metrics для проб и мониторинга;
- KC_BOOTSTRAP_ADMIN_* создают стартового администратора при первом старте. После создания рабочих админов переменные можно убрать из конфигурации;
- KC_HOSTNAME_STRICT из старых версий не нужен: hostname v2 в 26.x использует один параметр KC_HOSTNAME.
Первый старт выполняет сборку конфигурации, обычно меньше минуты. Для продакшена собирайте неизменяемый образ: kc.sh build на этапе сборки контейнера, затем start --optimized при запуске.
Базовая настройка: realm, пользователи, роли
Создание realm и первичная конфигурация
- Войдите в админ-консоль, раскройте список realm в левом верхнем углу, нажмите Create realm.
- Имя: demo. Create.
- Realm settings -> Login: отключите User registration, включите Forgot password.
- Realm settings -> Email: заполните SMTP. Без него не уйдут письма сброса пароля и верификации.
- Realm settings -> Security -> Password policy: minimum 12 символов, digits, lowerCase, upperCase, specialChars. Хеширование по умолчанию - Argon2.
- Там же включите Brute force detection: temporary lockout после 5 неудачных попыток.
Realm settings -> Tokens: access token 5 минут, SSO idle 30 минут, SSO max 10 часов. Для внутренних приложений значения по умолчанию подходят, для партнерских интеграций подумайте об укорочении.
Пользователи, группы и роли
Users -> Add user: username, email, имя и фамилия. Во вкладке Credentials задайте пароль с флагом Temporary, тогда пользователь сменит его при первом входе.
Роли создайте в Realm roles (app-user, app-admin) или на уровне конкретного клиента. Группы удобнее для массовых операций: группа developers с ролью app-user, и каждый добавленный в нее пользователь сразу получает права. Вложенные группы наследуют роли по цепочке, composite role собирает несколько ролей в одну для назначения одним действием.
Проверка: откройте http://localhost:8080/realms/demo/account, войдите тестовым пользователем. Профиль должен открываться без лишних запросов пароля и OTP.
Настройка OIDC-клиента и подключение приложения
OIDC - основной протокол для современных приложений: проще SAML, поддерживается всеми популярными фреймворками и библиотеками.
Создание и настройка OIDC-клиента
- Clients -> Create client. Client type: OpenID Connect, Client ID: demo-app.
- Capability config: Client authentication ON (confidential), Standard flow ON, Direct access grants OFF, Implicit OFF.
- Login settings: Valid redirect URIs - http://localhost:3000/callback для теста и https://app.example.com/callback для прода. Web origins: https://app.example.com. Для SPA добавьте +, чтобы разрешить источники из redirect URI автоматически.
- Сохраните. Секрет клиента лежит в Clients -> demo-app -> Credentials.
Для SPA и мобильных приложений выбирайте public client с PKCE (S256). Для machine-to-machine интеграций включите Service accounts и используйте grant type client_credentials.
Все адреса и эндпоинты собраны в одном документе: https://sso.example.com/realms/demo/.well-known/openid-configuration. Оттуда приложение берет authorization_endpoint, token_endpoint, jwks_uri и end_session_endpoint.
Подключение тестового приложения и проверка токена
Проверка вручную: откройте в браузере authorization-запрос, получите code и обменяйте его на токены.
curl -s -X POST http://localhost:8080/realms/demo/protocol/openid-connect/token \ -d grant_type=authorization_code \ -d client_id=demo-app \ -d client_secret=SECRET \ -d code=CODE \ -d redirect_uri=http://localhost:3000/callback
В ответе придут access_token, refresh_token и id_token. Access token - JWT с подписью RS256. Приложение проверяет подпись по ключам из jwks_uri, затем сверяет iss, aud и exp:
from jose import jwt
import requests
ISSUER = "https://sso.example.com/realms/demo"
jwks = requests.get(f"{ISSUER}/protocol/openid-connect/certs").json()
claims = jwt.decode(
access_token, jwks,
algorithms=["RS256"],
audience="demo-app",
issuer=ISSUER,
)
print(claims["realm_access"]["roles"])
Если aud не содержит demo-app, добавьте Audience mapper: Clients -> demo-app -> Client scopes -> demo-app-dedicated -> Add mapper -> Audience, включите demo-app в оба токена. Это самая частая причина ошибки Invalid audience при подключении Grafana, Argo CD и других готовых продуктов.
Типичные ошибки:
- 400 invalid redirect_uri: URI в запросе отличается от настройки хоть одним символом;
- CORS в SPA: не заполнены Web origins;
- Invalid issuer: KC_HOSTNAME не совпадает с адресом, по которому открыта система;
- token is not active: рассинхронизация часов, лечится NTP;
- Account is not fully set up: у пользователя висят невыполненные Required actions.
Настройка SAML-провайдера и федерация с внешними IdP
SAML востребован в корпоративной среде: ADFS, ERP и внутренние порталы часто умеют только его. Keycloak работает в обе стороны: выступает Identity Provider для приложений и Service Provider для внешних IdP.
Keycloak как SAML Identity Provider
- Clients -> Create client, Client type: SAML. Client ID - entityID приложения, например urn:legacy-crm.
- Valid redirect URIs: ACS URL приложения (https://crm.example.com/saml/acs).
- В настройках клиента: Name ID format (email или persistent), Signature algorithm RSA_SHA256, Sign documents и Sign assertions ON.
- Экспортируйте metadata: Realm settings -> General -> SAML 2.0 Identity Provider Metadata. В XML будут entityID, SSO-эндпоинт /realms/demo/protocol/saml и публичные сертификаты.
Атрибуты в assertion добавляйте через mappers: username, email, роли. Отладка ведется SAML-tracer-ом в браузере и логами с уровнем DEBUG для org.keycloak.saml.
Федерация с внешним SAML IdP
- Identity providers -> Add provider -> SAML v2.0. Импортируйте metadata корпоративного IdP по URL или XML-файлом.
- Задайте Alias, например corporate-adfs.
- First login flow: выберите автоматическую привязку по email или подтверждение пользователем. Для домена компании настройте автомаппинг, чтобы не появлялись дубли аккаунтов.
- Добавьте IdP mappers: перенос групп из утверждений IdP в роли Keycloak.
SP-initiated flow стартует из приложения, IdP-initiated - из портала компании. Второй удобен для сотрудников, но требует внимательной проверки привязки сессий. Чтобы принудительно вести пользователей конкретного клиента через корпоративный IdP, добавьте в flow Identity Provider Redirector или передайте в запрос параметр kc_idp_hint=corporate-adfs.
Развертывание Keycloak в Kubernetes для production
Keycloak хранит состояние в PostgreSQL и распределенном кэше, поэтому в Kubernetes его разворачивают обычным Deployment с двумя и более репликами. StatefulSet и PVC нужны только если вы держите БД внутри кластера, для Keycloak выбирайте Deployment. База данных - внешняя managed PostgreSQL: с ней проще бэкапы, репликация и обновления без простоя.
Helm chart и Operator: что выбрать
Два подхода к деплою:
- Keycloak Operator: CRD-ресурсы Keycloak и Realm, декларативное управление через kubectl и GitOps, оператор сам создает Deployment, Service и следит за обновлениями;
- Helm chart: community-чарты (Bitnami, codecentric/keycloakx) и чарт из репозитория проекта. Гибче в мелочах, но realm-as-code и порядок обновлений придется организовывать самим.
Для типового кластера быстрее стартовать с Helm, для строгого GitOps с управлением realm из репозитория удобнее Operator. Фрагмент манифеста, который подходит чартам и оператору:
apiVersion: apps/v1
kind: Deployment
metadata:
name: keycloak
spec:
replicas: 2
selector:
matchLabels:
app: keycloak
template:
metadata:
labels:
app: keycloak
spec:
containers:
- name: keycloak
image: quay.io/keycloak/keycloak:26.3
args: ["start", "--optimized"]
env:
- name: KC_DB
value: postgres
- name: KC_DB_URL
value: jdbc:postgresql://postgres:5432/keycloak
- name: KC_DB_USERNAME
valueFrom:
secretKeyRef:
name: keycloak-db
key: username
- name: KC_DB_PASSWORD
valueFrom:
secretKeyRef:
name: keycloak-db
key: password
- name: KC_HOSTNAME
value: https://sso.example.com
- name: KC_HTTP_ENABLED
value: "true"
- name: KC_PROXY_HEADERS
value: xforwarded
- name: KC_CACHE_STACK
value: kubernetes
- name: KC_HEALTH_ENABLED
value: "true"
- name: JAVA_OPTS_APPEND
value: "-XX:MaxRAMPercentage=70"
readinessProbe:
httpGet:
path: /health/ready
port: 9000
livenessProbe:
httpGet:
path: /health/live
port: 9000
resources:
requests:
cpu: "500m"
memory: "1Gi"
limits:
memory: "2Gi"
Секреты БД приходят из Secret. readinessProbe смотрит на /health/ready, liveness - на /health/live; оба эндпоинта живут на management-порту 9000.
Если собственного кластера нет, managed-инфраструктуру с Kubernetes, базами данных и VDS можно заказать в Timeweb Cloud: PostgreSQL поднимается в пару кликов, а Keycloak ставится чартом в тот же кластер.
Кластеризация, кэш и горизонтальное масштабирование
Реплики находят друг друга через встроенный Infinispan. Для Kubernetes задайте KC_CACHE_STACK=kubernetes: discovery работает через API кластера или DNS. Сессии и кэш realm реплицируются между подами, выход одного пода из строя не разрывает вход пользователей.
На Ingress включите session affinity по cookie: это сокращает лишние редиректы в authorization code flow. Для географически распределенных контуров в 26.x есть multi-site схема с внешним Infinispan: активный и пассивный сайты синхронизируют сессии через отдельный кластер кэша.
Минимум для отказоустойчивости: два пода, PodDisruptionBudget с minAvailable: 1, HPA по CPU с порогом около 70%. Метрики включаются KC_METRICS_ENABLED=true и отдаются на порту 9000.
TLS, Ingress и параметры JVM
TLS проще завершать на Ingress (cert-manager с Let's Encrypt): Keycloak принимает HTTP внутри кластера, а KC_PROXY_HEADERS=xforwarded заставляет его доверять заголовкам X-Forwarded-For и X-Forwarded-Proto. Проверьте на прокси таймауты: медленные формы логина и админ-операции не должны обрываться на 30 секундах.
Если TLS терминируется в самом Keycloak, смонтируйте сертификаты и включите KC_HTTPS_CERTIFICATE_FILE и KC_HTTPS_CERTIFICATE_KEY_FILE.
JVM: для контейнера с лимитом 2 GiB задайте -XX:MaxRAMPercentage=70, оставив память на Metaspace и off-heap. Стартовые ресурсы: 500m CPU и 1 GiB памяти в requests, лимит памяти 2 GiB. Heap и GC держите под наблюдением: рост пауз GC при стабильной нагрузке - сигнал пересмотреть лимиты или версию.
Отдельная задача - пускать в кластер Kubernetes пользователей через этот же Keycloak: флаги kube-apiserver, kubeconfig с kubelogin и RBAC-привязки для групп разобраны в руководстве по интеграции IAM с Kubernetes.
Отказоустойчивость и производительность в production
Нагрузка концентрируется в двух местах: выдача и подпись токенов (CPU) и запись сессий и событий (БД и кэш). Задача тюнинга - не дать БД стать узким местом, а JVM - уйти в swap.
Тюнинг БД и пула соединений
- Внешняя PostgreSQL 16+ с репликацией и отдельными быстрыми дисками под журнал WAL;
- размер пула на под задается KC_DB_POOL_MAX_SIZE. Простая формула: max_connections в PostgreSQL делим на число подов с запасом. Для 3 подов и max_connections=100 подойдет 20 на под;
- следите за pg_stat_activity: долгие транзакции и состояние idle in transaction указывают на проблемы с пулом или диском;
- индексы схемы Keycloak руками не трогайте: схема обновляется автоматически при старте новой версии;
- при высокой нагрузке не храните login events в БД: отправляйте их во внешнюю систему или сократите срок хранения.
Мониторинг и бэкапы
KC_METRICS_ENABLED=true открывает /metrics на порту 9000. Снимайте метрики Prometheus и заведите алерты на четыре сигнала: рост ошибок входа, латентность token endpoint, заполнение пула соединений и частые GC-паузы. Логи в JSON включаются опцией --log-console-output=json, что упрощает отправку в Loki или Elasticsearch.
Бэкапы строятся на двух уровнях:
- Резервная копия PostgreSQL - pg_dump по расписанию или снапшоты managed-базы. В БД лежат пользователи, сессии, настройки realm и ключи подписи;
- Конфигурация как код - экспорт realm: kc.sh export --realm demo --file /backup/demo-realm.json. Экспорт удобен для ревью изменений и переноса стендов, но не заменяет дамп базы.
Обновления: сначала staging с копией базы, затем rolling update подов. Схема БД мигрирует автоматически при старте новой версии, откат на предыдущую мажорную версию после миграции не поддерживается. Release notes читайте до перехода, а не после.
Управление пользователями: LDAP, API и автоматизация
Интеграция с LDAP/Active Directory
- User Federation -> Add provider -> LDAP.
- Vendor: Active Directory. Connection URL: ldaps://dc.example.com:636. Укажите Bind DN и пароль сервисной учетной записи.
- Users DN: OU=Users,DC=example,DC=com. Username attribute: sAMAccountName, UUID attribute: objectGUID.
- Edit mode: READ_ONLY, Import users: ON. Пользователи кэшируются локально, пароли по-прежнему проверяются в AD.
- Sync settings: полная синхронизация раз в 12 часов, изменения подтягиваются инкрементально.
Kerberos/SPNEGO добавит прозрачный вход с доменных рабочих станций без ввода пароля. Для Azure AD и других облачных каталогов проще использовать OIDC-федерацию через Identity providers.
Admin REST API и автоматизация
Автоматизация начинается с сервисного аккаунта: создайте confidential-клиент в master realm, включите Service accounts и выдайте client-роли из realm-management (view-users, manage-users, manage-clients по необходимости). Токен получается стандартным client credentials:
TOKEN=$(curl -s -X POST https://sso.example.com/realms/master/protocol/openid-connect/token \ -d grant_type=client_credentials \ -d client_id=automation \ -d client_secret=SECRET | jq -r .access_token)
Дальше работает обычный REST:
# Поиск пользователя
curl -s -H "Authorization: Bearer $TOKEN" \
"https://sso.example.com/admin/realms/demo/users?username=jdoe"
# Создание пользователя: POST /admin/realms/demo/users
# Сброс пароля: PUT /admin/realms/demo/users/{id}/reset-password
# Назначение роли: POST /admin/realms/demo/users/{id}/role-mappings/realm
На хосте с Keycloak доступен CLI: kcadm.sh config credentials, create users, add-roles. Для IaC подходит Terraform-провайдер сообщества: realms, clients и роли описываются кодом и проходят ревью как любой другой конфиг.
Аудит: включите login events и admin events в Realm settings -> Events и отправляйте поток во внешнее хранилище. Долгое хранение событий в БД Keycloak бьет по производительности на активных системах.
Типичные ошибки и чек-лист перед продакшеном
Собрали грабли, которые чаще всего ломают запуск:
- start-dev в продакшене. Встроенная H2, отсутствие кластеризации, HTTP без TLS. Переводите систему на start с внешней БД до открытия доступа пользователям;
- Неверный KC_HOSTNAME. Issuer токенов расходится с адресом в браузере, и все интеграции падают на валидации. Внешний URL задавайте один раз;
- Слабый администратор master realm. Включите MFA и не создавайте приложения в master;
- Одна реплика. Обновление или падение пода останавливает вход во все сервисы;
- Нет бэкапов БД. Потеря PostgreSQL - потеря пользователей, сессий и настроек;
- Секреты в открытых переменных. Пароли БД и client secrets держите в Secret или Vault;
- Нет мониторинга. Без метрик о проблеме вы узнаете от пользователей, а не от алерта;
- Отложенные обновления. Релизы закрывают уязвимости; раз в квартал планируйте переход на свежую минорную версию.
Чек-лист production-готовности
- Внешняя PostgreSQL с репликацией, бэкапами и проверенным сценарием восстановления;
- TLS на входе, KC_HOSTNAME указывает на внешний URL;
- два и более пода, probes на /health/ready и /health/live, PodDisruptionBudget;
- session affinity на Ingress или внешний Infinispan;
- политики паролей, brute force protection, MFA для администраторов;
- мониторинг метрик, алерты, JSON-логи в централизованном хранилище;
- экспорт realm в git и регулярный дамп БД;
- ограничения ресурсов и настроенный heap JVM;
- процесс обновлений: staging, release notes, rolling update;
- аудит login и admin events.
Пример защиты кластера двухфакторной аутентификацией через Keycloak как OIDC-провайдер разобран в руководстве по 2FA для kubectl и веб-интерфейсов Kubernetes.
Практический старт: поднимите стенд через docker-compose, создайте realm demo и подключите одно пилотное приложение по OIDC. После этого пройдите чек-лист пункт за пунктом и переносите контур в Kubernetes: так вы получите работающий SSO без сюрпризов в проде.