Due modelli di autenticazione, uno preferibile

Azure SQL espone due modelli. L’autenticazione SQL usa login e password custoditi nel server logico o nell’istanza: funziona ovunque e non dipende da nessuna directory, ma le credenziali finiscono nelle connection string, non supportano MFA, non hanno revoca centralizzata e sopravvivono all’uscita della persona dall’azienda. L’autenticazione Microsoft Entra ID appoggia invece l’identità alla directory aziendale: un solo ciclo di vita per utente, MFA, conditional access, assegnazioni per gruppo, audit centralizzato.

All’esame la regola è meccanica: se lo scenario nomina MFA, accesso condizionale, offboarding, identità unica o eliminazione delle password dalle applicazioni, la risposta è Entra ID. La SQL authentication resta il ripiego per applicazioni legacy che non sanno parlare con la directory. Il presupposto è l’Entra admin del logical server o della managed instance — un utente oppure, molto meglio, un gruppo di sicurezza: senza quella assegnazione nessuna identità Entra riesce a connettersi, ed è un ruolo distinto dal SQL administrator login.

Identità Entra dentro il database

Dentro il database gli utenti si creano da identità Entra con CREATE USER [...] FROM EXTERNAL PROVIDER. Il target può essere una persona, un gruppo di sicurezza o un service principal, e il gruppo è quasi sempre la scelta giusta: si concede una volta sola e la gestione dell’appartenenza torna in Entra, dove sta il resto del provisioning. Su Azure SQL Database il pattern portante è l’utente contenuto nel database utente; su Azure SQL Managed Instance si possono creare anche login Entra a livello di istanza in master, coerentemente con la superficie SQL Server che l’istanza conserva. Su SQL Server in VM l’autenticazione Entra dipende dalla versione e dalla configurazione del prodotto, e non va data per scontata.

Per le applicazioni la risposta corretta è la managed identity — system-assigned se l’identità vive e muore con la risorsa, user-assigned se va condivisa fra più risorse o precreata. La risorsa ottiene un token dalla piattaforma, la connection string non contiene segreti e non c’è nulla da ruotare. Un service principal con client secret è il fallback, non l’obiettivo. Infine, l’opzione di autenticazione solo Entra (Microsoft Entra-only authentication) disattiva a livello di server la SQL authentication, incluso l’administrator login: è il controllo verificabile che un auditor chiede quando pretende “niente password locali”.

Principal, ruoli e permessi

I principal si dividono su due livelli. I login vivono a livello di server o di istanza e governano la connessione; gli utenti di database vivono nel singolo database e governano gli oggetti. Un utente mappato a un login dipende da master; un utente contenuto (con password o, meglio, da Entra) si autentica direttamente sul database e per questo sopravvive a una geo-replica o a un failover group, dove i login del server primario non seguono automaticamente.

Sui permessi valgono i ruoli fissi di database — db_datareader, db_datawriter, db_ddladmin, db_securityadmin, db_owner — comodi ma grossolani, e i ruoli personalizzati creati con CREATE ROLE a cui si concede esattamente ciò che serve. La terna è GRANT, DENY, REVOKE: GRANT concede, DENY nega, REVOKE rimuove una concessione o una negazione esistente senza negare nulla. La regola da ricordare è che il DENY vince sul GRANT, anche quando arrivano da gruppi diversi.

Privilegio minimo e lettura di un errore

Privilegio minimo significa partire da zero e aggiungere: GRANT EXECUTE sullo schema delle stored procedure invece di db_datareader su tutto, un ruolo di sola lettura sulle viste di reporting invece dell’accesso alle tabelle base. db_owner “per comodità” è la risposta sbagliata in ogni scenario d’esame.

Quando qualcosa non funziona, le cause sono tre. Permesso semplicemente mancante — si verifica con sys.fn_my_permissions o HAS_PERMS_BY_NAME. Catena di proprietà: se view e tabella hanno lo stesso proprietario il controllo sulla tabella viene saltato, se i proprietari differiscono la catena si spezza e l’errore compare. Contesto di esecuzione: un modulo gira come EXECUTE AS CALLER per default, e spostarlo su EXECUTE AS OWNER (o firmarlo con un certificato) risolve senza concedere permessi diretti sugli oggetti sottostanti.

Trappole tipiche d’esame

  • Applicazione in App Service che deve connettersi senza segreti → managed identity più utente Entra nel database: spostare la password in Key Vault riduce l’esposizione ma non elimina la credenziale; la managed identity sì.
  • Servono MFA e conditional access sugli accessi amministrativi → autenticazione Microsoft Entra ID: firewall, private endpoint e TDE compaiono come distrattori ma non hanno alcun effetto sull’autenticazione.
  • Gli utenti smettono di funzionare dopo un failover o su una secondaria geo-replicata → utenti contenuti (idealmente da Entra): i login vivono in master, che non segue il database replicato.
  • L’utente è in due gruppi, uno con GRANT e uno con DENY → prevale il DENY: e per rimuovere quel DENY serve REVOKE, non un GRANT che lo sovrascriva.
  • All’account serve solo eseguire alcune procedure → ruolo personalizzato con GRANT EXECUTE sullo schema: db_datareader o db_owner concedono molto più del necessario e violano il privilegio minimo.
  • Una view restituisce un errore di permessi sulla tabella sottostante → catena di proprietà spezzata: si allinea il proprietario o si usa EXECUTE AS / la firma del modulo, non si concede SELECT diretto sulla tabella.
  • L’audit chiede di impedire in modo verificabile ogni accesso con password locali → Microsoft Entra-only authentication: una policy documentata o la semplice rimozione dei login non è un controllo tecnico applicato dal servizio.