Skip to content

GSSO — Documentație tehnică

Cod documentSPEC-GSSO-2026 / Raportul 04
Versiune0.1-draft (sursa EN, text care prevalează)
Data2026-10-05
StatutProiect: descrie sistemul planificat. Încă nu există cod
Rapoarte însoțitoare00 Caiet de sarcini · 01 ADR · 02 Cerințe · 03 Consumatori și contract · 05 Foaie de parcurs
VersiuneDataModificări
0.1-draft2026-10-05Vederi C4, componente, model de date, fluxuri, configurația de bază a realm-urilor, securitate, implementare, runbook de preluare, dimensionare, observabilitate, testare
flowchart TB
admin([Administrator IAM / proprietar de platformă / aprobator / auditor / helpdesk])
staff([Utilizator angajat])
citizen([Cetățean])
apps[SaaS și PaaS gStack<br/>interdictii, cancelaria, gdocs, gregistry, drumuri,<br/>CRM, gDocFlow, gTenders, glog, gnotify, gstorage, gflow]
mob[gsso_mob GovSign]
gsso[[GSSO<br/>platforma de identitate și SSO]]
mpass[MPass / eID]
ldap[AD / LDAP al instituțiilor]
glog[GLog]
gnotify[GNotify]
smtp[Releu SMTP]
admin -- consolă --> gsso
staff -- autentificare / SSO --> gsso
citizen -- autentificare --> gsso
mob -- OIDC PKCE --> gsso
apps -- OIDC, JWKS, api/v1/app, evenimente Kafka --> gsso
gsso -- broker SAML --> mpass
gsso -- federare LDAP --> ldap
gsso -- evenimente de audit --> glog
gsso -- alerte, notificări de expirare --> gnotify
gsso -- invitații, e-mailuri de resetare --> smtp
flowchart LR
subgraph edge[Margine]
nginx[nginx / ingress<br/>sso.gstack… · gsso.gstack…]
end
subgraph gssoSys[GSSO]
web[gsso-web<br/>Angular + GDS<br/>static]
gw[gsso-gateway<br/>gateway JHipster 9.1 · BFF]
srv[gsso<br/>microserviciu JHipster 9.1]
db[(PostgreSQL<br/>gsso)]
kc[Keycloak 26.6.x<br/>+ gsso-kc-extensions<br/>+ tema gstack]
kdb[(PostgreSQL<br/>keycloak)]
boot[gsso-bootstrap<br/>job keycloak-config-cli]
end
kafka[[Kafka]]
glog[GLog]
gn[GNotify]
nginx --> web
nginx --> gw
nginx --> kc
gw -- /api/v1/** --> srv
gw -. flux OIDC code, client gsso-console .-> kc
srv -- Admin REST, SA gsso-reconciler --> kc
srv --- db
kc --- kdb
boot -- realm-uri de bază --> kc
kc -- gsso.kc-events.v1 --> kafka
kafka --> srv
srv -- gsso.access-revoked.v1, gsso.grant.v1 --> kafka
srv -- audit --> glog
srv -- notificare --> gn
ContainerTehnologieResponsabilitate
gsso-webAngular (versiunea conform JHipster 9.1.0), @gstack/gds-angular, ngx-translate ro/ru/enInterfața consolei; fără token-uri (cookie BFF)
gsso-gatewayGateway JHipster 9.1.0 (Spring Cloud Gateway), client OAuth2Autentificare și sesiune (BFF), CSRF, rutarea /api/v1/**, limitări de rată pe zona app
gssoMicroserviciu JHipster 9.1.0, Spring Boot, Hibernate, Liquibase, Kafka, keycloak-admin-client 26.xCatalog, atribuiri, reconciliator, consumator de evenimente, releu către GLog, rapoarte, API-urile admin și app
Keycloakquay.io/keycloak/keycloak:26.6.x (imagine personalizată cu extensii + temă, kc.sh build)Autentificare, token-uri, sesiuni, MFA, federare, consola contului
gsso-bootstrapadorsys/keycloak-config-cli compatibil cu 26.xAplică configurațiile de bază ale realm-urilor la implementare (idempotent)
PostgreSQL ×2așa cum este generat de JHipster 9.1.0 (gsso); versiune suportată de Keycloak (keycloak)Baze de date, copii de rezervă și cicluri de viață separate
Kafkaclusterul gStack partajat (țintă Strimzi; un singur broker în compose)Transportul evenimentelor

2.1 Structura depozitului (govtech/gstack/gsso)

Section titled “2.1 Structura depozitului (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/
Pachet (systems.esempla.gsso)ComponentăNote
domain, repository, service, web.restCRUD generat de JHipster pentru entitățile JDLregenerat; codul personalizat se află în clase cu denumiri separate
keycloakKeycloakAdminGatewaySingura clasă care accesează keycloak-admin-client. Căutări după cheie naturală, marcajul gsso.managed, traducerea erorilor în RFC 7807
syncJobOutbox, ReconcilerWorker, RealmDiffer, DriftPolicyJoburi outbox, worker cu FOR UPDATE SKIP LOCKED + advisory lock per realm, diff complet periodic
sync.handlersRealmHandler, ClientHandler, RoleHandler, RoleMappingHandler, UserHandler, PolicyHandler, OrgUnitHandlerUn handler per tip de obiect: apply(job), diff(realm)
grantGrantLifecycleService, GrantExpiryScheduler, ApprovalPolicyMașina de stări, principiul „patru ochi”, expirare, notificări
eventsKcEventConsumer, EventStore, HashChain, GlogRelay, RevocationPublisherConsum idempotent, stocare append-only, redirecționare, evenimente de ieșire
projectionUserProjectionUpdater, NightlyUserSyncProiectieUtilizator
reportDashboardAggregator, AccessReportKPI-uri, intervale de autentificări, structura metodelor de autentificare
web.rest.admin, web.rest.appControlere de fațadăZone, scope-uri, filtru de delimitare pe realm, stocarea Idempotency-Key
securityRealmScopeAuthorizationManager, PlatformScopeAuthorizationManagerDelimitarea GSSO_REALM_ADMIN/GSSO_PLATFORM_OWNER
notifyGnotifyClientAvertismente de expirare, alerte
erDiagram
REALM ||--o{ CLIENT_APLICATIE : "conține"
REALM ||--|| POLITICA_AUTENTIFICARE : "are"
REALM ||--o{ UNITATE_ORGANIZATIONALA : "are"
REALM ||--o{ PROIECTIE_UTILIZATOR : "proiectează"
PLATFORMA ||--o{ CLIENT_APLICATIE : "deține"
PLATFORMA ||--o{ ROL_PLATFORMA : "expune"
PLATFORMA }o--o{ REALM : "implementată în"
ROL_PLATFORMA ||--o{ ROL_PLATFORMA : "compus din"
PACHET_ROLURI }o--o{ ROL_PLATFORMA : "grupează"
ATRIBUIRE_ACCES }o--|| ROL_PLATFORMA : "acordă"
ATRIBUIRE_ACCES }o--o| PACHET_ROLURI : "prin pachet"
ATRIBUIRE_ACCES }o--o| UNITATE_ORGANIZATIONALA : "delimitată la"
ATRIBUIRE_ACCES ||--o{ APROBARE : "aprobată prin"
UNITATE_ORGANIZATIONALA ||--o{ UNITATE_ORGANIZATIONALA : "părinte"
JOB_SINCRONIZARE }o--|| REALM : "vizează"
EVENIMENT_GSSO }o--|| REALM : "în"

Definiția de referință este gsso.jdl. Câmpurile principale:

EntitateCâmpuri-cheieNote
Realmnume (unic), denumireAfisata, tip {STAFF, CETATEAN, TENANT, SERVICE}, brokerAlias, politicaDrift {REPORT, ENFORCE, IGNORE}, stare {ACTIV, INACTIV}, stareSync, kcId, adoptat
Platformacod (unic), denumire, tip {SAAS, PAAS}, descriere (ro/ru/en), urlBaza, accent, stare, autoInregistrareproprietarii prin ProprietarPlatforma(sub)
ClientAplicatieclientId, protocol {OIDC, SAML}, tipAcces {PUBLIC_PKCE, CONFIDENTIAL, BEARER_ONLY, SERVICE_ACCOUNT}, redirectUris, webOrigins, postLogoutUris, backchannelLogoutUrl, audienta, scopuri, audienteSchimb, sensibil, stare, stareSync, kcIdunic (realm, clientId)
RolPlatformacod (cu prefix, unic per realm), descriereRo/Ru/En, compozit, sensibil, valabilitateImplicitaZile, stareSync, kcIdrolurile-copil prin autorelație
PachetRoluricod, denumire, rolurireconciliat ca grup Keycloak
AtribuireAccesuserSub, realm, rol / pachet, unitate, validDe, validPana, stare {SOLICITATA, APROBATA, ACTIVA, RESPINSA, REVOCATA, EXPIRATA}, solicitant, motiv, sursa {CONSOLA, APP, ADOPTAT, DIRECT}, motivRevocare
Aprobareatribuire, aprobator, nivel (1/2), decizie, comentariu, data
UnitateOrganizationalacod, denumire (ro/ru/en), parinte, sefi
PoliticaAutentificareparola, otp, webauthn, qr, client, broker, magic (booleene), politicaParola, mfaRoluriSensibile, sesiuneInactivMin, sesiuneMaxOre, tokenAccesMinuna per realm
JobSincronizarerealm, tipObiect, cheieObiect, operatie {CREATE, UPDATE, DELETE, MAP, UNMAP, DIFF}, stare {PENDING, RUNNING, OK, FAILED, DRIFT, ACCEPTAT}, incercari, urmatoareaIncercare, eroare, diff (jsonb), corelatie
ProiectieUtilizatorsub, realm, username, nume, email, idnpCriptat, activ, mfa (set), ultimaAutentificare, ultimulEsec, unitate, locale, actualizatLamodel de citire
EvenimentGssoid (UUID), realm, tip, categorie {KC_USER, KC_ADMIN, CATALOG, GRANT, SYNC, CONSOLE}, actor, subiect, client, ip, moment, payload (jsonb), hashPrecedent, hash, glogIdappend-only; partiții lunare

Coloanele JSONB (diff, payload, descriere) sunt declarate ca TextBlob în JDL și convertite printr-un changelog Liquibase suplimentar cu @JdbcTypeCode(SqlTypes.JSON). Changelog-urile sunt append-only.

5.1 Înregistrarea unei platforme → clienți și roluri în Keycloak

Section titled “5.1 Înregistrarea unei platforme → clienți și roluri în Keycloak”
sequenceDiagram
actor A as Administrator de platformă
participant W as gsso-web
participant G as gsso-gateway
participant S as gsso
participant DB as BD gsso
participant R as ReconcilerWorker
participant K as Keycloak
A->>W: Creează platforma "crm" + clienți + roluri
W->>G: POST /api/v1/admin/platforme (Idempotency-Key)
G->>S: releu (token-ul utilizatorului)
S->>DB: tx: Platforma, ClientAplicatie*, RolPlatforma*, JobSincronizare*, EvenimentGsso
S-->>W: 201 (stareSync=PENDING)
R->>DB: preia joburile (SKIP LOCKED, lock pe realm)
R->>K: GET client după clientId → absent → POST client (gsso.managed=true)
R->>K: POST roluri, compozite, mapper de audiență
R->>DB: job OK, kcId stocat, stareSync=IN_SYNC, eveniment SYNC_OK
W->>G: interogare / reîmprospătare → insigna „sincronizat”

5.2 Cerere de atribuire → aprobare → token

Section titled “5.2 Cerere de atribuire → aprobare → token”
sequenceDiagram
actor Req as Solicitant
actor Own as Proprietar de platformă
actor Ap2 as Aprobator (sensibil)
participant S as gsso
participant K as Keycloak
participant N as GNotify
Req->>S: POST /admin/atribuiri {sub, CRM_ADMIN, motiv}
S->>S: SOLICITATA (+eveniment)
S->>N: notifică proprietarul
Own->>S: aprobă (nivelul 1)
alt rol sensibil
Ap2->>S: aprobă (nivelul 2, ≠ solicitant, ≠ aprobatorul-proprietar)
end
S->>S: APROBATA + Job MAP
S->>K: adăugare role-mapping (reconciliator)
K-->>S: 204
S->>S: ACTIVA (+eveniment, gsso.grant.v1)
Note over K: următorul token al utilizatorului conține CRM_ADMIN în roles
sequenceDiagram
actor O as Proprietar
participant S as gsso
participant K as Keycloak
participant Kf as Kafka
participant App as Aplicație (starter)
O->>S: revocă atribuirea (motiv)
S->>K: ștergere role-mapping
S->>K: POST /users/{id}/logout (sesiuni + back-channel logout)
S->>Kf: gsso.access-revoked.v1 {sub, notBefore=now}
Kf->>App: deny-list pentru sub până la expirarea TTL-ului token-ului
App-->>App: cereri cu iat < notBefore → 401
S->>S: REVOCATA (+eveniment → GLog)

5.4 Eveniment de autentificare → tablou de bord și GLog

Section titled “5.4 Eveniment de autentificare → tablou de bord și GLog”
sequenceDiagram
participant U as Utilizator
participant K as Keycloak (+gsso-kafka)
participant Kf as Kafka
participant S as gsso
participant L as GLog
U->>K: autentificare (parolă + OTP)
K-->>U: token-uri
K--)Kf: eveniment LOGIN (asincron)
Kf->>S: consum (deduplicare după eventId)
S->>S: EvenimentGsso (lanț de hash-uri), projection.lastLogin, agregate
S->>L: POST /api/v1/app/audit-events (client credentials)
L-->>S: id de confirmare
  1. La fiecare 15 min sau la cerere, RealmDiffer încarcă starea dorită pentru realm și citește Keycloak (clienți, roluri, compozite, mapările rolurilor gestionate, grupuri, fluxuri și câmpurile de politică pe care le gestionează).
  2. Pentru fiecare diferență creează un JobSincronizare(DIFF):
    • lipsește în Keycloak → CREATE (când politica este ENFORCE) sau DRIFT;
    • diferit → UPDATE sau DRIFT;
    • prezent în Keycloak cu gsso.managed=true, dar absent în GSSO → DELETE sau DRIFT;
    • prezent fără marcaj → NEGUVERNAT (doar raportare).
  3. În consolă, un administrator poate reîncerca, impune (aplică valoarea din GSSO) sau accepta drift-ul (copiază valoarea din Keycloak în GSSO).

5.6 Adoptarea unui realm existent (de ex. interdictii)

Section titled “5.6 Adoptarea unui realm existent (de ex. interdictii)”

Mai întâi se face o rulare de probă (GSSO-FR-080), apoi importul:

  • clienții sunt grupați în platforme pe baza unui fișier de mapare (clientId → codul platformei);
  • rolurile realm-ului sunt mapate la roluri de platformă prin reguli de redenumire (de exemplu ROLE_ADMIN → candidați <APP>_ADMIN per platformă, marcați pentru revizuire);
  • mapările curente utilizator→rol devin AtribuireAcces(ACTIVA, sursa=ADOPTAT).

Nimic nu se scrie în Keycloak cât timp politica de drift este IGNORE.

  1. Browserul deschide gsso.gstack…, iar gsso-gateway îl redirecționează către Keycloak (realm gstack, client gsso-console, PKCE + confidențial).
  2. Utilizatorul se autentifică. MFA este obligatorie pentru orice rol GSSO_* (NFR-SEC-008).
  3. Gateway-ul stochează token-urile în sesiunea de pe server și setează cookie-ul SESSION (HttpOnly, Secure, SameSite=Lax) plus cookie-ul CSRF.
  4. Apelurile SPA poartă cookie-ul. Gateway-ul transmite access token-ul către gsso, care aplică delimitarea pe realm și pe platformă pe baza rolurilor GSSO_* și a atributelor acestora.

5.8 Autentificarea cetățeanului prin MPass

Section titled “5.8 Autentificarea cetățeanului prin MPass”
  1. Un client cetatean redirecționează cetățeanul către Keycloak, care intermediază (broker) către MPass (SAML POST).
  2. Aserțiunea revine. Fluxul first-broker-login caută utilizatorul după atributul IDNP; dacă îl găsește, leagă contul, altfel creează utilizatorul cu atributele mapate.
  3. Keycloak setează valoarea acr pe baza nivelului de asigurare MPass, iar token-ul este emis pentru portal.

6. Configurația de bază a realm-ului (keycloak/realms/gstack.json, rezumat)

Section titled “6. Configurația de bază a realm-ului (keycloak/realms/gstack.json, rezumat)”
SetareValoare
Temă de autentificare / cont / e-mailgstack (GDS), limbi ro, ru, en, implicit ro
Protecție brute forceactivă, 5 eșecuri, increment de așteptare 60 s, maxim 15 min
Politica de parolelength(12) and upperCase(1) and lowerCase(1) and digits(1) and notUsername and notEmail and passwordHistory(5)
Sesiune SSO inactivă / maximă30 min / 10 h
Access token5 min
Evenimenteevenimente de utilizator + de administrare activate, evenimente de administrare cu reprezentare, listener-e jboss-logging, gsso-kafka, expirare 7 zile
Client scopes (implicite)profile, email, gsso-roles (roluri plate), gsso-org (org_unit, org_unit_path, roles_scoped), gsso-locale, acr
Client scopes (opționale)idnp, gsso-roles-filtered, offline_access
Fluxul browserCookie (alt) → Identity provider redirector (alt) → Formulare: username+parolă (req) → OTP/WebAuthn condiționat (condiție: utilizatorul are rolul GSSO_MFA_REQUIRED sau orice rol marcat sensibil)
Roluri impliciteROLE_USER
Clienți de bazăgsso-console (confidențial, standard flow, PKCE), gsso-api (bearer), gsso-reconciler se află în master
Acțiuni obligatoriiverificarea e-mailului, actualizarea parolei, configurarea OTP, înregistrarea WebAuthn, termeni (dezactivat)
Token exchangetoken exchange standard V2 activat; permisiuni per client din GSSO

cetatean.json folosește aceeași temă și setări diferite:

  • un identity provider SAML MPass cu un flux first-broker-login care face potrivirea după IDNP;
  • fără LDAP;
  • autentificarea cu parolă dezactivată implicit;
  • sesiune inactivă 15 min.

tenant-template.json este o copie parametrizată a gstack, fără federare.

AspectMăsură
Accesul la consolăBFF; roluri GSSO_*; MFA obligatorie; inactivitate 15 min; CSRF; CSP
Delimitarea pe realmGSSO_REALM_ADMIN poartă atributul gsso.realm; filtru pe server la fiecare interogare și comandă; testat prin matricea de autorizare
Delimitarea pe platformăGSSO_PLATFORM_OWNER cu atributul gsso.platforma (multi-valoare)
ReconciliatorulService account în master doar cu rolurile manage-*/view-* ale realm-urilor gestionate (fine-grained admin permissions V2); credențiale în depozitul de secrete; rotite la fiecare 90 de zile
Principiul „patru ochi”ApprovalPolicy: solicitant ≠ aprobator; pentru rolurile sensibile doi aprobatori distincți; rolurile GSSO sunt ele însele sensibile
SecreteSecretele clienților sunt generate de Keycloak, afișate o singură dată în consolă și nu sunt persistate în BD GSSO
Date cu caracter personalIDNP criptat (AES-GCM, cheie din depozitul de secrete) și mascat; jurnale curățate
Integritatea evenimentelorLanț de hash-uri + trigger în BD + copie WORM în GLog
CheiChei de realm RS256, rotație la 90 de zile cu suprapunere (cheia nouă activă, cea veche pasivă până trece TTL-ul maxim al token-ului)
Lanțul de aprovizionareSBOM (CycloneDX), Trivy, Semgrep, Gitleaks prin /gsast; imaginea Keycloak construită dintr-un digest fixat

