Executive summary
Ogni sistema informatico che gestisce dati riservati o operazioni critiche deve rispondere a due domande fondamentali: chi sta effettuando una richiesta e quali operazioni quella persona o quel componente è autorizzato a compiere. Questo articolo analizza in profondità i meccanismi, i modelli e le architetture che la ricerca e l'industria hanno sviluppato negli ultimi quindici anni per rispondere a queste domande in modo rigoroso, scalabile e adattabile a sistemi composti da molte parti indipendenti. L'analisi evidenzia una transizione significativa: dai sistemi che si affidavano alla protezione dei confini della rete verso architetture in cui ogni singola richiesta viene verificata indipendentemente, sulla base dell'identità di chi la effettua e delle circostanze in cui viene effettuata. Le soluzioni più robuste combinano regole di accesso espresse in modo formale con meccanismi di verifica continua, dove la fiducia non è concessa una volta per tutte ma rivalutata ad ogni interazione.
Background
Il problema del controllo dell'identità e dell'accesso è antico quanto i sistemi multi-utente, ma la sua complessità è cresciuta in modo non lineare con l'avvento delle architetture distribuite, dei servizi cloud e delle integrazioni tra organizzazioni diverse. Nei sistemi monolitici tradizionali, l'autenticazione si risolveva con una verifica locale di credenziali e l'autorizzazione con una matrice di accesso gestita centralmente. L'introduzione di architetture a microservizi, API pubbliche e collaborazioni inter-organizzative ha reso questo approccio insufficiente: un singolo flusso applicativo può attraversare decine di componenti distribuiti, ciascuno con requisiti di accesso distinti, e coinvolgere identità umane, applicative e infrastrutturali che operano su reti eterogenee e potenzialmente non fidate.
La distinzione fondamentale tra autenticazione e autorizzazione, pur essendo concettualmente elementare, ha implicazioni architetturali profonde. L'autenticazione stabilisce chi è il richiedente (un utente, un servizio, un dispositivo) attraverso la verifica di credenziali crittografiche. L'autorizzazione determina che cosa il richiedente autenticato può fare, sulla base di politiche che possono dipendere dal ruolo, dagli attributi del contesto, dalla sensibilità della risorsa o dalla combinazione di tutti questi fattori. In un sistema distribuito moderno, queste due funzioni devono essere eseguite in modo indipendente, componibile e verificabile, senza introdurre colli di bottiglia che compromettano la latenza o la disponibilità del servizio.
Il panorama degli standard riflette questa complessità. Il protocollo OAuth 2.0, formalizzato nella RFC 6749 [1], ha introdotto un framework di delega che separa il concetto di autorizzazione dall'autenticazione, consentendo a un'applicazione terza di ottenere accesso limitato a una risorsa senza acquisire le credenziali del proprietario. OpenID Connect (OIDC) [2] ha costruito sopra OAuth 2.0 un livello di identità standardizzato, risolvendo il problema dell'autenticazione federata. Parallelamente, la ricerca sui modelli di controllo dell'accesso ha prodotto una progressione dai modelli role-based (RBAC) [3] a quelli attribute-based (ABAC) [4] fino ai sistemi relationship-based (ReBAC) [5], ciascuno con trade-off distinti in termini di espressività, scalabilità e complessità amministrativa. La convergenza di questi sviluppi con il paradigma zero-trust [6] ha ridefinito le assunzioni fondamentali sulla sicurezza dei sistemi distribuiti, spostando il perimetro di fiducia dal livello di rete al livello di singola richiesta.
Protocolli di delega e identità federata
OAuth 2.0: il framework di autorizzazione delegata
OAuth 2.0, definito nella RFC 6749 pubblicata nell'ottobre 2012, è il framework di autorizzazione più adottato per la delega dell'accesso alle risorse protette [1]. L'architettura definisce quattro ruoli: il resource owner (l'entità che possiede la risorsa), il resource server (il server che ospita la risorsa protetta), il client (l'applicazione che richiede l'accesso) e l'authorization server (il server che emette i token dopo aver autenticato il resource owner e ottenuto il suo consenso). La separazione tra authorization server e resource server è una decisione architetturale fondamentale che consente la centralizzazione della logica di autenticazione e consenso indipendentemente dalla distribuzione delle risorse protette.
Il meccanismo centrale è l'access token: una stringa opaca o strutturata che rappresenta una delega con scope, durata e attributi specifici. Il resource owner non condivide mai le proprie credenziali con il client; piuttosto, autorizza l'authorization server a emettere un token con permessi limitati. La RFC 6749 definisce quattro grant type (authorization code, implicit, resource owner password credentials e client credentials), ma la pratica ha progressivamente consolidato l'authorization code grant come il flusso di riferimento, poiché gli altri presentano vulnerabilità strutturali documentate [7].
La RFC 7636 ha introdotto PKCE (Proof Key for Code Exchange), un meccanismo che mitiga gli attacchi di intercettazione dell'authorization code, particolarmente rilevanti per client pubblici come le applicazioni mobile e le single-page application [8]. PKCE opera attraverso una sfida crittografica: il client genera un code verifier casuale, ne calcola un hash (code challenge) e lo invia con la richiesta di autorizzazione; al momento dello scambio del codice per il token, il client presenta il code verifier originale, che l'authorization server verifica contro il challenge memorizzato. Un attaccante che intercetta l'authorization code non può completare lo scambio senza possedere il code verifier. La bozza OAuth 2.1 [9], che consolida un decennio di esperienza operativa, rende PKCE obbligatorio per tutti i client (inclusi quelli confidenziali) ed elimina i grant type implicit e resource owner password credentials, riconosciuti come vettori di rischio strutturali.
La pubblicazione della RFC 9700 nel gennaio 2025 ha consolidato le best practice di sicurezza per OAuth 2.0, aggiornando il modello di minaccia originale per incorporare le esperienze pratiche accumulate dal 2012 e le nuove vulnerabilità emerse dall'applicazione diffusa del protocollo [7]. Tra le raccomandazioni, la RFC 9700 prescrive l'uso esclusivo di authorization code con PKCE, la validazione rigorosa dei redirect URI con corrispondenza esatta, l'uso di token sender-constrained e l'adozione di refresh token rotation per mitigare gli attacchi di replay.
OpenID Connect: il livello di identità
OAuth 2.0 risolve il problema della delega dell'accesso, ma non fornisce un meccanismo standardizzato per verificare l'identità dell'utente. OpenID Connect 1.0 (OIDC) colma questa lacuna introducendo un livello di identità sopra il framework OAuth 2.0, consentendo al client di verificare l'identità dell'utente finale sulla base dell'autenticazione eseguita dall'authorization server e di ottenere informazioni di profilo in modo interoperabile [2]. Il protocollo introduce il concetto di ID token, un JSON Web Token (JWT) firmato dall'authorization server che contiene claim sull'autenticazione e sull'identità dell'utente.
L'ID token è il differenziatore architetturale di OIDC rispetto a OAuth 2.0. Mentre l'access token è tipicamente opaco per il client e destinato al resource server, l'ID token è progettato per essere validato e letto dal client stesso, fornendo garanzie crittografiche sull'identità dell'utente, il momento dell'autenticazione, il metodo di autenticazione utilizzato e l'authorization server che lo ha emesso. La specifica definisce un insieme di claim standard, tra cui sub (identificativo univoco del soggetto), iss (emittente), aud (destinatario), exp (scadenza), iat (momento di emissione), nonce (per prevenire replay) e auth_time (momento dell'autenticazione), che forniscono al client le informazioni necessarie per prendere decisioni di autorizzazione informate.
OIDC supporta tre flussi di autenticazione (Authorization Code Flow, Implicit Flow e Hybrid Flow) che si adattano a diversi scenari applicativi, dalla web application server-side alla single-page application. L'endpoint UserInfo consente al client di recuperare claim aggiuntivi sull'utente autenticato utilizzando l'access token ottenuto durante il flusso OIDC. Il protocollo Discovery (OpenID Connect Discovery 1.0) consente ai client di determinare automaticamente la configurazione dell'OpenID Provider attraverso un well-known URI, standardizzando il bootstrap della federazione di identità. L'adozione di OIDC è universale tra i principali identity provider: Google, Microsoft, Apple, Okta e Auth0 implementano tutti la specifica come meccanismo primario di autenticazione federata.
Sender-constrained token: DPoP e mTLS
Un limite strutturale dei bearer token, come definiti dalla RFC 6750, è che chiunque li possieda può utilizzarli: se un access token viene intercettato o esfiltrato, l'attaccante può impersonare il client legittimo fino alla scadenza del token. I sender-constrained token mitigano questa vulnerabilità legando crittograficamente il token all'entità che lo ha richiesto, rendendo inutilizzabile un token rubato senza il possesso della chiave privata corrispondente.
La RFC 9449 definisce DPoP (Demonstrating Proof of Possession), un meccanismo a livello applicativo che consente al client di dimostrare il possesso di una coppia di chiavi crittografiche [10]. Ad ogni richiesta, il client genera un DPoP proof, un JWT firmato con la propria chiave privata contenente l'hash dell'access token, il metodo HTTP e l'URI della richiesta, e lo include nell'header HTTP. L'authorization server vincola l'access token alla chiave pubblica dichiarata dal client, e il resource server verifica che il DPoP proof sia firmato dalla chiave corrispondente. Questo meccanismo opera interamente a livello applicativo, senza richiedere certificati X.509 o configurazioni TLS specifiche, rendendolo particolarmente adatto a client pubblici, applicazioni mobile e single-page application dove la gestione di certificati TLS client-side non è praticabile [10].
L'alternativa basata su mTLS (mutual TLS) offre garanzie analoghe a livello di trasporto: l'authorization server vincola il token al certificato client presentato durante l'handshake TLS. Questa soluzione è più robusta dal punto di vista crittografico ma richiede un'infrastruttura PKI e la gestione del ciclo di vita dei certificati, risultando più adatta a scenari service-to-service in ambienti controllati.
JSON Web Token: struttura, crittografia e superfici di attacco
Architettura del formato
Il JSON Web Token (JWT), definito nella RFC 7519 [11], è diventato il formato dominante per la rappresentazione di claim di identità e autorizzazione nei sistemi distribuiti. Un JWT è composto da tre segmenti codificati in Base64url separati da punti: l'header, il payload e la firma. L'header specifica l'algoritmo crittografico (alg) e il tipo di token (typ); il payload contiene i claim, un insieme di coppie nome-valore che rappresentano asserzioni sull'identità o sull'autorizzazione; la firma garantisce l'integrità e l'autenticità del token.
La specifica definisce due famiglie di operazioni crittografiche. I JSON Web Signature (JWS, RFC 7515) forniscono integrità e autenticità attraverso firme digitali o HMAC. I JSON Web Encryption (JWE, RFC 7516) aggiungono confidenzialità, crittografando il payload in modo che solo il destinatario intenzionale possa leggerlo. Gli algoritmi crittografici ammessi sono definiti nella RFC 7518 (JSON Web Algorithms), che specifica famiglie HMAC (HS256, HS384, HS512), RSA (RS256, PS256), ed ECDSA (ES256, ES384, ES512). La scelta dell'algoritmo ha implicazioni di sicurezza significative: gli algoritmi simmetrici (famiglia HS) richiedono che emittente e verificatore condividano un segreto, mentre gli algoritmi asimmetrici (famiglie RS, PS, ES) consentono la verifica con la sola chiave pubblica, un requisito essenziale in architetture distribuite dove il resource server non deve possedere il segreto dell'authorization server.
Vulnerabilità documentate e contromisure
Il JWT, pur essendo uno standard robusto nella sua specificazione formale, presenta una superficie di attacco non trascurabile quando le implementazioni non rispettano le best practice consolidate. La RFC 8725 (JSON Web Token Best Current Practices) documenta le vulnerabilità più critiche e le contromisure raccomandate [12].
La vulnerabilità dell'algoritmo none è la più elementare e pericolosa: la RFC 7518 definisce un algoritmo none che produce JWT senza firma, e implementazioni che non validano esplicitamente l'algoritmo possono accettare token non firmati come validi, consentendo a un attaccante di forgiare arbitrariamente claim di identità e autorizzazione. La contromisura è la validazione rigorosa dell'header alg contro una whitelist di algoritmi ammessi, rifiutando qualsiasi token il cui algoritmo non sia esplicitamente previsto dalla configurazione del verificatore [12].
L'algorithm confusion attack sfrutta la differenza tra algoritmi simmetrici e asimmetrici. In un sistema configurato per verificare token firmati con RSA (RS256), un attaccante può modificare l'header del token impostando alg: HS256 e firmare il payload utilizzando la chiave pubblica RSA del server come segreto HMAC. Se l'implementazione seleziona l'algoritmo dal token anziché dalla propria configurazione, la verifica avrà successo perché il server utilizzerà la propria chiave pubblica, che è nota, come segreto HMAC, credendo di star verificando una firma simmetrica legittima [12]. La contromisura fondamentale è che il verificatore non deve mai derivare l'algoritmo dall'header del token, ma deve imporre l'algoritmo atteso dalla propria configurazione.
Gli attacchi basati sui parametri dell'header jwk, jku e x5u consentono a un attaccante di iniettare la propria chiave pubblica direttamente nel token o di indirizzare il verificatore verso un endpoint controllato dall'attaccante per recuperare le chiavi di verifica. La contromisura è ignorare completamente questi header nel token e utilizzare esclusivamente chiavi provenienti da fonti fidate configurate server-side, tipicamente un JWKS endpoint dell'authorization server noto [12].
Un aspetto critico spesso trascurato è che il payload JWT utilizza la codifica Base64url, non la crittografia: qualsiasi soggetto che intercetti un token può leggerne il contenuto. L'inserimento di informazioni sensibili nel payload (numeri di carta, indirizzi email, dati sanitari) espone questi dati a chiunque intercetti il token durante il transito o abbia accesso ai log. Quando la confidenzialità del payload è un requisito, è necessario utilizzare JWE anziché JWS, oppure limitare il payload a identificativi opachi e recuperare le informazioni sensibili attraverso canali protetti.
Modelli di controllo dell'accesso
RBAC: il modello basato sui ruoli
Il modello RBAC (Role-Based Access Control) formalizzato da Sandhu et al. nel 1996 [3] ha introdotto un'astrazione fondamentale: anziché assegnare permessi direttamente agli utenti, i permessi sono associati a ruoli, e gli utenti acquisiscono permessi attraverso l'assegnazione a ruoli. Questa indirezione riduce la complessità amministrativa da $O(|U| \times |P|)$ a $O(|U| \times |R| + |R| \times |P|)$, dove $|U|$, $|R|$ e $|P|$ rappresentano rispettivamente la cardinalità degli insiemi di utenti, ruoli e permessi. In organizzazioni con migliaia di utenti e centinaia di permessi, questa riduzione è significativa.
Il modello RBAC96 è organizzato in quattro livelli di funzionalità crescente. RBAC0 (flat RBAC) definisce il modello base con utenti, ruoli, permessi e sessioni. RBAC1 introduce le gerarchie di ruoli, consentendo l'ereditarietà dei permessi: un ruolo senior eredita automaticamente i permessi dei ruoli subordinati, riflettendo strutture organizzative reali. RBAC2 aggiunge vincoli, tra cui la separation of duties (SoD), statica e dinamica, che impedisce a un singolo utente di accumulare combinazioni di ruoli che creerebbero conflitti di interesse. RBAC3 combina gerarchie e vincoli nel modello più espressivo [3]. Il NIST ha successivamente standardizzato il modello come ANSI/INCITS 359-2004, rivisto nel 2012.
La forza di RBAC risiede nella sua semplicità concettuale e nella facilità di audit: dato un utente, è immediato determinare i suoi ruoli e, per ciascun ruolo, i permessi corrispondenti. Questa trasparenza lo rende particolarmente adatto a contesti regolamentati dove la conformità richiede dimostrabilità delle politiche di accesso. Il limite strutturale di RBAC emerge in scenari che richiedono decisioni contestuali: un medico non dovrebbe accedere a tutti i dati dei pazienti in virtù del suo ruolo, ma solo a quelli dei pazienti che ha in carico, durante il turno di servizio, dalla rete dell'ospedale. Questa granularità richiede attributi che RBAC puro non può esprimere senza una proliferazione di ruoli, il fenomeno noto come role explosion, che ne vanifica i benefici amministrativi.
ABAC: il modello basato sugli attributi
Il modello ABAC (Attribute-Based Access Control), formalizzato dal NIST nella SP 800-162 [4], generalizza RBAC esprimendo le politiche di accesso come funzioni booleane su attributi del soggetto, dell'oggetto, dell'operazione richiesta e dell'ambiente. Una politica ABAC ha la forma:
$$\text{allow}(s, o, a) \iff f(attr_s, attr_o, attr_a, attr_e) = \text{true}$$
dove $attr_s$ sono gli attributi del soggetto (ruolo, dipartimento, livello di clearance), $attr_o$ quelli dell'oggetto (classificazione, proprietario, tipo), $attr_a$ quelli dell'azione (lettura, scrittura, approvazione) e $attr_e$ quelli dell'ambiente (ora, posizione, livello di rischio della sessione) [4].
L'architettura ABAC definisce quattro componenti funzionali: il Policy Enforcement Point (PEP) che intercetta le richieste di accesso, il Policy Decision Point (PDP) che valuta la richiesta contro le politiche, il Policy Information Point (PIP) che fornisce gli attributi necessari alla valutazione, e il Policy Administration Point (PAP) che consente la definizione e la gestione delle politiche [4]. Questa decomposizione funzionale separa l'enforcement dalla decisione e dalla gestione, consentendo implementazioni distribuite in cui ciascun componente può essere scalato indipendentemente.
Il vantaggio strutturale di ABAC è l'eliminazione del role explosion: nuovi soggetti possono accedere alle risorse senza modificare le politiche o le assegnazioni esistenti, purché possiedano gli attributi richiesti. Le decisioni di accesso possono cambiare dinamicamente al variare degli attributi (ad esempio, la revoca dell'accesso quando un medico esce dal turno) senza intervento amministrativo. Lo standard XACML (eXtensible Access Control Markup Language) fornisce un linguaggio per esprimere politiche ABAC in formato XML, e implementazioni moderne possono valutare 10.000 richieste in circa 10 millisecondi, rendendo ABAC praticabile per scenari ad alto throughput come API gateway e microservizi.
Il costo di questa espressività è la complessità: la definizione e il testing di politiche ABAC richiedono competenze specifiche, e l'audit delle politiche, ovvero determinare chi ha accesso a cosa, è computazionalmente più costoso che in RBAC, dove la risposta è una semplice traversata della gerarchia dei ruoli. In pratica, molte organizzazioni adottano un approccio ibrido in cui RBAC definisce la struttura base dei permessi e ABAC aggiunge vincoli contestuali dove necessario.
ReBAC: il modello relazionale di Zanzibar
Il sistema Zanzibar, sviluppato da Google e presentato alla USENIX ATC 2019, ha introdotto un modello di autorizzazione basato sulle relazioni tra entità (ReBAC) che ha definito un nuovo paradigma per l'autorizzazione su scala globale [5]. In Zanzibar, i permessi non sono proprietà degli utenti o attributi degli oggetti, ma emergono dalle relazioni tra entità, espresse come tuple della forma (object#relation@user). La politica di accesso è definita da un namespace configuration che specifica come le relazioni si compongono: ad esempio, un utente ha il permesso di leggere un documento se è il proprietario del documento, oppure se ha il permesso di lettura sulla cartella che contiene il documento.
L'aspetto più significativo di Zanzibar non è il modello relazionale in sé, ma le garanzie di consistenza e scala che offre. Il sistema opera su Google Spanner per garantire external consistency: le decisioni di autorizzazione rispettano l'ordinamento causale delle modifiche alle ACL, prevenendo il cosiddetto new enemy problem, ovvero il rischio che un utente a cui è stato appena revocato l'accesso possa ancora accedere alla risorsa a causa di stale read. Zanzibar scala a trilioni di ACL e milioni di richieste di autorizzazione al secondo, con una latenza al 95° percentile inferiore a 10 millisecondi e una disponibilità superiore al 99.999% su tre anni di operazione in produzione [5].
L'influenza di Zanzibar si estende ben oltre Google. Progetti open-source come SpiceDB (Authzed), OpenFGA (CNCF), Keto (Ory) e Permify implementano varianti del modello Zanzibar, portando il paradigma ReBAC in contesti al di fuori dell'infrastruttura Google. Questi sistemi condividono la rappresentazione delle autorizzazioni come grafo di relazioni e l'uso di graph traversal per valutare i permessi, ma differiscono nelle garanzie di consistenza, dato che la maggior parte non dispone di un equivalente di Spanner, e nelle strategie di caching e materializzazione.
Policy-as-code e authorization engine
La separazione tra logica di autorizzazione e logica applicativa è un principio architetturale consolidato, ma la sua implementazione rigorosa richiede strumenti specifici. L'approccio policy-as-code esprime le politiche di accesso in linguaggi dichiarativi versionabili, testabili e deployabili indipendentemente dal codice applicativo, trasformando l'autorizzazione da logica embedded in una funzione infrastrutturale gestita con le stesse pratiche del software engineering.
Open Policy Agent (OPA), progetto graduated della CNCF, è il policy engine più adottato in questo ambito [13]. OPA disaccoppia la decisione di policy dal suo enforcement: le applicazioni inviano una richiesta di decisione a OPA, tipicamente via REST API o SDK, fornendo dati strutturati come contesto, e OPA valuta la richiesta contro le politiche definite nel linguaggio Rego. Rego è un linguaggio dichiarativo domain-specific progettato per esprimere politiche su strutture dati gerarchiche complesse, e opera su dati pre-caricati in memoria, garantendo valutazioni a bassa latenza. OPA supporta modelli RBAC, ABAC e ReBAC, consentendo alle organizzazioni di esprimere politiche di complessità arbitraria in un framework unificato.
Il ciclo di vita delle politiche in un approccio policy-as-code segue un modello GitOps: le politiche sono definite in un repository versionato, sottoposte a unit test e analisi statica in pipeline CI/CD, e deployate in produzione solo dopo aver superato tutti i controlli. OPAL (Open Policy Administration Layer) automatizza la distribuzione delle politiche e dei dati alle istanze OPA in produzione, monitorando il branch di produzione e propagando automaticamente le modifiche approvate. Questo modello offre auditabilità completa, dato che ogni modifica alla politica è tracciata nel version control, e riproducibilità: una decisione di accesso può essere ricostruita riapplicando la politica al contesto della richiesta originale.
L'integrazione di policy engine con service mesh e API gateway consente di applicare le politiche di autorizzazione in modo trasparente al traffico di rete, senza richiedere modifiche al codice applicativo. Envoy, Istio e Kong supportano nativamente l'integrazione con OPA, consentendo una separazione architetturale netta tra l'applicazione, che implementa la logica di business, e l'infrastruttura, che applica le politiche di accesso. Questa architettura riduce il rischio di bypass dell'autorizzazione (un vettore di attacco frequente quando la logica di accesso è distribuita nel codice applicativo) e centralizza l'audit delle decisioni di accesso.
Architettura zero-trust e identità dei workload
Principi fondamentali
Il paradigma zero-trust, formalizzato dal NIST nella SP 800-207 [6], rappresenta un cambiamento concettuale nelle assunzioni sulla sicurezza dei sistemi distribuiti. Il modello tradizionale basato sulla difesa perimetrale assume che il traffico interno alla rete aziendale sia fidato e quello esterno sia ostile, un'assunzione falsificata sistematicamente da decenni di violazioni che sfruttano la compromissione di un singolo nodo interno per muoversi lateralmente senza restrizioni. Zero-trust elimina la nozione di rete fidata: nessuna richiesta è considerata affidabile a priori, indipendentemente dalla sua origine di rete.
La SP 800-207 definisce un'architettura modulare basata su tre componenti: il Policy Engine (PE), che prende decisioni di accesso utilizzando politiche, punteggi di rischio, identità e telemetria; il Policy Administrator (PA), che traduce le decisioni del PE in azioni concrete (consentire, negare, instradare); e il Policy Enforcement Point (PEP), che applica le decisioni di accesso, operando come intermediario tra il richiedente e la risorsa [6]. Ogni richiesta di accesso attraversa il PEP, che interroga il PE per ottenere una decisione basata sull'identità del richiedente, la postura del dispositivo, il contesto della richiesta e la sensibilità della risorsa. L'autenticazione e l'autorizzazione sono funzioni discrete eseguite per ogni sessione, non garanzie ereditate dalla posizione di rete.
Google ha documentato la propria implementazione del paradigma zero-trust attraverso la serie di pubblicazioni BeyondCorp, iniziata nel 2014 [14]. BeyondCorp ha eliminato il requisito di una rete intranet privilegiata, spostando le applicazioni aziendali su Internet e basando tutte le decisioni di accesso sull'identità dell'utente, la postura del dispositivo e il contesto della richiesta, senza l'uso di VPN. L'architettura include un inventario dei dispositivi, un servizio di identità, un access proxy che media tutte le richieste e un policy engine che valuta ogni richiesta in tempo reale. L'esperienza di Google, maturata a partire dal 2011 su decine di migliaia di dipendenti e centinaia di applicazioni, ha dimostrato la praticabilità del modello zero-trust su scala enterprise e ha influenzato profondamente lo sviluppo della SP 800-207 e le architetture di sicurezza dell'industria.
Identità dei workload: SPIFFE e SPIRE
In un'architettura zero-trust, l'identità non è un attributo esclusivo degli utenti umani: ogni workload (container, servizio, processo) richiede un'identità verificabile per partecipare alle comunicazioni autenticate. Il framework SPIFFE (Secure Production Identity Framework For Everyone), progetto graduated della CNCF [15], definisce uno standard per l'assegnazione di identità crittografiche ai workload in ambienti eterogenei e dinamici.
SPIFFE introduce il concetto di SPIFFE ID, un identificatore univoco nella forma di un URI (spiffe://trust-domain/workload-identifier) che identifica un workload indipendentemente dalla sua localizzazione fisica o dal provider cloud. L'identità è attestata attraverso SVID (SPIFFE Verifiable Identity Document), che possono assumere la forma di certificati X.509 o JWT a breve durata. Il runtime SPIRE (SPIFFE Runtime Environment) gestisce il ciclo di vita delle identità: attesta i workload verificando la loro provenienza attraverso selettori di nodo e di workload (identità del processo, namespace Kubernetes, metadati dell'infrastruttura), emette SVID a breve durata e li rinnova automaticamente prima della scadenza [15].
L'adozione di SPIFFE elimina la necessità di credenziali condivise (shared secret) tra servizi, un vettore di rischio significativo nelle architetture a microservizi dove le credenziali sono spesso codificate in file di configurazione o variabili d'ambiente. Due workload stabiliscono fiducia reciproca attraverso mTLS utilizzando i propri SVID X.509, o verificando un JWT SVID, senza dipendere da infrastrutture centralizzate di gestione delle credenziali. Bloomberg, ByteDance, Pinterest e Uber sono tra le organizzazioni che hanno adottato SPIFFE/SPIRE in produzione per la gestione dell'identità dei workload su scala.
Limiti, problemi aperti e direzioni emergenti
L'ecosistema dell'autenticazione e dell'autorizzazione, pur avendo raggiunto un livello di maturità significativo negli standard e nelle implementazioni di riferimento, presenta problemi aperti e tensioni irrisolte che meritano attenzione.
La complessità della composizione rimane una sfida centrale. Un flusso applicativo moderno può coinvolgere OAuth 2.0 per la delega, OIDC per l'identità, JWT per la rappresentazione dei claim, RBAC per i permessi base, ABAC per i vincoli contestuali e mTLS per l'identità dei workload. La corretta integrazione di questi componenti richiede competenze specialistiche significative, e gli errori di configurazione (redirect URI non validati, algoritmi JWT non vincolati, scope troppo ampi) sono il vettore di attacco più frequente nella pratica. La RFC 9700 [7] documenta sistematicamente queste vulnerabilità, ma la loro persistenza nel campo indica che la complessità del protocollo eccede la capacità di molti team di implementarlo correttamente.
La gestione delle politiche di autorizzazione su scala rimane un problema aperto. ABAC offre l'espressività necessaria per politiche contestuali, ma la verifica formale delle proprietà di sicurezza di un insieme di politiche ABAC, ad esempio la garanzia che nessuna combinazione di attributi consenta l'accesso non autorizzato a una classe di risorse, è un problema computazionalmente costoso. La ricerca sui metodi formali per la verifica delle politiche di accesso è attiva, ma non ha ancora prodotto strumenti accessibili alle organizzazioni che non dispongono di competenze specialistiche in verifica formale. L'approccio policy-as-code con OPA mitiga parzialmente questo problema attraverso il testing automatizzato, ma il testing può dimostrare la presenza di difetti, non la loro assenza.
La tensione tra consistenza e latenza nelle decisioni di autorizzazione è strutturale nei sistemi distribuiti. Zanzibar affronta questo problema con external consistency garantita da Spanner, ma al costo di una dipendenza infrastrutturale che non è replicabile al di fuori dell'ecosistema Google. Le implementazioni open-source di ReBAC adottano compromessi diversi (eventual consistency, caching con TTL, materializzazione parziale), ciascuno con implicazioni specifiche per la finestra temporale in cui una revoca non è ancora effettiva. In contesti dove la revoca immediata è un requisito regolamentare (GDPR, sanzioni), questa latenza è un rischio di compliance concreto.
L'evoluzione verso architetture zero-trust è ostacolata dalla complessità della migrazione. La SP 800-207A, pubblicata dal NIST nel 2023, estende il modello zero-trust alle applicazioni cloud-native in ambienti multi-cloud, ma riconosce esplicitamente che la transizione da architetture perimetrali a zero-trust è un processo incrementale che richiede anni e investimenti significativi in infrastruttura di identità, policy engine e telemetria [6]. La sfida non è solo tecnologica ma organizzativa: zero-trust richiede che ogni team di sviluppo integri l'autenticazione e l'autorizzazione come requisiti architetturali di primo livello, non come controlli aggiunti a posteriori.
Tra le direzioni emergenti, l'applicazione di Verifiable Credentials (VC) e Decentralized Identifiers (DID) al dominio dell'autenticazione e dell'autorizzazione promette di ridurre la dipendenza da identity provider centralizzati, consentendo ai soggetti di presentare claim verificabili senza contattare l'emittente al momento della verifica. L'integrazione di segnali di rischio continuo (behavioral analytics, device posture, threat intelligence) nelle decisioni di autorizzazione evolve il modello da decisioni binarie (ammesso/negato) a valutazioni continue di rischio che possono adattare il livello di accesso in tempo reale. Queste direzioni convergono verso un modello in cui l'identità è decentralizzata, verificabile crittograficamente, e l'autorizzazione è una funzione continua del contesto piuttosto che una decisione puntuale.
Riferimenti
[1] D. Hardt, "The OAuth 2.0 Authorization Framework," RFC 6749, IETF, 2012. https://datatracker.ietf.org/doc/html/rfc6749
[2] N. Sakimura et al., "OpenID Connect Core 1.0," OpenID Foundation, 2014. https://openid.net/specs/openid-connect-core-1_0.html
[3] R. S. Sandhu et al., "Role-Based Access Control Models," IEEE Computer, vol. 29, no. 2, pp. 38-47, 1996. https://profsandhu.com/journals/computer/i94rbac(org).pdf
[4] V. C. Hu et al., "Guide to Attribute Based Access Control (ABAC) Definition and Considerations," NIST SP 800-162, 2014. https://csrc.nist.gov/pubs/sp/800/162/upd2/final
[5] R. Pang et al., "Zanzibar: Google's Consistent, Global Authorization System," in Proc. USENIX ATC, 2019. https://www.usenix.org/conference/atc19/presentation/pang
[6] S. Rose et al., "Zero Trust Architecture," NIST SP 800-207, 2020. https://csrc.nist.gov/pubs/sp/800/207/final
[7] T. Lodderstedt et al., "Best Current Practice for OAuth 2.0 Security," RFC 9700, IETF, 2025. https://datatracker.ietf.org/doc/rfc9700/
[8] N. Sakimura et al., "Proof Key for Code Exchange by OAuth Public Clients," RFC 7636, IETF, 2015. https://datatracker.ietf.org/doc/html/rfc7636
[9] D. Hardt et al., "The OAuth 2.1 Authorization Framework," IETF Internet-Draft, 2025. https://datatracker.ietf.org/doc/draft-ietf-oauth-v2-1/
[10] D. Fett et al., "OAuth 2.0 Demonstrating Proof of Possession (DPoP)," RFC 9449, IETF, 2023. https://www.rfc-editor.org/rfc/rfc9449.html
[11] M. Jones et al., "JSON Web Token (JWT)," RFC 7519, IETF, 2015. https://datatracker.ietf.org/doc/html/rfc7519
[12] Y. Sheffer et al., "JSON Web Token Best Current Practices," RFC 8725, IETF, 2020. https://datatracker.ietf.org/doc/html/rfc8725
[13] Open Policy Agent, "OPA Documentation," CNCF, 2025. https://www.openpolicyagent.org/docs
[14] R. Ward and B. Beyer, "BeyondCorp: A New Approach to Enterprise Security," ;login:, USENIX, 2014. https://research.google/pubs/pub43231/
[15] SPIFFE, "Secure Production Identity Framework For Everyone," CNCF, 2025. https://spiffe.io/