Database
 sql >> Datenbank >  >> RDS >> Database

Eingehende Untersuchung der Sicherheit auf Zeilenebene

Einführung

Unternehmen machen sich immer mehr Gedanken darüber, wie sie die Kosten für die Lizenzierung von Datenbanklösungen durch Konsolidierung senken können. Eine gewisse Konsolidierung kann in SQL Server erreicht werden, indem einfach die bestehende 1:n-Beziehung zwischen Instanzen und Datenbanken ausgenutzt wird. Es gibt jedoch Fälle, in denen die Lösung erfordert, dass Daten in einer Tabelle konsolidiert werden. In einem solchen Fall kann es Bedenken geben, wie der Zugriff auf die Daten eingeschränkt werden kann.

Sicherheit auf Zeilenebene wurde in SQL Server 2016 als Lösung für ähnliche Szenarien wie oben eingeführt. Sie ermöglicht es Ihnen, den Zugriff auf Zeilen in einer Tabelle basierend auf Bedingungen einzuschränken, die in einer Inline-Tabellenwertfunktion namens Prädikatfunktion definiert sind . Wenn eine Prädikatfunktion auf eine Benutzertabelle angewendet wird, die konsolidierte Daten enthält, kann das System so konfiguriert werden, dass verschiedene Datensätze an verschiedene Benutzer zurückgegeben werden, abhängig von ihren Rollen, die wiederum beispielsweise von ihren Stellenbeschreibungen oder Abteilungen abhängen.

Szenario

Wir werden ein einfaches Szenario erstellen, um dieses Konzept anhand eines Finanzinstituts zu veranschaulichen. Eine Bank hat beschlossen, Konten für alle ihre Kunden in einer einzigen Datenbank und den Transaktionen zu konsolidieren Die Tabelle ist eine einzelne partitionierte Tabelle, die alle Transaktionen enthält, ebenso wie die Kunden Tabelle zur Speicherung aller Kunden der Bank. Die Bank ist in mehreren Ländern vertreten und expandiert ebenfalls. Jedes Land wird durch eine AffiliateID identifiziert Säule. Das Unternehmen ist so strukturiert, dass der Zugriff auf Schlüsseltabellen basierend auf dem Dienstalter beschränkt ist.

Sicherbare Elemente identifizieren

Wir müssen eine Sicherheitslösung auf Zeilenebene implementieren, die den Zugriff auf die Kunden- und Transaktionsdaten basierend auf Rollen und einer Sicherheitsrichtlinie auf Zeilenebene einschränkt. Unser erster Schritt besteht darin, die erforderlichen Tabellen zu erstellen. Listing 1 zeigt die DDL für die Schlüsseltabellen, die wir testen werden. Die gesamte für diesen Test verwendete Datenbank kann hier heruntergeladen werden.

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)

Wir erstellen dann eine Reihe von Tabellen, die wir verwenden können, um Mitarbeiter zu identifizieren. In diesem Setup hat jeder Mitarbeiter eine ScopeID die bestimmt, inwieweit er oder sie Daten einsehen oder manipulieren kann:

  1. National – Ein Mitarbeiter kann nur Daten im Land des Mitarbeiters (wo er oder sie arbeitet) manipulieren
  2. Regional – Ein Mitarbeiter kann nur Daten in seiner Region (z. B. Westafrika) manipulieren
  3. Weltweit – Ein Mitarbeiter kann Daten in jedem Land manipulieren, in dem die Bank jemals eine Filiale haben wird

Jeder Bereich wird den Mitarbeitern auf der Grundlage ihrer Bezeichnung zugewiesen. Der Geltungsbereich eines Gruppenmanagers ist Global , ist der Bereich eines Country Managers Regional und der Geltungsbereich einer Führungskraft ist National . Der traditionelle Weg, den Zugriff auf Daten einzuschränken, ist oft die Verwendung von Rollen und Berechtigungen. Das Zuweisen von Berechtigungen zu einer Rolle und das anschließende Zuweisen der Rolle zu einem Benutzer bedeutet, dass der Benutzer die mit dieser Rolle verbundenen Berechtigungen für den gesamten Datensatz in der betreffenden Tabelle hat. Die Sicherheit auf Zeilenebene gibt uns die Möglichkeit, etwas Granulareres zu tun:Beschränken Sie die SELECT/UPDATE/DELETE-Berechtigungen des Benutzers auf eine Teilmenge des Datensatzes in der Tabelle (feinkörnige Zugriffskontrolle).

Abb. 1. StaffScope und Staff Tables

Datenbankrollen und Benutzer

