SQL SERVER 2016 RLS ( Row-Level Security )

Güvenlik veritabanı için en önemli adımlardan bir tanesidir. Şirketler kendi verilerinin erişilmesinde içerideki Development vb. Görevlere sahip arkadaşların bile belirli yetki protokelleri üzerinden olmasını ister. SQL Server da DB bazlı, Tablo bazlı , obje ve hatta kolon bazlı bile yetkilendirmeler gerçekleştirmektedir.

Fakat bazen satır (Row) bazlı yetkilendirmelere de ihtiyaç duyulmaktadır. İşte tam bu noktasa SQL Server , 2016 sürümü ile duyurduğu yeniliği olan Row-Level Security (RLS) özelliği ile artık kullanıcılar sadece kendisini ilgilendiren kayıtları görebilecekler.

Örneğin , firmamızın sipariş ağı var ve tedarikçilerimizden elemanlarımız siparişler sisteme girmekte . Bu sipariş verilerimizi sipariş tablomuzda tutmaktayız. Fakat herkesin kendi siparişini görmesini istiyoruz. Yani elemanlar girdikleri siparişlerin takibini yapabilsinler sadece.

Şimdi bu örneğimizi uygulamalı olarak gerçekleştirelim ;

  • Test Veritabanımızı oluşturuyoruz.
CREATE DATABASE SQLTR_ROWLevel
GO
  • Daha sonra sisteme veri girecek elemanlarımızı tanımlıyoruz. Yani DB üzerinde user oluşturuyoruz.
USE SQLTR_ROWLevel
GO
CREATE USER yusufkahveci WITHOUT LOGIN
CREATE USER keremk WITHOUT LOGIN
CREATE USER serkanh WITHOUT LOGIN
CREATE USER serkanb WITHOUT LOGIN
  • Bu işlemlerin ardından Sipariş tablomuzu oluşturup , içerisine de sipariş datalarını yükleyelim.
CREATE TABLE dbo.Siparis
(
Tedarikci_No int,
Tedarikci_Kodu varchar(100),
Siparis_Tarih datetime,
Siparis_Miktar int,
Siparis_Sahibi Varchar(100)
)           
Insert into dbo.Siparis values(10,'XYZ Tic','2015-12-01 00:10:00:090',13400,'yusufkahveci')
Insert into dbo.Siparis values(11,'MNO Tic','2014-01-08 19:44:51:090',610,'serkanh')
Insert into dbo.Siparis values(12,'ZJK Tic','2015-08-19 19:44:51:090',200,'serkanh')
Insert into dbo.Siparis values(13,'LMK Tic','2014-08-19 19:44:51:090',1049,'keremk')
Insert into dbo.Siparis values(14,'AAL Tic','2014-08-04 19:44:51:090',313,'yusufkahveci')
Insert into dbo.Siparis values(15,'ZZZ Tic','2015-08-10 19:44:51:090',787,'yusufkahveci')
Insert into dbo.Siparis values(16,'VFF Tic','2015-04-17 19:44:51:090',9999,'yusufkahveci')
Insert into dbo.Siparis values(17,'ALK Tic','2015-08-21 19:44:51:090',354,'yusufkahveci')
Insert into dbo.Siparis values(18,'ZUZ Tic','2015-08-06 19:44:51:090',244,'yusufkahveci')
Insert into dbo.Siparis values(19,'VFF Tic','2015-08-26 19:44:51:090',18,'serkanb')
  • Çalışanlarımıza tablo üzerinde sipariş takiplerini yapmaları için SELECT yetkisi verdik.
GRANT SELECT ON dbo.Siparis TO yusufkahveci
GRANT SELECT ON dbo.Siparis TO keremk
GRANT SELECT ON dbo.Siparis TO serkanh
GRANT SELECT ON dbo.Siparis TO serkanb
  • Daha sonra elemanlarımızın sipariş takibi yapması için bağlantıyı gerçekleştiriyor ve tabloya SELECT yapıyoruz.
EXECUTE AS USER = 'yusufkahveci'
SELECT * FROM Siparis;
REVERT

Yukarıda ki işelmden sonra yusufkahveci adlı elemanız aşağıda ki sonuçları görmektedir.

RowLevelSecurity_1

Fakat görüldüğü üzere yusufkahveci adlı çalışanımız diğer çalışanlarında sipariş süreçlerini görmektedir. İşte tam bu durumda SQL Server 2016 ile hayatımıza gire RLS yani Row-Level Security özelliği devreye girmektedir.

Bu özelliği kullanabilmek için ilk adım olarak kullanıcı sorgu çalıştırdığında True değeri dönen InLine Table Value Function oluşturalım.

CREATE FUNCTION dbo.fn_RLS (@UName as sysname)
RETURNS TABLE
WITH SCHEMABINDING
AS
RETURN SELECT 1 AS fn_RLS_result
WHERE @UName = USER_NAME()
GO

Bu işlemden sonra oluşturduğumuz fonksiyonumuzu oluşturacak olduğumuz POLICY için Filter Predicate olarak ekleyelim.

CREATE SECURITY POLICY fn_SecurityFilter
ADD FILTER PREDICATE dbo.fn_RLS(Siparis_Sahibi)
ON dbo.Siparis
WITH (STATE = ON);
GO

Function ve Policy blok unu inceleyecek olur isek ; gördüğünüz üzere fonksiyonumuz parametre olarak kullanıcı adı alıyor ve geriye True ve NULL değer leri döndürüyor. POLICY bölümümüzde ise PRADICATE bölümünde oluşturduğumuz fn_RLS adında ki Function ‘ımız tablomuz üzerinde sorgu çalıştırıldığında otomatik olarak Filtrelemek için kullanılacağını ve hangi tablo üzerinde işlemi gerçekleştireceğini belirtmiş oluyoruz.

Aynı şekilde tekrar yusufkahveci kullanıcımız ile sipariş tablomuzu sorgulayalım.

EXECUTE AS USER = 'yusufkahveci'
SELECT * FROM Siparis;
REVERT

Gördüğünüz üzere sadece yusufkahveci ‘ye ait kayıtlar gelmektedir.

RowLevelSecurity_2_SQLTRR

Örneğimizde RLS’i uygulamalı olarak sizlere aktarmış olduk. Bu özellik ile biz sorgularımıza bir parametre eklemesek de arka planda kullanıcı adını parametre olarak eklemektedir. Bu bölümde dikkat edilmesi gereken nokta ise SQL bu parametreyi eklerken performans sorunu oluşturabilir. Aşağıda Execution Plans for RLS bölümümüzde detaylı değineceğiz.

Execution Plans For RLS makalemiz yakında.

 

Leave a Reply

Your email address will not be published. Required fields are marked *