Dela via


Säkerhet på radnivå

Använd gruppmedlemskap eller körningskontext för att styra åtkomsten till rader i en databastabell.

Säkerheten på radnivå (RLS) förenklar design och kodning av säkerheten. Med den här funktionen kan du begränsa åtkomsten till datarader i ditt program. Du kan till exempel begränsa användaråtkomsten till rader som är relevanta för deras avdelning eller begränsa kundåtkomsten till endast de data som är relevanta för företaget.

Logiken för åtkomstbegränsning finns på databasnivån i stället för från data på en annan programnivå. Databassystemet tillämpar åtkomstbegränsningarna varje gång dataåtkomst görs från valfri nivå. Den här logiken gör ditt säkerhetssystem mer tillförlitligt och robust genom att minska säkerhetssystemets yta.

Med RLS kan du ge åtkomst till andra program och användare, endast till en viss del av en tabell. Du kanske till exempel vill:

  • Bevilja endast åtkomst till rader som uppfyller vissa villkor
  • Maskera data i vissa kolumner
  • Alla alternativ ovan

Anteckning

När en RLS-princip är aktiverad i en tabell ersätts åtkomsten helt av den RLS-fråga som definieras i tabellen. Åtkomstbegränsningen gäller för alla användare, inklusive databasadministratörer och RLS-skaparen. RLS-frågan måste uttryckligen innehålla definitioner för alla typer av användare som du vill ge åtkomst till.

Mer information finns i hanteringskommandon för hantering av säkerhetsprincipen på radnivå.

Tips

Dessa funktioner är ofta användbara för row_level_security frågor:

Begränsningar

  • Det finns ingen gräns för hur många tabeller som säkerhetsprincipen på radnivå kan konfigureras för.
  • Det går inte att konfigurera en säkerhetsprincip på radnivå i externa tabeller.
  • RLS-principen kan inte aktiveras i en tabell under följande omständigheter:

Exempel

Begränsa åtkomsten till tabellen Försäljning

I en tabell med namnet Salesinnehåller varje rad information om en försäljning. En av kolumnerna innehåller namnet på säljaren. I stället för att ge säljarna åtkomst till alla poster i Salesaktiverar du en säkerhetsprincip på radnivå i den här tabellen för att endast returnera poster där säljaren är den aktuella användaren:

Sales | where SalesPersonAadUser == current_principal()

Du kan också maskera e-postadressen:

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

Om du vill att alla säljare ska se all försäljning i ett visst land/region kan du definiera en fråga som liknar:

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))

Om du har en grupp som innehåller cheferna kanske du vill ge dem åtkomst till alla rader. Här är frågan för säkerhetsprincipen på radnivå.

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

Exponera olika data för medlemmar i olika Microsoft Entra grupper

Om du har flera Microsoft Entra grupper och vill att medlemmarna i varje grupp ska se olika delmängder av data använder du den här strukturen för en RLS-fråga.

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>)

Tillämpa samma RLS-funktion på flera tabeller

Definiera först en funktion som tar emot tabellnamnet som en strängparameter och refererar till tabellen med operatorn table() .

Exempel:

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

Konfigurera sedan RLS på flera tabeller på det här sättet:

.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')"

Skapa ett fel vid obehörig åtkomst

Om du vill att icke-auktoriserade tabellanvändare ska få ett fel i stället för att returnera en tom tabell använder du assert() funktionen . I följande exempel visas hur du skapar det här felet i en RLS-funktion:

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

Du kan kombinera den här metoden med andra exempel. Du kan till exempel visa olika resultat för användare i olika Microsoft Entra grupper och skapa ett fel för alla andra.

Kontrollera behörigheter för uppföljningsdatabaser

Den RLS-princip som du konfigurerar på produktionsdatabasen börjar också gälla i de följande databaserna. Du kan inte konfigurera olika RLS-principer för produktions- och uppföljningsdatabaserna. Du kan dock använda current_cluster_endpoint() funktionen i din RLS-fråga för att uppnå samma effekt, som att ha olika RLS-frågor i följartabeller.

Exempel:

.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
}

Anteckning

RLS-funktionen ovan har ingen som helst prestandapåverkan på frågor i leader-klustret. Prestandapåverkan på frågor på följande kluster påverkas endast av DataForFollowerClusterskomplexiteten i .

Fler användningsfall

  • En kundtjänst kan identifiera uppringare med flera siffror i sitt personnummer. Det här numret ska inte vara helt exponerat för supporten. En RLS-princip kan tillämpas på tabellen för att maskera alla utom de sista fyra siffrorna i personnumret i resultatuppsättningen för en fråga.
  • Ange en RLS-princip som maskerar personligt identifierbar information (PII) och gör det möjligt för utvecklare att köra frågor mot produktionsmiljöer i felsökningssyfte utan att bryta mot efterlevnadsreglerna.
  • Ett sjukhus kan ange en RLS-princip som gör det möjligt för sjuksköterskor att visa datarader endast för sina patienter.
  • En bank kan ange en RLS-princip för att begränsa åtkomsten till finansiella datarader baserat på en medarbetares affärsdivision eller roll.
  • Ett program för flera innehavare kan lagra data från många klienter i en enda tabelluppsättning (vilket är effektivt). De skulle använda en RLS-princip för att framtvinga en logisk separation av varje klients datarader från alla andra klientorganisationers rader, så att varje klientorganisation bara kan se sina datarader.

Prestandapåverkan på frågor

När en RLS-princip är aktiverad i en tabell kommer prestanda att påverka frågor som har åtkomst till tabellen. Åtkomsten till tabellen ersätts av den RLS-fråga som har definierats i tabellen. Prestandaeffekten för en RLS-fråga består normalt av två delar:

  • Medlemskapskontroller i Microsoft Entra ID: Kontrollerna är effektiva. Du kan kontrollera medlemskap i tiotals eller till och med hundratals grupper utan större inverkan på frågeprestandan.
  • Filter, kopplingar och andra åtgärder som tillämpas på data: Effekten beror på frågans komplexitet

Exempel:

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

Om användaren inte är en del av some_group@domain.comIsRestrictedUser utvärderas till false. Frågan som utvärderas liknar den här:

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

IsRestrictedUser Om utvärderas till trueutvärderas på samma sätt endast frågan förPartialData.

Förbättra frågeprestanda när RLS används

Prestandapåverkan på inmatning

Inmatningen påverkas inte av prestanda.