Criterio rowlevelsecurity
Si applica a: ✅Microsoft Fabric✅Azure Esplora dati
Usare l'appartenenza al gruppo o il contesto di esecuzione per controllare l'accesso alle righe di 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 pertinenti al proprio 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 risposte 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 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:
Limiti
- 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:
- Quando viene fatto riferimento a una query dei criteri di aggiornamento , mentre i criteri di aggiornamento non sono configurati con un'identità gestita.
- Quando fa riferimento a un'esportazione continua che usa un metodo di autenticazione diverso dalla rappresentazione.
- Quando per la tabella è configurato un criterio di accesso alla visualizzazione con restrizioni.
- La query di sicurezza a livello di riga non può fare riferimento a tabelle che si trovano in altri database.
Esempi
Limitare l'accesso alla tabella Sales
In una tabella denominata Sales
ogni 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 di 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 relativa ai 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 diversi gruppi di Microsoft Entra
Se sono presenti più gruppi di Microsoft Entra e si desidera 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 vuole che gli utenti di tabelle non autorizzate 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 diversi gruppi di Microsoft Entra 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 di sicurezza a livello di riga precedente non ha alcun impatto sulle prestazioni sulle query nel cluster leader. L'impatto sulle prestazioni sulle query sui cluster follower sarà influenzato solo dalla complessità di DataForFollowerClusters
.
Controllare le autorizzazioni per i database di collegamento
I criteri di sicurezza a livello di riga configurati nel database di produzione avranno effetto anche nei database di scelta rapida. Non è possibile configurare criteri di sicurezza a livello di riga diversi nei database di produzione e collegamento. 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 di scelta rapida.
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 database di origine. L'impatto sulle prestazioni delle query sui database di collegamento 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 criteri 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 da 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 alcun 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, IsRestrictedUser
viene 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
- Se un filtro viene applicato a una colonna a cardinalità elevata, ad esempio DeviceID, è consigliabile usare i criteri di partizionamento o i criteri di ordine di riga
- Se un filtro viene applicato a una colonna di cardinalità media bassa, è consigliabile usare i criteri ordine di riga
Impatto sulle prestazioni per l'inserimento
L'inserimento non influisce sulle prestazioni.