Share via


Sicurezza a livello di riga

Usare l'appartenenza al gruppo o il contesto di esecuzione per controllare l'accesso alle righe in una tabella di database.

La sicurezza a livello di riga (RLS) semplifica la progettazione e la codifica della sicurezza. Consente di applicare restrizioni per l'accesso a livello di riga dei dati nell'applicazione. Ad esempio, limitare l'accesso degli utenti alle righe rilevanti per il reparto o limitare l'accesso dei clienti solo ai dati rilevanti per la propria azienda.

La logica di restrizione dell'accesso si trova nel livello di database, anziché dai dati in un altro livello applicazione. Il sistema di database applica le restrizioni di accesso ogni volta che si tenta l'accesso ai dati da qualsiasi livello. Questa logica rende il sistema di sicurezza più affidabile e affidabile riducendo la superficie di attacco del sistema di sicurezza.

La sicurezza a livello di riga consente di fornire l'accesso ad altre applicazioni e utenti, solo a una determinata parte di una tabella. Può, ad esempio, essere necessario:

  • Concedere l'accesso solo alle righe che soddisfano alcuni criteri
  • Rendere anonimi i dati in alcune colonne
  • Tutte le precedenti

Nota

Quando un criterio di sicurezza a livello di riga è abilitato in una tabella, l'accesso viene completamente sostituito dalla query di sicurezza a livello di riga definita nella tabella. La restrizione di accesso si applica a tutti gli utenti, inclusi gli amministratori del database e l'autore della sicurezza a livello di riga. La query di sicurezza a livello di riga deve includere in modo esplicito le definizioni per tutti i tipi di utenti a cui si vuole concedere l'accesso.

Per altre informazioni, vedere Comandi di gestione per la gestione dei criteri di sicurezza a livello di riga.

Suggerimento

Queste funzioni sono spesso utili per row_level_security query:

Limitazioni

  • Non esiste alcun limite al numero di tabelle in cui è possibile configurare i criteri di sicurezza a livello di riga.
  • I criteri di sicurezza a livello di riga non possono essere configurati nelle tabelle esterne.
  • I criteri di sicurezza a livello di riga non possono essere abilitati in una tabella nelle circostanze seguenti:

Esempio

Limitare l'accesso alla tabella Sales

In una tabella denominata Salesogni riga contiene i dettagli relativi a una vendita. Una delle colonne contiene il nome del venditore. Invece di concedere ai venditori l'accesso a tutti i record in Sales, abilitare un criterio di sicurezza a livello di riga in questa tabella per restituire solo i record in cui il venditore è l'utente corrente:

Sales | where SalesPersonAadUser == current_principal()

È anche possibile mascherare l'indirizzo di posta elettronica:

Sales | where SalesPersonAadUser == current_principal() | extend EmailAddress = "****"

Se si vuole che ogni venditore visualizzi tutte le vendite di un paese o un'area geografica specifica, è possibile definire una query simile a:

let UserToCountryMapping = datatable(User:string, Country:string)
[
  "john@domain.com", "USA",
  "anna@domain.com", "France"
];
Sales
| where Country in ((UserToCountryMapping | where User == current_principal_details()["UserPrincipalName"] | project Country))

Se si dispone di un gruppo che contiene i responsabili, è possibile concedere loro l'accesso a tutte le righe. Ecco la query per i criteri di sicurezza a livello di riga.

let IsManager = current_principal_is_member_of('aadgroup=sales_managers@domain.com');
let AllData = Sales | where IsManager;
let PartialData = Sales | where not(IsManager) and (SalesPersonAadUser == current_principal()) | extend EmailAddress = "****";
union AllData, PartialData

Esporre dati diversi ai membri di gruppi di Microsoft Entra diversi

Se sono presenti più gruppi di Microsoft Entra e si vuole che i membri di ogni gruppo visualizzino un subset di dati diverso, usare questa struttura per una query di sicurezza a livello di riga.

Customers
| where (current_principal_is_member_of('aadgroup=group1@domain.com') and <filtering specific for group1>) or
        (current_principal_is_member_of('aadgroup=group2@domain.com') and <filtering specific for group2>) or
        (current_principal_is_member_of('aadgroup=group3@domain.com') and <filtering specific for group3>)

Applicare la stessa funzione di sicurezza a livello di riga in più tabelle

Definire prima di tutto una funzione che riceve il nome della tabella come parametro stringa e fa riferimento alla tabella usando l'operatore table() .

Ad esempio:

.create-or-alter function RLSForCustomersTables(TableName: string) {
    table(TableName)
    | ...
}

Configurare quindi la sicurezza a livello di riga in più tabelle in questo modo:

.alter table Customers1 policy row_level_security enable "RLSForCustomersTables('Customers1')"
.alter table Customers2 policy row_level_security enable "RLSForCustomersTables('Customers2')"
.alter table Customers3 policy row_level_security enable "RLSForCustomersTables('Customers3')"

