Артём Ефимов

Расширение Keycloak · Apache-2.0

Keycloak Event Listener for RabbitMQ

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

Форк aznamier/keycloak-event-listener-rabbitmq для Keycloak 26. Mizzle Studio взяла его под своё крыло: можно рассчитывать на свежие релизы, которые работают с новыми версиями Keycloak, а потребители, написанные для 3.0.5, продолжают работать.

Скачать 4.1.0Исходный код на GitHub

Поддерживает Mizzle Studio

  • Релиз 4.1.0, 17 окт. 2026
  • Проверен на Keycloak 26.0–26.8
  • Java 17 и новее
  • RabbitMQ 3.x и 4.x
Очередь keycloak-events, привязанная к amq.topic ключом KK.EVENT.#: поверх прежних событий Keycloak приходят вход пользователя и создание пользователя администратором

Что делает расширение

Keycloak передаёт слушателю каждое событие пользователя (LOGIN, LOGOUT, REGISTER, LOGIN_ERROR, …) и каждое событие администратора (создан пользователь, выдана роль, изменён клиент, …) в тех realm, где вы его включили.

После коммита транзакции запроса слушатель публикует по одному JSON-сообщению на событие в обменник (exchange), по умолчанию amq.topic, с ключом маршрутизации вроде KK.EVENT.CLIENT.<realm>.<SUCCESS|ERROR>.<client>.<event type>.

Каждый потребитель привязывает свою очередь нужными ключами: все события, один realm, только ошибки, только изменения от администраторов.

  1. Keycloakсобытия пользователей и администраторов
  2. amq.topictopic-обменник, у каждого события свой ключ
  3. Ваши очередикаждая привязана нужными ключами

Для кого

Для команд, у которых работает Keycloak 26, а другим сервисам нужно реагировать на его события: синхронизация пользователей, которая следит за регистрациями и изменениями аккаунтов, оповещения об ошибках входа, реакция на удаление пользователей администраторами. Если вы пользуетесь расширением aznamier, ваши потребители продолжат работать без изменений.

Установка

Скачайте и проверьте jar-файл

В каждом релизе есть jar-файл и файл keycloak-to-rabbit.sha256, оба собраны в CI из тега релиза. Проверьте jar-файл до установки: Keycloak запускает jar-файлы провайдеров со всеми своими правами.

VERSION=4.1.0
BASE=https://github.com/Mizzle-Studio/keycloak-event-listener-rabbitmq/releases/download/v$VERSION
curl -fLO "$BASE/keycloak-to-rabbit-$VERSION.jar"
curl -fLO "$BASE/keycloak-to-rabbit.sha256"
sha256sum --check keycloak-to-rabbit.sha256

На macOS проверка — shasum -a 256 --check keycloak-to-rabbit.sha256. С версии 4.1.0 в релизах есть ещё SBOM и подписанная аттестация происхождения сборки (build provenance); её проверяет GitHub CLI:

gh attestation verify keycloak-to-rabbit-$VERSION.jar --repo Mizzle-Studio/keycloak-event-listener-rabbitmq

Установите его в Keycloak

  1. Положите jar-файл в каталог providers/ Keycloak (/opt/keycloak/providers/ в контейнерном образе) и удалите старые jar-файлы keycloak-to-rabbit. Если Keycloak запускается с --optimized, выполните kc.sh build.
  2. Укажите слушателю ваш брокер (см. Настройка) и перезапустите Keycloak.
  3. Включите слушатель в каждом realm: Realm settings › Events › Event listeners, добавьте keycloak-to-rabbitmq и нажмите Save. Или через kcadm.sh (список заменяет текущий):
kcadm.sh update realms/myrealm -s 'eventsListeners=["jboss-logging","keycloak-to-rabbitmq"]'

Для своего образа Keycloak в руководстве по установке есть Dockerfile, который при сборке скачивает jar-файл релиза и проверяет его контрольную сумму, а также примеры для Keycloak Operator и Helm-чартов.

Попробуйте в Docker Compose

Keycloak, RabbitMQ и слушатель на вашей машине: когда образы скачаны, всё готово примерно за полминуты.

git clone https://github.com/Mizzle-Studio/keycloak-event-listener-rabbitmq.git
cd keycloak-event-listener-rabbitmq/examples/docker-compose
docker compose up -d --wait

Войдите как демо-пользователь alice и прочитайте событие из очереди keycloak-events:

curl -s -o /dev/null -w '%{http_code}\n' \
  -d client_id=demo-app -d username=alice -d password=alice -d grant_type=password \
  http://localhost:8080/realms/demo/protocol/openid-connect/token

curl -s -u demo:demo -H 'content-type: application/json' \
  -d '{"count":1,"ackmode":"ack_requeue_false","encoding":"auto"}' \
  http://localhost:15672/api/queues/%2F/keycloak-events/get

