sql >> Databáze >  >> RDS >> Database

Hloubkový průzkum zabezpečení na úrovni řádků

Úvod

Organizace se stále více zajímají o to, jak snížit náklady na licencování databázových řešení pomocí konsolidace. Určité konsolidace lze na serveru SQL Server dosáhnout jednoduše využitím stávajícího vztahu jedna k mnoha mezi instancemi a databázemi. Existují však případy, kdy řešení vyžaduje konsolidaci dat do jedné tabulky. V takovém případě mohou existovat obavy, jak omezit přístup k datům.

Zabezpečení na úrovni řádků bylo představeno v SQL Server 2016 jako řešení pro scénáře podobné výše uvedeným. Umožňuje vám omezit přístup k řádkům v tabulce na základě podmínek definovaných v inline funkci s hodnotou tabulky nazývanou Predikátová funkce . Když je predikátová funkce aplikována na uživatelskou tabulku obsahující konsolidovaná data, systém lze nakonfigurovat tak, aby vracel různé datové sady různým uživatelům v závislosti na jejich rolích, což zase závisí například na jejich popisu práce nebo oddělení.

Scénář

Sestavíme jednoduchý scénář pro ilustraci tohoto konceptu pomocí finanční instituce. Banka se rozhodla konsolidovat účty všech svých zákazníků do jedné databáze a Transakce tabulka je jedna dělená tabulka obsahující všechny transakce stejně jako Zákazníci stůl pro uložení všech zákazníků banky. Banka sídlí v několika zemích a také expanduje. Každá země je identifikována pomocí AffiliateID sloupec. Společnost je strukturována tak, že přístup ke klíčovým tabulkám je omezen na základě seniority.

Identifikujte cenné papíry

Budeme muset implementovat řešení zabezpečení na úrovni řádků, které omezí přístup k datům zákazníků a transakcím na základě rolí a zásad zabezpečení na úrovni řádků. Naším prvním krokem je vytvoření požadovaných tabulek. Výpis 1 ukazuje DDL pro klíčové tabulky, které budeme testovat. Celou databázi použitou pro tento test lze stáhnout zde.

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)

Poté vytvoříme sadu tabulek, které můžeme použít k identifikaci zaměstnanců. V tomto nastavení má každý personál ScopeID který určuje, do jaké míry může prohlížet data nebo s nimi manipulovat:

  1. Národní – Zaměstnanci mohou manipulovat s daty pouze v zemi zaměstnance (kde pracuje)
  2. Regionální – Zaměstnanec může manipulovat s daty pouze v regionu zaměstnance (např. západní Afrika)
  3. Globální – Zaměstnanci mohou manipulovat s daty v jakékoli zemi, kde bude mít banka pobočku

Každý rozsah je přidělen zaměstnancům na základě jejich označení. Rozsah působnosti správce skupiny je globální , oblast působnosti country managera je regionální a působnost výkonného pracovníka je národní . Tradičním způsobem omezení přístupu k datům je často používání rolí a oprávnění. Přiřazení oprávnění roli a následné přiřazení role uživateli znamená, že uživatel má oprávnění přidružená k této roli pro celou sadu dat v příslušné tabulce. Zabezpečení na úrovni řádků nám dává příležitost udělat něco podrobnějšího:omezit uživatelská oprávnění SELECT/UPDATE/DELETE na podmnožinu datové sady v tabulce (jemné řízení přístupu).

Obr. 1. StaffScope a Staff Tables

Role a uživatelé databáze

