sql >> Databasteknik >  >> RDS >> Database

Fördjupad undersökning av säkerhet på radnivå

Introduktion

Organisationer blir mer och mer bekymrade över hur man kan minska kostnaderna för att licensiera databaslösningar med hjälp av konsolidering. Viss konsolidering kan uppnås i SQL Server helt enkelt genom att dra fördel av den befintliga en-till-många-relationen mellan instanser och databaser. Det finns dock fall där lösningen kräver att data konsolideras i en tabell. I ett sådant fall kan det finnas oro över hur man begränsar åtkomsten till data.

Row Level Security introducerades i SQL Server 2016 som en lösning på scenarier som liknar ovanstående. Det låter dig begränsa åtkomsten till rader i en tabell baserat på villkor som definieras i en inline tabellvärderad funktion som kallas en Predikatfunktion . När en predikatfunktion appliceras på en användartabell som innehåller konsoliderade data, kan systemet konfigureras att returnera olika datamängder till olika användare beroende på deras roller, vilket i sin tur beror på deras arbetsbeskrivningar eller avdelningar till exempel.

Scenario

Vi ska bygga ett enkelt scenario för att illustrera detta koncept med hjälp av en finansiell institution. En bank har beslutat att samla konton för alla sina kunder i en enda databas och Transaktioner tabellen är en enda partitionerad tabell som innehåller alla transaktioner liksom Kunderna bord för förvaring av alla bankens kunder. Banken finns i flera länder och expanderar också. Varje land identifieras av ett AffiliateID kolumn. Företaget är strukturerat så att tillgången till nyckeltabeller begränsas utifrån tjänstgöringstid.

Identifiera säkerhetsobjekt

Vi kommer att behöva implementera en Row Level Security-lösning som begränsar åtkomst till kund- och transaktionsdata baserat på roller och en Row Level Security-policy. Vårt första steg är att skapa de tabeller som krävs. Lista 1 visar DDL för nyckeltabellerna vi ska testa. Hela databasen som används för detta test kan laddas ner härifrån.

Listing 1 – Core Tables in West African Commercial Bank Database;
-- Customers;
create table Customers
(CustID int identity (1000,1) not null Primary Key
,FirstName varchar(100)
,LastName varchar(100)
,PhoneNo bigint
,ContactAddress varchar(4000)
,AffiliateID char(3) foreign key references Affiliates(AffiliateID)
,AccountNo1 bigint
,AccountNo2 bigint
,AccountNo3 bigint
,AccountNo1Curr char (3)
,AccountNo2Curr char (3)
,AccountNo3Curr char (3)
)
GO

-- Transactions;
create table Transactions
(TranID int identity (1000,1) not null 
,AcctID int foreign key references Accounts (AcctID)
,TranDate datetime 
,TranAmt money
,AffiliateID char(3) foreign key references Affiliates(AffiliateID)
,primary key (TranID,TranDate))
ON PartSch (TranDate)

-- Transaction_History;
create table Transaction_History
(TranID int identity (1000,1) not null 
,AcctID int foreign key references Accounts (AcctID)
,TranDate datetime 
,TranAmt money
,AffiliateID char(3) foreign key references Affiliates(AffiliateID)
,primary key (TranID,TranDate))
ON PartSch (TranDate)

Vi skapar sedan en uppsättning tabeller som vi kan använda för att identifiera personal. I den här inställningen har varje personal ett ScopeID som avgör i vilken utsträckning han eller hon kan se eller manipulera data:

  1. Nationell – En anställd kan bara manipulera data i personalens land (där han eller hon arbetar)
  2. Regional – En personal kan bara manipulera data i personalens region (t.ex. Västafrika)
  3. Global – En anställd kan manipulera data i vilket land som helst där banken någonsin kommer att ha en filial

Varje scope tilldelas personalen utifrån deras beteckning. En gruppchefs omfattning är Global , en Country Managers omfattning är Regional och en chefs omfattning är nationell . Det traditionella sättet att begränsa åtkomsten till data är ofta användningen av roller och behörigheter. Att tilldela behörigheter till en roll och sedan tilldela rollen till en användare innebär att användaren har de behörigheter som är kopplade till den rollen för hela datamängden i tabellen i fråga. Row Level Security ger oss möjlighet att göra något mer detaljerat:begränsa användarens SELECT/UPDATE/DELETE-behörigheter till en delmängd av datamängden i tabellen (finkornig åtkomstkontroll).

Fig. 1. StaffScope och Staff Tables