Вторая команда выведет сообщение: ключ маршрутизации KK.EVENT.CLIENT.demo.SUCCESS.demo-app.LOGIN, свойства AMQP и событие в JSON. Интерфейс RabbitMQ открывается на http://localhost:15672 (demo / demo), а docker compose down -v всё удаляет. Это не продакшн-конфигурация: Keycloak работает в режиме разработки, пароли демонстрационные.

Настройка

Каждый параметр берётся из конфигурации провайдера Keycloak (spi-events-listener-keycloak-to-rabbitmq-<name>), затем из переменной окружения KK_TO_RMQ_<NAME>, затем из значения по умолчанию. При старте слушатель пишет в лог значение каждого параметра, пароли скрыты.

ПараметрПеременная окруженияПо умолчаниюПримечания
urlKK_TO_RMQ_URLlocalhostимя хоста брокера, не URI
portKK_TO_RMQ_PORT5672порт TLS укажите сами, обычно 5671
vhostKK_TO_RMQ_VHOSTпустопусто — значит /, виртуальный хост RabbitMQ по умолчанию; релизам до 4.1.0 нужно задать / явно
exchangeKK_TO_RMQ_EXCHANGEamq.topicдолжен существовать: слушатель его не объявляет
usernameKK_TO_RMQ_USERNAMEadminнужно только право записи в обменник
passwordKK_TO_RMQ_PASSWORDadminникогда не попадает в лог
use_tlsKK_TO_RMQ_USE_TLSfalseTLS включает только true
trust_storeKK_TO_RMQ_TRUST_STOREпустоPKCS12 или JKS; пусто — хранилище JVM по умолчанию, в котором есть доверенные сертификаты Keycloak
trust_store_passKK_TO_RMQ_TRUST_STORE_PASSпустопароль хранилища доверенных сертификатов; не попадает в лог
key_storeKK_TO_RMQ_KEY_STOREпустоPKCS12 с клиентским сертификатом, для взаимного TLS
key_store_passKK_TO_RMQ_KEY_STORE_PASSпустоон же пароль ключа; не попадает в лог

Задавайте параметры переменными KK_TO_RMQ_*, в командной строке (--spi-events-listener-keycloak-to-rabbitmq-use_tls=true) или в keycloak.conf и сохраняйте подчёркивания в именах: Keycloak 26.8 игнорирует переменные KC_SPI_… для пяти параметров с подчёркиванием в имени. Все способы, TLS и примеры — в руководстве по настройке.

Совместимость

keycloak-to-rabbitKeycloakJavaRabbitMQ
4.1.026.0 и новее в линии 26.x17 и новее (в образах Keycloak — 21)4.x и 3.x
исходный 3.0.5собран под 21.1.2; по его README — 16 и новее8 и новее—

На каждое изменение CI запускает интеграционный тест с настоящими контейнерами Keycloak и RabbitMQ и собранным jar-файлом: на последнем патч-релизе каждой линии Keycloak 26 от 26.0 до 26.7 и на 26.8.1 с RabbitMQ 4.3.6, а также на 26.8.1 с RabbitMQ 3.13. Раз в неделю отдельный workflow проверяет последний релиз и основную ветку на самом новом образе Keycloak, quay.io/keycloak/keycloak:latest; если тест не проходит, открывается issue с меткой keycloak-latest.

Релиз 4.1.0 прошёл интеграционный тест на:

Формат сообщений

Одно JSON-сообщение на событие. Ключи маршрутизации (из имён realm и клиента удаляются точки; <RESULT> — это SUCCESS или ERROR):

KK.EVENT.CLIENT.<REALM>.<RESULT>.<CLIENT>.<EVENT_TYPE>        события пользователей
KK.EVENT.ADMIN.<REALM>.<RESULT>.<RESOURCE_TYPE>.<OPERATION>   события администраторов
Ключ привязкиЧто придёт
KK.EVENT.#все события
KK.EVENT.CLIENT.#все события пользователей
KK.EVENT.ADMIN.#все события администраторов
KK.EVENT.*.myrealm.ERROR.#все ошибки в realm myrealm
KK.EVENT.CLIENT.*.SUCCESS.*.LOGINуспешные входы в любом realm
KK.EVENT.ADMIN.*.SUCCESS.USER.DELETEпользователи, удалённые администраторами

Вход в realm demo через клиент demo-app: ключ маршрутизации KK.EVENT.CLIENT.demo.SUCCESS.demo-app.LOGIN, свойства app_id=Keycloak, content_type=application/json и content_encoding=UTF-8, заголовок __TypeId__ и такое тело (details сокращены):

