Привет, Хабр! На связи разработчик Куратов Кирилл из команды дирекции качества РТЛабс. Представлю вам нашу внутреннюю разработку — User Pool.

По названию понятно, что это пул пользователей, но глобально он представляет собой сервис для получения данных тестовых учётных записей. Наша команда использует User Pool во фреймворке для написания автотестов и в браузерном расширении для автоматической авторизации тестовых учётных записей в тестируемых сервисах. Например, в единой системе идентификации и аутентификации (ТЕСИА), речь о которой пойдёт ниже. Также в конце будет небольшая история о том, как мы разрабатывали расширение для браузера и с какими трудностями столкнулись.

ТЕСИА: сложный процесс авторизации с уникальными требованиями

Что такое ТЕСИА и зачем мы к ней обращаемся
Госуслуги — один из основных государственных сервисов и должен быть надёжным. Для его тестирования существуют разные стенды, на которых обкатываются услуги команд. Но это всё также нужно тестировать.

ТЕСИА используется как тестовый контур единой системы идентификации и аутентификации. В рамках User Pool мы обращаемся к ТЕСИА для получения авторизационных данных тестового пользователя, которые затем могут использоваться в автотестах, тестовых сценариях или браузерном расширении.

Важно понимать, что ТЕСИА — это не часть тестового фреймворка, а внешний сервис авторизации со своими требованиями к безопасности, стабильности и корректности запросов. Поэтому процесс авторизации через ТЕСИА отличается от обычной авторизации по логину и паролю: он может включать несколько последовательных шагов, обработку промежуточных ответов и получение итоговых авторизационных данных только после успешного прохождения всего сценария.

Также при авторизации через ТЕСИА может использоваться дополнительная проверка пользователя, например подтверждение входа одноразовым кодом. Для тестовых сценариев этот процесс должен быть предсказуемым, поэтому User Pool поддерживает обработку таких промежуточных шагов авторизации.

Если ТЕСИА возвращает требование дополнительного подтверждения, сервис выполняет необходимый этап сценария и продолжает авторизацию до получения итоговых авторизационных данных.

Отдельно хочу отметить, что в User Pool включена авторизация по ТЕСИА. В статье она постоянно будет встречаться, ниже напишу, почему для нас она так важна.

Проблемы с ЕСИА

  1. Сложный процесс авторизации. Для получения авторизационных данных в ТЕСИА нужно выполнить 3 шага: запросить авторизацию, подтвердить через смс или email и после этого получить авторизационные данные. Из-за этого авторизация становится трудоёмким и сложным для автоматизации процессом. Каждый стенд ТЕСИА, то есть тестовое окружение, имеет свои особенности и требует адаптации процесса авторизации.

  2. Разные роли и параметры учётных записей (УЗ). Тестовые УЗ в ТЕСИА имеют разные роли (ИП, организация, физическое лицо) и параметры (регион, сервис и др.). Это требует гибкого подхода к управлению УЗ, чтобы каждая команда могла запрашивать их с нужными параметрами и авторизационные данные приходили с определённого стенда.

Как User Pool решает проблемы с ТЕСИА

  1. Автоматизация процесса авторизации:

    — автоматизирует сложный процесс в ТЕСИА, выполняя вместо тестировщика все 3 шага. Это позволяет быстро получать авторизационные данные и использовать в тестах;
    — учитывает особенности разных стендов ТЕСИА, что делает процесс авторизации универсальным для всех окружений;

  2. Обработка дополнительных проверок при авторизации. При авторизации через ТЕСИА могут возникать дополнительные этапы проверки пользователя. User Pool поддерживает обработку таких сценариев и продолжает процесс авторизации до получения итоговых авторизационных данных.

  3. Гибкость для разных ролей и параметров УЗ:
    — предоставляет гибкий API, который позволяет каждой команде запрашивать УЗ с нужными параметрами. Например, можно запросить УЗ для конкретного сервиса или с определённой ролью — ИП, организация, физическое лицо;

    — каждая УЗ имеет набор параметров — дополнительных данных, которые учитываются при поиске. Это позволяет легко находить нужные УЗ для разных сценариев тестирования.

