POWER BI ROW LEVEL SECURITY

Yaygın bir yanlış var: "RLS sadece tabloya filtre koymak demek." Bu cümle, Row-Level Security'yi anlamamış pek çok ekibin başına iş açıyor. RLS aslında bir filtre değil — Power BI semantic model üzerinde çalışan, DAX ile yazılmış bir role expression'dır. Bu ifade her sorgu çalıştığında değerlendirilir, kullanıcının kim olduğuna göre yeniden hesaplanır ve modeldeki tüm ilişkili tablolara çapraz filtre olarak yayılır. Dolayısıyla "bir kolona WHERE koymak" ile RLS arasındaki fark, basit bir SQL filtresi ile dinamik yetkilendirme katmanı arasındaki fark kadar büyüktür.
1. RLS Neden "Sadece Filtre" Değildir?
Bir Power BI raporunda kullanıcı bazlı erişim kontrolü kurmaya çalıştığınızda, ilk akla gelen yaklaşım genellikle şudur: "Slicer'a kullanıcı ismini koyalım, kendi verisini görsün." Bu güvenlik değil, görsel filtredir. URL'yi değiştiren, raporu Desktop'ta açan ya da DAX studio ile sorgulayan herhangi biri tüm veriyi görür. RLS ise farklıdır:
- Semantic model katmanında çalışır — görsel katmanın altındadır
- Sorgu motoruna (VertiPaq/DirectQuery) gömülür, bypass edilemez
- Tek yönlü ilişkiler üzerinden cross-filter olarak yayılır
- Hem import hem DirectQuery modellerde çalışır
- Workspace Viewer rolüne sahip kullanıcılar bile kuralı atlatamaz
Yani RLS, "kullanıcı X şu satırları görür" cümlesinin DAX ile yazılmış, sorgu sırasında değerlendirilen ve modelin tüm ilişki grafiğine yayılan bir ifadesidir. Power BI üzerinde daha güçlü bir temele sahip olmak için Power BI eğitimi içeriğinden yararlanabilirsiniz.
2. DAX Role Expression: RLS'nin Kalbi
Bir rol oluşturduğunuzda, Power BI Desktop'ta "Manage Roles" ekranında her tablo için bir DAX ifadesi yazarsınız. Bu ifade boolean dönmek zorundadır — TRUE dönen satırlar görünür, FALSE dönenler gizlenir.
En basit haliyle statik bir rol şöyle yazılır:
[Region] = "Marmara"→ Sadece Marmara bölgesini gören rol[Department] IN {"Finance", "HR"}→ İki departmanı birden gören rol[Year] >= 2024→ Sadece son iki yılın verisi
Bu statik yaklaşımın sorunu açık: her bölge için ayrı bir rol oluşturmak, 40 bölgeli bir şirkette 40 rol yönetmek demektir. İşte burada dynamic RLS devreye girer.