Rolurile consolei GSSO (realm gstack):

RolSensibil
GSSO_ADMINda
GSSO_REALM_ADMINda
GSSO_PLATFORM_OWNERda
GSSO_APPROVERda
GSSO_HELPDESKda
GSSO_AUDITORnu
GSSO_IDNP_VIEWda
GSSO_MFA_REQUIREDmarcaj

8.1 Gazda demo (convenția gStack actuală)

Section titled “8.1 Gazda demo (convenția gStack actuală)”
  • Stiva compose ~/devops/gsso/ pe gazda partajată. Containerele se alătură rețelei externe gstack-web.
  • Containerele active keycloak + postgres-keycloak sunt preluate (§11.1): imaginea standard este înlocuită cu imaginea GSSO, construită pe aceeași versiune, cu extensii și temă adăugate.
  • gsso, gsso-gateway, gsso-web, gsso-postgres și, dacă nu este disponibil un Kafka partajat, un Kafka cu un singur nod (KRaft).
  • vhost-uri:
    • sso.gstack.esempla.systems → keycloak:8080, ca în prezent;
    • nou gsso.gstack.esempla.systems → gsso-web + gateway. Orice modificare a nginx-ului de margine necesită aprobarea proprietarului, iar reînnoirea certificatului trebuie reparată mai întâi (NFR-AVL-006).
  • Fluxul de implementare: construirea imaginilor amd64 → push în registry.esempla.systems/govtech/gstack/gsso-* (sau docker save | ssh | docker load) → docker compose up -d --no-deps --force-recreate <svc>.
  • Bugetul de memorie pe gazda de ~8 GB:
    • Keycloak heap de 1 GB;
    • gsso 512 MB;
    • gateway 384 MB;
    • postgres ×2 câte 256 MB fiecare;
    • Kafka 512 MB, dacă este local.
  • Keycloak: 2 replici (cluster Infinispan prin DNS_PING Kubernetes), cu PDB și HPA pe CPU.
  • gsso: 2 replici. Reconciliatorul este singleton per realm prin advisory lock, astfel încât ambele replici pot rula.
  • gateway: 2 replici, sesiuni în Redis sau JDBC.
  • PostgreSQL: CloudNativePG, câte 2 instanțe fiecare.
  • Kafka: clusterul Strimzi partajat.