Для удобства и простоты понимания объединим эти данные в таблицу:

Проблема

Решение с User Pool

Разрозненные механизмы управления УЗ

Централизованное управление через API

Дублирование кода при работе с учётными данными в разных сервисах

Единая точка доступа, устраняющая необходимость дублирования

Необходимость синхронизировать изменения в разных частях системы

Единый сервис, упрощающий обновление логики работы с УЗ

Проблемы безопасности при хранении учётных данных на локальных машинах

Централизованное безопасное хранилище — Vault

Ограниченные возможности параллельного выполнения тестов

Механизм блокировки и освобождения УЗ

Почему существующие фреймворки не справились с ТЕСИА

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

Итог: свой велосипед лучше чужого грузовика

Иногда проще построить свою лёгкую и удобную модель, чем пытаться превратить многотонный грузовик в простой горный велосипед. User Pool — это именно тот случай. Мы выбрали нелёгкий путь, но в итоге получили решение, которое идеально подходит для наших задач и не требует постоянных костылей для адаптации чужого инструмента.

Отдаём предпочтение нашему сервису за преимущества
Отдаём предпочтение нашему сервису за преимущества

Почему выбрали свой путь: User Pool против Amazon Cognito, Keycloak и ORY Hydra & Kratos

Мы рассмотрели несколько популярных альтернатив — Amazon Cognito, Keycloak и ORY Hydra & Kratos — и пришли к выводу, что ни одно из них не подходит для наших задач. Почему?

Общие признаки у всех фреймворков

  • ТЕСИА — нетиповой флоу. Готовые IdP хорошо подходят для стандартных протоколов и типовых процессов входа, но не закрывают задачу получения авторизационных данных тестовой УЗ с учётом особенностей разных стендов и параметров УЗ. Поэтому для User Pool был выбран собственный подход, ориентированный на тестовые сценарии, работу с разными окружениями и удобную интеграцию с автотестами.

  • Нет модели аренды тестовых УЗ. Отсутствует нативная семантика lock/TTL/release для конкурентных прогонов. Нужен внешний механизм, например Redis, и свой API оркестрации.

  • Нет доменной аллокации аккаунтов. Сложная выборка по атрибутам — роль ФЛ/ЮЛ/ИП, сервис, environment, регион, история использования, и правила бронирования — это бизнес-логика, которую всё равно надо реализовывать в отдельном сервисе.

  • Инфра и операционная стоимость. Перенос авторизации в чужую платформу или стек ломает текущие предпосылки — whitelist IP к ТЕСИА, Vault, PostgreSQL, Redis, добавляет квоты или лимиты и рост TCO.

  • Избыточность. Большая часть функциональности прод-IAM нам не нужна, настройка или поддержка выше, чем у узкоспециализированного сервиса

Рассмотрим фреймы более подробно

Amazon Cognito

Природа: managed IdP в AWS. Поддерживает User Pools, Identity Pools, OIDC/OAuth2/SAML, Hosted UI, MFA и Lambda-триггеры.

Ограничения для нас:

  • не автоматизирует специфичный многошаговый сценарий авторизации через ТЕСИА. Для этого всё равно потребуется отдельная прикладная логика;

  • нет встроенной модели временной аренды тестовых УЗ — lock, TTL, release. Для этого потребуются Lambda-функции и внешнее хранилище;

  • доменная аллокация УЗ по роли, сервису, окружению, региону и истории использования всё равно должна реализовываться отдельным слоем;

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

Keycloak

Природа: OSS IdP/IAM. Поддерживает OIDC/OAuth2/SAML, realms, clients, roles, настраиваемые authentication flows, User Federation, Identity Brokering, расширение через SPI, внешнюю БД и кэш.