Databasroller och användare

Lista 2 visar användarna och rollerna vi måste skapa för att fortsätta med vår lösning. Tanken är att det finns en relation mellan personalen som lagras i användartabellerna Staff och StaffScope och de Databas Principals som denna personal så småningom kommer att använda för att komma åt data. Observera kolumnen i Fig. 1 som heter DBUserID . Denna kolumn fylls i med funktionen DATABASE_PRINCIPAL_ID (se lista 2)

Listing 2 – Staff, Database User IDs and Roles

-- Populate Staff Table
use WACB
go
insert into Staff values ('John','Edu',DATABASE_PRINCIPAL_ID(),'Manager','233205678493','2','Accra, Ghana','EGH');
insert into Staff values ('Margaret','Harrison',DATABASE_PRINCIPAL_ID(),'Group Manager','2348030006574','3','Lagos, Nigeria','ENG');
insert into Staff values ('Edward','Antwi',DATABASE_PRINCIPAL_ID(),'Executive','22824567493','1','Lome, Togo','ETG');
insert into Staff values ('Barbara','Orji',DATABASE_PRINCIPAL_ID(),'Executive','22424567493','1','Abuja, Nigeria','ENG');
GO

-- Create Database User IDs for Staff
create user jedu without login;
create user mharrison without login;
create user eantwi without login;
create user borji without login;

-- Associate Database Principal IDs with Staff
update staff set DBUserID=DATABASE_PRINCIPAL_ID(concat(left(firstname,1),lastname));


-- Create Database Roles
create role [National] ;
create role [Regional] ;
create role [Global] ;

-- Grant Permissions on Desired Tables to Database Roles
grant select on customers to [National];
grant select, update on customers to Regional;
grant select, update on customers to Global;
grant select on Transactions to Regional, Global;
grant select on Transaction_History to Regional, Global;
grant update on Transactions to Global;


-- Grant Database Roles to Database Users Associated with Staff
alter role [National] add member eantwi;
alter role [National] add member borji;
alter role [Regional] add member jedu;
alter role [Global] add member mharrison;

Så långt i sammanfattning är vad vi har gjort:

  1. Skapa/identifiera tabellerna vi behöver säkra
  2. Skapa tabeller som anger vilka kriterier vi ska använda för att begränsa åtkomsten till data på radnivå (Scope)
  3. Skapade databasroller och användare som vi ska tillämpa begränsningar på
  4. Begränsad åtkomst till kärntabellerna ("Table Level Security") med hjälp av roller och behörigheter

Förutsägelsefunktion och säkerhetspolicy

Hittills har vi vad vi kan kalla Table Level Security implementerat med hjälp av roller och behörigheter. Nu vill vi gå djupare. Vi vill att två principaler som har SELECT-privilegier på en tabell ska kunna fråga tabellen men se olika datauppsättningar baserat på villkor som vi ställer in. Anteckning 3 visar oss hur vi uppnår detta.

Listing 3 - Implement Row Level Security

-- Create Predicate Function
create schema rls;
go

create function rls.AccessPredicate (@AffiliateID char(3))
returns table
with schemabinding
as
return select 1 as access 
from dbo.Staff as s 
join dbo.StaffScope ss on s.ScopeID=ss.ScopeID 
join dbo.Affiliates a on s.AffiliateID=a.AffiliateID
where (
IS_MEMBER('National')=1
and s.DBUserID=DATABASE_PRINCIPAL_ID()
and @AffiliateID=s.AffiliateID
)
OR
(
IS_MEMBER('Regional')=1
and @AffiliateID in (select a.AffiliateID from dbo.Affiliates where Region='West Africa')
)
OR
(
IS_MEMBER('Global')=1
);
GO

-- Create Security Policy
create security policy rls.dataSecurityPol
add filter predicate rls.AccessPredicate (AffiliateID) on dbo.Customers,
add filter predicate rls.AccessPredicate (AffiliateID) on dbo.Transactions,
add filter predicate rls.AccessPredicate (AffiliateID) on dbo.Transaction_History,
add block predicate rls.AccessPredicate (AffiliateID) on dbo.Customers after update,
add block predicate rls.AccessPredicate (AffiliateID) on dbo.Transactions after update,
add block predicate rls.AccessPredicate (AffiliateID) on dbo.Transaction_History after update;
GO

-- Alter Security Policy
alter security policy rls.dataSecurityPol
add filter predicate rls.AccessPredicate (AffiliateID) on dbo.Transaction_History,
add block predicate rls.AccessPredicate (AffiliateID) on dbo.Transaction_History after update;
GO

