Перейти к основному содержимому
  1. Posts/
  2. IAM и IdP решения./

Установка и настройка Keycloak

··1171 слово·6 минут· loading · loading · ·
Stilicho2011
Автор
Stilicho2011
Пишу о homelab, self-hosting, автоматизации и open-source решениях
Оглавление
IAM-решения - This article is part of a series.
Part : This Article

Что такое Keycloak
#

Если вам понравилась настоящая статья, то можете поддержать автора став спонсором на бусти (ссылка в разделе контакты).

Keycloak - open-source решение для управления идентификацией и доступом (IAM) от Red Hat, с поддержкой SSO, OAuth2, OpenID Connect, SAML 2.0 и ещё доброго десятка стандартов помельче. Это, пожалуй, самый “тяжёлый” и одновременно самый функциональный игрок из всех IAM-решений, которые я разбирал в этой серии - в enterprise-среде он де-факто стандарт, и если вам когда-нибудь приходилось логиниться в корпоративный портал через страницу с логотипом “Keycloak” внизу - вот это оно и было.

В домашней лаборатории Keycloak оправдан не всегда - он ощутимо тяжелее, чем тот же Authentik или Authelia, и требует Java-стек под капотом. Но если вы хотите пощупать тот самый инструмент, с которым реально работают в проде на работе, или вам нужны специфичные корпоративные фичи вроде реалмов и федерации - это то, что нужно.

Зачем нужен Keycloak
#

Централизованно управлять аутентификацией пользователей Keycloak умеет широко:

  • единый вход (SSO) сразу во все подключённые приложения;
  • вход через внешних провайдеров - Google, GitHub и другие через OAuth2/OIDC;
  • подключение LDAP и Active Directory, если у вас уже есть корпоративный каталог пользователей;
  • полноценная веб-админка, а не только конфиг-файлы;
  • нативная поддержка OpenID Connect и OAuth 2.0 без костылей.

Что понадобится
#

  • Docker и Docker Compose;
  • обратный прокси - в этой статье я использую Traefik;
  • домен с настроенным DNS (у меня keycloak.stilicho.ru);
  • SSL-сертификат, проще всего через Let’s Encrypt силами того же Traefik.

Возможности Keycloak
#

Возможностей у Keycloak действительно много, и разложу их по смысловым группам, чтобы было понятно, что вообще получаете при установке.

Аутентификация и авторизация. Single Sign-On для всех подключённых приложений, вход через социальные провайдеры (Google, Facebook, GitHub и другие), поддержка OAuth2/OIDC/SAML 2.0 и многофакторная аутентификация через TOTP (Google Authenticator и аналоги).

Управление пользователями и ролями. Полноценное создание и управление пользователями, группами и ролями, делегированное администрирование - можно разграничить, кто из админов какими пользователями управляет, - плюс импорт и экспорт пользователей через LDAP, CSV или REST API.

Интеграция с корпоративной инфраструктурой. Прямая интеграция с LDAP и Active Directory, SCIM-подобные возможности через REST API, полноценный CLI-клиент и Admin REST API для автоматизации.

Multi-tenancy и реалмы. Пожалуй, главная архитектурная фишка Keycloak - реалмы (realms), изолированные домены аутентификации. У каждого реалма свои настройки, пользователи, клиенты и политики - можно держать один Keycloak на несколько независимых проектов или клиентов, не боясь, что они “увидят” пользователей друг друга.

Кастомизация. Можно кастомизировать UI экранов входа и регистрации под свой бренд, расширять функциональность через Java SPI и плагины, локализовать интерфейс под нужный язык.

Аудит и безопасность. Аудит логов входа и действий пользователей, гибко настраиваемые политики паролей, ограничения по IP и встроенная защита от brute-force атак.

Docker Compose файл, который используется в ролике
#

Ниже - конфигурация, с которой я разворачивал Keycloak в видео. Она состоит из двух сервисов: базы PostgreSQL и самого Keycloak за Traefik.