Ограничения для нас:

  • нет нативной модели временной аренды тестовых УЗ. Для сценариев lock, TTL и release потребуется внешний механизм хранения состояния и кастомная логика;

  • ЕСИА/ТЕСИА остаётся внешним специфичным сценарием авторизации. Keycloak сам по себе не выполняет прикладной процесс получения авторизационных данных тестовой УЗ;

  • сложная доменная выборка УЗ по роли, сервису, окружению, региону и истории использования всё равно должна быть реализована отдельно;

  • высокая операционная сложность: realms, flows, мапперы, провайдеры, темы, HA-настройки и сопровождение. Для задачи User Pool это избыточно, потому что основная цель сервиса — подобрать подходящую тестовую УЗ, временно забронировать её и вернуть результат для тестового сценария.

Как User Pool может пригодиться в вашем проекте

Допустим, у вас есть несколько микросервисов, которым нужны учётные данные пользователей, например для логина. В нашем приложении для тестировщиков есть функция автологина. Как это реализовать? Мы связываем наше приложение для автологина с User Pool, API которого предоставляет 4 базовые операции: Create, Delete, Update, Get.

Для автологина можно использовать методы: /api/v1/users/authUser — возвращает куку авторизации любого пользователя по параметрам.

Идеальное решение: API абстрагирует вас от подкапотных процессов, позволяя быть уверенными, что мы будем получать данные для автологина.

Стек технологий

User Pool реализован с использованием следующих технологий:

  • Java + Spring — основной язык и фреймворк, поскольку автотесты в проектах пишутся на Java,

  • PostgreSQL — основная база данных для хранения учётных записей и их атрибутов,

  • Vault — хранилище паролей и генерация токенов для безопасного доступа,

  • Feign Client (Apache Client) — удобный HTTP-клиент для работы с API,

  • OpenAPI Swagger — инструмент для документирования API.

Вот как примерно выглядит всё, что используется в User Pool:

Технологии, которые используются в User Pool
Технологии, которые используются в User Pool

Теперь можно рассмотреть весь процесс получения данных учётной записи. Для простоты понимания уйду от технической стороны и приведу упрощённое описание всех процессов.

Так как в нашей команде было принято решение сделать максимально защищённую систему авторизации и не возвращать пароли, в ответе используется кука. Во время запуска теста первым действием происходит запрос на авторизацию в сервисе ТЕСИА и получение самой куки. Внутренний метод фреймворка посылает запрос на адрес пула /userpool/api/v1/users/auth с телом запроса:

Запрос на адрес пула
Запрос на адрес пула

ответ на этот запрос:

Ответ на запрос
Ответ на запрос

Что же происходит под капотом запроса /auth? Тело запроса разбивается на составляющие, которые определят, какая УЗ будет взята.

Вот как выглядит DTO ответа с учётной записью:

DTO учетной записи
DTO учетной записи

Коротко, что за поля:

  • id — генерируемый id-номер учётной записи,

  • login — в нашем случае логин это email или СНИЛС,

  • additionalData — ключ-значение, в котором мы храним данные по УЗ для её удобного поиска,

  • service, environment — это информация для внутренних команд о принадлежности УЗ.

Эти параметры отправляются через search запрос в нашу БД, и ищется подходящая учётная запись.Теперь у нас есть ID УЗ и по нему мы берём пароль из Vault.

Реализация получения пароля через Vault простая:

Получение пароля через Vault
Получение пароля через Vault

Производим авторизацию через API ТЕСИА и вытаскиваем куку с токеном. Упрощённо схема получения cookie выглядит так:

Получение cookie
Получение cookie

С момента вызова метода авторизации пользователя происходит несколько действий:

  • данные для входа отправляются POST-запросом на ТЕСИА;

  • в ответ приходит ссылка для перехода, по которой мы выбираем роль, остальные параметры нужны для множества других случаев и разных департаментов, для классических госуслуг это не используется;

  • по итогу из всех cookies вытаскиваем cookie с авторизационными данными.