Listing 2 zeigt die Benutzer und Rollen, die wir erstellen müssen, um mit unserer Lösung fortzufahren. Die Idee ist, dass es eine Beziehung zwischen dem Personal gibt, wie es in den Benutzertabellen Staff und StaffScope gespeichert ist, und den Datenbankprinzipalen, die dieses Personal schließlich verwendet, um auf die Daten zuzugreifen. Beachten Sie die Spalte in Abb. 1 namens DBUserID . Diese Spalte wird mit der Funktion DATABASE_PRINCIPAL_ID gefüllt (siehe Listing 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;

Zusammenfassend haben wir bisher Folgendes getan:

  1. Erstellen/identifizieren Sie die Tabellen, die wir sichern müssen
  2. Erstellen Sie Tabellen, die die Kriterien angeben, die wir verwenden, um den Zugriff auf Daten auf Zeilenebene einzuschränken (Geltungsbereich)
  3. Erstellte Datenbankrollen und Benutzer, auf die wir Einschränkungen anwenden werden
  4. Eingeschränkter Zugriff auf die Kerntabellen („Sicherheit auf Tabellenebene“) mithilfe von Rollen und Berechtigungen

Vorhersagefunktion und Sicherheitsrichtlinie

Bisher haben wir das, was wir Tabellenebenensicherheit nennen könnten, mithilfe von Rollen und Berechtigungen implementiert. Jetzt wollen wir tiefer gehen. Wir möchten, dass zwei Prinzipale, die über SELECT-Berechtigungen für eine Tabelle verfügen, in der Lage sind, die Tabelle abzufragen, aber basierend auf den von uns eingerichteten Bedingungen unterschiedliche Datensätze sehen. Auflistung 3 zeigt uns, wie wir das erreichen.

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

Die Prädikatfunktion definiert die Bedingungen, die erfüllt sein müssen, damit ein Prinzipal eine Teilmenge der interessanten Daten sehen kann. In dieser Funktion gibt es drei Bedingungen:

  1. Der Datenbanknutzer des Personals ist Mitglied des National Rolle und die AffiliateID mit dem des Stabs OR übereinstimmt
  2. Der Datenbankbenutzer des Personals ist Mitglied der Regional Rolle und die AffiliateID stimmt mit der Liste von AffiliateID überein gehört zur westafrikanischen Region OR
  3. Der Datenbankbenutzer des Staffs ist ein Mitglied von Global

Dies impliziert, dass ein Mitglied der Global Rolle sieht alle Daten, einfach weil er oder sie zu dieser Rolle gehört. Mitglieder der anderen beiden Rollen müssen jedoch zusätzliche Kriterien erfüllen, die an die AffiliateIDs angrenzen .

Damit die Funktion nützlich ist, wenden Sie sie entweder als FILTER-Prädikate oder als BLOCK-Prädikate auf Tabellen an. FILTER-Prädikate schränken ein, was der Prinzipal sehen kann, während BLOCK-Prädikate sicherstellen, dass der Prinzipal keine Daten außerhalb der Daten manipulieren kann, die ihm/ihr durch die in der Funktion definierten Beschränkungen präsentiert werden. Eine Sicherheitsrichtlinie ist ein Container, in dem wir die Prädikate FILTER und BLOCK für alle Tabellen angeben, an denen wir interessiert sind. Sehen Sie sich Listing 3 an nochmal.

Ein sehr interessanter Aspekt dieses Ansatzes ist die Modularität. Wir können die Prädikate auf zusätzliche Tabellen in der Sicherheitsrichtlinie anwenden, ohne die vorhandenen definierten Tabellen zu beeinflussen, wir können neue Datenbankprinzipale (Mitarbeiter) hinzufügen, indem wir Datenbankbenutzer erstellen und ihnen die entsprechenden Rollen zuweisen. Wenn Mitarbeiterbewegungen stattfinden, können wir die Rollenzuweisungen aktualisieren und so weiter.

Testen der Implementierung

Jetzt, da wir fertig sind, können wir die Datenbankprinzipale imitieren, um festzustellen, ob wir die erwarteten Ergebnisse mit dem Code in Listing 4 haben. Bevor wir uns das ansehen, sehen wir uns die Rollen an, die den einzelnen Mitarbeitern und ihren Partnern in Abb. 2 zugeordnet sind.

Abb. 2. Personalliste

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

In der ersten Zeile frage ich die Kunden ab Tabelle als Systemadministrator, aber ich bekomme KEINE REIHEN. Das heißt, selbst ein Administrator kann die Auswirkungen von RLS nicht ohne Identitätswechsel außer Kraft setzen.

Abb. 4. SysAdmin sieht keine Zeilen

Barbara und Edward sind beide Führungskräfte und gehören dem nationalen Bereich an, aber sie arbeiten in verschiedenen Ländern, sodass sie die Kunden sehen, die mit ihren jeweiligen Tochtergesellschaften verbunden sind. (Siehe Mitarbeiternamen in Abb. 1).

Abb. 5. Führungskräfte sehen die Zeilen ihrer Partner

John und Margaret sind Länder- und Gruppenmanager. Sie gehören zur Regional und Global Bereiche bzw. John sieht Daten für Westafrika, während Margaret Daten für alle Regionen sieht.

Abb. 6. Manager sehen die Zeilen ihrer Region

Die Ergebnisse sind für alle anderen Tabellen, auf die die Sicherheitsrichtlinie angewendet wurde, dieselben. Beachten Sie das ohne Berechtigungen für die Transaktionen Tabelle, die Sicherheit auf Zeilenebene hat keinen Wert.

Abb. 7. Keine SELECT-Berechtigungen für Transaktionen Tabelle

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

Abb. 8. Transaktionen Tabelle aus Sicht der Führungskräfte

Fazit

Sicherheit auf Zeilenebene ist eine leistungsstarke Methode zur Nutzung der feinkörnigen Zugriffssteuerungsfunktion von SQL Server. Die Verwendung dieser Funktion erfordert, dass Sie SQL Server 2016 oder höher ausführen. Wie der Name schon sagt, besteht das Ziel darin, den Zugriff auf Zeilen innerhalb einer Tabelle mithilfe komplexer Abfragen einzuschränken, nachdem Sie sich um die „Sicherheit auf Tabellenebene“ gekümmert haben. Die Szenarien, in denen diese Funktion angewendet werden kann, sind endlos, daher ist sie für eine Vielzahl von Umgebungen sehr nützlich. Tun Sie gut, um zu erkunden und zu sehen, was es für Sie tun kann.

Referenzen

Isakov, V. (2018). Prüfung Nr. 70-764:Verwaltung einer SQL-Datenbankinfrastruktur . Pearson-Bildung

Sicherheit auf Zeilenebene