{
  "@class" : "com.github.aznamier.keycloak.event.provider.EventClientNotificationMqMsg",
  "time" : 1792178809437,
  "type" : "LOGIN",
  "realmId" : "b43f6f2c-1a03-40d4-a3c2-6cd8df8e49b6",
  "clientId" : "demo-app",
  "userId" : "05fce3fd-ee8b-4d27-bbbd-de6f3a29820b",
  "sessionId" : "gIOG9-ZDDp96Liom5YidaEd1",
  "ipAddress" : "172.24.0.1",
  "details" : {
    "auth_method" : "openid-connect",
    "grant_type" : "password",
    "username" : "alice"
  }
}

События администраторов, все поля и точные правила — в описании формата сообщений, а потребители на Spring Boot, Node.js и Python — в примерах потребителей.

Переход с aznamier 3.0.5

Потребителям ничего менять не нужно: на той же версии Keycloak слушатель публикует те же ключи маршрутизации, свойства AMQP, заголовки и поля JSON, что и aznamier/keycloak-event-listener-rabbitmq 3.0.5. Идентификатор провайдера по-прежнему keycloak-to-rabbitmq, поэтому настройки и экспорт realm остаются в силе, а каждый параметр сохраняет своё имя и переменную KK_TO_RMQ_*.

Что меняется на стороне Keycloak:

Порядок действий:

  1. Замените jar-файл в providers/ (или в своём образе) и выполните kc.sh build, если запускаете Keycloak с --optimized.
  2. Если используете TLS, убедитесь, что сертификату брокера доверяют и он выпущен на имя хоста из url.
  3. Если параметры заданы переменными KC_SPI_…, после обновления проверьте строки лога слушателя configuration:.
  4. Перезапустите Keycloak и следите за строками keycloak-to-rabbitmq ERROR.

Подробности и переход с форка focus-shift — в руководстве по переходу.

Частые вопросы

Как отправлять события Keycloak в RabbitMQ?

Установите этот слушатель: положите его jar-файл в каталог providers/ Keycloak, укажите брокер переменными KK_TO_RMQ_URL, KK_TO_RMQ_USERNAME и KK_TO_RMQ_PASSWORD, перезапустите Keycloak и добавьте keycloak-to-rabbitmq в слушатели событий каждого нужного realm. После этого каждое событие пользователя и администратора в этом realm публикуется в JSON в обменник, по умолчанию amq.topic, а ваши потребители привязывают очереди нужными ключами маршрутизации.

Публикует ли он события администраторов?

Да. Публикуется каждое событие администратора в realm, где включён слушатель: создание пользователя, выдача роли, изменение клиента и так далее. Ключ маршрутизации — KK.EVENT.ADMIN.<realm>.<SUCCESS|ERROR>.<resource type>.<operation>, например KK.EVENT.ADMIN.acme.SUCCESS.USER.CREATE. Изменённый ресурс лежит в поле representation — это JSON внутри строки. Настройки realm «Save events» не фильтруют то, что получает слушатель.

Какие версии Keycloak поддерживаются?

Keycloak 26.0 и новее в линии 26.x, на Java 17 и новее. CI проверяет jar-файл на последнем патч-релизе каждой линии Keycloak 26 от 26.0 до 26.7 и на 26.8.1, а еженедельный workflow — на самом новом релизе Keycloak. Работают RabbitMQ 4.x и 3.x; в CI — 4.3.6 и 3.13.

Можно ли просто заменить им расширение aznamier?

Для потребителей — да: идентификатор провайдера keycloak-to-rabbitmq, параметры и переменные окружения, имена Java-классов в @class и __TypeId__, ключи маршрутизации и поля JSON те же, что в 3.0.5 на той же версии Keycloak, и это закрепляют контрактные тесты, написанные ещё на 3.0.5. На стороне Keycloak вы меняете jar-файл: нужны Keycloak 26 и Java 17, сертификат TLS брокера проверяется, а пустой vhost с версии 4.1.0 означает /.

Как проверить релиз?

Рядом с jar-файлом в каждом релизе лежит keycloak-to-rabbit.sha256: выполните sha256sum --check keycloak-to-rabbit.sha256, а на macOS — shasum -a 256 --check keycloak-to-rabbit.sha256. С версии 4.1.0 в релизах есть ещё SBOM в формате CycloneDX и подписанная аттестация происхождения сборки; её проверяет gh attestation verify keycloak-to-rabbit-4.1.0.jar --repo Mizzle-Studio/keycloak-event-listener-rabbitmq. Сборка воспроизводима: тег релиза, собранный на Temurin 21, даёт ту же контрольную сумму.

Что будет, если RabbitMQ недоступен?

Keycloak продолжает работать: запросы выполняются, а их события отбрасываются с записью в лог. Доставка — не более одного раза (at most once), без повторов и буфера, поэтому для полного аудита опирайтесь на собственное хранилище событий Keycloak. До первого подключения хост брокера, который не отвечает, может задерживать запросы на время тайм-аута подключения клиента — до 60 секунд; после подключения клиент переподключается в фоне, а во время memory- или disk-alarm в RabbitMQ события отбрасываются, а не задерживают вход.