Авторизация через ТЕСИА

Код авторизации через ТЕСИА в документации не приводится, так как он содержит внутренние детали интеграции с внешним сервисом авторизации.

На уровне пользовательской документации важно понимать общий принцип работы: User Pool получает данные тестовой УЗ, определяет нужный сервис, окружение и роль пользователя, после чего запускает сценарий авторизации через ТЕСИА.

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

В общем виде процесс выглядит так:

  1. User Pool получает тестовую учётную запись и параметры авторизации.

  2. Определяет сервис, окружение и роль пользователя.

  3. Запускает сценарий авторизации через ТЕСИА.

  4. Обрабатывает ответ внешнего сервиса.

  5. При необходимости выполняет дополнительные поддерживаемые этапы авторизации.

  6. После успешного завершения возвращает результат в формате, удобном для автотестов, тестовых сценариев или браузерного расширения.

Такой подход позволяет скрыть сложность авторизации от тестировщика. Пользователю не нужно вручную проходить весь сценарий входа: достаточно выбрать подходящую тестовую УЗ или параметры поиска, а User Pool выполнит необходимые действия автоматически.

Учётная запись блокируется на то время, которое пришло в запросе или на 15 минут.

При завершении теста УЗ освобождается запросом: /userpool/api/v1/users/release/{id}, где id нам известен и хранится в тесте.

Графически все взаимодействия User Pool можно представить как:

Схема взаимодействий User Pool
Схема взаимодействий User Pool

Как User Pool пригодился в расширении для браузера

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

Суть нового расширения

Как говорилось выше, задача User Pool — сделать процесс авторизации на Госуслугах в тестовый контур наиболее безопасным. Это расширение само встраивает в cookies необходимые тестовые данные для авторизации в учётную запись.

Как это происходит глазами тестировщика

После добавления расширения в браузер оно появляется в соответствующем меню.

Расширение в меню браузера
Расширение в меню браузера

Можно увидеть 5 полей с тем, что надо заполнить. Самое нижнее — Token. Это токен для доступа к User Pool, который можно получить через команду поддержки.

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

Получение токена
Получение токена

Если токен рабочий и никаких ошибок не произошло, тестировщик увидит сообщение «Пользователь авторизован» и логин будет отображаться в поле «Recent used account».

На Госуслугах есть несколько ролей: физлица, ИП и организации. С учётом выбора в расширении роль тоже выбирается автоматически.

В качестве защиты от забывчивых тестировщиков, чтобы не морозить УЗ постоянно, мы сделали сессию 15 минут. По истечении времени появится сообщение с выбором продления или завершения сессии:

Окно завершения или продления сессии
Окно завершения или продления сессии

Подкапотная часть расширения

Рассмотрим, как устроено браузерное расширение и какие задачи оно решает внутри всей схемы авторизации.

Если User Pool отвечает за подбор тестовой УЗ, её временное бронирование и получение результата авторизации, то расширение отвечает за вторую часть процесса — применение этого результата в браузере. Именно расширение связывает действия тестировщика в интерфейсе, запросы к User Pool и дальнейшую работу в браузерной сессии.

Стек расширения достаточно простой: JavaScript, TypeScript и Node.js.

По объёму расширение заметно меньше, чем сам User Pool, но в разработке оно оказалось не таким простым, как может показаться на первый взгляд. Основные сложности были связаны не с бизнес-логикой, а с особенностями браузерных API, Manifest V3, фонового service worker, popup-интерфейса, состояния вкладок и ограничений платформы расширений.

Manifest.json

Любое браузерное расширение начинается с файла manifest.json. Это основной конфигурационный файл, который описывает браузеру, что представляет собой расширение, какие файлы нужно загрузить, какой интерфейс показать пользователю и какая фоновая логика должна быть запущена.

Проще говоря, manifest.json — это паспорт расширения.

В нём указываются:

  • название и описание расширения,

  • версия расширения,

  • версия формата manifest,

  • иконки разных размеров,

  • фоновый скрипт,

  • popup-интерфейс,

  • необходимые разрешения и возможности браузера.

В нашем случае расширение использует Manifest V3. Это актуальный формат расширений Chrome, в котором фоновая логика строится вокруг service worker. Такой подход отличается от старых версий manifest: фоновый скрипт не живёт постоянно, а запускается браузером при наступлении нужных событий.

Это важный момент, потому что при разработке приходится учитывать жизненный цикл service worker: он может быть остановлен и запущен заново, поэтому состояние расширения нельзя проектировать так, будто фоновый процесс всегда находится в памяти.

Popup-интерфейс

Пользователь взаимодействует с расширением через popup — небольшое окно, которое открывается при нажатии на иконку расширения.

В этом окне тестировщик выбирает параметры нужной учётной записи: группу, тип, роль или конкретный логин. После этого расширение передаёт выбранные параметры в основную логику и запускает процесс авторизации через User Pool.

На уровне идеи popup выполняет роль панели управления:

  • собирает параметры от пользователя;

  • отправляет команду на авторизацию;

  • показывает результат выполнения;

  • позволяет управлять текущей сессией.

Применение результата авторизации

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

После того как User Pool нашёл подходящую тестовую УЗ и выполнил авторизационный сценарий, расширение получает результат и подготавливает браузер к дальнейшей работе. Благодаря этому тестировщик может перейти к нужному сервису уже в авторизованном состоянии, без ручного прохождения всего процесса входа.

На верхнем уровне это выглядит так:

  1. Расширение получает результат авторизации от User Pool.

  2. Определяет активный браузерный контекст.

  3. Учитывает выбранное тестовое окружение.

  4. Применяет результат авторизации к текущей сессии.

  5. Открывает или подготавливает нужную страницу для дальнейшей работы.

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

Управление временем сессии

Ещё одна важная задача расширения — контроль времени использования тестовой УЗ.

Так как User Pool работает с моделью временного бронирования УЗ, расширение должно понимать, что сессия не бесконечная. Учётная запись выдаётся на ограниченное время, после чего её нужно либо продлить, либо освободить.

Для этого в расширении есть механизм таймеров и уведомлений. Когда время использования УЗ подходит к концу, расширение показывает уведомление пользователю. В уведомлении предлагается выбрать дальнейшее действие: продлить работу или завершить сессию.

Такой механизм нужен по двум причинам.

Во-первых, он помогает тестировщику не потерять сессию внезапно. Пользователь заранее видит предупреждение и может продлить работу, если сценарий ещё не завершён.

Во-вторых, он защищает сам пул УЗ от зависших сессий. Если УЗ больше не используется, она должна быть освобождена и возвращена обратно в пул, чтобы её могли использовать другие тесты или другие пользователи.

Авторизация через User Pool

Ключевая функция расширения — запуск авторизации через User Pool.

Тестировщик выбирает параметры в popup-интерфейсе, после чего расширение формирует запрос к User Pool. На стороне User Pool происходит поиск подходящей УЗ, её временное бронирование и запуск авторизационного сценария.

На уровне статьи процесс можно описать так:

  1. Расширение проверяет, нет ли уже активной сессии.

  2. Если активная сессия есть, она предварительно завершается.

  3. Расширение собирает параметры, выбранные пользователем.

  4. User Pool подбирает подходящую тестовую УЗ.

  5. Выполняется авторизация в тестовом контуре.

  6. Расширение получает результат и применяет его в браузере.

  7. Пользователь продолжает работу уже в авторизованном состоянии.

Важная деталь: расширение не просто «логинит пользователя». Оно участвует в общей модели управления тестовыми УЗ. То есть оно должно не только начать сессию, но и корректно завершить её.