services:
    postgres:
        image: postgres:16-alpine
        container_name: keycloak-db
        restart: always
        expose:
            - 5432
        volumes:
            - /home/path/to/keycloak/database:/var/lib/postgresql/data
        environment:
            POSTGRES_DB: ${POSTGRES_DB}
            POSTGRES_USER: ${POSTGRES_USER}
            POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
        healthcheck:
            test:
                [
                    "CMD",
                    "pg_isready",
                    "-q",
                    "-d",
                    "${POSTGRES_DB}",
                    "-U",
                    "${POSTGRES_USER}",
                ]
            interval: 10s
            timeout: 5s
            retries: 3
            start_period: 60s
        networks:
            - keycloak

    keycloak:
        image: quay.io/keycloak/keycloak:26.6.4 # не используйте :latest - зафиксируйте версию явно, актуальную смотрите на https://quay.io/repository/keycloak/keycloak?tab=tags
        container_name: keycloak
        command: start
        environment:
            KC_HOSTNAME: ${KEYCLOAK_HOSTNAME}
            KC_BOOTSTRAP_ADMIN_USERNAME: ${KC_BOOTSTRAP_ADMIN_USERNAME}
            KC_BOOTSTRAP_ADMIN_PASSWORD: ${KC_BOOTSTRAP_ADMIN_PASSWORD}
            KC_DB: postgres
            KC_DB_URL: jdbc:postgresql://postgres/${POSTGRES_DB}
            KC_DB_USERNAME: ${POSTGRES_USER}
            KC_DB_PASSWORD: ${POSTGRES_PASSWORD}
            KC_PROXY_HEADERS: "xforwarded"
            KC_HTTP_ENABLED: true
            KC_HEALTH_ENABLED: true
            PROXY_ADDRESS_FORWARDING: "true"
        healthcheck:
            test:
                - "CMD-SHELL"
                - |
                    exec 3<>/dev/tcp/localhost/9000 &&
                    echo -e 'GET /health/ready HTTP/1.1\r\nHost: localhost\r\nConnection: close\r\n\r\n' >&3 &&
                    cat <&3 | tee /tmp/healthcheck.log | grep -q '200 OK'
            interval: 10s
            timeout: 5s
            retries: 3
            start_period: 90s
        #ports:
        #  - 8080:8080
        #expose:
        #  - 8080 # web ui http
        #  - 9000 # health endpoint
        restart: always
        depends_on:
            postgres:
                condition: service_healthy
        networks:
            - keycloak
            - proxy
        labels:
            - "traefik.enable=true"
            - "traefik.http.routers.keycloak.entrypoints=http"
            - "traefik.http.routers.keycloak.rule=Host(`keycloak.domain.ru`)"
            - "traefik.http.middlewares.keycloak-https-redirect.redirectscheme.scheme=https"
            - "traefik.http.routers.keycloak.middlewares=keycloak-https-redirect"
            - "traefik.http.routers.keycloak-secure.entrypoints=https"
            - "traefik.http.routers.keycloak-secure.rule=Host(`keycloak.domain.ru`)"
            - "traefik.http.routers.keycloak-secure.tls=true"
            - "traefik.http.routers.keycloak-secure.service=keycloak"
            - "traefik.http.services.keycloak.loadbalancer.server.port=8080"
            - "traefik.docker.network=proxy"

networks:
    keycloak:
        internal: true
    proxy:
        external: true

Значения в файле переменных

# define FQDN hostname
KEYCLOAK_HOSTNAME=keycloak.stilicho.ru

# define login credentials
KC_BOOTSTRAP_ADMIN_USERNAME=admin
KC_BOOTSTRAP_ADMIN_PASSWORD=password

# define database credentials
POSTGRES_DB=keycloak_db
POSTGRES_USER=keycloak_db_user
POSTGRES_PASSWORD=keycloak_db_user_password

Пару слов про то, что здесь происходит, потому что бездумно копировать чужой compose-файл - плохая идея.

Сеть keycloak намеренно объявлена как internal: true - у базы данных нет и не должно быть прямого выхода наружу, к ней обращается только сам контейнер Keycloak внутри той же docker-сети. Наружу торчит только сеть proxy, через которую Traefik подхватывает контейнер по лейблам.

