Sari la conținut

GSSO — Înregistrări ale deciziilor de arhitectură

Acest conținut nu este încă disponibil în limba selectată.

Cod documentSPEC-GSSO-2026 / Raportul 01
Versiune0.2 (sursa EN, text care prevalează)
Data2026-10-06
StatutAcceptat. GSSO-ADR-001..014 sunt Acceptat (decizia proprietarului, 2026-10-06); proprietarul poate încă solicita modificări, care necesită un ADR nou care îl înlocuiește
Rapoarte însoțitoare00 RFP · 02 Cerințe · 03 Consumatori și contract · 04 Documentație tehnică · 05 Foaie de parcurs
VersiuneDataModificări
0.1-draft2026-10-05GSSO-ADR-001..014, toate Propuse
0.22026-10-06GSSO-ADR-001..014 acceptate de proprietar (Acceptat); revizuirea unor ADR-uri poate urma prin ADR-uri noi care le înlocuiesc
0.32026-10-06Constatări din implementarea S1: GSSO-ADR-015 (modifică 008) și GSSO-ADR-016 (rafinează 004), ambele Propus

Un ADR consemnează o decizie semnificativă:

  • contextul: situația care a impus luarea unei decizii;
  • decizia: ce s-a ales;
  • alternativele luate în considerare: ce a fost respins și de ce;
  • consecințele: efectele pozitive și negative pe care echipa le acceptă.

Stilul casei urmează gregistry/docs/adr și paas_gflow/docs/reports/01-adr.en.md. Odată acceptat, un ADR este imuabil, iar o modificare necesită un ADR nou care îl înlocuiește.

Decizii din amonte care trebuie respectate:

  • saas_crm/docs/reports/DECISIONS.md: D9 (GSSO este platforma de identitate gStack), D27/D28 (GSSO este un PaaS existent, care trebuie reutilizat), D33 (stiva DEV-PLAYBOOK §2 pentru fiecare aplicație).
  • gregistry/docs/adr/ADR-002-auth-oidc-gsso.md: fără parole locale, rolurile în GSSO, SPA-ul folosește PKCE, comunicarea M2M folosește client credentials.
IDTitluStatut
GSSO-ADR-001GSSO este un plan de control peste Keycloak, nu un nou furnizor de identitateAcceptat
GSSO-ADR-002Model hibrid de realm-uri: gstack (personal), cetatean (cetățeni), tenant-* (izolate)Acceptat
GSSO-ADR-003Un singur cluster Keycloak 26.6.x cu PostgreSQL propriu; se păstrează instanța existentăAcceptat
GSSO-ADR-004Reconcilierea stării dorite prin Keycloak Admin REST APIAcceptat
GSSO-ADR-005Roluri cu spațiu de nume per platformă și un claim roles platAcceptat
GSSO-ADR-006Accesul se acordă prin AtribuireAcces, cu ciclu de viață și principiul „patru ochi”Acceptat
GSSO-ADR-007Evenimentele Keycloak printr-un SPI event-listener către Kafka; stocare append-only; redirecționare către GLogAcceptat
GSSO-ADR-008Utilizatorii rămân în Keycloak; GSSO păstrează o proiecție de citireAcceptat
GSSO-ADR-009Un singur model de integrare pentru aplicații: gsso-spring-boot-starter și @gstack/gsso-angularAcceptat
GSSO-ADR-010Stiva DEV-PLAYBOOK: microserviciul JHipster 9.1.0 gsso + gateway-ul gsso-gateway + gsso-webAcceptat
GSSO-ADR-011Configurația ca cod: baseline-ul realm-urilor, extensiile și temele în depozitAcceptat
GSSO-ADR-012Token exchange (RFC 8693, Keycloak standard token exchange V2) pentru apelurile în numele utilizatoruluiAcceptat
GSSO-ADR-013Revocare în 60 s: token-uri scurte, închiderea sesiunilor, evenimente de revocareAcceptat
GSSO-ADR-014Triajul EU AI Act: GSSO nu este un sistem de IAAcceptat
GSSO-ADR-015Operațiunile asupra utilizatorilor sunt apeluri directe, auditate, la Admin API (modifică GSSO-ADR-008)Propus
GSSO-ADR-016Implementarea reconcilierului: client Admin REST subțire, marcaje de proprietate, token lightweight (rafinează GSSO-ADR-004)Propus

GSSO-ADR-001 — GSSO este un plan de control peste Keycloak, nu un nou furnizor de identitate

Section titled “GSSO-ADR-001 — GSSO este un plan de control peste Keycloak, nu un nou furnizor de identitate”

Statut: Acceptat (2026-10-06)

Context.

  • Keycloak 26.6.3 deservește deja fiecare aplicație gStack la sso.gstack.esempla.systems. Este un furnizor OIDC/SAML certificat, cu MFA, WebAuthn, brokering, federare LDAP, token exchange și o consolă de cont.
  • Ceea ce lipsește este guvernanța:
    • un catalog de servicii;
    • roluri delimitate per platformă;
    • aprobarea accesului;
    • controlul drift-ului;
    • un audit durabil;
    • un standard unic de integrare;
    • o consolă în sistemul de design gStack.
  • Designul GSSO.dc.html prezintă GSSO drept „Single Sign-On (Keycloak)”.

