Задача 1. Предложите архитектурное решение и доработайте диаграмму C4 для управления учётными данными пользователя.
Решение должно учитывать и обеспечивать следующие аспекты:
- Унификацию доступа в системе BionicPRO. Это будет осуществляться через запрос данных учётных записей из внешнего источника, который расположен в стране представительства компании. Принципы локального хранения персональной и медицинской информации не должны быть нарушены.
- Безопасную схему работы с access- и refresh-токенами, которая исключает передачу фронтенду токенов, которые были получены от IdP.
- Возможность поддержки аутентификации пользователей через различные внешние удостоверяющие службы, действующие в разных странах.
Для подготовки архитектуры решения используйте draw.io.
Задача 2. Улучшите безопасность существующего приложения, заменив Code Grant на PKCE.
Его нужно добавить к уже существующим приложениям — фронтенду и Keycloak. Мы неслучайно не рассказывали в теории, как это сделать. Чтобы разобраться, изучите официальную документацию.
Использовал PKCE во фронтенде и бэкэнде.
Задача 3. Обеспечьте безопасное получение и хранение access-и refresh-токенов.
- Перенесите механизм запроса access- и refresh-токен из фронтенда в новый бэкенд-сервис, который реализует интеграцию с Keycloak и работу с сессиями.
- Назовите сервер bionicpro-auth. Написать его можно на любом из стандартных для бэкенда языков — Java, C#, Go, Python. Можно использовать либы и фреймворки.
- Ограничений по выбору языка нет. Можно использовать фреймворки и библиотеки для реализации задания, например, для Java — Spring Security.
- Настройте Keycloak на работу с refresh_token. Установите время работы access_token — не более 2 минут.
- При успешной авторизации на бэкенде сохраните refresh_token на защищённом хранилище или в зашифрованном виде в оперативной памяти, или в распределённом кеше.
- Сохраните access_token в оперативной памяти сервера либо в распределённом кеше.
- Обеспечьте привязку access_token и refresh_token к сессии.
- В ответе фронтенду вместо токенов отдайте сессионную cookie c HTTP-only и Secure-флагами.
- Время жизни сессии должно быть больше времени жизни access_token, чтобы при истечении access_token можно было обновить access_token через refresh_token. 10. Обновите код фронтенд-приложения, убрав из него механизм получения токенов и сделав обязательным прокидывание на бэкенд сессионной cookie. 11. Если access_token устареет, то сервис сам должен сходить за новым в keycloak, используя refresh token. 12. Реализуйте ротацию сессии в рамках действующего access_token для предотвращения session fixation attack. Для этого при очередном запросе к защищённому ресурсу при успешной проверке сессии на сервисе он перепривязывает access_token и refresh_token к новому session id, обновляет cookie и возвращает новый session id в ответе фронтенду.
Создал сервис bionicpro-auth на C++, овтечающий требованиям. Так же добавил cpp_builder для ускоренной компиляции проектов и bionicpro-openid как общую библиотеку с другим бэкэнд сервисом.
Задача 4. Добавьте LDAP для возможности получения данных о пользователях представительства BionicPRO в другой стране.
- Разверните LDAP-сервер OpenLDAP. Файл конфигурации развёртывания и также файл ldif с пользователями и ролями лежит в репозитории спринта.
- Настройте Keycloak, чтобы он ходил в LDAP-сервер за авторизацией пользователей.
- Добавьте маппинг ролей для синхронизации ролей разных представительств BionicPRO.
Добавил LDAP сервер (конфиг config.ldif), подключил его к Keycloak. С трудом перенёс конфигурацию в читаемый вид конфига realm-export.json.
Задача 5. Настройте MFA.
- Настройте в Keycloak механизм OTP-аутентификации.
- Включите обязательный ввод одноразового пароля для всех пользователей.
- Убедитесь, что под пользователем можно войти в систему только после ввода одноразового пароля из Google Authenticator или FreeOTP.
Настроил OTP-аутентификацию для пользователя, которого нет в приложенном конфиге.
Задача 6. Добавьте OAuth 2.0 от Яндекс ID.
- Используя механизм Identity Brokering, реализуйте аутентификацию пользователей через внешний Identity Prodider Яндекс ID. Обратите внимание, что сервис протезов получает данные профиля пользователя из Яндекса.
- После аутентификации сервис должен спрашивать пользователя о разрешении использовать данные.
- Сервис должен запрашивать у Яндекса данные профиля и сохранять их в БД.
Успешно произвёл эти манипуляции в ручном режиме, но не стал добавлять это в сервис, т.к. это не может работать во время ревью: для работы нужен "ClientID" и "Client secret", которые могли бы скомпроментировать мой аккаунт. Выкладывание секрета в публичный репозиторий нежелательно, потому что им может воспользоваться злоумышленник, а без секрета конфигурация не заработает.
Но концепция ясна: настраиваем Keycloak на работу с Яндексом, и разрешаем конфликты scope (openid, email, profile -> login:info login:email). Либо через прокси-приложение, которое бы переправляло запросы с Keycloak в Яндекс и обратно, либо через mapper этих самых scope'ов в конфигурации Keycloak. Первое проще, второе оптимальнее.
Задача 1. Создать архитектуру решения для подготовки и получения отчётов.
Решение должно включать в себя ETL-процесс, который объединяет данные с датчиков и данные из CRM, используя Apache Airflow, и формирует готовую витрину отчётности в OLAP БД. Итоговый отчёт по пользователю должен быть доступен через бэкенд-сервис API, который обозначен на исходной архитектуре.
Для подготовки архитектуры решения используйте draw.io.
Задача 2. Разработать Airflow DAG и настроить его на запуск по расписанию.
- Реализуйте ETL-процесс с использованием Airflow, который будет извлекать данные из CRM-системы и записывать их в базу OLAP.
- Подготовьте витрину — отдельную таблицу для сервиса отчётов, в которой вам предстоит объединить данные телеметрии и данные о клиентах из CRM-системы. Для этого нужно будет сгруппировать аналитику по телеметрии в разрезе клиентов. Спроектируйте структуру витрины таким образом, чтобы обеспечить быстрый доступ к данным по пользователям. За основу при написании DAG можно взять материал уроков спринта.
- Настройте расписание сбора данных и подготовки витрины.
Сделал DAG telemetry_aggregation_mart.py, отвечающий требованиям. Также сделал DAG generate_user_reports.py, который создаёт готовый отчёт на основе данных из OLAP БД и кладёт информацию в специальную таблицу в той же БД и напрямую в minio.
Задача 3. Создайте бэкенд-часть приложения для API.
- Выберите удобный для вас язык — Python, Java, C# или любой другой.
- Добавьте API /reports в этот бэкенд для передачи отчётов, который будет возвращать подготовленный отчёт по заданному пользователю. Отчёт должен запрашиваться из OLAP-базы без необходимости выполнять сложные вычисления в реальном времени.
Создал сервис bionicpro-reports на C++, овтечающий требованиям. Отчёт запрашивается напрямую из minio - Airflow кладёт отчёт и в OLAP БД (clickhouse), и в minio. Из minio брать оптимальнее, т.к. там уже сформирован файл, который отдаётся пользователю.
Задача 4. Реализуйте ограничение доступа к эндпоинту отчётности.
Доступ к отчёту по пользователю должен предоставляться только в отношении себя.
Пользователь имеет доступ только к основному фронтэнду, который генерирует отчёт на основе информации LDAP сервера: из cookie берётся access token, по нему запрашивается информация о пользователе в keycloak (который и лезет в LDAP). На основе этой информации вычисляется ID пользователя в OLAP данных (email пользователя как ключ). Для вычисления связки email <-> user_id сервис bionicpro-reports подписывается на очередь Kafka, которая создана через Debezium для переноса данных из crm-db в olap-db.
Задача 5. Добавьте в UI кнопку получения отчёта и вызова эндпоинта его генерации.
- Добавьте в API-сервис реализацию записи сформированных отчётов в объектное хранилище, поддерживающее S3 API (Ceph, Minio). Конфигурация развёртывания Minio находится в репозитории спринта.
Добавлен Minio.
- При запросе отчёта сервис сначала проверяет наличие отчёта в S3. Если он там есть, то отдаёт ссылку на CDN. Если же отчёт не обнаружен, сервис должен его сгенерировать, положить в S3 и отдать ссылку на CDN в ответе. Для эмуляции CDN необходимо поднять и настроить Nginx как reverse proxy c включённым кешированием статических файлов.
Не стал эмулировать CDN - сервис отчётов сразу берёт обноваляемую DAG'ом информацию из minio. Сделал пример конфигурации nginx, как это могло бы выглядеть, но единая точка входа без необходимости перегенерации данных выглядит более оптимальным решением.
- Продумать механизм обновления кеша в CDN и структуру хранения отчётов в S3 для быстрого доступа.
Кэш обновляется через DAG, этого достаточно.
- Реализуйте механизм Change Data Capture (CDC) для отслеживания изменений в таблицах БД CRM. В качестве инструмента CDC используйте Debezium. С теорией по Debezium вы можете ознакомиться в уроке 6 спринта 6. С документацией Postgres Debezium Connector вы можете ознакомиться в статье на официальном сайте.
Реализовал через Debezium.
- Настройте Debezium на отправку данных в топик Kafka.
Сделано в init-crm-connect.sql.
- Настройте приём данных из топика Kafka в OLAP БД Clickhouse с помощью механизма KafkaEngine.
Сделано в init-crm-connect.sql.
- Подготовьте витрину для отчётности, объединив данные при помощи MaterializedView в Clickhouse.
Сделано в crm_cdc_to_clickhouse.py.
- Переведите сервис API на новую витрину.
Сервис и так работает через minio.
Этот проект представляет собой комплексную систему для управления безопасной аутентификацией, генерацией аналитических отчётов и эффективной обработкой данных в распределённой архитектуре. Он реализует современные подходы к безопасности, микросервисной архитектуре, обработке данных и интеграции внешних систем.
- Все пользователи проходят аутентификацию через Keycloak.
- Поддерживается MFA (OTP) — после ввода логина/пароля пользователь должен ввести одноразовый пароль из Google Authenticator.
- Реализован PKCE (Proof Key for Code Exchange) для защиты от перехвата кодов авторизации.
- Добавлен LDAP-бэкенд для хранения пользователей в страновых представительствах. Keycloak автоматически синхронизирует данные из LDAP.
- Поддержка внешних провайдеров (Identity Brokering) — например, Яндекс ID (настроено вручную, не в репозитории из-за секретов).
- Фронтенд не получает
access_tokenиrefresh_token. - Токены запрашиваются и хранятся внутри сервиса
bionicpro-auth. - В браузер отправляется HTTP-only, Secure cookie с сессией.
- При истечении
access_token— автоматически обновляется черезrefresh_tokenна сервере. - Реализована ротация сессии при каждом запросе для защиты от атак фиксации сессии.
- Фронтенд — только UI.
- bionicpro-auth — управление сессиями и токенами.
- bionicpro-reports — бизнес-логика отчётов и проверка прав доступа.
Работают по расписанию и объединяют данные:
- CRM (PostgreSQL) → клиенты, заказы.
- Телеметрия (датчики) → данные с устройств.
- ClickHouse — аналитическая база данных.
telemetry_aggregation_mart— агрегирует телеметрию и связывает с клиентами.crm_cdc_to_clickhouse— отслеживает изменения в CRM через Debezium (CDC) и передаёт их в ClickHouse.generate_user_reports— генерирует готовые отчёты по пользователям и сохраняет в MinIO и ClickHouse.
- Отчёты сохраняются в MinIO (объектное хранилище).
- При запросе:
- Сервис
bionicpro-reportsпроверяет наличие отчёта в MinIO. - Если нет — запускает генерацию (через Airflow).
- Отдаёт ссылку на отчёт через безопасный интерфейс.
- Сервис
- Для ускорения доступа используется NGINX как кэш (CDN).
- Пользователь видит только свой отчёт.
- Проверка на основе:
- Сессии из cookie.
- Данных из Keycloak (через LDAP).
- Связки
email ↔ user_idиз Kafka-потока CDC.
- Docker + docker-compose — оркестрация всех сервисов.
- C++ — основной язык для бэкенд-сервисов (
bionicpro-auth,bionicpro-reports). - Airflow — управление ETL-процессами.
- ClickHouse — аналитическая OLAP-база.
- PostgreSQL — транзакционная CRM-база.
- Kafka + Debezium — репликация изменений из CRM в реальном времени.
- MinIO — S3-совместимое хранилище отчётов.
- NGINX — кэширование и CDN-подобное поведение.
- Redis — кэш сессий и токенов.
- OpenLDAP — централизованное управление пользователями.
- Пользователь заходит на фронтенд (
localhost:3000). - Перенаправляется в Keycloak для входа (с MFA).
- После успешного входа — bionicpro-auth получает токены, создаёт сессию и устанавливает безопасную cookie.
- Пользователь нажимает «Получить отчёт».
- bionicpro-reports:
- Проверяет сессию.
- По email из Keycloak находит
user_id. - Проверяет наличие отчёта в MinIO.
- Если нет — инициирует генерацию (через Airflow).
- Отдаёт ссылку на отчёт.
- Отчёт кэшируется в NGINX и отдаётся быстро при повторных запросах.
- Безопасность в приоритете: токены не покидают бэкенд, MFA, ротация сессий, HTTP-only cookies.
- Масштабируемость: все компоненты — микросервисы, могут масштабироваться отдельно.
- Автоматизация: Airflow запускает DAG'и по расписанию и при старте.
- Реальное время: CDC через Debezium обеспечивает синхронизацию данных без задержек.
- Гибкость: поддержка нескольких стран, LDAP, внешних провайдеров (OAuth).
-
Запустите всё:
bash
docker-compose up --build -
Откройте:
http://localhost:3000— фронтенд.http://localhost:8080— Keycloak (логин:admin/ пароль:admin).http://localhost:8085— Airflow.http://localhost:9001— MinIO (логин:minio_user, пароль:minio_password).http://localhost:8888— NGINX (отдача отчётов).
-
Войдите в систему → нажмите кнопку «Отчёт» → получите CSV.
Проект BionicPRO демонстрирует зрелую архитектуру, сочетающую безопасность, производительность и современные практики DevOps и Data Engineering. Он решает реальные бизнес-задачи:
- Безопасный доступ из разных стран.
- Персонализированные отчёты в реальном времени.
- Надёжное хранение и кэширование.
- Поддержка масштабирования и отказоустойчивости.
Всё это реализовано с использованием открытых технологий и может быть легко адаптировано под другие регионы и требования.