KC_PROXY_HEADERS: "xforwarded" и PROXY_ADDRESS_FORWARDING: "true" говорят Keycloak, что он стоит за обратным прокси и должен доверять заголовкам X-Forwarded-* - без этого он будет путаться в том, какой протокол и хост реально использует клиент, и генерировать неправильные redirect-ссылки. KC_HTTP_ENABLED: true разрешает Keycloak слушать по обычному HTTP внутри контейнера - TLS-терминацию в этой схеме на себя берёт Traefik, а не сам Keycloak.

Healthcheck заслуживает отдельного слова: с определённой версии Keycloak health-эндпоинты переехали на отдельный management-порт 9000, а не висят на основном 8080 вместе с остальным приложением. Именно поэтому в healthcheck используется чистый bash через /dev/tcp вместо curl - в образе Keycloak его попросту нет, а тащить дополнительный пакет ради одной проверки не хочется.

Первый запуск и создание realm
#

Разворачиваем всё командой docker compose up -d, ждём, пока пройдёт healthcheck у базы и сам Keycloak поднимется - при первом старте это может занять заметно больше времени, чем последующие рестарты, так как сервис инициализирует внутренние схемы в PostgreSQL.

После этого заходим на https://keycloak.stilicho.ru (у вас, разумеется, будет свой домен) и логинимся под учёткой из KC_BOOTSTRAP_ADMIN_USERNAME/KC_BOOTSTRAP_ADMIN_PASSWORD. Дальше по порядку:

  1. Создаём отдельный realm. По умолчанию Keycloak предлагает работать в realm master, но это плохая практика - master предназначен для администрирования самого Keycloak, а не для ваших приложений. В левом верхнем углу выбираем Create realm, даём ему осмысленное имя (например, homelab).
  2. Создаём клиента. Внутри свежего realm идём в Clients → Create client, задаём Client ID (обычно совпадает с именем защищаемого сервиса), включаем нужный тип аутентификации (Standard flow для обычного веб-приложения через OIDC) и прописываем Valid redirect URIs - адрес, куда Keycloak будет возвращать пользователя после успешного входа.
  3. Заводим пользователей. В Users создаём нужные учётные записи, либо настраиваем интеграцию с внешним LDAP/Active Directory через User federation, если пользователи уже где-то есть и плодить их вручную не хочется.
  4. Настраиваем MFA при желании. В Authentication можно обязать конкретные группы пользователей проходить TOTP - это делается через flows, не требует правки конфигов и применяется сразу ко всем клиентам realm.

С этого момента любое приложение, поддерживающее OIDC или SAML, можно подключить к этому realm как отдельного клиента - и оно получит единый вход вместе со всеми остальными сервисами, подключёнными тем же способом.

Заключение
#

Keycloak - не самый лёгкий вариант для домашней лаборатории, и если вам нужен просто быстрый forward-auth перед парой сервисов, скорее всего, хватит Authelia или Authentik - я разбирал оба варианта в соседних статьях. Но если вы хотите разобраться с тем самым инструментом, который реально используют в enterprise, потренироваться на реалмах, федерации и делегированном администрировании, или у вас уже есть LDAP/Active Directory, которые нужно подключить как есть - Keycloak оправдывает свой вес с лихвой. Полное сравнение всех четырёх решений (включая ZITADEL) - в отдельной статье.

Ссылки
#

IAM-решения - This article is part of a series.
Part : This Article

Related

Authentik: обзор, архитектура, возможности и сравнение с Keycloak

··1013 слов·5 минут· loading · loading
Подробный обзор Authentik - open source системы для централизованной аутентификации и авторизации (IdP/SSO). Рассмотрим зачем нужны IAM-решения, архитектуру, ключевые функции и сравнение с альтернативами.

TOTP vs WebAuthn vs Passwordless: в чём разница и что выбрать

··1542 слов·8 минут· loading · loading
Подробно о TOTP, WebAuthn, passkeys и Passwordless Login: как они работают, их сильные и слабые стороны, а также рекомендации по выбору подходящей технологии для входа в свои сервисы.

Установка Authelia в Docker | Полный гайд

··827 слов·4 минут· loading · loading
Пошаговая инструкция по установке и настройке Authelia в Docker - развёртывание, конфигурация 2FA, интеграция с Traefik через forwardAuth и разбор основных параметров конфига.