Decizie.

  • GSSO este un plan de control în jurul unui Keycloak încorporat.
  • Keycloak deține autentificarea, credențialele, sesiunile, emiterea token-urilor, MFA, federarea, interfața de login (cu tema GDS) și autoservirea contului.
  • GSSO deține:
    • modelul guvernat (realm-uri, platforme, clienți, roluri de platformă, atribuiri, unități organizaționale, politici de autentificare);
    • reconcilierea acestuia în Keycloak;
    • depozitul de evenimente;
    • rapoartele;
    • API-ul app pentru consumatori;
    • consola de administrare.
  • GSSO nu manipulează niciodată parolele utilizatorilor și nu emite niciodată token-uri.

Alternative luate în considerare.

  1. Utilizarea exclusivă a consolei de administrare Keycloak standard. Respinsă: fără catalog, fără aprobare, fără detectarea drift-ului, fără GDS, fără audit dincolo de depozitul de evenimente propriu Keycloak, cu durată scurtă de păstrare.
  2. Scrierea unui furnizor de identitate propriu (Spring Authorization Server). Respinsă: ar reimplementa funcționalități certificate, critice pentru securitate (MFA, WebAuthn, broker SAML, LDAP), cu risc și cost ridicate.
  3. IAM comercial (Okta, Entra ID). Respinsă: constrângeri de suveranitate și de găzduire pentru datele guvernamentale, costul licențelor și investiția existentă în Keycloak.

Consecințe.

  • (+) Codul critic pentru securitate rămâne într-un proiect matur, iar GSSO rămâne mic.
  • (+) Aplicațiile existente continuă să funcționeze; URL-ul issuer-ului nu se schimbă pentru realm-urile preluate.
  • (−) Două surse de configurație pot diverge, ceea ce este atenuat prin reconciliere (GSSO-ADR-004).
  • (−) GSSO depinde de compatibilitatea Keycloak Admin API; actualizările sunt condiționate de teste (GSSO-NFR-OPS-004).

GSSO-ADR-002 — Model hibrid de realm-uri

Section titled “GSSO-ADR-002 — Model hibrid de realm-uri”

Statut: Acceptat (2026-10-06)

Context.

  • Sesiunile SSO Keycloak sunt per realm. Un utilizator autentificat în realm-ul A nu este autentificat în realm-ul B decât dacă B face brokering către A.
  • În prezent, realm-ul interdictii este, de facto, realm-ul partajat al personalului, în timp ce alte denumiri de realm (gdocs, gnotify, gstorage, gstack, ultra) apar în cod fără niciun plan în spate.
  • Macheta enumeră câte un realm per sistem (cancelaria, interdictii, portal-cetatean, glog-services). Aceasta oferă izolare, dar nu și SSO partajat.

Decizie.

RealmCineCliențiFederare
masterDoar inițializarea Keycloak și accesul de urgență (break-glass)gsso-reconciler (cont de serviciu)—
gstackÎntregul personal gStack și operatorii tuturor instituțiilorFiecare client SaaS și PaaS destinat personalului, consola GSSO, conturile de serviciu ale tuturor serviciilorAD/LDAP per instituție (opțional), fără MPass
cetateanCetățeni și mediul de afaceriPortaluri publice și SPA-uri destinate cetățenilorMPass/eID (broker SAML), legături first-broker-login după IDNP
tenant-<code>Clienți izolați (site-uri whitelabel ultra-*, bts-*, esempla-* sau o instituție care solicită realm propriu)Doar clienții acelui clientPer tenant
  • Instituțiile din gstack sunt separate prin unități organizaționale (claim-ul org_unit) și roluri de platformă, nu prin realm-uri.
  • Realm-urile de tenant sunt create dintr-un șablon de realm versionat.
  • Selectorul de realm din consolă stabilește domeniul de realm al fiecărui ecran.

Alternative luate în considerare.

  1. Câte un realm per aplicație (ca în machetă). Respinsă pentru personal: fără SSO între aplicații, iar rolurile și utilizatorii sunt duplicați per realm. Se păstrează doar pentru tenant-*.
  2. Un singur realm pentru tot, inclusiv pentru cetățeni. Respinsă: cetățenii și personalul au politici diferite (MFA, durata sesiunii, federare, minimizarea datelor), iar interfețele de administrare pentru personal nu trebuie să fie accesibile cu un cont de cetățean.
  3. Keycloak Organizations (mai multe organizații într-un singur realm). Luată în considerare pentru instituții. Se păstrează ca opțiune ulterioară (Q-GSSO-1). Unitățile organizaționale prin atribute acoperă necesitățile actuale, cu o cuplare mai redusă la o funcționalitate recentă.

