SSO на микросервисной архитектуре. Используем Keycloak. Часть №1

В любой крупной компании, и X5 Retail Group не исключение, по мере развития возрастает количество проектов, где требуется авторизация пользователей. С течением времени требуется бесшовный переход пользователей из одного приложения в другой и тогда возникает необходимость использования единого сервера Single-Sing-On (SSO). Но как быть, когда такие идентификационные провайдеры как AD или иные, не обладающие дополнительными атрибутами, уже используются в различных проектах. На помощь придет класс систем под названием «идентификационные брокеры». Наиболее функциональными являются его представители, такие как Keycloak, Gravitee Access management и пр. Чаще всего сценарии использования могут быть различны: машинное взаимодействие, участие пользователей и пр. Решение должно поддерживать гибкий и масштабируемый функционал, способный объединить все требования в одном, и такие решением в нашей компании сейчас является индикационный брокер — Keycloak.

hmbiehmxsfcq_cfltz8xj0mhrgc.jpeg
Keycloak — это продукт с открытым исходным кодом, предназначенный для идентификации и контроля доступа и поддерживаемый компанией RedHat. Он является основой для продуктов компании использующих SSO — RH-SSO.

Основные понятия


Прежде чем начать разбираться с решениями и подходами следует определиться в терминах и последовательности процессов:

mmj1c2uynwb23y5j4me13zzcrb4.png

Идентификация — это процедура распознавания субъекта по его идентификатору (проще говоря, это определение имени, логина или номера).

Аутентификация — это процедура проверки подлинности (пользователя проверяют с помощью пароля, письмо проверяют по электронной подписи и т.д.)

Авторизация — это предоставление доступа к какому-либо ресурсу (например, к электронной почте).

Идентификационный брокер Keycloak


Keycloak — это решение для управления идентификацией и доступом с открытым исходным кодом, предназначенное для использования в ИС где могут использоваться паттерны микросервисной архитектуры.

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

Базовый функционал, поддерживаемый в Keycloak:

  • Single-Sign On and Single-Sign Out для браузерных приложений.
  • Поддержка OpenID/OAuth 2.0/SAML.
  • Identity Brokering — аутентификация с помощью внешних OpenID Connect или SAML идентификационных провайдеров.
  • Social Login — поддержка Google, GitHub, Facebook, Twitter для идентификации пользователей.
  • User Federation — синхронизация пользователей из LDAP и Active Directory серверов и других идентификационных провайдеров.
  • Kerberos bridge — использование Kerberos сервера для автоматической аутентификации пользователей.
  • Admin Console — для единого управления настройками и параметрами решения через Web.
  • Account Management Console — для самостоятельного управления профилем пользователей.
  • Кастомизация решения на основе фирменного стиля компании.
  • 2FA Authentication — поддержка TOTP/HOTP с помощью Google Authenticator или FreeOTP.
  • Login Flows — возможна саморегистрация пользователей, восстановление и сброс пароля и прочие.
  • Session Management — администраторы могут управлять из единой точки сессиями пользователей.
  • Token Mappers — привязка атрибутов пользователей, ролей и иных требуемых атрибутов в токены.
  • Гибкое управление политиками через realm, application и пользователей.
  • CORS Support — клиентские адаптеры имеют встроенную поддержку CORS.
  • Service Provider Interfaces (SPI) — большое количество SPI, позволяющих настраивать различные аспекты работы сервера: потоки аутентификации, идентификационных провайдеров, сопоставление протоколов и многое другое.
  • Клиентские адаптеры для JavaScript applications, WildFly, JBoss EAP, Fuse, Tomcat, Jetty, Spring.
  • Поддержка работы с различными приложениями, поддерживающими OpenID Connect Relying Party library или SAML 2.0 Service Provider Library.
  • Возможность расширения с использованием plugins.


Для процессов CI/CD, а так же автоматизации процессов управления в Keycloak, может использоваться REST API/ JAVA API. Документация доступна в электронном виде:

