![Как я себя чувствовал Как я себя чувствовал](https://habrastorage.org/getpro/habr/upload_files/6d2/e55/8b4/6d2e558b4b48f340b46c809c23886c36.png)
Привет, Хабр! Меня зову Амир и я хотел бы сегодня поделиться с Вами своим опытом поднятия сервиса SSO на базе решения KeyCloak.
Вводные:
Требования со стороны бизнеса:
-
Для внутренних сервисов компании требуется единая точка входа с подключением пользователей из существующей Active Directory.
-
Требуется что бы пользователь мог иметь доступ к одному или нескольким сервисам (в каждом из сервисов имел одну или несколько ролей). Если доступ к тому или иному сервису отсутствует, сообщать ему об этом.
Требования взаимодействия с КС
-
KC должен работать по https.
-
На стороне фронта будет использоваться пакет от KC https://www.npmjs.com/package/keycloak-js.
-
Возможность отправлять события в Kafka
Требования развертки
-
KC должен быть развернут в Docker с помощью Docker compose
Версия KC: 25.0.2, так же проверял на версии 26.0.0 (тоже норм)
Ну вот с вводными разобрались, теперь приступим к реализации.
Build and deploy
Dockerfile
FROM keycloak/keycloak:25.0.2 COPY keycloak-kafka-1.1.5.jar /opt/keycloak/providers/ ENTRYPOINT ["/opt/keycloak/bin/kc.sh"]
Для подключения Kafka к CK используем keycloak-kafka-1.1.5
Dokcer-compose.yaml
version: "3.9" services: keycloak: image: my_docker_hub/keycloak:latest volumes: - ./themes:/opt/keycloak/themes - ./cert/cert.jks:/etc/x509/https/truststore.jks container_name: keycloak ports: - "8443:8443" env_file: ./.env command: start depends_on: keycloak-postgres: condition: service_healthy healthcheck: test: [ "CMD-SHELL", "exec 3<>/dev/tcp/127.0.0.1/9000;echo -e 'GET /health/ready HTTP/1.1\r\nhost: http://localhost\r\nConnection: close\r\n\r\n' >&3;if [ $? -eq 0 ]; then echo 'Healthcheck Successful';exit 0;else echo 'Healthcheck Failed';exit 1;fi;", ] start_period: 10s interval: 30s retries: 3 timeout: 5s keycloak-postgres: container_name: keycloak-postgres image: postgres volumes: - ./db/data:/var/lib/postgresql/data env_file: ./.env healthcheck: test: pg_isready -d postgres interval: 10s timeout: 5s retries: 3 start_period: 5s
.env
KC_FEATURES: preview KC_HEALTH_ENABLED: true KC_METRICS_ENABLED: true KC_HOSTNAME: host_keycloak KC_HTTPS_PORT: 8443 KC_HTTPS_KEY_STORE_PASSWORD=STORE_PASSWORD KC_HTTPS_KEY_STORE_FILE=/etc/x509/https/truststore.jks KC_PROXY_HEADERS: xforwarded KEYCLOAK_ADMIN: admin KEYCLOAK_ADMIN_PASSWORD: admin KAFKA_TOPIC: user.event.user KAFKA_ADMIN_TOPIC: user.event.admin KAFKA_CLIENT_ID: keycloak KAFKA_BOOTSTRAP_SERVERS: BOOTSTRAP_SERVERS KAFKA_EVENTS: LOGIN,LOGOUT KC_DB: postgres KC_DB_URL: jdbc:postgresql://keycloak-postgres:5432/keycloak KC_DB_USERNAME: keycloak KC_DB_PASSWORD: keycloak KC_DB_SCHEMA: public POSTGRES_DB: keycloak PGUSER: keycloak POSTGRES_USER : keycloak POSTGRES_PASSWORD : keycloak PGPASSWORD: password
Процесс сборки и развертывания опускаю, т.к. там ничего интересного нет.
Настраиваем HTTPS (В моем случае у меня есть root cert)
На этом моменте я прям залип знатно, т.к. в интернетах приводятся вагон вариаций исполнения, но к сожалению много устаревших либо не подходящих по типу сертификата
-
Копируем root сертификат в /opt/keycloak/cert
-
Выполняем команды
keytool -importkeystore -srckeystore cert.pfx -srcstoretype pkcs12 -destkeystore ./cert.jks -deststoretype pkcs12 cd /opt/keycloak/cert
Указываем пароль от сертификата cert.pfx и назначаем пароль для keystore
-
В docker-compose прокидываем cert.jks
volumes: - ./cert/cert.jks:/etc/x509/https/truststore.jks
-
В файле .env
Прописываем следующие переменные
KC_HOSTNAME: host_keycloak KC_HTTPS_PORT: 8443 KC_HTTPS_KEY_STORE_PASSWORD=STORE_PASSWORD KC_HTTPS_KEY_STORE_FILE=/etc/x509/https/truststore.jks KC_PROXY_HEADERS: xforwarded
После развертывания через Docker compose, можем открывать KC.
Поздравляю! До этого момента я добирался долго )
https://host_name:8443/
![Стартовая страница KC Стартовая страница KC](https://habrastorage.org/getpro/habr/upload_files/5e5/3b9/8ce/5e53b98ce6986d822ebe0cab53bfb5f9.png)
Заходим под admin / admin
Подключаем AD
Создаем свой Realm
Идем в User federation и создаем Ldap providers
![](https://habrastorage.org/getpro/habr/upload_files/d36/fb4/e12/d36fb4e1274723e07ed5cabe74a39cac.png)
Далее действовал по описанию в статье
https://habr.com/ru/companies/swordfish_security/articles/533264/
Ребятам и Swordfish Security огромное спасибо за статью
По обычаю, принимаясь за задачу по KC хотел уже потратить день другой на блогах и форумах в поисках решения/гайда, как тут уже все написано 🙂
Подключаем Kafka
Заходим в Realm settings, переходим в Events, в селекте выбираем kafka
![](https://habrastorage.org/getpro/habr/upload_files/8e8/3d8/f26/8e83d8f26786d515a0ce683f83bc6eef.png)
Теперь все события произведенные в админе будут отправляться в топик указанный в .env admin, а пользовательские события login/logout в топик user
Настройка Client
Создаем Client
![](https://habrastorage.org/getpro/habr/upload_files/d24/430/752/d244307526b942b1fd41889ac5bd1b43.png)
![Оставляем все настройки как есть Оставляем все настройки как есть](https://habrastorage.org/getpro/habr/upload_files/50e/b72/114/50eb7211410c15f768d9058f498071fe.png)
После создания в настройках обязательно указываем разрешенные URL откуда можем обращаться и т.д.
![](https://habrastorage.org/getpro/habr/upload_files/aa9/44b/319/aa944b3198ccea192f363223d595f13f.png)
Создаем client scope audience, что бы добавить аудиенцию клиента в токен.
![add client scope add client scope](https://habrastorage.org/getpro/habr/upload_files/6ae/304/6fc/6ae3046fc7c408a4bd94ac05102350a7.png)
![create client scope create client scope](https://habrastorage.org/getpro/habr/upload_files/075/e3b/c83/075e3bc83018aafae3fbe07e49bb162c.png)
Переходим на вкладку Mappers, жмём на Configure a new mapper
![Audience Audience](https://habrastorage.org/getpro/habr/upload_files/e05/29c/f5b/e0529cf5b83e20123f093feea85cab7b.png)
![add mapper add mapper](https://habrastorage.org/getpro/habr/upload_files/e54/e0a/762/e54e0a762282d310758336fc845fab8f.png)
Name — указываете как удобно
Included Client Audience — выбираем нашего клиента
Сохраняем.
Добавляем наш scope нашему клиенту
Переходим в меню Clients — вкладка Client scopes — Add client scope
![Add client scope Add client scope](https://habrastorage.org/getpro/habr/upload_files/eb4/616/590/eb461659073f87c23d36ab6f23f3f8e0.png)
Выбираем наш scope и добавляем с признаком Default
Создание роли доступа для нашего client
![Realm roles Realm roles](https://habrastorage.org/getpro/habr/upload_files/4e4/343/f96/4e4343f96c7b350ac61cece497b4c33a.png)
Меню — Realm roles — Create role
![Можно заполнить подобным образом Можно заполнить подобным образом](https://habrastorage.org/getpro/habr/upload_files/0aa/7c2/038/0aa7c20382f98ea787c893173c288ead.png)
Создание группы пользователей для доступа в наш client
![Groups Groups](https://habrastorage.org/getpro/habr/upload_files/35b/445/585/35b445585e308a1f17a7ff35fa384291.png)
Меню — Groups — Create group
Название я предпочитаю задавать для групп доступа = client id
![Role mapping Role mapping](https://habrastorage.org/getpro/habr/upload_files/612/754/0b1/6127540b10ff2152209cdb3c58f87c2e.png)
Связываем роль доступа с нашей группой на вкладке Role mapping
![Assign roles to my-client account Assign roles to my-client account](https://habrastorage.org/getpro/habr/upload_files/67a/b84/920/67ab8492080729743e79d29cf318a861.png)
Создание Flow для аутентификации через браузер для нашего клиента
Меню — authentication — Flows — дублируем browser
![](https://habrastorage.org/getpro/habr/upload_files/22b/c00/38d/22bc0038d180d1bdda4b2e9a3d2dc21f.png)
![](https://habrastorage.org/getpro/habr/upload_files/cbc/b3d/cf6/cbcb3dcf6bd58668f0b88f7bd2eb016c.png)
Далее формируем следующую структуру
Странно, но не думал что ситуация которую мне нужно было разрешить, настолько редкая и по этой тепе в интернете было совсем мало инфы (нуууу очень мало). Решение нашел на stackoverflow, которое было представлено в виде скрина, которое в итоге было модифицировано 🙂
Flow - Required: { name: Login: <Название клиента> } Step - Alternative: Cookie Step - Alternative: Identity Provider Redirector config Flow - Alternative: { name: gated browser form: <Название клиента> } Step - Required: Username Form Flow - Conditional: { name: gated browser form - Conditional OTP Form config: <Название клиента> } Condition - Required: Condition - user configured Step - Required: OTP Form Flow: { name: RBA - Conditiona: <Название клиента> } Condition - Required: Condition - user role { Alias: user role <Название клиента>, User role: Выбираем роль созданную для нашего Client, Negate output: On } Step - Required: Deny access { Alias: Deny access config <Название клиента>, Error message: Доступ в приложение <Название приложения> запрещен }
![Condition - user role config Condition - user role config](https://habrastorage.org/getpro/habr/upload_files/518/e82/3e6/518e823e65421d1f6b43b54f10dec8e3.png)
![Deny access config Deny access config](https://habrastorage.org/getpro/habr/upload_files/45d/6c4/1fc/45d6c41fc98d8ed869ba965ccacee267.png)
![Должно получиться так Должно получиться так](https://habrastorage.org/getpro/habr/upload_files/562/cb2/7f9/562cb27f9aaf29154333f77d27b85ace.png)
Далее, указываем наш созданный Flow как основной для Client
![advanced advanced](https://habrastorage.org/getpro/habr/upload_files/581/2e2/eb6/5812e2eb6cc52988a4d18bc002ae736f.png)
![](https://habrastorage.org/getpro/habr/upload_files/2b4/e8d/271/2b4e8d27136bffe5b677caf641b151d1.png)
Если сейчас мы попробуем пройти авторизацию в KC через адаптер keycloak-js получим следующий результат
![У Вас нет доступа в my-client У Вас нет доступа в my-client](https://habrastorage.org/getpro/habr/upload_files/dc0/9af/57f/dc09af57f8411fc935578e4a7ab2cac4.png)
Добавление пользователя в группу доступа к my-client
Меню — members — Add member — выбираем пользователя из локальной базы или импортированного из AD
![](https://habrastorage.org/getpro/habr/upload_files/f2b/1a6/497/f2b1a6497a71dba5677f55540a4ab0ca.png)
Далее пробуем пройти авторизацию через адаптер keycloak-js, получим результат «Успешная авторизация» с получением токена и редиректа на страницу указанную в настройках Client.
Итог
В этой мы рассмотрели реализацию авторизации в нашем приложении через популярное SSO ПО KeyCloak. Надеюсь было написано исчерпывающе, т.к. во время настройки всего я испытал много боли и может это кому то поможет.
Спасибо за прочтение.
ссылка на оригинал статьи https://habr.com/ru/articles/856532/
Добавить комментарий