Consecințe.

  • (+) Un singur login pentru toate aplicațiile personalului (obiectivul G-1).
  • (+) Datele și politicile cetățenilor sunt izolate de cele ale personalului.
  • (−) Realm-ul gstack devine critic. Disponibilitatea lui este disponibilitatea fiecărei aplicații a personalului (GSSO-NFR-AVL-*).
  • (−) Clienții existenți din interdictii trebuie migrați (raportul 05, faza S4) sau interdictii este preluat ca gstack (Q-GSSO-1).

GSSO-ADR-003 — Un singur cluster Keycloak 26.6.x cu PostgreSQL propriu; se păstrează instanța existentă

Section titled “GSSO-ADR-003 — Un singur cluster Keycloak 26.6.x cu PostgreSQL propriu; se păstrează instanța existentă”

Statut: Acceptat (2026-10-06)

Context.

  • Keycloak-ul în funcțiune este 26.6.3 (containerul keycloak, containerul de bază de date postgres-keycloak) pe gazda demo partajată, în spatele nginx-ului de la margine (edge).
  • Fișierul de design gstyle menționează „Keycloak 24”, dar informația este depășită.

Decizie.

  • GSSO fixează Keycloak 26.6.x (actualizările de patch sunt permise), cu o bază de date PostgreSQL dedicată, separată de baza de date GSSO.
  • Depozitul GSSO furnizează definițiile compose și Helm care reproduc instanța în funcțiune:
    • KC_PROXY_HEADERS=xforwarded;
    • hostname-ul sso.gstack.esempla.systems;
    • JAR-ul de extensii și temele montate;
    • health și metrics activate.
  • Instanța în funcțiune este preluată pe loc, nu înlocuită. Mai întâi se face backup bazei ei de date, apoi extensiile și tema GSSO sunt adăugate într-o fereastră de mentenanță aprobată de proprietar.
  • Ținta HA pentru producție: 2 noduri Keycloak cu clusterul Infinispan încorporat (sesiuni replicate), în spatele ingress-ului.

Alternative luate în considerare.

  • Keycloak nou și migrarea datelor: respinsă. Ar schimba secretele și ID-urile utilizatorilor (sub) și ar strica fiecare aplicație.
  • PostgreSQL partajat cu GSSO: respinsă, deoarece cele două au profiluri diferite de backup, de actualizare și de rază de impact (blast radius).

Consecințe.

  • (+) Nicio schimbare a URL-ului issuer-ului sau a sub pentru utilizatorii existenți.
  • (−) Preluarea necesită un runbook atent (raportul 04 §11) și un punct de rollback.

GSSO-ADR-004 — Reconcilierea stării dorite prin Keycloak Admin REST API

Section titled “GSSO-ADR-004 — Reconcilierea stării dorite prin Keycloak Admin REST API”

Statut: Acceptat (2026-10-06)

Context.

  • GSSO trebuie să aducă Keycloak în concordanță cu modelul său guvernat, să supraviețuiască eșecurilor parțiale și să evidențieze modificările manuale.

Decizie.

  • Calea de scriere: fiecare modificare de catalog sau de atribuire înregistrează (commit), într-o singură tranzacție, modificarea entității GSSO plus un JobSincronizare (outbox tranzacțional). Worker-ul reconcilier preia joburile în așteptare (SELECT … FOR UPDATE SKIP LOCKED) și le aplică prin keycloak-admin-client 26.x cu contul de serviciu gsso-reconciler.
  • Idempotență: fiecare operație caută după cheia naturală (numele realm-ului, clientId, numele rolului, id-ul utilizatorului + rolul), apoi creează, actualizează sau nu face nimic (no-op). Id-ul intern Keycloak este stocat înapoi ca kcId.
  • Reîncercare: backoff exponențial (1 s → 5 min, maximum 10 încercări), apoi FAILED, ceea ce declanșează o alertă prin GNotify.
  • Reconciliere completă:
    • periodic (implicit la fiecare 15 min) și la cerere;
    • calculează o diferență (diff) per realm între starea dorită și Keycloak, doar pentru tipurile de obiecte gestionate;
    • constatările devin rânduri JobSincronizare cu stare=DRIFT și un diff JSON.
  • Politica de drift per realm:
    • REPORT (implicit): doar afișare;
    • ENFORCE: corectare automată;
    • IGNORE: pentru realm-urile preluate, pe durata migrării.
  • Marcaj de proprietate: obiectele create de GSSO poartă atributul gsso.managed=true. Obiectele negestionate sunt raportate ca „negestionate” și nu sunt niciodată șterse decât dacă sunt preluate.
  • Preluare (adoptare): un import doar-citire al clienților, rolurilor și maparilor de roluri ale unui realm în catalog, ca Platforma + ClientAplicatie + RolPlatforma + AtribuireAcces(ACTIVA, sursa=ADOPTAT).

Alternative luate în considerare.

  1. Doar keycloak-config-cli / Terraform: potrivite pentru baseline-uri statice (folosite în GSSO-ADR-011), dar fără atribuiri la runtime, fără aprobare și fără interfață.
  2. Scrieri directe în baza de date Keycloak: respinsă ca nesuportată și nesigură.
  3. Apeluri sincrone din interfață, fără joburi: respinsă, deoarece eșecurile parțiale lasă o stare inconsecventă, fără reîncercare.