Výpis 2 ukazuje uživatele a role, které musíme vytvořit, abychom mohli pokračovat v našem řešení. Myšlenka je taková, že existuje vztah mezi zaměstnanci uloženými v uživatelských tabulkách Staff a StaffScope a Database Principals, které tito zaměstnanci nakonec použijí pro přístup k datům. Sledujte sloupec na obr. 1 s názvem DBUserID . Tento sloupec je vyplněn pomocí funkce DATABASE_PRINCIPAL_ID (viz výpis 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;

Zatím shrnuto, co jsme udělali, je:

  1. Vytvořte/identifikujte tabulky, které potřebujeme zabezpečit
  2. Vytvořte tabulky, které označují kritéria, která použijeme k omezení přístupu k datům na úrovni řádků (rozsah)
  3. Vytvořené databázové role a uživatelé, na které použijeme omezení
  4. Omezený přístup k základním tabulkám („zabezpečení na úrovni tabulky“) pomocí rolí a oprávnění

Funkce predikce a zásady zabezpečení

Zatím máme to, co můžeme nazvat zabezpečení na úrovni tabulky, implementované pomocí rolí a oprávnění. Nyní chceme jít hlouběji. Chceme, aby dva principálové, kteří mají oprávnění SELECT pro tabulku, mohli dotazovat tabulku, ale viděli různé datové sady na základě podmínek, které jsme nastavili. Výpis 3 nám ukazuje, jak toho dosáhneme.

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

Predikátová funkce definuje podmínky, které musí být splněny, aby principál viděl podmnožinu zajímavých dat. Tato funkce má tři podmínky:

  1. Uživatel databáze zaměstnanců je členem Národní role a AffiliateID odpovídá zaměstnancům NEBO
  2. Uživatel databáze zaměstnanců je členem Regionální role a AffiliateID odpovídá seznamu AffiliateID 's patřící do regionu Západní Afrika OR
  3. Uživatel databáze zaměstnanců je členem Global

To znamená, že člen Global role vidí všechna data jednoduše proto, že do dané role patří. Členové dalších dvou rolí však musí splňovat další kritéria hraničící s AffiliateID .

Aby byla funkce užitečná, použijte ji na tabulky jako predikáty FILTER nebo BLOCK. Predikáty FILTER omezují to, co může principál vidět, zatímco predikáty BLOCK zajišťují, že principál nemůže manipulovat s žádnými daty mimo data, která jsou mu prezentována omezeními definovanými ve funkci. Bezpečnostní politika je kontejner, ve kterém specifikujeme predikáty FILTER a BLOCK pro všechny tabulky, které nás zajímají. Podívejte se na Výpis 3 znovu.

Jedním z velmi zajímavých aspektů tohoto přístupu je modularita. Predikáty můžeme aplikovat na další tabulky v Bezpečnostní politice, aniž bychom ovlivnili existující definované tabulky, můžeme přidat nové databázové principály (Staff) vytvořením uživatelů databáze a přidělením příslušných rolí. Když dojde k pohybu zaměstnanců, můžeme aktualizovat přiřazení rolí a tak dále.

Testování implementace

Nyní, když jsme hotovi, se můžeme vydávat za správce databáze, abychom určili, zda máme očekávané výsledky pomocí kódu ve výpisu 4. Než se na to podíváme, podívejme se na role spojené s každým personálem a jejich přidruženými společnostmi na obr. 2.

Obr. 2. Seznam zaměstnanců

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';

V prvním řádku se ptám Zákazníky tabulky jako sysadmin, ale nemám ŽÁDNÉ ŘÁDKY. To znamená, že ani správce nemůže potlačit účinky RLS bez zosobnění.

Obr. 4. SysAdmin nevidí žádné řádky

Barbara a Edward jsou oba jednatelé a patří do National Scope, ale pracují v různých zemích, takže vidí zákazníky spojené s jejich příslušnými přidruženými společnostmi. (Viz jména zaměstnanců na obr. 1).

Obr. 5. Vedoucí pracovníci vidí řádky svých přidružených společností

John a Margaret jsou manažeři zemí a skupin. Patří do Regionální a Globální Rozsahy resp. John vidí data pro západní Afriku, zatímco Margaret vidí data pro všechny oblasti.

Obr. 6. Manažeři vidí řádky svého regionu

Výsledky jsou stejné pro všechny ostatní tabulky, na které byla aplikována bezpečnostní politika. Všimněte si, že bez oprávnění k Transakcím tabulka, zabezpečení na úrovni řádků nemá žádnou hodnotu.

Obr. 7. Žádná SELECT oprávnění pro Transakce Tabulka

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

Obr. 8. Transakce Stůl z pohledu vedoucích pracovníků

Závěr

Zabezpečení na úrovni řádků je výkonná metoda pro využití jemnozrnné schopnosti řízení přístupu SQL Server. Použití této funkce vyžaduje, abyste používali SQL Server 2016 nebo vyšší. Jak název napovídá, cílem je omezit přístup k řádkům v tabulce pomocí složitých dotazů poté, co se postaráte o „zabezpečení na úrovni tabulky“. Scénáře, ve kterých lze tuto schopnost použít, jsou nekonečné, a proto jsou velmi užitečné pro širokou škálu prostředí. Dobře prozkoumejte a uvidíte, co pro vás může udělat.

Odkazy

Isakov, V. (2018). Zkouška č. 70-764 Správa infrastruktury databáze SQL . Pearson Education

Zabezpečení na úrovni řádků


  1. SQLAlchemy - SQLite pro testování a Postgresql pro vývoj - Jak portovat?

  2. SQL aktualizační dotaz pomocí spojení

  3. Sloučení/kombinace více souborů PDF do jednoho PDF v Oracle pomocí balíčku PLPDF_TOOLKIT PL/SQL

  4. Jak převést databázi MySQL do kódování UTF-8