REST API https://www.keycloak.org/docs-api/8.0/rest-api/index.html
JAVA API https://www.keycloak.org/docs-api/8.0/javadocs/index.html

Идентификационные провайдеры уровня предприятия (On-Premise)


Возможность аутентификации пользователей через User Federation сервисы.

8js9cl3cx9whnsshxcel0xynpqs.png

Также может быть использована сквозная аутентификация — если пользователи проходят аутентификацию на рабочих станциях с Kerberos (LDAP или AD), то они могут быть автоматически аутентифицированы на Keycloak без необходимости снова указывать свое имя пользователя и пароль.

Для аутентификации и дальнейшей авторизации пользователей возможно использование реляционной СУБД, что наиболее применимо для сред разработки, так как не влечет длительных настроек и интеграций на ранних стадиях проектов. По умолчанию в Keycloak используется встроенная СУБД для хранения настроек и данных о пользователях.

Список поддерживаемых СУБД обширен и включает в себя: MS SQL, Oracle, PostgreSQL, MariaDB, Oracle и другие. Наиболее протестированными на данный момент являются Oracle 12C Release1 RAC и Galera 3.12 cluster для MariaDB 10.1.19.

Идентификационные провайдеры — social login


Возможно использование логина из социальных сетей. Для активации возможности аутентифицировать пользователей используется консоль администратора Keycloack. Изменений в коде приложений не требуется и данный функционал доступен «из коробки» и может быть активирован в любой стадии реализации проекта.

bsrjvpxnw7eojom-_bv816iwoxk.png

Для аутентификации пользователей возможно использование OpenID/SAML Identity провайдеров.

Типовые сценарии авторизации с использование OAuth2 в Keycloak


Authorization Code Flow  — используется с серверными приложениями (server-side applications). Один из наиболее распространенных типов разрешения на авторизацию, поскольку он хорошо подходит для серверных приложений, в которых исходный код приложения и даные клиента не доступны посторонним. Процесс в данном случае строится на перенаправлении (redirection). Приложение должно быть в состоянии взаимодействовать с пользовательским агентом (user-agent), таким как веб-браузер — получать коды авторизации API перенаправляемые через пользовательский агент.

Implicit Flow — используется мобильными или веб-приложениями (приложения, работающие на устройстве пользователя).

Неявный тип разрешения на авторизацию используется мобильными и веб-приложениями, где конфиденциальность клиента не может быть гарантирована. Неявный тип разрешения также использует перенаправление пользовательского агента, при этом токен доступа передается пользовательскому агенту для дальнейшего использовании в приложении. Это делает токен доступным пользователю и другим приложениям на устройстве пользователя. При этом типе разрешения на авторизацию не осуществляется аутентификация подлинности приложения, а сам процесс полагается на URL перенаправления (зарегистрированный ранее в сервисе).

Implicit Flow не поддерживает токены обновления токена доступа (refresh tokens).
Client Credentials Grant Flow — используются при доступе приложения к API. Этот тип разрешения на авторизацию обычно используется для взаимодействий «сервер-сервер», которые должны выполняться в фоновом режиме без немедленного взаимодействия с пользователем. Поток предоставления учетных данных клиента позволяет веб-службе (конфиденциальному клиенту) использовать собственные учетные данные вместо олицетворения пользователя для проверки подлинности при вызове другой веб-службы. Для более высокого уровня безопасности возможно вызывающей службе использовать сертификат (вместо общего секрета) в качестве учетных данных.

Спецификация OAuth2 описана в 
RFC-6749
RFC-8252
RFC-6819

JWT токен и его преимущества


