Как я KeyCloak побеждал

от автора

Как я себя чувствовал

Как я себя чувствовал

Привет, Хабр! Меня зову Амир и я хотел бы сегодня поделиться с Вами своим опытом поднятия сервиса 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)

На этом моменте я прям залип знатно, т.к. в интернетах приводятся вагон вариаций исполнения, но к сожалению много устаревших либо не подходящих по типу сертификата

  1. Копируем root сертификат в /opt/keycloak/cert

  2. Выполняем команды

    keytool -importkeystore -srckeystore cert.pfx -srcstoretype pkcs12 -destkeystore ./cert.jks -deststoretype pkcs12 cd /opt/keycloak/cert

    Указываем пароль от сертификата cert.pfx и назначаем пароль для keystore

  1. В docker-compose прокидываем cert.jks

volumes:       - ./cert/cert.jks:/etc/x509/https/truststore.jks
  1. В файле .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

Заходим под admin / admin

Подключаем AD

Создаем свой Realm
Идем в User federation и создаем Ldap providers

Далее действовал по описанию в статье

https://habr.com/ru/companies/swordfish_security/articles/533264/

Ребятам и Swordfish Security огромное спасибо за статью

По обычаю, принимаясь за задачу по KC хотел уже потратить день другой на блогах и форумах в поисках решения/гайда, как тут уже все написано 🙂

Подключаем Kafka

Заходим в Realm settings, переходим в Events, в селекте выбираем kafka

Теперь все события произведенные в админе будут отправляться в топик указанный в .env admin, а пользовательские события login/logout в топик user

Настройка Client

Создаем Client

Оставляем все настройки как есть

Оставляем все настройки как есть

После создания в настройках обязательно указываем разрешенные URL откуда можем обращаться и т.д.

Создаем client scope audience, что бы добавить аудиенцию клиента в токен.

add client scope

add client scope
create client scope

create client scope

Переходим на вкладку Mappers, жмём на Configure a new mapper

Audience

Audience
add mapper

add mapper

Name — указываете как удобно
Included Client Audience — выбираем нашего клиента

Сохраняем.

Добавляем наш scope нашему клиенту

Переходим в меню Clients — вкладка Client scopes — Add client scope

Add client scope

Add client scope

Выбираем наш scope и добавляем с признаком Default

Создание роли доступа для нашего client

Realm roles

Realm roles

Меню — Realm roles — Create role

Можно заполнить подобным образом

Можно заполнить подобным образом

Создание группы пользователей для доступа в наш client

Groups

Groups

Меню — Groups — Create group

Название я предпочитаю задавать для групп доступа = client id

Role mapping

Role mapping

Связываем роль доступа с нашей группой на вкладке Role mapping

Assign roles to my-client account

Assign roles to my-client account

Создание Flow для аутентификации через браузер для нашего клиента

Меню — authentication — Flows — дублируем browser

Далее формируем следующую структуру

Странно, но не думал что ситуация которую мне нужно было разрешить, настолько редкая и по этой тепе в интернете было совсем мало инфы (нуууу очень мало). Решение нашел на 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
Deny access config

Deny access config
Должно получиться так

Должно получиться так

Далее, указываем наш созданный Flow как основной для Client

advanced

advanced

Если сейчас мы попробуем пройти авторизацию в KC через адаптер keycloak-js получим следующий результат

У Вас нет доступа в my-client

У Вас нет доступа в my-client

Добавление пользователя в группу доступа к my-client

Меню — members — Add member — выбираем пользователя из локальной базы или импортированного из AD

Далее пробуем пройти авторизацию через адаптер keycloak-js, получим результат «Успешная авторизация» с получением токена и редиректа на страницу указанную в настройках Client.

Итог

В этой мы рассмотрели реализацию авторизации в нашем приложении через популярное SSO ПО KeyCloak. Надеюсь было написано исчерпывающе, т.к. во время настройки всего я испытал много боли и может это кому то поможет.

Спасибо за прочтение.


ссылка на оригинал статьи https://habr.com/ru/articles/856532/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *