Proč je zabezpečení na úrovni řádků důležité?
Před SQL Serverem 2016 bylo zabezpečení na úrovni tabulky výchozí nejnižší úrovní zabezpečení databáze. Jinými slovy, uživatel by mohl mít omezený přístup k tabulce jako celku. V některých případech však potřebujeme, aby uživatelé měli přístup k tabulce, ale ne ke konkrétním řádkům v tabulce. Před SQL Serverem 2016 to vyžadovalo napsání vlastních uložených procedur pro poskytování tak jemného zabezpečení. Takové uložené procedury jsou však náchylné k vkládání SQL a dalším bezpečnostním upozorněním.
Používání funkce SQL Server Row Level Security v praxi
SQL Server 2016 zavedl novou funkci zabezpečení na úrovni řádků, která uživatelům umožňuje mít přístup k tabulce, ale omezuje je na přístup ke konkrétním řádkům v této tabulce. Pojďme se podívat, jak to lze prakticky využít.
Popis
Existují čtyři kroky k implementaci zabezpečení na úrovni řádků v SQL Server.
- Udělte oprávnění Select uživatelům v tabulce, ve které chcete implementovat zabezpečení na úrovni řádků.
- Dále musíte napsat funkci hodnot vložené tabulky obsahující predikát filtru. Přidejte logiku filtru do predikátu filtru.
- Nakonec je třeba svázat predikát filtru, který jste vytvořili v druhém kroku, se zásadou zabezpečení.
- Otestujte funkci zabezpečení na úrovni řádků.
Než provedeme výše uvedené kroky, musíme vytvořit fiktivní databázi s několika fiktivními záznamy. Chcete-li to provést, spusťte následující skript:
CREATE DATABASE UniversityGOUSE UniversityGOUSE UniversityCREATE TABLE Osoby(Id INT PRIMÁRNÍ KLÍČ IDENTITA(1,1),Jméno VARCHAR (50),Role VARCHAR (50))GOUSE UniversityINSERT INTO Persons VALUES ('Sally', 'Principal' )INSERT INTO HODNOTY osob ('Edward', 'Student' )INSERT INTO Persons VALUES ('Jon', 'Student' )INSERT INTO Persons VALUES ('Scot', 'Student')INSERT INTO Persons VALUES ('Ben', 'Student' ) INSERT INTO Persons VALUES ('Isabel', 'Učitel' )INSERT IN Persons VALUES ('David', 'Učitel' )INSERT INTO Persons VALUES ('Laura', 'Učitel' )INSERT INTO Persons VALUES ('Jean', 'Učitel ')INSERT INTO Persons VALUES ('František', 'Učitel' )
Ve skriptu vytvoříme fiktivní databázi „Univerzita“. Dále spustíme skript, který vytvoří tabulku s názvem „Osoby“. Pokud se podíváte na návrh tabulky, můžete vidět, že obsahuje tři sloupce Id, Name a Role. Sloupec ID je sloupec primárního klíče s omezením IDENTITY. Sloupec Jméno obsahuje jméno osoby a sloupec Role obsahuje roli osoby. Nakonec jsme do tabulky Osoby vložili 10 záznamů. Stůl má 1 ředitele, 4 učitele a 5 studentů.
Proveďme jednoduchý příkaz SELECT, abychom viděli záznamy v tabulce:
Použít UniversitySELECT * FROM Osoby
Výsledek vypadá takto:
Chceme, aby měl uživatel jménem Principal přístup ke všem řádkům v tabulce Osoby. Podobně by učitel měl mít přístup pouze k záznamům učitelů, zatímco studenti by měli mít přístup pouze k záznamům studentů. Toto je klasický případ zabezpečení na úrovni řádků.
Při implementaci zabezpečení na úrovni řádků budeme postupovat podle kroků, které jsme probrali dříve.
Krok 1:Udělte vybraná oprávnění uživatelům v tabulce
Vytvoříme tři uživatele s rolemi Ředitel, Učitel a Student a udělíme jim přístup SELECT k těmto uživatelům v tabulce Osoby. Chcete-li to provést, spusťte následující skript:
VYTVOŘIT UŽIVATELE Ředitele BEZ PŘIHLÁŠENÍ;GOCREATE UŽIVATELE Učitele BEZ PŘIHLÁŠENÍ;GOCREATE USER Student BEZ PŘIHLÁŠENÍ;GOuse University SELECT ON Person Řediteli;GOGRANT SELECT ON Osoby Učiteli;GOGRANT SELECT ON Osoby Studentovi;GO
Krok 2:Vytvoření predikátu filtru
Jakmile jsou uživatelům udělena oprávnění, dalším krokem je vytvoření predikátu filtru.
Následující skript to dělá:
Použijte FUNKCI UniversityGOCREATE dbo.fn_SP_Person(@Role AS sysname) VRÁTÍ TABLEWITH SCHEMABINDINGAS RETURN SELECT 1 AS fn_SP_Person_output -- Predikátová logika WHERE @Role =USER_NAME() OR USER_NAME()' =USER_NAME;Predikát filtru je vytvořen uvnitř funkce s inline tabulkou a přebírá roli uživatele jako parametr. Vrátí ty záznamy, kde hodnota role předaná jako parametr odpovídá hodnotě role ve sloupci Role. Nebo pokud je uživatelská role ‚Principal‘, vrátí se všechny role. Pokud se podíváte na predikátový filtr, nenajdete název tabulky, pro kterou filtr vytváříme. Predikát filtru je připojen k tabulce prostřednictvím bezpečnostní politiky, kterou uvidíme v dalším kroku.
Krok 3:Vytvoření zásad zabezpečení
Spuštěním následujícího skriptu vytvořte zásady zabezpečení pro predikát filtru, který jsme vytvořili v posledním kroku:
Použít BEZPEČNOSTNÍ ZÁSADY UniversityGoCREATE RoleFilterADD FILTER PREDICATE dbo.fn_SP_Person(Role)ON dbo.PersonsWITH (STATE =ON);GOV Bezpečnostní politice jsme jednoduše přidali predikát filtru, který jsme vytvořili, do tabulky Osoby. Chcete-li tuto zásadu povolit, příznak „STATE“ by měl být nastaven na hodnotu ON.
Krok 4:Testování zabezpečení na úrovni řádků
Provedli jsme všechny kroky potřebné k vynucení zabezpečení na úrovni řádků v tabulce Osoby univerzitní databáze. Zkusme nejprve přistupovat k záznamům v tabulce Osoby přes výchozího uživatele. Spusťte následující skript:
Použijte UniversitySELECT * FROM Persons;GOVe výstupu neuvidíte nic, protože výchozí uživatel nemá přístup k tabulce Osoby.
Přepneme se na uživatele Student, kterého jsme vytvořili dříve, a zkusme VYBRAT záznamy z tabulky Osoby:
EXECUTE AS USER ='Student';Použít UniversitySELECT * FROM Osoby; -- Pouze záznamy studentůREVERT;GOVe skriptu výše se přepneme na uživatele ‚Student‘, vybrané záznamy z tabulky Osoby a vrátíme se zpět k výchozímu uživateli. Výstup vypadá takto:
Vidíte, že díky zabezpečení na úrovni řádků se zobrazují pouze záznamy, kde má sloupec Role hodnotu Student.
Podobně uživatel Učitel bude mít přístup pouze k záznamům, kde má sloupec Role hodnotu Učitel. Chcete-li to ověřit, spusťte následující skript:
EXECUTE AS USER ='Učitel';Použít UniversitySELECT * FROM Osoby; -- All RecordsREVERT;GOVe výstupu budete mít následující záznamy:
Nakonec jsme v našem predikátu filtru implementovali logiku, podle níž má uživatel Principal přístup ke všem záznamům. Ověřte si to provedením následujícího dotazu:
EXECUTE AS USER ='Principal';Použít UniversitySELECT * FROM Osoby; -- All RecordsREVERT;GOVe výstupu uvidíte všechny záznamy, jak je uvedeno níže:
Závěr
Funkce zabezpečení na úrovni řádků je mimořádně užitečná, když chcete, aby uživatelé měli podrobný přístup ke konkrétním datům. Funkce zabezpečení na úrovni řádků však zahrnuje funkci vložené tabulky s hodnotou, která může způsobit snížení výkonu.
Obecně platí, že pokud plánujete v predikátové funkci použít jednoduchou klauzuli WHERE, váš výkon by neměl být ovlivněn. Na druhou stranu byste se měli vyhnout složitým příkazům spojení zahrnujícím vyhledávací tabulky, pokud jste implementovali zabezpečení na úrovni řádků.