ElementEstimare
Utilizatori angajați5 000 (inițial) → 20 000
Vârf de autentificări50/min tipic, rafală de 10/s la ora 9:00
Evenimente/zi≈ 50 000 (autentificări, reîmprospătarea token-urilor nu este jurnalizată implicit, administrare) → ≈ 30 MB/zi jsonb → partiții pe 90 de zile ≈ 3 GB
BD GSSO< 10 GB în primul an
BD Keycloak< 5 GB (sesiuni în memorie, funcția de sesiuni persistente de utilizator activată în 26.x → +1 GB)
  • Metrici (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);
    • metrici JVM și HTTP.
  • Jurnale: JSON cu trace id; filtru de curățare pentru Authorization, access_token, client_secret, password, idnp.
  • Tracing: OpenTelemetry pe traseul gateway → gsso → apelurile admin către Keycloak.
  • Alerte: NFR-OBS-004, rutate prin GNotify.
  1. Obțineți aprobarea proprietarului și conveniți o fereastră. Reparați mai întâi reînnoirea TLS.
  2. Faceți pg_dump al bazei de date Keycloak și copiați-l în afara gazdei. Exportați fiecare realm (kc.sh export --realm … --users different_files) ca referință.
  3. Construiți imaginea Keycloak GSSO pe aceeași versiune (26.6.3), cu extensii și temă adăugate. Încă nu se aplică nicio configurație de bază.
  4. Înlocuiți imaginea și verificați:
    • autentificările pentru toate aplicațiile;
    • issuer-ul este neschimbat;
    • JWKS este neschimbat. Rollback = imaginea anterioară, aceeași bază de date.
  5. Activați listener-ul gsso-kafka în realm-ul interdictii (acțiune de administrare), apoi porniți gsso cu realm-ul interdictii adoptat, IGNORE.
  6. Aplicați configurațiile de bază gstack și cetatean (realm-uri noi; nimic existent nu se modifică).