Consecințe.

  • (+) Rezilient, observabil și reluabil.
  • (−) Interfața trebuie să afișeze starea de sincronizare a fiecărui obiect (stareSync).
  • (−) Consistență eventuală: de regulă sub 2 s, limitată de politica de reîncercare.

GSSO-ADR-005 — Roluri cu spațiu de nume per platformă și un claim roles plat

Section titled “GSSO-ADR-005 — Roluri cu spațiu de nume per platformă și un claim roles plat”

Statut: Acceptat (2026-10-06)

Context.

  • În prezent, rolurile de realm ROLE_ADMIN și ROLE_USER sunt partajate de toate aplicațiile.
  • Aplicațiile le citesc din realm_access.roles sau dintr-un claim personalizat roles.
  • Grupurile candidate gFlow necesită denumiri de roluri prefixate cu aplicația (CRM_*, GTENDERS_*).

Decizie.

  • Fiecare rol expus de o platformă este un rol de realm denumit <PLATFORMA_COD_UPPER>_<ROL> (de exemplu INTERDICTII_EMITENT, CRM_ADMIN, GLOG_AUDITOR) și poartă atributul gsso.platforma=<cod>.
  • Rolurile compozite grupează rolurile inferioare din cadrul aceleiași platforme.
  • Rolul implicit ROLE_USER se păstrează pentru „utilizator autentificat din personal”.
  • ROLE_ADMIN este depreciat. Pe durata migrării este mapat la <APP>_ADMIN pentru fiecare aplicație care îl folosește, apoi este eliminat (raportul 05 S4).
  • Rolurile de client sunt permise pentru domeniile conturilor de serviciu (de exemplu gstorage-service: object:read). Autorizarea oamenilor folosește doar roluri de realm, astfel încât un singur claim roles să deservească fiecare aplicație.
  • Mapper-ul GSSO emite un tablou plat roles (rolurile de realm ale utilizatorului, efective după aplicarea compozitelor).
  • Client scope-ul gsso-roles-filtered poate limita tabloul la rolurile platformei din audiența token-ului plus ROLE_USER, pentru a păstra token-urile mici.
  • Starter-ul mapează roles la autorități Spring. <APP>_X devine autoritatea <APP>_X; pentru compatibilitate cu JHipster, aplicația poate mapa local <APP>_ADMIN la ROLE_ADMIN.

Alternative luate în considerare.

  • Roluri de client per aplicație pentru oameni: respinsă. Token-urile ar avea atunci nevoie de o structură de claim per client (resource_access), iar grupurile candidate gFlow și interogările între aplicații ar deveni mai dificile.
  • Grupuri în loc de roluri: grupurile se folosesc în continuare, dar doar ca modalitate de a grupa roluri (de exemplu „Operator Cancelaria”). Autorizarea se face întotdeauna pe roluri.

Consecințe.

  • (+) Rază de impact clară per platformă (obiectivul G-2).
  • (+) Un singur claim pentru toate aplicațiile.
  • (−) Aplicațiile existente trebuie să-și redenumească verificările de rol, ceea ce este atenuat prin harta de aliasuri a starter-ului pe durata migrării.

GSSO-ADR-006 — Accesul se acordă prin AtribuireAcces, cu ciclu de viață și principiul „patru ochi”

Section titled “GSSO-ADR-006 — Accesul se acordă prin AtribuireAcces, cu ciclu de viață și principiul „patru ochi””

Statut: Acceptat (2026-10-06)

Context.

  • Mapările de roluri făcute direct în Keycloak nu au motiv, aprobator sau termen de expirare.
  • NFRQ56–66 impun principiul privilegiului minim și un audit de securitate.
  • CAP-GSSO-04 necesită revocare rapidă.

Decizie.

  • Rolul de platformă al unei persoane este atribuit exclusiv printr-o AtribuireAcces:
SOLICITATA ──approve──▶ APROBATA ──reconciled──▶ ACTIVA ──revoke──▶ REVOCATA
│ │ └──validPana passed──▶ EXPIRATA
└──reject──▶ RESPINSA └──second approval required (sensitive)──▶ stays APROBATA(1/2)
  • Reguli, aplicate în stratul de servicii; fiecare tranziție scrie un EvenimentGsso:
    • Solicitantul poate fi utilizatorul, managerul acestuia, proprietarul platformei sau o aplicație prin api/v1/app. Motivul este obligatoriu.
    • Aprobatorul este proprietarul platformei sau un administrator de realm. Pentru rolurile sensibile este necesar și un al doilea aprobator, distinct, cu GSSO_APPROVER. Nimeni nu își aprobă propria solicitare.
    • ACTIVA se setează doar după ce reconcilierul confirmă maparea în Keycloak.
    • validPana este opțional. Valoarea sa implicită provine din politica rolului (Q-GSSO-5). Un planificator orar face să expire atribuirile scadente. Utilizatorii primesc o avertizare de expirare cu 14 zile și cu 1 zi înainte, prin GNotify.
    • Revocarea și expirarea elimină maparea și declanșează GSSO-ADR-013.
    • Administratorii pot acorda direct (solicitare și aprobare într-un singur pas) doar pentru rolurile nesensibile. Acest lucru este auditat ca ACORDARE_DIRECTA.
  • Conturile de serviciu primesc roluri prin configurația ClientAplicatie, nu prin atribuiri.