Predikatfunktionen definierar villkoren som måste uppfyllas för att en huvudman ska se en delmängd av intressanta data. I den här funktionen finns det tre villkor:

  1. Personalens databasanvändare är medlem i National roll och AffiliateID matchar personalens ELLER
  2. Personalens databasanvändare är medlem i Regional roll och AffiliateID matchar listan med AffiliateID som tillhör den västafrikanska regionen ELLER
  3. Personalens databasanvändare är medlem i Global

Detta innebär att en medlem av Global rollen ser all data helt enkelt för att han eller hon tillhör den rollen. Medlemmar av de två andra rollerna måste dock uppfylla ytterligare kriterier som gränsar till AffiliateIDs .

För att funktionen ska vara användbar, använd detta på tabeller som antingen FILTER-predikat eller BLOCK-predikat. FILTER-predikat begränsar vad rektor kan se medan BLOCK-predikat säkerställer att rektor inte kan manipulera någon data utanför den som presenteras för honom/henne av de begränsningar som definieras i funktionen. En säkerhetspolicy är en behållare där vi anger FILTER- och BLOCK-predikaten för alla tabeller vi är intresserade av. Ta en titt på List 3 igen.

En mycket intressant aspekt av detta tillvägagångssätt är modulariteten. Vi kan tillämpa predikaten på ytterligare tabeller i säkerhetspolicyn utan att påverka de befintliga definierade tabellerna, vi kan lägga till nya databasprinciper (Staff) genom att skapa databasanvändare och ge dem lämpliga roller. När personalförflyttning sker kan vi uppdatera rolltilldelningarna och så vidare.

Testa implementeringen

Så nu när vi är klara kan vi imitera databasens principer för att avgöra om vi har de förväntade resultaten med hjälp av koden i Lista 4. Innan vi tittar på det, låt oss se rollerna som är associerade med varje personal och deras affiliates i Fig. 2.

Fig. 2. Personallista

Listing 4 – Testing the Implementation

select * from Customers;
execute ('select * from Customers') as user='eantwi';
execute ('select * from Customers') as user='borji';
execute ('select * from Customers') as user='jedu';
execute ('select * from Customers') as user='mharrison';

På första raden frågar jag kunderna tabellen som en sysadmin, men jag får INGA RADER. Det betyder att även en administratör inte kan åsidosätta effekterna av RLS utan identitetsstöld.

Fig. 4. SysAdmin ser inga rader

Barbara och Edward är båda verkställande direktörer och tillhör National Scope men de arbetar i olika länder så de ser kunderna associerade med sina respektive dotterbolag. (Se personalens namn i fig. 1).

Fig. 5. Chefer ser sina affiliates rader

John och Margaret är lands- och gruppchefer. De tillhör Regional och Global Omfattningar respektive. John ser data för Västafrika, medan Margaret ser data för alla regioner.

Fig. 6. Chefer ser sin regions rader

Resultaten är desamma för alla andra tabeller som säkerhetspolicyn har tillämpats på. Observera att utan tillstånd på Transaktioner tabell, Säkerhet på radnivå saknar värde.

Fig. 7. Inga SELECT-behörigheter för Transaktioner Tabell

Listing 5 – Permissions on Transactions Table
grant select on dbo.Transactions to [National];

Fig. 8. Transaktioner Tabell sett av chefer

Slutsats

Row Level Security är en kraftfull metod för att utnyttja SQL Servers finkorniga åtkomstkontrollkapacitet. Att använda den här funktionen kräver att du kör SQL Server 2016 eller högre. Som namnet antyder är målet att begränsa åtkomsten till rader i en tabell med hjälp av komplexa frågor efter att du har tagit hand om "tabellnivåsäkerhet". Scenarierna där denna förmåga kan tillämpas är oändliga, så den är mycket användbar för ett brett spektrum av miljöer. Gör klokt i att utforska och se vad det kan göra för dig.

Referenser

Isakov, V. (2018). Testreferens 70-764 Administrera en SQL-databasinfrastruktur . Pearson Education

Säkerhet på radnivå


  1. Hur man importerar och exporterar en databas via phpMyAdmin (felet 'Access denied create database db_name')

  2. Hur hittar man de privilegier och roller som ges till en användare i Oracle?

  3. Hur anger man ett portnummer i SQL Server-anslutningssträngen?

  4. Relationella vs icke-relationella databaser – Del 3