RunbookPași
Actualizarea KeycloakCopie de rezervă a bazei de date → rularea suitei IT pentru configurația de bază + reconciliator pe imaginea nouă → lansare etapizată → smoke test
Rotația cheilorAdăugați o cheie RS256 nouă (prioritate mai mare) → așteptați cel puțin 1 TTL de token + refresh → setați cheia veche ca pasivă → eliminați-o după durata maximă a sesiunii
Rotația secretului de client„Rotire” în consolă → fereastră de grație cu secret dublu → reimplementarea aplicației → secretul vechi invalidat
Acces de urgență (break-glass)Folosiți administratorul de urgență din master (credențiale sigilate, regula celor două persoane); fiecare utilizare este raportată
RestaurareRestaurați baza de date Keycloak din copia de rezervă → rulați o reconciliere completă în REPORT → analizați drift-ul → ENFORCE
CertificatReînnoire prin webroot; alertă cu 21 de zile înainte; job lunar de verificare
NivelDomeniuInstrumente
UnitarMașina de stări a atribuirilor, politica de aprobare, differ-ul, lanțul de hash-uri, mapper-ele, maparea din starterJUnit 5, AssertJ
IntegrareReconciliatorul pe Keycloak real, listener de evenimente → Kafka → consumator, Liquibase + trigger append-onlyTestcontainers (Keycloak 26.6.x cu extensii, PostgreSQL, Kafka) și deploy/docker-compose.test.yml (întotdeauna down -v)
ContractOpenAPI api/v1/app, scheme de evenimente (CloudEvents + JSON Schema)api_audit.py, teste de schemă
E2EFluxurile consolei (înregistrarea platformei, utilizator, aprobarea atribuirii, revocare, drift), SSO între două aplicații-exemplu, mock MPassCypress
SecuritateMatricea de autorizare (delimitare pe realm/platformă, principiul „patru ochi”), ZAP baseline, antete, SAST/SCA/secrete/gtestgen, /gtest, /gsast
PerformanțăRafală de autentificări, liste din consolă, reconcilierea a 1 000 de clienți/load-test, k6 pentru Keycloak
Verificare UIControale nefuncționale, chei netraduse, accesibilitate (a11y)/gfront

Scenariile de testare sunt listate în test-scenarios.md (TS-GSSO-NN) și reutilizează cazurile comune TC-COM-*.

ElementEstimare
Gazda demoÎncape pe gazda existentă (≈ 3 GB RAM suplimentar)
Ținta Kubernetes3 vCPU / 6 GB requests (Keycloak 2×, gsso 2×, gateway 2×) + 2 clustere PostgreSQL
Efortul de construire (S0–S3)≈ 14–18 persoane-săptămâni (1 backend, 1 frontend, 0,5 Keycloak/DevOps)
Migrarea aplicațiilor existente (S4)≈ 1–2 persoane-săptămâni per aplicație de tip A, ≈ 0,5 per aplicație de tip B