KsaiLab
Глава 4

4 Реализация серверной части платформы и апробация

DOCX

4 Реализация серверной части платформы и апробация

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

4.1 Реализация подсистемы разграничения доступа

Спроектированная гибридная модель (подраздел 3.6) реализована на уровне REST API по схеме PDP/PEP. В роли точки исполнения политики (PEP) выступает слой промежуточной обработки в FastAPI и механизм инъекции зависимостей (Depends): он перехватывает запрос, инициирует проверку требуемого полномочия (capability) и последующую ресурсную проверку, а при отказе завершает запрос кодом 403. Решение принимает точка принятия решения (PDP) — набор функций проверки доступа, которые обращаются за атрибутами к точке предоставления информации (PIP) — базе данных. Для снижения нагрузки на СУБД результаты ресурсных проверок кэшируются в Redis (обёртка get_or_set_access). Пример PDP-функции приведён в листинге 4.1.

Листинг 4.1 — Пример PDP-функции для проверки доступа студента к теме (ABAC)

async def check_student_topic_access(session: AsyncSession, user_id: int, topic_id: int) -> bool:
    stmt = select(Topic).join(GroupTopics).join(Group).join(GroupStudents).where(
        GroupStudents.user_id == user_id,
        Topic.id == topic_id,
        GroupStudents.status == GroupStudentStatus.ACTIVE,
        Topic.is_archived.is_(False)
    )
    result = await session.execute(stmt)
    return result.scalar_one_or_none() is not None

Прохождение запроса через точки исполнения и принятия решения показано на рисунке 4.1.

%%{init: {"theme": "neutral", "themeVariables": {"fontFamily": "Times New Roman, serif"}}}%%
flowchart TB
    U(["Пользователь<br/>(сессия / JWT)"])
    PEP["PEP<br/>(промежуточный слой)"]
    CAP["Проверка<br/>полномочия"]
    PDP["PDP<br/>(модуль решений)"]
    PIP[("PIP<br/>(PostgreSQL)")]
    CACHE[("Redis<br/>кэш решений")]
    BIZ["Прикладная логика<br/>(контроллер)"]

    U -->|"HTTP-запрос"| PEP
    PEP -->|"1. полномочие"| CAP
    CAP -->|"2. ресурсная проверка"| PDP
    PDP <-->|"3. атрибуты"| PIP
    PDP <-->|"кэш"| CACHE
    PDP -.->|"4. решение"| PEP
    PEP -->|"5. контроллер"| BIZ

Рисунок 4.1 — Прохождение запроса через точки исполнения (PEP) и принятия решения (PDP)

Обозначения: PEP — точка исполнения политики; CAP — проверка наличия требуемого полномочия (capability); PDP — точка принятия решения; PIP — точка предоставления информации (PostgreSQL); Redis — кэш результатов проверок доступа; JWT — подписанный токен доступа.

4.1.1 Ролевое разграничение (RBAC)

Распределение доступа к характерным конечным точкам API по ролям приведено в таблице 4.1.

Таблица 4.1 — Распределение доступа к конечным точкам API по ролям

Конечная точкаАдминистраторПреподавательСтудент
POST /api/v1/onboarding/teachers201 Created403 Forbidden403 Forbidden
POST /api/v1/groups/management201 Created201 Created403 Forbidden
POST /api/v1/questions201 Created201 Created403 Forbidden
GET /api/v1/topics200 OK200 OK200 OK
GET /api/v1/auth/me200 OK200 OK200 OK

Распределение прав соответствует системному каталогу возможностей платформы (приложение А): операции онбординга доступны только администратору, управление дисциплинами и банком вопросов — администратору и преподавателю, а чтение учебных материалов и поднятие сессии — всем ролям с последующим ограничением конкретного ресурса на уровне ABAC. Системный каталог возможностей и его сопоставление ролям приведены на рисунке 4.2.

Рисунок 4.2 — Системный каталог возможностей платформы (спецификация API)

4.1.2 Контекстное (атрибутное) разграничение (ABAC)

Атрибутное разграничение действует поверх ролевого: доступ к учебному ресурсу (теме, разделу или тесту) предоставляется студенту только при наличии активной связи с учебной группой, которой назначена соответствующая дисциплина. Серверная часть отклоняет доступ к материалам, не входящим в активный учебный план студента, даже при наличии у него легитимного токена. Выдаваемые студенту данные попытки прохождения теста не содержат правильных ответов и служебных полей, а доступ к файлам материалов авторизуется через связанный учебный ресурс, а не по пути объекта в хранилище.

4.2 Интеграция с поставщиком аутентификации (Keycloak)

Поставщиком аутентификации выступает Keycloak 17: серверная часть проверяет подлинность пользователя по протоколу OpenID Connect 23 (валидация токена по метаданным издателя и набору ключей JWKS) и не хранит пароли. Для браузерных клиентов применяется модель серверной сессии (backend-owned session): после входа серверная часть обменивает код авторизации на токены, хранит их на своей стороне в Redis, а браузеру выдаёт только идентификатор сессии в cookie с признаком HttpOnly, что исключает кражу токенов средствами межсайтового скриптинга (XSS) 18. Поднятие текущего пользователя и его эффективных прав выполняется единым запросом GET /api/v1/auth/me, вход и выход — через GET /api/v1/auth/login, GET /api/v1/auth/callback и POST /api/v1/auth/logout. Контракт инициализации сессии и состав эффективных прав, выдаваемых методом /auth/me, приведены на рисунке 4.3, а соответствующие системные роли во внешнем поставщике аутентификации — на рисунке 4.4.

