Row Level Security, Power BI modellerinde veriyi kullanıcının kim olduğuna göre maskelememizi sağlayan bir çeşit kullanıcı otorizasyon sistemidir. Bir sonraki topoloji yazı konusu “Object Level Security” ile birlikte, otorizasyon tarafında kullanabileceğimiz en temel yöntemlerden biri.
Yazı İçeriği
Bu yazıda statik diye tabir edilen Row Level Security yapısından bahsedeceğim.
RLS Nasıl Çalışıyor?
Row Level Security, ya da kısa adıyla RLS, satır bazlı filtreler oluşturduğumuzda, bu filtrelerin tablolar arasındaki ilişkiler üzerinden fact tablosunu filtrelemesiyle çalışır. Satır bazlı filtre diyerek neyi kastediyorum, açalım!
Veri modeli resimdeki gibi olan modelimizde “Ürün Kategorileri” tablosu var.
Ve bu tablonun satırlarında kategori isimleri var.
RLS’yi uygulamanın iki bacağı var: Önce Power BI Desktop tarafında ilgili modelde “roller” yaratırız. Modeli bulutta yayınladığımızda, ilgili dataset’in “security” ayarlarından yarattığımız bu rollere kullanıcıları ekleriz. Kullanıcıları tek tek email adresleriyle ekleyecebileceğimiz gibi Azure AD Security gruplarını da ekleyebiliriz. (Office 365 grupları olmaz! )
Rolleri nasıl yaratıyoruz?
Modelling tabından –> Manage Roles diyerek yeni bir rol yarattığımızda, model içerisindeki tüm tablolar ve bu tablolardaki tüm sütunlar listelenir. “Add Filter” diyerek istediğimiz herhangi bir sütunun satır değerleri üzerinden satır bazlı bir filtre yazabiliriz.
Ürün Kategorileri tablosundaki kategori sütununun satır değerlerini kullanarak -misal- her bir kategori için roller yaratabiliriz.
“Ev Aletleri” rolüne bulut tarafında eklediğimiz kullanıcılar raporu açtığında sadece ve sadece bu kategorinin satışlarını görür, diğer kategorileri görmez!
Yarattığımız satır bazlı filtre, ilişkilerin ok yönü boyunca fact tablosuna kadar akar ve tabloyu filtreler. (İlk resim)
Burada bir uyarıda bulunayım: Filtreye yazdığımız -misal- string değerlerde herhangi bir yazım yanlışı yaparsanız, role atadığınız kullanıcı hiçbir şey görmez! Modelde kategori sütununda “Ev Aletleri” var. Kazara “EvAletleri” yazmamalısınız!
Yarattığımız rolleri buluta basmadan önce desktop tarafında test edebiliriz. “View As” ‘den ilgili rolü seçmek yeterli.
Şu kişiler sadece bu rolü görsün, yönetim “tüm kategorileri görsün” demek ihtiyacımız varsa hiçbir filtrenin olmadığı bir rol daha yaratmak gerekiyor.
Herhangi bir role atanmamış bir kullanıcı bulutta bu raporu açmaya çalıştığında hata mesajı alır ve açamaz! Dolayısıyla erişmesini istediğimiz kullanıcıları mutlaka bir veya birden fazla role atamış olmamız lazım!
Kullanıcıları tek bir role’mi yoksa birden fazla role’mi atayalım, aradaki fark nedire geçmeden önce filtre olarak yazabileceğimiz DAX ifadelerine bakalım!
Ne tür filtreler yazabiliriz?
Tablolardaki sütunlara verebileceğimiz DAX ifadeleri, sonucu ancak TRUE/FALSE olan ifadeler olabilir. [Kategori]=”Ev Aletleri” gibi bir filtre, role atanmış bir kullanıcı için TRUE döner, atanmamış bir kullanıcı için FALSE döner.
Filtreleri yazarken &&-|| veya bunların karşılığı olan AND-OR operatörlerini kullanabiliriz. OR yerine IN operatörü kullanabiliriz.
Bu şekilde =, >,<= gibi eşitlik karşılaştıran ifadeler performans açısından genellikle tercih edilen ifadelerdir.
Fakat özellikle “string” araması yapmamızı sağlayacak CONTAINSSTRING veya LOOKUPVALUE gibi fonksiyonları filtre ifadesi olarak kullanırken performans sorunları yaşabilirsiniz!
Yukarıdaki örneğe göre, ürünler tablosundaki renk sütununda, içinde kırmızı kelimesi geçen ne kadar ürün varsa sadece bunların satışını gösterecek bir rol yarattık. Ürünler tablosu diyelim 10000 satırsa belki sorun olmaz, ama 1 milyon satırsa performansı kesinlikle olumsuz yönde tetikleyecektir. Hele ki böyle bir string arama işini bol satırlı bir fact tablosu üzerinde yapıyorsanız ciddi performans sorunu yaşayabilirsiniz!
Çoklu Filtre ve Çoklu Rol Durumu
Bir rol yaratırken farklı veya aynı tablodan gelen birden fazla sütuna filtre koyabiliriz. Yukarıdaki resimlere tekrar bakacak olursanız, “Ev Aletleri + Kameralar” rolünde hem “Tarih” hem de “Kategori” sütunları üzerinde filtre var.
Bir tanesi
[Kategori] IN {"Ev Aletleri" , "Kameralar" }
diyor, diğeri
[Tarih] < DATE(2009,07,28) && [Tarih] >= DATE(2007,01,10)
Bu tür durumlarda, sütunlar üzerindeki filtreler birbiriyle AND ile birleşir.
Yani kategorisi “ev aletleri” veya “kameralar” olacak VE 10.01.2007-28.07.2009 arasında satılmış olacak.
Bir başka durum, kullanıcıyı tek bir role mi yoksa birden fazla role mi atayalım sorusuyla ilgili! Teknik olarak bir kullanıcıyı birden fazla role atamak mümkün.
Bir kullanıcıyı birden fazla role atadığınızda, ilgili rollerdeki filtreler OR ile birleşir.
Örnek modele göre, bir kullanıcıyı hem “Ev Aletleri” hem de “Kameralar” rollerine atarsanız her iki kategorinin de satışlarını görür!
Best practice olarak, her bir kullanıcıyı sadece bir role atayacak şekilde RLS’yi tasarlamak daha iyi.
Row Level Security her zaman çalışır mı?
İçinde rollerin tanımlandığı bir modelde RLS her zaman çalışır mı? Hayır! Bazı durumlara dikkat etmek gerekiyor.
En önemlisi, RLS barındıran bir modelin yayınlandığı çalışma alanına davet ettiğiniz kullanıcıların yetkileri!
Çalışma alanına sadece “Viewer” olarak davet edilmiş kullanıcılar için RLS çalışır. Diğer yetkilere sahip kullanıcılar için, RLS rollerine atanmış olsalar bile RLS çalışmaz!
RLS, direct query ile oluşturulmuş modellerde de çalışır, ama composite modellerde ve many-to-many türü ilişki içeren modellerde yanlış sonuçlar üretebiliyor!
Raporu başka tenant’lardaki kullanıcılarla paylaşmak üzere “Publish to Web” yöntemini kullandıysanız RLS gene çalışmaz!
RLS ve Performans
Row Level Security raporların çalışma performansını nasıl etkiliyor? El cevap: Olumsuz yönde!
String araması yapmadığınız rollerde bile RLS her zaman için performansı olumsuz anlamda etkiler. Bu kullanmayın demek değil elbette, kesinlikle kullanılması gereken bir özellik. Eğer hali hazırda veri modeli düzgün tasarlanmış, metrikleri düzgün yazılmış, gayet iyi çalışan bir modeliniz varsa ve string arama gibi bir filtreyi fact tablonuz değil de boyut tabloları üzerinden yapıyorsanız aradaki farkı hissetmeyebilirsiniz bile!
Ama hali hazırda yavaş çalışan bir modele RLS eklerseniz, filtreleriniz biraz kompleks ise RLS durumu daha da kötü hale getirebilir. Bu durumda filtreleri rollerde yaratmak yerine Power Query tarafında oluşturup ayrı ayrı dataset’ler halinde yayınlamak daha makul bir çözüm olabilir.
Bu yazıda tariflediğim RLS örnekleri statik RLS olarak tanımlanıyor genelde. Roller yaratıyorsunuz, buluttan kullanıcıları rollere atıyorsunuz, statik bir yapı üretiyorsunuz.
Bir sonraki yazı, dinamik diye adlandırılan RLS yapısıyla ilgili olacak.
Yazıdaki modeli -bloga üyeyseniz- indirebilirsiniz.
Sadece üyeler görebilir. Hızlı üyelik için sosyal medya hesabınızla giriş yapabilirsiniz!