JWT (JSON Web Token) — открытый стандарт (https://tools.ietf.org/html/rfc7519), который определяет компактный и автономный способ для защищенной передачи информации между сторонами в виде JSON-объекта.

Согласно стандарту, токен состоит из трех частей в base-64 формате, разделенных точками. Первая часть называется заголовком (header), в которой содержится тип токена и название хэш-алгоритма для получения цифровой подписи. Вторая часть хранит основную информацию (пользователь, атрибуты и т.д.). Третья часть — цифровая подпись.

..
Никогда не сохраняйте токен в вашей БД. Потому что действительный токен эквивалентен паролю, хранить токен– это все равно, что хранить пароль в открытом виде.
Access-токен — это токен, который предоставляет доступ его владельцу к защищенным ресурсам сервера. Обычно он имеет короткий срок жизни и может нести в себе дополнительную информацию, такую как IP-адрес стороны, запрашивающей данный токен.

Refresh-токен — это токен, позволяющий клиентам запрашивать новые access-токены по истечении их времени жизни. Данные токены обычно выдаются на длительный срок.

Основные преимущества применения в микросервисной архитектуре:

  • Возможность доступа к различным приложениям и сервисам посредством единовременной аутентификации.
  • При отсутствии ряда требуемых атрибутов в профиле пользователей возможно дообогащение данными, которые могут быть добавлены в полезную нагрузку, в том числе и автоматизировано и «на лету».
  • Отсутствует необходимость хранения информации об активных сессиях, серверное приложение должно только проверить подпись.
  • Более гибкое управление доступом за счет дополнительных атрибутов в полезной нагрузке.
  • Применение подписи токена для заголовка и полезной нагрузки повышает безопасность решения в целом.


JWT токен — состав


Заголовок — по умолчанию, заголовок содержит только тип токена и алгоритм, используемый для шифрования.

Тип токена хранится в ключе «typ». Ключ «typ» игнорируется в JWT. Если ключ «typ» присутствует, его значение должно быть JWT, чтобы указать, что этот объект является JSON Web Token.

Второй ключ «alg» определяет алгоритм, используемый для шифрования токена. По умолчанию он должен быть установлен в HS256. Заголовок кодируется в base64.

{ «alg»: «HS256», «typ»: «JWT»}
Payload (содержимое) — в полезной нагрузке хранится любая информация, которую нужно проверить. Каждый ключ в полезной нагрузке известен как «заявление». К примеру, в приложение можно войти только по приглашению (закрытое промо). Когда мы хотим пригласить кого-то поучаствовать, мы отправляем ему письмо с приглашением. Важно проверить, что адрес электронной почты принадлежит человеку, который принимает приглашение, поэтому мы включим этот адрес в полезную нагрузку, для этого сохраним его в ключе «e-mail»

{ «email»: «example@x5.ru» }
Ключи в payload могут быть произвольными. Тем не менее, есть несколько зарезервированных:

  • iss (Issuer) — определяет приложение, из которого отправляется токен.
  • sub (Subject) — определяет тему токена.
  • aud (Audience) — массив чувствительных к регистру строк или URI, являющийся списком получателей данного токена. Когда принимающая сторона получает JWT с данным ключом, она должна проверить наличие себя в получателях — иначе проигнорировать токен.
  • exp (Expiration Time) — указывает, когда истекает срок действия маркера. Стандарт JWT требует, чтобы во всех его реализациях маркеры с истекшим сроком действия отклонялись. Exp ключ должен быть отметкой времени в unix формате.
  • nbf (Not Before) — это время в unix формате, определяющее момент, когда токен станет валидным.
  • iat (Issued At) — этот ключ представляет собой время, когда маркер был выдан и может быть использован для определения возраста JWT. iat ключ должен быть отметкой времени в unix формате.
  • Jti (JWT ID) — строка, определяющая уникальный идентификатор данного токена c учетом регистра.


Важно понимать, что полезная нагрузка не передается в зашифрованном виде (хотя, токены могут быть вложенными и тогда возможно передавать зашифрованные данные). Поэтому в ней нельзя хранить любую секретную информацию. Как и заголовок, полезная нагрузка кодируется в base64.
Подпись — когда у нас есть заголовок и payload, можно вычислить подпись.

Берутся закодированные в base64: заголовок и payload, они объединяются в строку через точку. Затем эта строка и секретный ключ поступает на вход алгоритма шифрования, указанного в заголовке (ключ «alg»). Ключом может быть любая строка. Более длинные строки будут наиболее предпочтительнее, поскольку потребуется больше времени на подбор.

{«alg»: «RSA1_5», «payload»: «A128CBC-HS256»}

Построение архитектуры отказоустойчивого кластера Keycloak


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

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

Для работы в режиме Active/Active и Active/Passive кластера требуется обеспечивать консистентность данных в реляционной базе данных — оба узла базы данных должны синхронно реплицироваться между различными геораспределенными ЦОД.

Самый простой пример отказоустойчивой инсталяции.

xotw7wkifwb3h6nnclvnjbbe72c.png

Какие преимущества дает использование единого кластера:

  • Высокая доступность и производительность.
  • Поддержка режимов работы: Active/Active, Active/Passive.
  • Возможность динамического масштабирования — при использовании контейнерной виртуализации.
  • Возможность централизованного управления и мониторинга.
  • Единый подход для идентификации/аутентификации/авторизации пользователей в проектах.
  • Более прозрачное взаимодействие между различными проектами без участия пользователей.
  • Возможность переиспользования JWT токена в различных проектах.
  • Единая точка доверия.
  • Более быстрый запуск проектов с использованием микросервисов/контейнерной виртуализации (не требуется поднятие и настройка дополнительных компонентов).
  • Возможно приобретение коммерческой поддержки от вендора.


На что стоит обратить внимание при планировании кластера


СУБД


Keycloak использует систему управления СУБД для сохранения: realms, clients, users и пр.
Поддерживается большой спектр СУБД: MS SQL, Oracle, MySQL, PostgreSQL. Keycloak поставляется с собственной встроенной реляционной базой данных. Рекомендуется использование для ненагруженных сред — такие как среды разработки.

Для работы в режиме Active/Active и Active/Passive кластера требуется обеспечивать консистентность данных в реляционной базе данных и оба узла кластера баз данных синхронно реплицируются между ЦОД.

Распределенный кеш (Infinspan)


Для корректной работы кластера требуется дополнительная синхронизация следующих типов кеша с использованием JBoss Data Grid:

Authentication sessions — используемый для сохранения данных при аутентификации конкретного пользователя. Запросы из этого кэша обычно включают только браузер и сервер Keycloak, а не приложение.

Action tokens — используются для сценариев, когда пользователю необходимо подтвердить действие асинхронно (по электронной почте). Например, во время потока forget password кэш actionTokens Infinispan используется для отслеживания метаданных о связанных маркерах действий, которые уже использовались, поэтому его нельзя использовать повторно.

Caching and invalidation of persistent data — используется для кэширования постоянных данных, чтобы избежать лишних запросов к базе данных. Когда какой-либо сервер Keycloak обновляет данные, все остальные серверы Keycloak во всех центрах обработки данных должны знать об этом.

Work — используется только для отправки сообщений о недействительности между узлами кластера и центрами обработки данных.

User sessions — используются для сохранения данных о сеансах пользователя, которые действительны в течение сеанса браузера пользователя. Кэш должен обрабатывать HTTP-запросы от конечного пользователя и приложения.

Brute force protection — используется для отслеживания данных о неудачных входах.

Балансировка нагрузки


Балансировщик нагрузки является единой точкой входа в keycloak и должен поддерживать sticky sessions.

Сервера приложений


Используются для контроля взаимодействия компонентов между собой и могут быть виртуализированы или контейнерезированы с применением имеющихся средств автоматизации и динамического масштабирования средств автоматизации инфраструктуры. Наиболее распространенные сценарии развертывания в OpenShift, Kubernates, Rancher.

На этом первая часть — теоретическая — закончена. В следующих циклах статей будут разобраны примеры интеграций с различными идентификационными провайдерами и примеры настроек.

© Habrahabr.ru