3. Dynamic RLS: Tek Rol, Binlerce Kullanıcı
Dynamic RLS'in temel fikri şudur: rolün içine kullanıcının kimliğini sabit yazmak yerine, çalışma anında o kullanıcının kim olduğunu öğreniriz ve bu kimliği veriyle eşleştirmek için bir user-permission tablosu kullanırız.
Tipik mimari şu üç bileşenden oluşur:
- UserAccess tablosu: Kullanıcının e-postası ve erişebileceği bölge/departman/müşteri eşleşmesi
- İlişki: UserAccess[Region] ile Sales[Region] tablosu arasında tek yönlü ilişki
- DAX rolü: UserAccess tablosuna kullanıcıyı filtreleyen ifade
Rol ifadesi tek satırla biten bir şey değildir — modelin ilişki grafiği boyunca cross-filter yayılır. Yani UserAccess tablosuna yazdığınız bir filtre, oradan Region tablosuna, oradan Sales tablosuna otomatik akar. Bu da modelleme disiplini gerektirir: ilişkilerin yönü, kardinalitesi ve "ambiguous path" hataları RLS davranışını doğrudan etkiler.
4. USERPRINCIPALNAME Kapsamı
Dynamic RLS'in temel fonksiyonu USERPRINCIPALNAME()'dir. Bu fonksiyon, raporu çalıştıran kullanıcının Microsoft Entra ID (eski Azure AD) e-posta adresini döner. Tipik kullanım:
[UserEmail] = USERPRINCIPALNAME()
Burada kritik bir nokta var: bu fonksiyon yalnızca Power BI Service'te bir kullanıcı bağlamında çalıştığında doğru değer döner. Bilmesi gereken farklar:
- Power BI Desktop'ta: "View as role" ile test ederken manuel e-posta girmeniz gerekir
- Power BI Service'te: Otomatik olarak giriş yapan kullanıcının UPN'ini döner
- Embedded senaryolarda: EffectiveIdentity parametresiyle override edilebilir
- Service Principal'lar için: UPN dönmez — bu durumlar için CUSTOMDATA() düşünülmelidir
- Büyük/küçük harf: UPN karşılaştırması case-insensitive değildir; UPPER() veya LOWER() ile normalize etmek best practice
Bir diğer fonksiyon olan USERNAME() on-premise senaryolarda DOMAIN\user formatı döner; bulut senaryolarında ise USERPRINCIPALNAME ile aynı sonucu verir. Karışıklığı önlemek için bulut tabanlı projelerde her zaman USERPRINCIPALNAME tercih edilmelidir.
5. Hiyerarşik RLS: Yönetici Kendi Ekibini Görsün
Gerçek hayat senaryoları nadiren "kullanıcı = bölge" kadar düzdür. Yönetici, kendi ekibini ve ekibinin altındaki tüm seviyeleri görmek ister. Bu, RLS'de parent-child hierarchy ile çözülür.
PATH(), PATHCONTAINS() ve LOOKUPVALUE() fonksiyonları burada birlikte kullanılır. Örneğin bir Employee tablosunda her çalışanın ManagerID'si varsa, PATH ile her çalışan için kök yöneticiye giden hiyerarşik yol üretilir. Sonra PATHCONTAINS ile o yolda raporu açan kişinin olup olmadığı kontrol edilir. Bu, ROW LEVEL'in nasıl ORGANIZATION LEVEL'a evrildiğinin klasik örneğidir.
6. RLS Test Etmek ve Yaygın Hatalar
RLS, "yazdım, herhalde çalışır" denilebilecek bir özellik değildir. Power BI Desktop'ın "View as Roles" özelliği ile her rol için manuel test yapılmalıdır. Service'te ise rolün üyelerini ayarladıktan sonra "Test as role" seçeneği vardır. Konfigürasyon adımları ve rol yönetim senaryoları için resmi dokümantasyona başvurmak yaygın tuzakları görmenize de yardımcı olur.
Yaygın hatalar şunlardır:
- İlişkilerin both direction olması — RLS'i beklenmedik tablolara yayar
- UserAccess tablosunun model dışından (ör. Excel) gelmesi ve refresh sırasında kırılması
- USERPRINCIPALNAME'in Desktop'ta test edilirken e-posta yerine kullanıcı adı sanılması
- Rolün workspace düzeyinde değil, semantic model düzeyinde atanması gerektiğinin unutulması
- Object-level security (OLS) ile RLS'in karıştırılması — OLS sütun gizler, RLS satır filtreler
- Aggregation tabloları kullanılan modellerde RLS'in agregat tablolara da yayılmasının atlanması