Рисунок 4.3 — Контракт инициализации сессии GET /api/v1/auth/me (спецификация API)

Рисунок 4.4 — Системные роли пользователей во внешнем поставщике аутентификации (Keycloak)

4.3 Автоматизация ввода пользователей (Onboarding)

Серверная часть выступает «ведущим» при регистрации пользователей: учётная запись создаётся во внешнем поставщике аутентификации через Keycloak Admin API, после чего в базе платформы сохраняется связанный профиль. Ввод пользователей автоматизирован через отдельный контур из пяти операций: создание преподавателя, создание учебной группы, назначение преподавателя в группу, массовый ввод студентов в группу и получение учётных данных. Для безопасной передачи учётных данных используется модель выдачи по запросу (Credential Receipt): вместо пароля операция создания возвращает одноразовую квитанцию (receipt); временный пароль раскрывается только через отдельный одноразовый consume-запрос и ограничен по времени жизни; при первом входе обязательна смена пароля. Удаление пользователей не выполняется напрямую — профиль архивируется или деактивируется, что сохраняет целостность учебной истории. Пример ответа сервера при создании профиля преподавателя приведён в листинге 4.2.

Листинг 4.2 — Структура ответа API при успешном Onboarding-процессе

{
  "profile": {
    "username": "ivanov_teacher",
    "role": "teacher"
  },
  "provisioning": {
    "keycloak_user_exists": true,
    "keycloak_sub": "550e8400-e29b-41d4-a716-446655440000",
    "local_profile_bound": true
  },
  "credential_receipt": {
    "receipt_id": "b1f2c0a4",
    "expires_at": "2026-06-03T12:00:00Z"
  }
}

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

%%{init: {"theme": "neutral", "themeVariables": {"fontFamily": "Times New Roman, serif"}, "sequence": {"mirrorActors": false, "wrap": true, "width": 180}}}%%
sequenceDiagram
    participant FE as Клиент
    participant BE as Серверная часть
    participant KC as Keycloak
    participant DB as База данных

    FE->>BE: POST /onboarding/teachers
    BE->>KC: Создание учётной записи
    KC-->>BE: HTTP 201 + keycloak_sub
    BE->>DB: Сохранение профиля пользователя
    DB-->>BE: Подтверждение
    BE-->>FE: 201 Created (с метаданными)

Рисунок 4.5 — Алгоритм синхронизации учётных данных при вводе пользователя (Onboarding)

4.4 Автоматизация управления лабораторными работами и изолированными средами

Со стороны серверной части автоматизация управления лабораторными работами реализована как управление каталогом лабораторных работ, жизненным циклом лабораторных сессий и квотами, тогда как исполнение — создание изолированных окружений в кластере — делегируется инфраструктурному слою согласно контракту (подраздел 3.7).

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

Рисунок 4.6 — Реестр контейнерных образов платформы (GitLab Container Registry)

Изоляция учебных сред обеспечивается на нескольких уровнях. Каждая среда выполняется в выделенном пространстве с сетевыми политиками «запрет по умолчанию», исключающими связность между окружениями разных обучающихся, что соответствует требованию изоляции (НФТ-3) и противодействует угрозам несанкционированного доступа к данным другого обучающегося (подраздел 2.5). Ресурсные квоты и лимиты ограничивают потребление процессора и памяти, защищая кластер от исчерпания ресурсов, а контейнеры запускаются без привилегий. На стороне серверной части дополнительно ограничивается число одновременно запущенных сред на одного студента, что предотвращает злоупотребление общими ресурсами. Низкоуровневые механизмы изоляции (пространства имён, сетевые политики, стандарты безопасности подов) реализуются инфраструктурным слоем и проектируются отдельно от серверной части.

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

Сквозной сценарий объединяет рассмотренные механизмы. Студент входит через внешнего поставщика аутентификации, получает список доступных ему дисциплин (с учётом ABAC) и инициирует запуск лабораторной среды. Серверная часть выполняет следующую цепочку действий:

  1. проверка полномочия (capability) и доступа к ресурсу (ABAC);
  2. фиксация лабораторной сессии в состоянии ожидания и публикация задачи в очередь с возвратом идентификатора задачи;
  3. опрос статуса задачи клиентом;
  4. выдача адреса подключения (connection_url) по готовности среды.

Создание вычислительных ресурсов, изоляция и очистка относятся к инфраструктурному слою и выполняются асинхронно вне серверной части. Журналирование действий в аудит-логе позволяет администратору восстановить последовательность событий при расследовании инцидентов ИБ. Развёртывание самой серверной части автоматизировано средствами непрерывной интеграции: собранные образы публикуются в реестре контейнеров, а конфигурация развёртывания описана пакетом Helm (рисунок 4.7).

Рисунок 4.7 — Структура пакета развёртывания серверной части (Helm-чарт)

В четвёртой главе спроектированные решения доведены до программной реализации: подсистема разграничения доступа реализована по схеме PDP/PEP с кэшированием решений, интеграция с поставщиком аутентификации построена на протоколе OpenID Connect и серверно-управляемой сессии, а ввод пользователей автоматизирован с безопасной выдачей учётных данных по одноразовой квитанции. Апробация на программном интерфейсе подтвердила соответствие ролевого и атрибутного разграничения системному каталогу возможностей. Управление лабораторными работами и изолированными средами реализовано как асинхронная оркестрация с делегированием исполнения инфраструктурному слою. Таким образом, разработанная серверная часть реализует аутентификацию, гибридное разграничение доступа и автоматизацию управления учебным процессом; архитектура рассчитана на использование в учебных группах численностью до 100 одновременных пользователей на один экземпляр управления.