Access control e identità 🔐
L’access control sembra una categoria pulita finché non cambia il tipo di risorsa. Nel Web controlli una route; in un’API devi controllare ogni oggetto e proprietà; in Kubernetes un’identità macchina; in un agente una capacità che può produrre altre azioni. Controllare “l’accesso” senza dire a quale risorsa è come promettere di proteggere un edificio senza dire di quale porta stai parlando.
La prima cosa da interiorizzare è che la lista Web tratta l’access control come un unico contenitore (A01:2025, che assorbe anche SSRF), mentre la lista API lo scompone in tre granularità e Kubernetes lo tratta come configurazione dichiarativa. Non è incoerenza: è ogni dominio che seleziona il livello che gli serve.
Stesso principio, meccanismi diversi 🧩
| Dominio | Fallimento tipico | Categoria | Controllo utile |
|---|---|---|---|
| Web | Route amministrativa raggiungibile | A01 | Autorizzazione server-side per ogni richiesta |
| API | BOLA, mass assignment o BFLA | API1 / API3 / API5 | Check ownership e policy per oggetto e funzione |
| Kubernetes | RBAC con wildcard o cluster-admin | K03 | Role minimi, service account distinti, audit |
| CI/CD | Build job con credenziali cloud di produzione | CICD-SEC-5 (PBAC) | Permessi legati allo scope del job, zero standing access |
| Serverless | Funzione con ruolo IAM onnicomprensivo | S4 | Role specifico per evento e risorsa |
| LLM/agenti | Tool con privilegi eccessivi e nessuna conferma | LLM08 / LLM07 | Capability ristrette, approvazione e limiti |
La scomposizione API è il caso didattico migliore: API1 (BOLA) riguarda l’oggetto (GET /api/v1/orders/{id} di un altro utente), API3 (Broken Object Property Level Authorization) riguarda le proprietà — lettura di campi nascosti e scrittura non autorizzata via mass assignment — e API5 (BFLA) riguarda le funzioni, come un utente normale che invoca DELETE /api/v1/users. Tre livelli, tre check, tre test. La lista Web li riassume in A01; chi progetta API deve risultare più fine.
Autenticazione e autorizzazione: due domande, una sola parola 💬
Autenticazione risponde a “chi sei?”; autorizzazione a “cosa puoi fare qui, ora, su questa risorsa?”. Un JWT valido non autorizza automaticamente a leggere l’ordine 1234. Sembra ovvio, finché quel controllo è disperso in cinque endpoint e due worker.
Attenzione alla trappola dell’identità per gli agenti: separa identità dell’utente, identità del servizio e identità del tool. L’agente non deve ereditare un super-token solo perché è comodo nella demo. Nelle pipeline vale lo stesso: le credenziali cloud del build runner (CICD-SEC-6) devono essere a breve vita e legate allo scope del job, non una chiave di amministrazione condivisa in un vault di gruppo. La Mobile Top 10 fonde invece autenticazione e autorizzazione in un’unica categoria (M3) proprio perché sul client nessuna delle due è auto-gestita: è la pagina in cui il “confuso deputy” diventa architettura, dall’altra parte rispetto al server.
La gestione delle sessioni non ha più una riga autonoma: è assorbita da identità, autorizzazione e secret. Il che significa che una policy sulle sessioni va cercata in tre luoghi, non in uno.
La delega, dove l’identità diventa curatoriale 🎭
Quando un’applicazione autentica con OAuth/OIDC, chi sta davvero agendo? Il problema classico è il confused deputy: il token di un utente viene emesso a un servizio che ha più poteri dell’utente, e la richiesta successiva parte con i privilegi del servizio. Lo stesso vale per gli agenti: se l’agente che “parla a nome dell’utente” viaggia con un token del servizio più ricco, ogni abuso downstream non è attribuibile all’utente — è firmato dal servizio.
La regola operativa per la delega è triplice: emissione minima (scopi ristretti, non openid profile email a caso), confronto dell’audience (il token dice per chi è stato emesso e per quale audience) e attenzione dell’invocatore (l’agente media, non sostituisce l’utente). Nelle pipeline la stessa trilogia si chiama OIDC federato: il build runner ottiene credenziali cloud a breve vita legate allo scope del job, non una chiave statica con accesso di scrittura alla produzione.
Controlli che resistono al cambio di dominio 🛡️
Quattro invarianti attraversano Web, API, Kubernetes, pipeline e agenti:
- Least privilege e zero standing access per identità umane e macchina: se un’identità non usa un privilegio abitualmente, non deve averlo.
- Decisione sul server o sul control plane, mai sul client, sul manifest non validato o sul tool che si auto-attribuisce il permesso.
- Deny by default: l’azione non autorizzata è negata, non “permessa se nessun altro controlla”.
- Audit delle decisioni: log di chi ha concesso cosa, a chi, e perché — la base per la rotazione dei ruoli.
Testa i casi negativi: utenti dello stesso tenant, ruoli inferiori, token scaduti, tool invocati fuori dal percorso previsto. Se la tua suite di autorizzazione non contiene un solo test “deve fallire”, stai testando il caso felice con l’aria di fare sicurezza.
Un anti-pattern da riconoscere presto: l’autorizzazione a grappolo, in cui un middleware controlla “sei autenticato?” e poi lascia che siano cinque handler a ricordarsi (ma non sempre) di verificare la proprietà della risorsa. Funziona finché la demo è su due endpoint; crolla quando un nuovo endpoint copia l’handler vicino senza controllarne i dettagli. La regola non è “aggiungi un check ovunque”: è centralizzare la decisione (una policy per funzione o una funzione per oggetto) e renderla impossibile da aggirare per omissione. Se il controllo vive solo in un metodo che “spero venga chiamato”, non è un controllo: è un auspicio.
Checklist ✅
- Autorizzazione vicina alla risorsa, non al solo frontend.
- Privilegi minimi e identità dedicate per workload, pipeline e agenti.
- Check per oggetto, proprietà e funzione dove l’architettura lo richiede.
- Test di accesso negato inclusi nella suite.
- Log di decisione e revisione periodica dei ruoli.
- Identità separata per utente, servizio e tool negli agenti.
L’access control è il controllo che non si vede quando funziona. Quando lo disegni male, è il primo che vedi.
Leggi la matrice e integra questa analisi nel threat modeling.