GSSO — Техническая документация
Acest conținut nu este încă disponibil în limba selectată.
| Код документа | SPEC-GSSO-2026 / Отчёт 04 |
| Версия | 0.1-draft (исходный текст EN, имеющий преимущественную силу) |
| Дата | 2026-10-05 |
| Статус | Черновик: описывает планируемую систему. Код пока не существует |
| Сопутствующие отчёты | 00 Техническое задание · 01 ADR · 02 Требования · 03 Потребители и контракт · 05 Дорожная карта |
История изменений
Section titled “История изменений”| Версия | Дата | Изменения |
|---|---|---|
| 0.1-draft | 2026-10-05 | Представления C4, компоненты, модель данных, потоки, базовая конфигурация realm, безопасность, развёртывание, runbook перехода под управление, сайзинг, наблюдаемость, тестирование |
1. Системный контекст (C4, уровень 1)
Section titled “1. Системный контекст (C4, уровень 1)”flowchart TB admin([Администратор IAM / владелец платформы / согласующий / аудитор / helpdesk]) staff([Сотрудник]) citizen([Гражданин]) apps[SaaS и PaaS gStack<br/>interdictii, cancelaria, gdocs, gregistry, drumuri,<br/>CRM, gDocFlow, gTenders, glog, gnotify, gstorage, gflow] mob[gsso_mob GovSign] gsso[[GSSO<br/>платформа идентификации и SSO]] mpass[MPass / eID] ldap[AD / LDAP учреждений] glog[GLog] gnotify[GNotify] smtp[SMTP relay]
admin -- консоль --> gsso staff -- вход / SSO --> gsso citizen -- вход --> gsso mob -- OIDC PKCE --> gsso apps -- OIDC, JWKS, api/v1/app, события Kafka --> gsso gsso -- SAML broker --> mpass gsso -- федерация LDAP --> ldap gsso -- события аудита --> glog gsso -- оповещения, уведомления об истечении --> gnotify gsso -- приглашения, письма сброса --> smtp2. Контейнеры (C4, уровень 2)
Section titled “2. Контейнеры (C4, уровень 2)”flowchart LR subgraph edge[Периметр] nginx[nginx / ingress<br/>sso.gstack… · gsso.gstack…] end subgraph gssoSys[GSSO] web[gsso-web<br/>Angular + GDS<br/>статика] gw[gsso-gateway<br/>шлюз JHipster 9.1 · BFF] srv[gsso<br/>микросервис JHipster 9.1] db[(PostgreSQL<br/>gsso)] kc[Keycloak 26.6.x<br/>+ gsso-kc-extensions<br/>+ тема gstack] kdb[(PostgreSQL<br/>keycloak)] boot[gsso-bootstrap<br/>задание keycloak-config-cli] end kafka[[Kafka]] glog[GLog] gn[GNotify]
nginx --> web nginx --> gw nginx --> kc gw -- /api/v1/** --> srv gw -. OIDC code flow, клиент gsso-console .-> kc srv -- Admin REST, SA gsso-reconciler --> kc srv --- db kc --- kdb boot -- базовые realm --> kc kc -- gsso.kc-events.v1 --> kafka kafka --> srv srv -- gsso.access-revoked.v1, gsso.grant.v1 --> kafka srv -- аудит --> glog srv -- уведомления --> gn| Контейнер | Технология | Ответственность |
|---|---|---|
gsso-web | Angular (версия согласно JHipster 9.1.0), @gstack/gds-angular, ngx-translate ro/ru/en | UI консоли; без token (cookie BFF) |
gsso-gateway | шлюз JHipster 9.1.0 (Spring Cloud Gateway), клиент OAuth2 | Вход и сессия (BFF), CSRF, маршрутизация /api/v1/**, ограничения частоты запросов для зоны app |
gsso | микросервис JHipster 9.1.0, Spring Boot, Hibernate, Liquibase, Kafka, keycloak-admin-client 26.x | Каталог, предоставления доступа, reconciler, потребитель событий, ретрансляция в GLog, отчёты, API admin и app |
| Keycloak | quay.io/keycloak/keycloak:26.6.x (собственный образ с расширениями + темой, kc.sh build) | Аутентификация, token, сессии, MFA, федерация, консоль учётной записи |
gsso-bootstrap | adorsys/keycloak-config-cli, соответствующий 26.x | Применяет базовые конфигурации realm при развёртывании (идемпотентно) |
| PostgreSQL ×2 | в том виде, в каком генерирует JHipster 9.1.0 (gsso); версия, поддерживаемая Keycloak (keycloak) | Раздельные базы данных, резервные копии, жизненные циклы |
| Kafka | общий кластер gStack (целевой вариант — Strimzi; один broker в compose) | Транспорт событий |
2.1 Структура репозитория (govtech/gstack/gsso)
Section titled “2.1 Структура репозитория (govtech/gstack/gsso)”gsso/ CLAUDE.md gsso.jdl gsso.dc.html test-scenarios.md .env.example docs/reports/ 00..05 (en, ro, ru), README, docx/, pdf/, img/ keycloak/ extensions/ Maven module: gsso-kafka event listener, mappers (roles, roles_scoped, org_unit, tenant), conditional-role authenticator themes/gstack/ login/, account/, email/ (FreeMarker + GDS CSS, messages_ro/ru/en) realms/ gstack.json, cetatean.json, tenant-template.json (keycloak-config-cli, ${ENV} placeholders) Dockerfile FROM keycloak:26.6.x → kc.sh build with providers + theme gsso/ JHipster 9.1.0 microservice (generated from gsso.jdl + custom code) gsso-gateway/ JHipster 9.1.0 gateway gsso-web/ Angular SPA on GDS sdk/ gsso-spring-boot-starter/ gsso-angular/ deploy/ docker-compose.yml local + demo host stack docker-compose.test.yml postgres + kafka + keycloak for IT (always `down -v`) nginx/gsso.conf vhost templates (applied only with owner approval) helm/gsso/ Kubernetes target testing/results/3. Компоненты gsso
Section titled “3. Компоненты gsso”Пакет (systems.esempla.gsso) | Компонент | Примечания |
|---|---|---|
domain, repository, service, web.rest | CRUD для сущностей JDL, сгенерированный JHipster | регенерируется; собственный код находится в классах с отдельными именами |
keycloak | KeycloakAdminGateway | Единственный класс, обращающийся к keycloak-admin-client. Поиск по естественным ключам, маркер gsso.managed, преобразование ошибок в RFC 7807 |
sync | JobOutbox, ReconcilerWorker, RealmDiffer, DriftPolicy | Задания outbox, worker с FOR UPDATE SKIP LOCKED + advisory lock на каждый realm, периодическое полное сравнение |
sync.handlers | RealmHandler, ClientHandler, RoleHandler, RoleMappingHandler, UserHandler, PolicyHandler, OrgUnitHandler | Один обработчик на тип объекта: apply(job), diff(realm) |
grant | GrantLifecycleService, GrantExpiryScheduler, ApprovalPolicy | Машина состояний, принцип «четырёх глаз», истечение срока, уведомления |
events | KcEventConsumer, EventStore, HashChain, GlogRelay, RevocationPublisher | Идемпотентное потребление, хранилище только для добавления (append-only), пересылка, исходящие события |
projection | UserProjectionUpdater, NightlyUserSync | ProiectieUtilizator |
report | DashboardAggregator, AccessReport | KPI, корзины входов, структура способов аутентификации |
web.rest.admin, web.rest.app | Фасадные контроллеры | Зоны, scope, фильтр ограничения по realm, хранилище Idempotency-Key |
security | RealmScopeAuthorizationManager, PlatformScopeAuthorizationManager | Ограничение области GSSO_REALM_ADMIN/GSSO_PLATFORM_OWNER |
notify | GnotifyClient | Предупреждения об истечении срока, оповещения |
4. Модель данных
Section titled “4. Модель данных”erDiagram REALM ||--o{ CLIENT_APLICATIE : "содержит" REALM ||--|| POLITICA_AUTENTIFICARE : "имеет" REALM ||--o{ UNITATE_ORGANIZATIONALA : "имеет" REALM ||--o{ PROIECTIE_UTILIZATOR : "проецирует" PLATFORMA ||--o{ CLIENT_APLICATIE : "владеет" PLATFORMA ||--o{ ROL_PLATFORMA : "предоставляет" PLATFORMA }o--o{ REALM : "развёрнута в" ROL_PLATFORMA ||--o{ ROL_PLATFORMA : "составная из" PACHET_ROLURI }o--o{ ROL_PLATFORMA : "объединяет" ATRIBUIRE_ACCES }o--|| ROL_PLATFORMA : "предоставляет" ATRIBUIRE_ACCES }o--o| PACHET_ROLURI : "через пакет" ATRIBUIRE_ACCES }o--o| UNITATE_ORGANIZATIONALA : "ограничена" ATRIBUIRE_ACCES ||--o{ APROBARE : "согласована" UNITATE_ORGANIZATIONALA ||--o{ UNITATE_ORGANIZATIONALA : "родитель" JOB_SINCRONIZARE }o--|| REALM : "нацелено на" EVENIMENT_GSSO }o--|| REALM : "в"Определяющим является gsso.jdl. Основные поля:
| Сущность | Ключевые поля | Примечания |
|---|---|---|
Realm | nume (уникальное), denumireAfisata, tip {STAFF, CETATEAN, TENANT, SERVICE}, brokerAlias, politicaDrift {REPORT, ENFORCE, IGNORE}, stare {ACTIV, INACTIV}, stareSync, kcId, adoptat | |
Platforma | cod (уникальное), denumire, tip {SAAS, PAAS}, descriere (ro/ru/en), urlBaza, accent, stare, autoInregistrare | владельцы через ProprietarPlatforma(sub) |
ClientAplicatie | clientId, protocol {OIDC, SAML}, tipAcces {PUBLIC_PKCE, CONFIDENTIAL, BEARER_ONLY, SERVICE_ACCOUNT}, redirectUris, webOrigins, postLogoutUris, backchannelLogoutUrl, audienta, scopuri, audienteSchimb, sensibil, stare, stareSync, kcId | уникально по (realm, clientId) |
RolPlatforma | cod (с префиксом, уникальное в пределах realm), descriereRo/Ru/En, compozit, sensibil, valabilitateImplicitaZile, stareSync, kcId | дочерние роли через связь с самой собой |
PachetRoluri | cod, denumire, роли | синхронизируется как группа Keycloak |
AtribuireAcces | userSub, realm, rol / pachet, unitate, validDe, validPana, stare {SOLICITATA, APROBATA, ACTIVA, RESPINSA, REVOCATA, EXPIRATA}, solicitant, motiv, sursa {CONSOLA, APP, ADOPTAT, DIRECT}, motivRevocare | |
Aprobare | atribuire, aprobator, nivel (1/2), decizie, comentariu, data | |
UnitateOrganizationala | cod, denumire (ro/ru/en), parinte, sefi | |
PoliticaAutentificare | parola, otp, webauthn, qr, client, broker, magic (булевы), politicaParola, mfaRoluriSensibile, sesiuneInactivMin, sesiuneMaxOre, tokenAccesMin | одна на realm |
JobSincronizare | realm, tipObiect, cheieObiect, operatie {CREATE, UPDATE, DELETE, MAP, UNMAP, DIFF}, stare {PENDING, RUNNING, OK, FAILED, DRIFT, ACCEPTAT}, incercari, urmatoareaIncercare, eroare, diff (jsonb), corelatie | |
ProiectieUtilizator | sub, realm, username, nume, email, idnpCriptat, activ, mfa (множество), ultimaAutentificare, ultimulEsec, unitate, locale, actualizatLa | модель чтения |
EvenimentGsso | id (UUID), realm, tip, categorie {KC_USER, KC_ADMIN, CATALOG, GRANT, SYNC, CONSOLE}, actor, subiect, client, ip, moment, payload (jsonb), hashPrecedent, hash, glogId | только добавление (append-only); ежемесячные партиции |
Столбцы JSONB (diff, payload, descriere) объявлены в JDL как TextBlob и преобразуются дополнительным changelog Liquibase с @JdbcTypeCode(SqlTypes.JSON). Changelog-и только дополняются (append-only).
5. Сквозные потоки
Section titled “5. Сквозные потоки”5.1 Регистрация платформы → клиенты и роли в Keycloak
Section titled “5.1 Регистрация платформы → клиенты и роли в Keycloak”sequenceDiagram actor A as Администратор платформы participant W as gsso-web participant G as gsso-gateway participant S as gsso participant DB as БД gsso participant R as ReconcilerWorker participant K as Keycloak A->>W: Создать платформу "crm" + клиенты + роли W->>G: POST /api/v1/admin/platforme (Idempotency-Key) G->>S: ретрансляция (token пользователя) S->>DB: tx: Platforma, ClientAplicatie*, RolPlatforma*, JobSincronizare*, EvenimentGsso S-->>W: 201 (stareSync=PENDING) R->>DB: взять задания (SKIP LOCKED, блокировка realm) R->>K: GET client по clientId → отсутствует → POST client (gsso.managed=true) R->>K: POST роли, составные роли, audience mapper R->>DB: задание OK, kcId сохранён, stareSync=IN_SYNC, событие SYNC_OK W->>G: опрос / обновление → значок "синхронизировано"5.2 Запрос доступа → согласование → token
Section titled “5.2 Запрос доступа → согласование → token”sequenceDiagram actor Req as Заявитель actor Own as Владелец платформы actor Ap2 as Согласующий (чувствительная роль) participant S as gsso participant K as Keycloak participant N as GNotify Req->>S: POST /admin/atribuiri {sub, CRM_ADMIN, motiv} S->>S: SOLICITATA (+событие) S->>N: уведомить владельца Own->>S: согласовать (уровень 1) alt чувствительная роль Ap2->>S: согласовать (уровень 2, ≠ заявитель, ≠ согласовавший владелец) end S->>S: APROBATA + задание MAP S->>K: добавить role-mapping (reconciler) K-->>S: 204 S->>S: ACTIVA (+событие, gsso.grant.v1) Note over K: следующий token пользователя содержит CRM_ADMIN в roles5.3 Отзыв в течение 60 с
Section titled “5.3 Отзыв в течение 60 с”sequenceDiagram actor O as Владелец participant S as gsso participant K as Keycloak participant Kf as Kafka participant App as Приложение (starter) O->>S: отозвать доступ (motiv) S->>K: удалить role-mapping S->>K: POST /users/{id}/logout (сессии + back-channel logout) S->>Kf: gsso.access-revoked.v1 {sub, notBefore=now} Kf->>App: deny-list для sub до истечения TTL token App-->>App: запросы с iat < notBefore → 401 S->>S: REVOCATA (+событие → GLog)5.4 Событие входа → дашборд и GLog
Section titled “5.4 Событие входа → дашборд и GLog”sequenceDiagram participant U as Пользователь participant K as Keycloak (+gsso-kafka) participant Kf as Kafka participant S as gsso participant L as GLog U->>K: вход (пароль + OTP) K-->>U: token K--)Kf: событие LOGIN (асинхронно) Kf->>S: потребление (дедупликация eventId) S->>S: EvenimentGsso (hash chain), projection.lastLogin, агрегаты S->>L: POST /api/v1/app/audit-events (client credentials) L-->>S: id квитанции5.5 Полная синхронизация и drift
Section titled “5.5 Полная синхронизация и drift”- Каждые 15 мин или по запросу
RealmDifferзагружает желаемое состояние realm и считывает Keycloak (клиенты, роли, составные роли, сопоставления управляемых ролей, группы, flow и поля политик, которыми он управляет). - Для каждого расхождения создаётся
JobSincronizare(DIFF):- отсутствует в Keycloak →
CREATE(если политикаENFORCE) илиDRIFT; - отличается →
UPDATEилиDRIFT; - присутствует в Keycloak с
gsso.managed=true, но отсутствует в GSSO →DELETEилиDRIFT; - присутствует без маркера →
NEGUVERNAT(только отчёт).
- отсутствует в Keycloak →
- В консоли администратор может повторить, принудительно применить (применить значение GSSO) или принять drift (скопировать значение Keycloak в GSSO).
5.6 Принятие под управление существующего realm (например, interdictii)
Section titled “5.6 Принятие под управление существующего realm (например, interdictii)”Сначала выполняется пробный прогон (dry run, GSSO-FR-080), затем импорт:
- клиенты группируются в платформы по файлу сопоставления (
clientId→ код платформы); - роли realm сопоставляются с ролями платформ по правилам переименования (например,
ROLE_ADMIN→ кандидаты<APP>_ADMINдля каждой платформы, помеченные для проверки); - текущие сопоставления пользователь→роль становятся
AtribuireAcces(ACTIVA, sursa=ADOPTAT).
Пока политика drift имеет значение IGNORE, в Keycloak ничего не записывается.
5.7 Вход в консоль (BFF)
Section titled “5.7 Вход в консоль (BFF)”- Браузер открывает
gsso.gstack…, иgsso-gatewayперенаправляет его в Keycloak (realmgstack, клиентgsso-console, PKCE + confidential). - Пользователь входит в систему. MFA обязательна для любой роли
GSSO_*(NFR-SEC-008). - Шлюз сохраняет token в серверной сессии и устанавливает cookie
SESSION(HttpOnly,Secure,SameSite=Lax), а также cookie CSRF. - Вызовы SPA передают cookie. Шлюз ретранслирует access token в
gsso, который применяет ограничение области по realm и платформе на основании ролейGSSO_*и их атрибутов.
5.8 Вход гражданина через MPass
Section titled “5.8 Вход гражданина через MPass”- Клиент
cetateanперенаправляет гражданина в Keycloak, который выступает broker к MPass (SAML POST). - Возвращается assertion. Flow first-broker-login ищет пользователя по атрибуту IDNP; если пользователь найден, учётная запись связывается, иначе пользователь создаётся с сопоставленными атрибутами.
- Keycloak устанавливает значение
acrпо уровню доверия MPass, и token выпускается для портала.
6. Базовая конфигурация realm (keycloak/realms/gstack.json, кратко)
Section titled “6. Базовая конфигурация realm (keycloak/realms/gstack.json, кратко)”| Параметр | Значение |
|---|---|
| Тема входа / учётной записи / email | gstack (GDS), локали ro, ru, en, по умолчанию ro |
| Защита от подбора (brute force) | включена, 5 неудачных попыток, приращение ожидания 60 с, максимум 15 мин |
| Политика паролей | length(12) and upperCase(1) and lowerCase(1) and digits(1) and notUsername and notEmail and passwordHistory(5) |
| Простой / максимум сессии SSO | 30 мин / 10 ч |
| Access token | 5 мин |
| События | включены пользовательские и административные события, административные события с представлением, слушатели jboss-logging, gsso-kafka, срок хранения 7 дней |
| Client scopes (по умолчанию) | profile, email, gsso-roles (плоский список ролей), gsso-org (org_unit, org_unit_path, roles_scoped), gsso-locale, acr |
| Client scopes (опциональные) | idnp, gsso-roles-filtered, offline_access |
| Browser flow | Cookie (alt) → Identity provider redirector (alt) → Forms: username+password (req) → Conditional OTP/WebAuthn (условие: у пользователя есть роль GSSO_MFA_REQUIRED или любая роль, помеченная как чувствительная) |
| Роли по умолчанию | ROLE_USER |
| Базовые клиенты | gsso-console (confidential, standard flow, PKCE), gsso-api (bearer), gsso-reconciler находится в master |
| Обязательные действия | подтверждение e-mail, смена пароля, настройка OTP, регистрация WebAuthn, условия использования (отключено) |
| Token exchange | включён стандартный token exchange V2; разрешения для каждого клиента — из GSSO |
cetatean.json использует ту же тему и другие параметры:
- SAML identity provider MPass с flow first-broker-login, сопоставляющим по IDNP;
- без LDAP;
- вход по паролю по умолчанию отключён;
- простой сессии 15 мин.
tenant-template.json — параметризованная копия gstack без федерации.
7. Модель безопасности
Section titled “7. Модель безопасности”| Аспект | Мера |
|---|---|
| Доступ к консоли | BFF; роли GSSO_*; обязательная MFA; простой 15 мин; CSRF; CSP |
| Ограничение по realm | GSSO_REALM_ADMIN несёт атрибут gsso.realm; серверный фильтр для каждого запроса и команды; проверяется матрицей авторизации |
| Ограничение по платформе | GSSO_PLATFORM_OWNER с атрибутом gsso.platforma (многозначным) |
| Reconciler | Сервисная учётная запись в master только с ролями manage-*/view-* управляемых realm (fine-grained admin permissions V2); учётные данные в хранилище секретов; ротация каждые 90 дней |
| Принцип «четырёх глаз» | ApprovalPolicy: заявитель ≠ согласующий; для чувствительных ролей — два разных согласующих; сами роли GSSO являются чувствительными |
| Секреты | Секреты клиентов генерируются Keycloak, показываются в консоли один раз и не сохраняются в БД GSSO |
| Персональные данные | IDNP зашифрован (AES-GCM, ключ из хранилища секретов) и маскируется; журналы очищаются |
| Целостность событий | Hash chain + триггер БД + копия WORM в GLog |
| Ключи | Ключи realm RS256, ротация каждые 90 дней с перекрытием (новый — активный, старый — пассивный до истечения максимального TTL token) |
| Цепочка поставок | SBOM (CycloneDX), Trivy, Semgrep, Gitleaks через /gsast; образ Keycloak собирается из зафиксированного digest |
Роли консоли GSSO (realm gstack):
| Роль | Чувствительная |
|---|---|
GSSO_ADMIN | да |
GSSO_REALM_ADMIN | да |
GSSO_PLATFORM_OWNER | да |
GSSO_APPROVER | да |
GSSO_HELPDESK | да |
GSSO_AUDITOR | нет |
GSSO_IDNP_VIEW | да |
GSSO_MFA_REQUIRED | маркер |
8. Развёртывание
Section titled “8. Развёртывание”8.1 Демо-хост (текущее соглашение gStack)
Section titled “8.1 Демо-хост (текущее соглашение gStack)”- Стек compose
~/devops/gsso/на общем хосте. Контейнеры подключаются к внешней сетиgstack-web. - Работающие контейнеры
keycloak+postgres-keycloakпринимаются под управление (§11.1): стандартный образ заменяется образом GSSO, собранным на той же версии с добавленными расширениями и темой. gsso,gsso-gateway,gsso-web,gsso-postgresи, если общий Kafka недоступен, одноузловой Kafka (KRaft).- vhost:
sso.gstack.esempla.systems→ keycloak:8080, как сейчас;- новый
gsso.gstack.esempla.systems→ gsso-web + gateway. Любое изменение периметрового nginx требует согласования владельца, а продление сертификатов должно быть исправлено в первую очередь (NFR-AVL-006).
- Процесс развёртывания: сборка образов amd64 → push в
registry.esempla.systems/govtech/gstack/gsso-*(илиdocker save | ssh | docker load) →docker compose up -d --no-deps --force-recreate <svc>. - Бюджет памяти на хосте ≈ 8 ГБ:
- Keycloak — heap 1 ГБ;
- gsso — 512 МБ;
- gateway — 384 МБ;
- postgres ×2 — по 256 МБ;
- Kafka — 512 МБ, если локальный.
8.2 Целевой вариант Kubernetes (Helm)
Section titled “8.2 Целевой вариант Kubernetes (Helm)”- Keycloak: 2 реплики (кластер Infinispan через Kubernetes DNS_PING), с PDB и HPA по CPU.
- gsso: 2 реплики. Reconciler является единственным экземпляром на realm благодаря advisory lock, поэтому могут работать обе реплики.
- gateway: 2 реплики, сессии в Redis или JDBC.
- PostgreSQL: CloudNativePG, по 2 экземпляра.
- Kafka: общий кластер Strimzi.
9. Сайзинг (начальный)
Section titled “9. Сайзинг (начальный)”| Показатель | Оценка |
|---|---|
| Пользователи-сотрудники | 5 000 (начально) → 20 000 |
| Пиковое число входов | 50/мин типично, всплеск 10/с в 9:00 |
| Событий в день | ≈ 50 000 (входы, обновление token по умолчанию не журналируется, административные) → ≈ 30 МБ/день jsonb → партиции за 90 дней ≈ 3 ГБ |
| БД GSSO | < 10 ГБ в первый год |
| БД Keycloak | < 5 ГБ (сессии в памяти, функция persistent user sessions включена в 26.x → +1 ГБ) |
10. Наблюдаемость
Section titled “10. Наблюдаемость”- Метрики (Micrometer → Prometheus):
gsso_sync_jobs{state},gsso_reconcile_seconds,gsso_drift_total,gsso_event_lag_seconds,gsso_glog_lag_seconds;- Keycloak
keycloak_logins_total,keycloak_failed_login_attempts_total(metrics SPI); - метрики JVM и HTTP.
- Журналы: JSON с trace id; фильтр очистки для
Authorization,access_token,client_secret,password,idnp. - Трассировка: OpenTelemetry по цепочке gateway → gsso → административные вызовы Keycloak.
- Оповещения: NFR-OBS-004, маршрутизируются через GNotify.
11. Эксплуатационный runbook (структура)
Section titled “11. Эксплуатационный runbook (структура)”11.1 Принятие под управление работающего Keycloak
Section titled “11.1 Принятие под управление работающего Keycloak”- Получить согласование владельца и согласовать окно работ. Сначала исправить продление TLS.
- Выполнить
pg_dumpбазы данных Keycloak и скопировать дамп за пределы хоста. Экспортировать каждый realm (kc.sh export --realm … --users different_files) для справки. - Собрать образ Keycloak GSSO на той же версии (26.6.3) с добавленными расширениями и темой. Базовая конфигурация пока не применяется.
- Заменить образ и проверить:
- входы для всех приложений;
- issuer не изменился;
- JWKS не изменился. Откат = предыдущий образ, та же база данных.
- Включить слушатель
gsso-kafkaв realminterdictii(административное действие), затем запуститьgssoс realminterdictiiпринятым под управление,IGNORE. - Применить базовые конфигурации
gstackиcetatean(новые realm; ничего существующего не меняется).
11.2 Прочие runbook
Section titled “11.2 Прочие runbook”| Runbook | Шаги |
|---|---|
| Обновление Keycloak | Резервное копирование базы данных → прогон набора IT базовой конфигурации + reconciler на новом образе → поэтапное развёртывание → smoke-тест |
| Ротация ключей | Добавить новый ключ RS256 (более высокий приоритет) → подождать не менее 1 TTL token + обновление → сделать старый ключ пассивным → удалить его по истечении максимальной сессии |
| Ротация секрета клиента | «Ротация» в консоли → окно с двумя действующими секретами → повторное развёртывание приложения → старый секрет аннулируется |
| Break-glass | Использовать аварийного администратора master (запечатанные учётные данные, правило двух лиц); о каждом использовании составляется отчёт |
| Восстановление | Восстановить базу данных Keycloak из резервной копии → выполнить полную синхронизацию в режиме REPORT → проанализировать drift → ENFORCE |
| Сертификат | Продление через webroot; оповещение за 21 день; ежемесячное проверочное задание |
12. Стратегия тестирования
Section titled “12. Стратегия тестирования”| Уровень | Охват | Инструменты |
|---|---|---|
| Модульный | Машина состояний предоставления доступа, политика согласования, differ, hash chain, mappers, сопоставление в starter | JUnit 5, AssertJ |
| Интеграционный | Reconciler с реальным Keycloak, слушатель событий → Kafka → потребитель, Liquibase + триггер append-only | Testcontainers (Keycloak 26.6.x с расширениями, PostgreSQL, Kafka) и deploy/docker-compose.test.yml (всегда down -v) |
| Контрактный | OpenAPI api/v1/app, схемы событий (CloudEvents + JSON Schema) | api_audit.py, тесты схем |
| E2E | Потоки консоли (регистрация платформы, пользователь, согласование доступа, отзыв, drift), SSO между двумя демонстрационными приложениями, mock MPass | Cypress |
| Безопасность | Матрица авторизации (ограничение по realm/платформе, принцип «четырёх глаз»), базовый ZAP, заголовки, SAST/SCA/секреты | /gtestgen, /gtest, /gsast |
| Производительность | Всплеск входов, списки консоли, синхронизация 1 000 клиентов | /load-test, k6 для Keycloak |
| Проверка UI | Неработающие элементы управления, непереведённые ключи, доступность (a11y) | /gfront |
Тестовые сценарии перечислены в test-scenarios.md (TS-GSSO-NN) и повторно используют общие случаи TC-COM-*.
13. Оценка стоимости
Section titled “13. Оценка стоимости”| Статья | Оценка |
|---|---|
| Демо-хост | Размещается на существующем хосте (≈ 3 ГБ дополнительной RAM) |
| Целевой вариант Kubernetes | 3 vCPU / 6 ГБ requests (Keycloak 2×, gsso 2×, gateway 2×) + 2 кластера PostgreSQL |
| Трудозатраты на разработку (S0–S3) | ≈ 14–18 человеко-недель (1 backend, 1 frontend, 0,5 Keycloak/DevOps) |
| Миграция существующих приложений (S4) | ≈ 1–2 человеко-недели на приложение шаблона A, ≈ 0,5 на приложение шаблона B |