7. RLS Performansı: Sessiz Maliyet
DAX role expression, her sorguda değerlendirilir. Yani basit bir [Region] = "X" dahi her görsel için sorgu planına eklenir. Karmaşık dynamic RLS'lerde, özellikle PATH/PATHCONTAINS gibi text işlemlerinde performans düşüşü gözlemlenebilir.
Performansı korumak için:
- UserAccess tablosunu mümkün olduğunca dar tutun (gereksiz sütun bulundurmayın)
- İlişki kardinalitesini doğru ayarlayın — many-to-many ilişkiler RLS davranışını yavaşlatır
- LOOKUPVALUE yerine ilişki + RELATED kullanmayı tercih edin
- RLS'i test ederken DAX Studio ile sorgu sürelerini ölçün
Detaylı DAX yapılarını ve modelleme tekniklerini daha derinlemesine kavramak isteyenler, Power BI eğitimi kapsamındaki konuları inceleyebilir.
8. RLS Ne Değildir?
Kapatmadan önce bir kez daha vurgulamak gerekirse: RLS, kullanıcının hangi satırları göreceğini belirler. Hangi sütunları göreceğini değil (bu OLS'tir). Hangi raporu açabileceğini değil (bu workspace izinleridir). Hangi semantic model'a bağlanabileceğini değil (bu build izinleridir). Bu katmanlar birbirini tamamlar; biri diğerinin yerine geçmez. RLS'i "filtre" diye düşünmeyi bıraktığınız an, onu bir yetkilendirme katmanı olarak doğru tasarlamaya başlarsınız.
Sıkça Sorulan Sorular
RLS'i Power BI Desktop'ta nasıl test ederim?
Modeling sekmesinde 'Manage Roles' ile rolleri tanımladıktan sonra, 'View as' butonuna tıklayıp ilgili rolü seçersiniz. Dynamic RLS test ederken 'Other user' kutusuna gerçek bir UPN (e-posta) yazmanız gerekir; aksi halde USERPRINCIPALNAME() boş döner ve filtre hiç eşleşmediği için kullanıcı veri göremez.
USERPRINCIPALNAME ile USERNAME arasındaki fark nedir?
Power BI Service'te ikisi de aynı UPN'i döner. Ancak on-premise Analysis Services veya gateway senaryolarında USERNAME, 'DOMAIN\user' formatı döner. Bulut tabanlı projelerde tutarlılık için her zaman USERPRINCIPALNAME tercih edilmelidir, böylece e-posta tabanlı UserAccess tabloları sorunsuz eşleşir.
Aynı kullanıcı birden fazla role atanırsa ne olur?
Power BI rolleri OR mantığı ile birleştirir. Yani kullanıcı hem 'Marmara' hem 'Ege' rolüne atandıysa her iki bölgenin verisini görür. Bu, esneklik sağlar ama dikkatli yönetilmezse beklenmedik geniş erişimlere yol açabilir; rol birleşimini production'a almadan önce mutlaka test edin.
Dynamic RLS'de UserAccess tablosu nereden gelmelidir?
İdeal olan, bu tabloyu kurumsal kimlik kaynağından (Entra ID, HR sistemi, SQL view) beslemek ve schedule refresh ile güncel tutmaktır. Excel dosyalarıyla başlanan projeler hızla yönetilemez hale gelir. UserAccess tablosu küçük, normalize ve sadece UPN + erişim anahtarı sütunlarını içermelidir.
RLS DirectQuery modellerde de çalışır mı?
Evet, RLS hem import hem DirectQuery modellerde çalışır. DirectQuery'de DAX role expression, kaynak sisteme gönderilen SQL sorgusuna WHERE koşulu olarak eklenir. Ancak USERPRINCIPALNAME gibi fonksiyonların değeri Power BI tarafında çözülüp parametre olarak gönderilir, performans bu nedenle kaynak veritabanının indeksleme stratejisine bağlıdır.
Rapor yayıncısı (publisher) RLS'den etkilenir mi?
Hayır. Semantic model sahibi ve workspace admin'leri RLS kurallarından muaftır; tüm veriyi görür. Bu davranış geliştirme için pratiktir ama production'da raporu sahibine değil, RLS rolüne dahil edilmiş test kullanıcısına açıp doğrulamak gerekir. Aksi halde 'bende çalışıyor' tuzağına düşülür.
RLS ile Object-Level Security (OLS) arasındaki fark nedir?
RLS satırları gizler — kullanıcı belirli bir bölgenin satışını görmez. OLS ise sütunu veya tabloyu tamamen gizler — kullanıcı 'Maaş' kolonunun var olduğunu bile bilmez. İkisi birlikte kullanılabilir: örneğin İK raporunda bölge bazlı satır filtresi (RLS) + maaş kolonunun belirli rollerden saklanması (OLS) tipik bir kombinasyondur.
RLS workspace seviyesinde mi yoksa semantic model seviyesinde mi atanır?
Roller semantic model üzerinde tanımlanır, üyeler ise Power BI Service'te o modelin 'Security' menüsünden eklenir. Workspace rolü (Viewer, Contributor) farklı bir yetki katmanıdır ve RLS'i bypass etmez; ancak Admin/Member rolündeki kullanıcılar RLS kurallarından muaftır, bu nedenle hassas raporlarda son kullanıcılar mutlaka Viewer rolünde tutulmalıdır.