Освобождение учётной записи

После завершения работы расширение освобождает тестовую УЗ в User Pool. Это обязательный этап, потому что одна и та же УЗ не должна одновременно использоваться несколькими тестировщиками или несколькими параллельными автотестами. Если УЗ не освобождать, пул быстро начнёт забиваться зависшими бронированиями и подходящие учётные записи перестанут находиться.

Общий процесс освобождения выглядит так:

  1. Расширение проверяет, есть ли активная УЗ.

  2. Если активная УЗ есть, расширение сообщает User Pool, что работа с ней завершена.

  3. Локальное состояние расширения очищается.

  4. Таймеры сессии сбрасываются.

  5. Учётная запись возвращается обратно в пул.

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

Итоговая схема работы расширения

В упрощённом виде работа расширения выглядит следующим образом:

  1. Тестировщик открывает popup расширения.

  2. Выбирает параметры нужной тестовой УЗ.

  3. Расширение обращается к User Pool.

  4. User Pool подбирает подходящую УЗ и выполняет авторизационный сценарий.

  5. Расширение применяет результат авторизации к браузерной сессии.

  6. Тестировщик работает с нужным сервисом в авторизованном состоянии.

  7. Перед завершением сессии расширение показывает уведомление.

  8. Пользователь продлевает сессию или завершает работу.

  9. После завершения работы расширение освобождает УЗ и возвращает её обратно в пул.

На первый взгляд расширение выглядит небольшой частью системы. Но на практике именно оно делает процесс удобным для тестировщика: убирает ручной вход, связывает браузер с User Pool, контролирует время использования УЗ и помогает корректно возвращать аккаунты обратно в пул.

Схема работы расширения
Схема работы расширения

Заключение

Для тех, кто сразу бежит в конец статьи, я собрал основную информацию, чтобы у вас был стимул прочитать её полностью.

User Pool доказал свою эффективность как специализированное решение для управления тестовыми учётными записями. В отличие от стандартных IAM-систем, он предлагает:

  • гибкость API — адаптированную под нужды тестировщиков;

  • высокую производительность — за счёт использования выбранных технологий;

  • безопасность — благодаря хранению данных в Vault и механизму временной блокировки учётных записей.

В сравнении с Amazon Cognito, Keycloak и ORY Hydra & Kratos наш сервис выигрывает в кастомизации и скорости работы.

Глобальное значение User Pool для нас

User Pool представляет собой не просто инструмент для управления УЗ, а часть экосистемы тестирования, направленной на упрощение работы команд QA.

Результаты от использования User Pool

  • Сократили затраты времени на подготовку тестовых данных

  • Минимизировали риск утечки конфиденциальных данных тестовых пользователей

  • Автоматизировали процессы управления УЗ, что дало возможность запускать тесты параллельно без конфликтов данных

  • Повысили безопасность тестирования за счёт использования централизованных механизмов хранения и доступа.

Благодаря гибкости архитектуры User Pool может быть адаптирован для использования в различных проектах, требующих безопасного управления тестовыми данными. Его принципы могут быть полезны не только в тестировании государственных сервисов, но и в корпоративных системах, где важна строгая регуляция доступа к тестовым УЗ.

Будущее развитие

Мы планируем:

  • расширить функциональность API для более удобной работы с УЗ;

  • внедрить дополнительные механизмы масштабирования и оптимизации запросов;

  • усилить интеграцию с тестовыми фреймворками, инструментами DevOps и расширение на большее количество команд;

  • разработать механизм детального логирования использования УЗ для повышения прозрачности процессов и отслеживания их использования;

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

Это значит, что User Pool продолжит эволюционировать, обеспечивая удобное и безопасное управление тестовыми УЗ, сокращая затраты времени тестировщиков и повышая надёжность автоматизированного тестирования.

Если у вас есть собственные решения для управления тестовыми учётными записями, делитесь своим опытом в комментариях.