Generare un errore in caso di accesso non autorizzato

Se si desidera che gli utenti di tabelle non autorizzati ricevano un errore anziché restituire una tabella vuota, usare la assert() funzione . L'esempio seguente illustra come generare questo errore in una funzione di sicurezza a livello di riga:

.create-or-alter function RLSForCustomersTables() {
    MyTable
    | where assert(current_principal_is_member_of('aadgroup=mygroup@mycompany.com') == true, "You don't have access")
}

È possibile combinare questo approccio con altri esempi. Ad esempio, è possibile visualizzare risultati diversi agli utenti in gruppi di Microsoft Entra diversi e generare un errore per tutti gli altri utenti.

Controllare le autorizzazioni per i database follower

I criteri di sicurezza a livello di riga configurati nel database di produzione avranno effetto anche nei database follower. Non è possibile configurare criteri di sicurezza a livello di riga diversi nei database di produzione e follower. Tuttavia, è possibile usare la current_cluster_endpoint() funzione nella query di sicurezza a livello di riga per ottenere lo stesso effetto, come la presenza di query di sicurezza a livello di riga diverse nelle tabelle follower.

Ad esempio:

.create-or-alter function RLSForCustomersTables() {
    let IsProductionCluster = current_cluster_endpoint() == "mycluster.eastus.kusto.windows.net";
    let DataForProductionCluster = TempTable | where IsProductionCluster;
    let DataForFollowerClusters = TempTable | where not(IsProductionCluster) | extend EmailAddress = "****";
    union DataForProductionCluster, DataForFollowerClusters
}

Nota

La funzione RLS precedente non ha alcun impatto sulle prestazioni sulle query nel cluster leader. L'impatto sulle prestazioni sulle query nei cluster follower sarà influenzato solo dalla complessità di DataForFollowerClusters.

Altri casi d'uso

  • Una persona di supporto del call center può identificare i chiamanti in base a diverse cifre del numero di previdenza sociale. Questo numero non deve essere completamente esposto alla persona di supporto. Un criterio di sicurezza a livello di riga può essere applicato alla tabella per mascherare tutte le ultime quattro cifre del numero di previdenza sociale nel set di risultati di qualsiasi query.
  • Impostare un criterio di sicurezza a livello di riga che maschera le informazioni personali e consente agli sviluppatori di eseguire query sugli ambienti di produzione per la risoluzione dei problemi senza violare le normative di conformità.
  • Un ospedale può impostare un criterio di sicurezza a livello di riga che consente agli infermieri di visualizzare solo le righe di dati per i pazienti.
  • Una banca può impostare un criterio di sicurezza a livello di riga per limitare l'accesso alle righe di dati finanziari in base alla divisione o al ruolo aziendale di un dipendente.
  • Un'applicazione multi-tenant può archiviare i dati di molti tenant in un singolo set di tabelle , efficiente. Userebbero criteri di sicurezza a livello di riga per applicare una separazione logica delle righe di dati di ogni tenant dalle righe di ogni altro tenant, in modo che ogni tenant possa visualizzare solo le righe di dati.

Impatto sulle prestazioni sulle query

Quando un criterio di sicurezza a livello di riga è abilitato in una tabella, si verificherà un impatto sulle prestazioni sulle query che accedono a tale tabella. L'accesso alla tabella verrà sostituito dalla query di sicurezza a livello di riga definita in tale tabella. L'impatto sulle prestazioni di una query di sicurezza a livello di riga è in genere costituito da due parti:

  • Controlli di appartenenza in Microsoft Entra ID: i controlli sono efficienti. È possibile controllare l'appartenenza a decine o anche centinaia di gruppi senza impatto significativo sulle prestazioni delle query.
  • Filtri, join e altre operazioni applicate ai dati: l'impatto dipende dalla complessità della query

Ad esempio:

let IsRestrictedUser = current_principal_is_member_of('aadgroup=some_group@domain.com');
let AllData = MyTable | where not(IsRestrictedUser);
let PartialData = MyTable | where IsRestrictedUser and (...);
union AllData, PartialData

Se l'utente non fa parte di some_group@domain.com, viene IsRestrictedUser valutato in false. La query valutata è simile alla seguente:

let AllData = MyTable;           // the condition evaluates to `true`, so the filter is dropped
let PartialData = <empty table>; // the condition evaluates to `false`, so the whole expression is replaced with an empty table
union AllData, PartialData       // this will just return AllData, as PartialData is empty

Analogamente, se IsRestrictedUser restituisce true, verrà valutata solo la query per PartialData .

Migliorare le prestazioni delle query quando viene usata la sicurezza a livello di riga

Impatto sulle prestazioni sull'inserimento

Non si verifica alcun impatto sulle prestazioni per l'inserimento.