Alternative luate în considerare.

  • Doar maparea rolurilor în Keycloak: fără guvernanță.
  • Un proces BPMN în gFlow: luat în considerare. GSSO este o dependență a gFlow (gFlow se autentifică prin GSSO), deci ar apărea o dependență circulară. Ciclul de viață este mic, iar o mașină de stări în stratul de servicii este suficientă.

Consecințe.

  • (+) Răspunde la întrebarea „cine are ce, de ce, de când, până când, aprobat de cine”.
  • (−) Adaugă un pas în munca administrativă zilnică, ceea ce este atenuat prin atribuiri în masă și șabloane de roluri (grupuri).

GSSO-ADR-007 — Evenimentele Keycloak printr-un SPI event-listener către Kafka; stocare append-only; redirecționare către GLog

Section titled “GSSO-ADR-007 — Evenimentele Keycloak printr-un SPI event-listener către Kafka; stocare append-only; redirecționare către GLog”

Statut: Acceptat (2026-10-06)

Context.

  • Keycloak păstrează evenimentele de utilizator și evenimentele de administrare în propria bază de date, cu expirare scurtă, și nu oferă mecanism de tip push.
  • Dashboard-ul, evenimentele de securitate, ultima autentificare și proiecția au nevoie de ele.
  • GLog este depozitul de audit WORM al gStack.

Decizie.

  • Event listener. Extensia GSSO pentru Keycloak furnizează un EventListenerProvider, gsso-kafka. Acesta publică fiecare eveniment de utilizator (LOGIN, LOGIN_ERROR, LOGOUT, CODE_TO_TOKEN, CLIENT_LOGIN, UPDATE_CREDENTIAL, REGISTER, IDENTITY_PROVIDER_*…) și fiecare eveniment de administrare (cu reprezentare) în topic-ul Kafka gsso.kc-events.v1:
    • CloudEvents în mod binar;
    • cheie = realmId:userId;
    • asincron, cu un buffer local limitat.
    • Dacă Kafka este indisponibil, evenimentul se află în continuare în depozitul de evenimente Keycloak, iar golul este completat retroactiv (back-fill) din Admin API de către consumatorul GSSO.
  • Consumator. gsso consumă topic-ul în mod idempotent (deduplicare după eventId), scrie EvenimentGsso și actualizează ProiectieUtilizator (ultima autentificare, eșecuri) și agregatele dashboard-ului.
  • Evenimentele proprii GSSO. Modificările de catalog, tranzițiile atribuirilor și joburile de sincronizare sunt scrise în EvenimentGsso în aceeași tranzacție cu modificarea.
  • Stocare. EvenimentGsso este append-only:
    • repository-ul nu are metode de actualizare sau de ștergere;
    • un trigger de bază de date respinge UPDATE și DELETE;
    • fiecare rând poartă hashPrecedent și hash (lanț SHA-256 per realm).
  • Redirecționare. Un releu redirecționează fiecare eveniment către GLog POST /api/v1/app/audit-events (client credentials, scope audit:write), cu reîncercare, înregistrând id-ul de confirmare GLog.
  • Retenție. 90 de zile în GSSO (Q-GSSO-7); GLog păstrează traseul pe termen lung.

Alternative luate în considerare.

  • Interogarea periodică (polling) a API-ului de evenimente Keycloak: respinsă ca mecanism principal din cauza latenței și a costului paginării. Se păstrează pentru back-fill.
  • Listener-e Kafka terțe: respinsă. Sunt necesare învelișul CloudEvents și convenția de denumire a topic-urilor gStack.

Consecințe.

  • (+) Dashboard aproape în timp real și traseu criminalistic (forensic).
  • (−) Adaugă Kafka la dependențele de runtime ale Keycloak. O indisponibilitate Kafka nu blochează autentificările, deoarece listener-ul este asincron și neblocant.

GSSO-ADR-008 — Utilizatorii rămân în Keycloak; GSSO păstrează o proiecție de citire

Section titled “GSSO-ADR-008 — Utilizatorii rămân în Keycloak; GSSO păstrează o proiecție de citire”

Statut: Acceptat (2026-10-06)

Context.

  • Utilizatorii și credențialele trebuie să aibă o singură sursă master. Consola are nevoie de căutare rapidă între realm-uri, de ultima autentificare și starea MFA, precum și de vizualizări ale atribuirilor per utilizator.

