node-user-profiling

Profilazione utente, ruoli, gruppi e permessi applicativi.
identity
/user-profilingauth: nginx

node-user-profiling

In sintesi

Servizio di autorizzazione enterprise: risponde alle domande "chi è questo utente?" e "cosa può fare?" per l'intero portale ditta. Mantiene la proiezione locale dell'identità applicativa — ruoli, permessi granulari, gruppi, team, policy ABAC dinamiche — e ne pubblica il risultato come decisione autorizzativa cache-friendly. Si distingue dal complementare node-user-auth, che gestisce come l'utente si autentica (cookie nginx, JWT, OAuth M2M): qui si concentra esclusivamente la logica RBAC/ABAC e l'analisi del rischio. Le route REST sono il canale primario; NATS è usato in modo puntuale per restare allineato a eventi di ciclo vita utente.

Funzionalità principali

  • RBAC gerarchico su cinque livelli (superadmin > admin > manager > operatore > viewer) con ereditarietà permessi e prevenzione cicli a livello DB
  • ABAC engine con policy allow / deny / conditional, condizioni runtime su orari, dipartimenti e attributi della richiesta, modalità fail_open / fail_closed
  • Gestione gruppi e team: CRUD completo, membership, ruoli e permessi collettivi su auth.gruppi (tipogruppo progetto o organizzativo), invalidazione cache transitiva
  • Check autorizzazione singolo e batch (POST /api/v1/authorization/check e /bulk-check) con cache distribuita Redis e TTL distinti per esiti positivi, sensibili e negativi
  • Endpoint nginx auth_request: verifica l'autorizzazione di una richiesta a partire dagli header inoltrati dal reverse proxy (/nginx-auth)
  • Anomaly detection con risk scoring 0-100, finestre di osservazione configurabili, alert su soglia, indagine pattern per singolo utente
  • Audit trail delle decisioni autorizzative tramite event bus interno (audit, metrics, security alert) con correlation ID propagato
  • Reconciliation utenti orfani (/api/v1/admin/users/exists) e endpoint internal S2S (/api/v1/internal/*) per fallback hard-delete e operazioni batch protette da X-Internal-Token
  • Migrazioni SQL idempotenti con checksum tracking eseguite all'avvio del processo

Architettura

Stack: Fastify v5 · Inversify (DI con @injectable / @inject e profili default / high-performance / high-security / development) · PostgreSQL via driver pg (schema auth) · Redis opzionale per cache decisioni · NATS opzionale per un singolo subject di sincronizzazione · @pzeta/fastify-utils (authPlugin, securityPlugin, errorHandlerPlugin, openapiPlugin, healthcheckPlugin) · @pzeta/authorization (libreria interna che fornisce AuthorizationOrchestrator, PermissionEvaluationService, BusinessPolicyService, SecurityAnalyticsService) · @pzeta/log per logging strutturato · Zod per validazione input.

Layout DDD (src/):

LayerContenuto
domain/authorization/Motori RBACEngine e ABACEngine (con OPAPolicyEngine), entità Role, Permission, Policy, PermissionConflict, AuthorizationDecision
domain/entities/Group e Team con value object di membership, ruoli e permessi
domain/events/Eventi di dominio PermissionGrantedEvent, PermissionDeniedEvent, PolicyEvaluatedEvent, AnomalyDetectedEvent, CacheInvalidatedEvent + DomainEventPublisher
domain/services/UserBehaviorAnalysisService per analisi pattern accessi e timing profile
application/services/AuthorizationAppService — orchestra i use case combinando l'orchestrator della libreria con CRUD policy/group/team e mapping HTTP↔domain
infrastructure/database/PostgresConnectionPool (pool tunato), MigrationRunner con checksum
infrastructure/repositories/RBACRepository e OptimizedRBACRepository (variante con prepared statement per profilo high-performance)
infrastructure/authorization/AuthorizationFactory, PostgresABACRepository, GroupRepository, TeamRepository
infrastructure/cache/PermissionCache Redis-backed e NullPermissionCache per esecuzione senza cache
infrastructure/messaging/NatsEventBus (wrapper riconnessione automatica) e UserDeletedSubscriber
infrastructure/di/AuthorizationContainer — wiring Inversify e registrazione subscriber dell'event bus in-memory
presentation/routes/13 moduli route (RoleRoutes, PermissionRoutes, UserRoleRoutes, UserPermissionRoutes, AuthorizationCheckRoutes, PolicyRoutes, GroupRoutes, TeamRoutes, StatsRoutes, AnomalyRoutes, NginxAuthRoutes, AdminRoutes, InternalRoutes)
presentation/middleware/Rate limiting per-user/IP, RequirePermission per protezione granulare

Pattern adottati: Clean Architecture + DDD, Dependency Injection (Inversify), Repository, Factory, Strategy (profili AUTH_SERVICE_PROFILE), in-memory event bus per side-effects post-decisione (audit / metrics / security alert), Result monad per error handling funzionale nei servizi di dominio.

RBAC e ABAC: le route applicano requirePermission() sulla coppia resource:action derivata dal contesto. Il check finale è risolto dall'AuthorizationOrchestrator che combina decisione RBAC (materializzata dai ruoli effettivi dell'utente: diretti + ereditati + da gruppi/team), valutazione ABAC della policy applicabile e politica di fallback fail_open / fail_closed per ogni policy.

Casi d'uso

  • Gestione ruoli da UI admin: il frontend Vue (sezione amministrativa) crea un nuovo ruolo via POST /api/v1/roles, ne dichiara il parentRoleId, associa permessi resource:action e lo assegna a gruppi/team o singoli utenti con eventuale scadenza
  • Check permessi runtime da altri microservizi: un servizio applicativo (es. node-orchestrator) invia POST /api/v1/authorization/check con { userId, resource, action, context } per decidere se eseguire un task sensibile; le decisioni sono cacheable con TTL configurabili
  • Autorizzazione del reverse proxy: nginx invoca /nginx-auth con header x-user-id e path target; il servizio risponde 200/403 e popola gli header inoltrati alla risorsa protetta
  • Sincronizzazione utenti da provider esterno: node-user-auth, dopo aver registrato un nuovo utente nell'identity provider, può triggerare la reconciliation via GET /api/v1/admin/users/exists o pubblicare un evento di cancellazione su NATS (vedi sezione eventing) per propagare l'hard-delete GDPR
  • Investigazione security: l'operatore SOC consulta /api/v1/anomalies per identificare utenti con risk score elevato, ricostruisce la timeline dei tentativi negati tramite gli aggregati esposti da /api/v1/stats e disabilita ruoli compromessi
  • Operazioni batch internal: pipeline di sistema chiamano /api/v1/internal/users/:userId/roles/batch (protette da X-Internal-Token) per riassegnare massivamente ruoli a fronte di una riorganizzazione

Identità & esposizione

CampoValore
Categoriaidentity
Versione cluster1.0.0
Imagegitea.pzetatouch.it/pzeta_touch/node-user-profiling:1.0.14
URL pubblicohttps://ditta.pzeta.it/user-profiling
Path regex ingress`/user-profiling(/
Rewrite a backend/$2
DNS internonode-user-profiling-ditta.ditta.svc.cluster.local:3000
Auth nginxauth_requestnode-user-auth
Repositorynode-user-profiling
Endpoint REST64 (vedi sezione "API reference")

Endpoint operazionali

Endpoint convenzionali esposti da tutti i microservizi PZeta basati su @pzeta/fastify-utils:

Path pubblicoScopo
https://ditta.pzeta.it/user-profiling/healthliveness probe
https://ditta.pzeta.it/user-profiling/readyreadiness probe
https://ditta.pzeta.it/user-profiling/metricsmetriche Prometheus
https://ditta.pzeta.it/user-profiling/api-docs.jsonspec OpenAPI runtime (richiede OPENAPI_EXPOSE_IN_PRODUCTION=true)
https://ditta.pzeta.it/user-profiling/api-docsSwagger UI (solo in NODE_ENV !== production)

Configurazione

Variabili d'ambiente che un integratore deve conoscere (per la lista completa vedi .env.example del repo):

VariabileRuolo
DATABASE_HOST / _PORT / _USER / _PASSWORD / _NAMEConnessione PostgreSQL — ruoli, permessi, gruppi, team, policy, audit
DATABASE_SCHEMADefault auth; isola gli oggetti di profilazione dal resto del DB applicativo
DATABASE_MAX_CONNECTIONSPool size del driver pg; alzare nei profili high-performance
AUTH_SERVICE_PROFILEProfilo di runtime: default, high-performance (repository ottimizzati + Redis aggressivo), high-security (policy fail_closed, soglie anomaly stringenti), development (Swagger UI esposto, error verbose)
REDIS_ENABLED / REDIS_HOST / _PORT / _PASSWORD / _DBCache distribuita delle decisioni autorizzative; off in dev
CACHE_STANDARD_TTL / CACHE_SENSITIVE_TTL / CACHE_DENY_TTLTTL in secondi per esiti standard, sensibili e di rifiuto
NGINX_AUTH_ENABLED / NGINX_AUTH_STRICTAbilita l'endpoint /nginx-auth e ne governa la modalità strict (rifiuta header malformati)
TRUST_X_USER_ID_HEADERForza il rispetto di x-user-id solo se ricevuto da nginx upstream; false in produzione esposta
SECURITY_RISK_THRESHOLD / SECURITY_ANALYSIS_WINDOW_HOURSSoglia di rischio e finestra di analisi per anomaly detection
RATE_LIMIT_ENABLED / RATE_LIMIT_MAX_REQUESTSRate limit sliding window per utente/IP via @pzeta/fastify-utils
MIGRATION_STRICT_CHECKSUMSe true, una migrazione modificata rispetto al checksum registrato blocca l'avvio
INTERNAL_API_TOKENToken (min 16 char) per le route /api/v1/internal/* di operazioni S2S
NATS_URL / NATS_USER / NATS_PASSWORD / NATS_NAMESPACEConnessione NATS opzionale; se assente, il servizio gira in modalità solo-HTTP
USER_DELETED_SUBJECTOverride del subject NATS per eventi di cancellazione utente; default ${NATS_NAMESPACE}.authz.user.deleted

Swagger UI e api-docs.json runtime sono esposti solo quando AUTH_SERVICE_PROFILE=development o, in produzione, se OPENAPI_EXPOSE_IN_PRODUCTION=true.

Note eventing NATS

Il servizio è principalmente HTTP-driven e usa NATS come canale secondario di sincronizzazione, non come trasporto primario delle decisioni autorizzative. La connessione NATS è opzionale: se NATS_URL non è configurato o non raggiungibile, il servizio prosegue in modalità degradata mantenendo intatte tutte le funzionalità REST.

Il subscriber NATS effettivamente registrato è uno solo: UserDeletedSubscriber ascolta ${NATS_NAMESPACE}.authz.user.deleted (override via USER_DELETED_SUBJECT) per ricevere notifiche di hard-delete GDPR pubblicate da node-user-auth. Alla ricezione invoca AuthorizationAppService.cleanupUser, idempotente per costruzione (DELETE su righe assenti = no-op). Le semantiche di delivery sono at-most-once (Core NATS senza JetStream): un errore nell'handler scarta il messaggio; il recupero avviene via endpoint HTTP /api/v1/internal/users/:userId/cleanup (manuale) o reconciliation batch /api/v1/admin/users/exists. L'upgrade a JetStream a livello infrastruttura aggiunge at-least-once senza modifiche al codice.

I dieci subject che lo scanner statico rileva nel file nats.json (permission.granted, permission.denied, anomaly.detected, policy.evaluated, cache.invalidated) non sono subject NATS: sono sottoscrizioni a un InMemoryEventPublisher interno usato per pipeline di side-effect (audit, metrics, security alert) generate dalle decisioni autorizzative. Vengono restituite dallo scanner perché l'API subscribe() è omonima a quella NATS, ma il dispatch avviene in-process. In altre parole, il servizio mantiene una proiezione locale dell'identità ma la mantiene per pull (HTTP) o per evento puntuale di lifecycle (cancellazione utente), non per stream continuo.

Dipendenze e dipendenti

Dipende da (servizi che questo servizio chiama):

  • Nessuna dipendenza applicativa diretta.

Consumato da (chi chiama questo servizio):

Infrastruttura (PostgreSQL, NATS, Redis, MinIO) non è elencata qui — vedi sezione Architettura del singolo servizio.

Loading OpenAPI…
Loading NATS contracts…