Decizie.

  • Keycloak este sursa master a utilizatorilor: identitate, atribute, credențiale, legături de federare.
  • Editările de utilizatori din consolă apelează Keycloak Admin API prin reconcilier (JobSincronizare de tip UTILIZATOR). Resetările de credențiale și acțiunile obligatorii (required actions) îl apelează sincron, deoarece nu reprezintă stare dorită.
  • ProiectieUtilizator este reîmprospătată în trei moduri:
    • din evenimente;
    • printr-o sincronizare completă nocturnă per realm (paginată, 500 pe pagină);
    • la cerere, când un utilizator este deschis. Stochează sub, username, numele, e-mailul, idnp (criptat), starea activ/inactiv, tipurile MFA, ultima autentificare și realm-ul.
  • Ștergerea unui utilizator în Keycloak elimină proiecția și anonimizează câmpurile de actor din tabelele de lucru ale GSSO. Rândurile de audit păstrează doar sub.

Consecințe.

  • (+) Fără dublă sursă master; utilizatorii federați (LDAP/MPass) sunt vizibili.
  • (−) Proiecția poate întârzia cu câteva secunde; consola afișează momentul „reîmprospătat la”.

GSSO-ADR-009 — Un singur model de integrare pentru aplicații

Section titled “GSSO-ADR-009 — Un singur model de integrare pentru aplicații”

Statut: Acceptat (2026-10-06)

Context.

  • În prezent există patru modele (raportul 00 §2).
  • Modelul A, cu JWT-uri HS512 emise de aplicație după autentificarea în Keycloak, păstrează o cheie locală de semnare și parole locale. Aceasta anulează logout-ul SSO, revocarea și auditul.

Decizie.

Tip de aplicațieModel
Gateway JHipster + microservicii (playbook)Gateway = client OAuth2 (BFF, authorization code + PKCE, confidențial). Microservicii = resource servers. Totul prin gsso-spring-boot-starter
Monolit Spring Boot cu SPAResource server prin starter; SPA = client public + PKCE prin @gstack/gsso-angular (sau modul BFF)
Serviciu-la-serviciuClient credentials, câte un client confidențial per serviciu apelant; token exchange pentru apeluri în numele utilizatorului (GSSO-ADR-012)
Clienți KafkaSASL OAUTHBEARER cu client credentials ale serviciului
Mobil (gsso_mob)Client public + PKCE + redirect cu schemă personalizată
Servicii non-Java (Python RAG, Node)Validare prin JWKS; fragment de cod documentat
  • Starter-ul (systems.esempla.gsso:gsso-spring-boot-starter):
    • validarea issuer-ului și JWKS plus un validator de audiență;
    • roles → autorități, cu o hartă de aliasuri opțională pentru migrare;
    • GssoPrincipal care expune sub, username, orgUnit, locale, idnp?;
    • un interceptor client-credentials pentru RestClient/WebClient și un helper pentru token exchange;
    • un listener pentru evenimentele de revocare (GSSO-ADR-013);
    • un KeycloakHealthIndicator în grupul readiness;
    • un helper Testcontainers. Reutilizează cod verificat din gregistry (AudienceValidator) și cancelarie (KeycloakHealthIndicator).
  • Biblioteca Angular (@gstack/gsso-angular): login PKCE (sau modul sesiune BFF), un guard de rol și directiva *gssoHasRole, reîmprospătare silențioasă, logout unic și sincronizarea limbii din claim-ul locale.
  • Parolele locale și token-urile emise de aplicație sunt interzise pentru aplicațiile noi și eliminate din cele existente pe durata migrării (raportul 03 §2).

Consecințe.

  • (+) O singură analiză de securitate acoperă toate aplicațiile; logout-ul și revocarea funcționează peste tot.
  • (−) Aplicațiile cu modelul A (interdictii, gdocs, gnotify) necesită modificări de cod, planificate în raportul 05.

Statut: Acceptat (2026-10-06)

Decizie.

  • gsso: JHipster 9.1.0, applicationType: microservice.
    • Pachetul systems.esempla.gsso, authenticationType: oauth2 (chiar GSSO, realm-ul gstack), Maven, PostgreSQL, Kafka.
    • languages: ro,ru,en cu ro nativ, skipClient: true.
    • Entitățile din gsso.jdl.
  • gsso-gateway: JHipster 9.1.0 applicationType: gateway. Este BFF-ul pentru gsso-web (clientul gsso-console, confidențial) și punctul unic de intrare API; rutează doar /api/v1/** și /api/v1/app/**.
  • gsso-web: un SPA Angular separat pe @gstack/gds-angular / @gstack/gds-core, cu tema gdsThemedCss('#7c3aed') (--gds-accent-gsso), i18n ro/ru/en.
  • keycloak/: extensiile (modul Maven, Java 21, Keycloak SPI 26.6.x), temele (FreeMarker + CSS GDS) și baseline-urile realm-urilor.
  • Versiunile Java, Spring Boot, Angular, PostgreSQL și Kafka sunt exact cele generate de JHipster 9.1.0, fixate la S0. Orice abatere necesită un ADR.
  • Inițializare (bootstrapping): consola se autentifică chiar în Keycloak-ul pe care îl gestionează. Dacă GSSO este indisponibil, Keycloak și toate autentificările continuă să funcționeze; doar guvernanța este suspendată.

Consecințe.

  • (+) Același set de instrumente și aceleași convenții ca celelalte aplicații gStack.
  • (−) Consola depinde de realm-ul gstack. Accesul de urgență (break-glass) este consola de administrare Keycloak master, păstrată doar pentru echipa platformei.

Statut: Acceptat (2026-10-06)

Decizie.

  • Depozitul conține următoarele, aplicate la momentul implementării de un job unic gsso-bootstrap care folosește keycloak-config-cli, cu substituție de variabile și fără secrete:
    • keycloak/realms/gstack.json, cetatean.json și tenant-template.json: baseline-ul, adică setările realm-ului, fluxurile, client scope-urile, mapper-ele, politica de parole, temele, event listener-ul și clienții gsso-console și gsso-reconciler;
    • keycloak/extensions/ (JAR);
    • keycloak/themes/gstack/ (login, cont, e-mail);
    • docker-compose.yml și helm/.
  • Obiectele de runtime (platformele, clienții și rolurile acestora, atribuirile, utilizatorii) sunt deținute de reconcilierul GSSO, nu de fișierele de baseline. Cele două seturi sunt disjuncte, astfel încât bootstrap-ul nu suprascrie niciodată obiectele de runtime.
  • Secretele (secretele clienților, credențialele reconcilierului, SMTP, LDAP bind) provin din mediu sau din depozitul de secrete. .env.example enumeră doar denumirile.

Consecințe.

  • (+) Un Keycloak poate fi reconstruit din git plus un backup al bazei de date (obiectivul G-4), iar modificările pot fi analizate în merge request-uri.

GSSO-ADR-012 — Token exchange pentru apelurile în numele utilizatorului

Section titled “GSSO-ADR-012 — Token exchange pentru apelurile în numele utilizatorului”

Statut: Acceptat (2026-10-06)

Context.

  • CAP-GSSO-07: apelurile CRM ↔ gDocFlow ↔ gTenders trebuie să poarte identitatea utilizatorului, astfel încât aplicația apelată să aplice vizibilitatea acestuia.

Decizie.

  • Se folosește standard token exchange (V2, internal-to-internal) din Keycloak, disponibil în 26.x.
  • Fiecare platformă-țintă are un client scope de audiență.
  • Un client-sursă poate face schimbul doar pentru audiențele enumerate în ClientAplicatie.audienteSchimb. GSSO reconciliază aceste liste în permisiunile de token exchange sau în politicile de client.
  • Token-urile obținute prin schimb:
    • păstrează sub al utilizatorului;
    • setează aud la țintă;
    • poartă act.sub = clientul apelant;
    • sunt limitate la rolurile platformei-țintă.
  • Impersonarea și schimbul external-to-internal sunt dezactivate.

Consecințe.

  • (+) Delegare cu privilegiu minim, fără transmiterea parolelor utilizatorilor sau a token-urilor cu durată lungă de viață.
  • (−) Perechile permise trebuie întreținute; ele sunt vizibile în consolă și în raportul 03.

Statut: Acceptat (2026-10-06)

Context.

  • CAP-GSSO-03/04 cer ca un utilizator sau un rol revocat să piardă accesul în 60 s (relaxat la 5 min în unele pachete).
  • Resource server-ele validează JWT-urile offline, astfel încât un rol revocat rămâne într-un token de acces neexpirat.

Decizie.

  • Durata de viață a token-ului de acces: 5 min în gstack; 2 min pentru clienții marcați sensitive.
  • La revocare, expirare, dezactivarea utilizatorului sau „închiderea sesiunilor”, GSSO:
    1. elimină maparea sau dezactivează utilizatorul;
    2. șterge sesiunile utilizatorului în Keycloak (logout al utilizatorului, care declanșează și back-channel logout către clienții care îl suportă);
    3. publică gsso.access-revoked.v1 pe Kafka cu sub, rolurile de platformă afectate și un moment not-before.
  • Starter-ul consumă gsso.access-revoked.v1 și păstrează în memorie o listă de interdicție (deny list) indexată după sub + not-before, pe durata de viață a token-ului. O cerere cu un token emis înainte de momentul not-before primește 401.
  • Gateway-urile BFF își elimină, de asemenea, sesiunea de pe server la back-channel logout.

Alternative luate în considerare.

  • Introspecția token-ului la fiecare cerere: respinsă din cauza latenței și a încărcării Keycloak pentru toate aplicațiile. Rămâne disponibilă pentru endpoint-urile foarte sensibile.

Consecințe.

  • (+) Revocare în 60 s pentru aplicațiile care folosesc starter-ul. Celelalte se bazează pe expirarea token-ului (maximum 5 min).

Statut: Acceptat (2026-10-06)

Decizie.

  • GSSO nu este un sistem de IA în sensul Reg. (UE) 2024/1689 art. 3 alin. (1). Nu conține inferență, scoring sau clasificare (ranking) a persoanelor.
  • Autentificarea bazată pe risc (MFA adaptiv pe baza semnalelor de IP sau de dispozitiv), dacă va fi adăugată ulterior, trebuie să fie bazată pe reguli și documentată. Orice scoring bazat pe ML necesită un nou triaj conform skill-ului ai-act înainte de proiectare.

GSSO-ADR-015 — Operațiunile asupra utilizatorilor sunt apeluri directe, auditate, la Admin API

Section titled “GSSO-ADR-015 — Operațiunile asupra utilizatorilor sunt apeluri directe, auditate, la Admin API”

Statut: Propus (2026-10-06). Modifică o frază din GSSO-ADR-008.

Context.

  • GSSO-ADR-008 prevede că editările de utilizatori din consolă trec prin reconcilier ca JobSincronizare de tip UTILIZATOR.
  • Utilizatorii nu sunt stare dorită: Keycloak este sursa lor master.
  • Crearea unui utilizator trebuie să returneze imediat consolei id-ul său Keycloak, iar un administrator se așteaptă ca o dezactivare sau o închidere a sesiunilor să aibă efect imediat, nu după o coadă.

Decizie.

  • Operațiunile asupra utilizatorilor apelează sincron Keycloak Admin API prin KeycloakAdminClient: creare, editare, activare/dezactivare, acțiuni obligatorii (required actions), eliminarea credențialelor, închiderea sesiunilor, deblocare.
  • Fiecare operațiune reușită adaugă un EvenimentGsso în aceeași cerere și reîmprospătează ProiectieUtilizator.
  • Erorile Keycloak sunt mapate la RFC 7807: 409 conflict, 400 validare, 502 pentru eșecurile Keycloak.
  • Coada reconcilierului rămâne pentru starea dorită: realm-uri, clienți, roluri și, din S2, mapările de roluri ale atribuirilor.

Consecințe.

  • (+) Feedback imediat și nicio coadă pentru operațiunile care nu reprezintă stare dorită.
  • (−) O indisponibilitate Keycloak face ca operațiunile asupra utilizatorilor să eșueze imediat, în loc să fie amânate; consola afișează eroarea.

GSSO-ADR-016 — Detalii de implementare ale reconcilierului

Section titled “GSSO-ADR-016 — Detalii de implementare ale reconcilierului”

Statut: Propus (2026-10-06). Rafinează GSSO-ADR-004; deciziile de acolo rămân valabile.

Context. Construirea și testarea S1 pe Keycloak 26.6.3 au evidențiat cinci aspecte pe care GSSO-ADR-004 le-a lăsat deschise sau le-a tratat greșit.

Decizie.

  1. Client Admin. Un client JSON subțire peste Spring RestClient (KeycloakAdminClient) înlocuiește keycloak-admin-client. Stiva RESTEasy a bibliotecii se potrivește prost cu Spring Boot 4, iar GSSO folosește o mică parte din API. Fiecare apel Keycloak trece în continuare prin această singură clasă.
  2. Marcaj de proprietate. gsso.managed ia două valori:
    • catalog: creat de reconcilier, care poate actualiza și șterge obiectul;
    • baseline: deținut de fișierele baseline ale realm-ului sau de șablonul de tenant; reconcilierul nu îl modifică și nu îl șterge niciodată, iar detectarea drift-ului îl ignoră. Obiectele nemarcate sunt negestionate: raportate, niciodată șterse. O singură valoare true ar fi permis modului ENFORCE să șteargă clientul consolei și rolul implicit ROLE_USER din fiecare realm de tenant.
  3. Token de acces lightweight pentru gsso-reconciler. Opțiunea client.use.lightweight.access.token.enabled. Un token complet poartă rolurile de administrare ale fiecărui realm creat de reconcilier și depășește limitele antetelor HTTP (HTTP 431) după câteva zeci de realm-uri. De asemenea, claim-urile sale devin învechite imediat după crearea unui realm (HTTP 403). Cu token-ul lightweight (≈780 de octeți, constant), Keycloak verifică permisiunile în timp real. Un 403 declanșează în continuare o reîmprospătare a token-ului și o reîncercare.
  4. Ordonare. Worker-ul preia joburile scadente cu FOR UPDATE SKIP LOCKED și nu preia niciodată un realm care are deja un job RUNNING, astfel încât joburile unui realm se aplică pe rând și în ordinea id-ului, inclusiv cu mai multe instanțe (GSSO-FR-079).
  5. Clase de eșec.
    • Tranzitorii: niciun răspuns, 401, 429, 5xx. Reîncercate cu backoff exponențial (1 s → 5 min), FAILED după 10 încercări.
    • Permanente: alte 4xx sau un obiect deținut de baseline. FAILED imediat.

Consecințe.

  • (+) Fiecare aspect este acoperit de teste de integrare pe un Keycloak real (ReconcilerIT).
  • (−) Clientul subțire trebuie extins manual când sunt necesare apeluri noi la Admin API.