Un manager regional deschide raportul de vânzări și vede magazinele din toată țara. Două zile mai târziu, head of operations descoperă incidentul: nu trebuia să vadă decât regiunea lui. Cauza? Row Level Security Power BI configurat parțial, testat doar pe contul de developer al echipei BI. Asta nu e un incident rar — e una dintre cele mai frecvente surse de scurgeri de date interne în implementări de BI.
Setarea RLS corect nu e dificilă, dar e plină de detalii care fac diferența între o implementare care funcționează în producție și una care eșuează la prima audit.
Row-Level Security: Ce este RLS și ce nu este
Row-Level Security în Power BI restricționează ce rânduri vede fiecare utilizator în același raport. Nu modifică conținutul vizual (toți văd aceleași grafice, aceleași dashboard-uri), doar filtrează datele subiacente conform rolului fiecăruia.
Important: RLS NU oferă column-level security (ascunderea anumitor coloane). Nu blochează exporturile (un user cu acces la raport poate exporta datele filtrate ale lui). Și nu protejează împotriva utilizatorilor cu acces la fișierul .pbix original — RLS funcționează doar publicat în Power BI Service sau Premium.
RLS are două variante principale: static (rolurile sunt definite cu valori fixe) și dynamic (rolurile se atribuie automat în funcție de identitatea utilizatorului). Diferența între ele e adesea diferența între o implementare care scalează și una care devine coșmar de mentenanță.
Static RLS — pentru cazuri simple
Cel mai direct mod: definești roluri în Power BI Desktop, în meniul Modeling → Manage Roles.
Pentru un raport care trebuie consultat doar de două echipe — echipa Nord și echipa Sud — creezi două roluri:
- Rol „Nord” cu filtrul DAX:
[Region] = "Nord" - Rol „Sud” cu filtrul DAX:
[Region] = "Sud"
După publicare în Power BI Service, mapezi utilizatorii sau grupurile Azure AD la roluri în setările dataset-ului → Security. Utilizatorul A primește rolul Nord, utilizatorul B rolul Sud. Când deschid raportul, fiecare vede doar datele lui.
Asta funcționează perfect pentru companii sub 50 de utilizatori cu împărțiri simple. Devine însă insuportabil când ai 300 de utilizatori în 47 de magazine. 47 de roluri create manual, fiecare mapat la utilizatorii corecți, întreținut la fiecare angajare sau plecare? Acolo intervine dynamic RLS.
Dynamic RLS — modul scalabil
Logica e simplă: în loc să creezi un rol per grup, creezi un singur rol care folosește identitatea utilizatorului curent pentru a determina filtrul automat.
Funcția DAX cheie: USERPRINCIPALNAME(). Returnează adresa de email a utilizatorului autentificat în Power BI Service (exemplu: maria.popescu@compania.ro).
Pașii concreți:
1. Creezi un tabel de mapare care leagă fiecare utilizator de zona lui de responsabilitate. Coloane minime: UserEmail, Region (sau StoreID, Department — orice e cheia ta de filtrare).
2. Creezi relația între tabelul de mapare și tabelul de fapt (sales, orders etc.) prin coloana de filtrare (Region, StoreID).
3. Definești un singur rol în Modeling → Manage Roles, cu expresia DAX:
[UserEmail] = USERPRINCIPALNAME()
Aplicat pe tabelul de mapare.
4. Atribui acest rol tuturor utilizatorilor în Power BI Service, sau preferabil unui grup Azure AD care conține toți utilizatorii relevanți.
Rezultatul: când un user deschide raportul, filtrul caută în tabelul de mapare emailul lui, găsește regiunea atribuită, și propagă filtrul prin relație până la tabelul de fapt. Fiecare user vede doar datele lui, fără ca tu să fi creat 47 de roluri.
Două detalii care strică implementarea
Direcția de filtrare a relației. În tabelul de mapare, dacă relația cu fact table-ul e single-direction (de la mapare către fact), filtrul se propagă corect. Dar dacă lucrezi cu schemă mai complexă (snowflake, multiple fact tables), s-ar putea să fii nevoit să folosești bidirectional filtering, ceea ce introduce alte riscuri (ambiguități, performanță). Verifică-ți planul.
Performanță pe modele mari. Dynamic RLS evaluat la fiecare query e o operație care costă. Pe modele cu zeci de milioane de rânduri și utilizatori concurenți, RLS bine gândit (cu mapare curată, fără relații circulare) rulează acceptabil. RLS greșit poate transforma un query de 2 secunde în unul de 25.
Hierarchii și manageri
Cazul comun: un manager regional vede toate magazinele din regiunea lui. Un district manager vede toate regiunile din districtul lui. CEO vede tot.
Soluția: tabel de mapare cu ierarhie. Schema posibilă:
UserEmail|AccessLevel|Region|District- maria@x.ro | „Region” | „Nord” | NULL
- radu@x.ro | „District” | NULL | „Est”
- ceo@x.ro | „All” | NULL | NULL
Expresia DAX pentru rol devine puțin mai complexă:
VAR currentUser = USERPRINCIPALNAME()
VAR accessLevel = LOOKUPVALUE(UserAccess[AccessLevel], UserAccess[UserEmail], currentUser)
RETURN
SWITCH(
accessLevel,
"All", TRUE(),
"District", [District] = LOOKUPVALUE(UserAccess[District], UserAccess[UserEmail], currentUser),
"Region", [Region] = LOOKUPVALUE(UserAccess[Region], UserAccess[UserEmail], currentUser),
FALSE()
)
Logica: după nivelul de acces al userului, filtrul se aplică diferit. CEO vede tot (TRUE()). District manager vede doar districtul lui. Region manager doar regiunea. Orice altcineva — fallback la FALSE(), adică nu vede nimic.
Această abordare e folosită în implementări serioase. Funcționează curat, e mentenabilă (modificările se fac în tabelul de mapare, nu în model) și scalează.
Testarea — partea pe care 80% o sar
Cea mai frecventă cauză de incidente RLS în producție: testarea făcută doar cu contul de developer.
Power BI Desktop oferă un buton „View as” în Modeling. Permite să simulezi un rol, sau chiar mai bine, să simulezi un utilizator specific prin „Other user” cu un email. Este obligatoriu să testezi:
- Cu utilizatori reali din fiecare rol (Maria din Nord, Radu din Est, CEO)
- Cu un utilizator care NU e în tabelul de mapare (ar trebui să nu vadă nimic)
- Cu un utilizator care e mapat la zone multiple
- Cu cazul „administrator Power BI” — un user cu permisiuni elevate la nivel de tenant poate ocoli RLS?
După publicare în Service, testează prin „Test as role” în setările dataset-ului. Niciodată nu publica RLS nou fără să verifici cu cel puțin 3 utilizatori reali din persoane diferite din business.
Capcana administratorilor
Workspace admins, dataset owners și Power BI Service admins NU sunt automat afectați de RLS. Asta e by design — au nevoie să poată face debugging, să exporte pentru audit, să modifice. Dar e o capcană pentru implementări nepregătite: dacă „doamna de la marketing care e și owner pe workspace” vede tot, întreaga ta arhitectură RLS e ineficientă pentru rolul ei.
Practica sănătoasă: workspace-urile cu rapoarte sensibile au ca owner contul de service, nu o persoană fizică din business. Utilizatorii primesc acces ca Viewer sau Member, niciodată ca Admin pe workspace-uri cu RLS implementat.
Mentenanță și governance
RLS funcțional în producție cere disciplină organizațională, nu doar tehnică.
Cine actualizează tabelul de mapare? Când Maria pleacă din regiunea Nord și e promovată în districtul Est, cineva trebuie să schimbe înregistrarea. Dacă acel cineva e „echipa BI”, procesul e fragil — fiecare HR change devine ticket. Dacă tabelul se alimentează automat din HRIS (BambooHR, Workday, sistemul intern) printr-un dataflow, e mult mai robust.
Audit-ul accesului. Cel puțin trimestrial, verifică cine are acces la ce. Power BI Service permite export de audit log prin Microsoft 365 admin center. Trecerea în revistă a accesului scoate la lumină utilizatori care încă au acces după ce au plecat din companie, mapări duplicate, conturi de test uitate active.
Documentare. Schema RLS, logica filtrelor, cum se actualizează tabelul de mapare — toate trebuie documentate. Persoana care a construit modelul nu va fi mereu acolo. Documentația minimă: un fișier text în repo-ul Power BI cu schema, logica și procedura de adăugare/eliminare utilizator.
RLS pe Power BI Embedded și apps
Pentru scenarii unde Power BI e embedded într-o aplicație SaaS proprie, RLS funcționează prin service principal și token-uri cu identitate efectivă (EffectiveIdentity). Aplicația ta de SaaS trimite în token-ul de generare a raportului numele rolului și valorile filtrului pentru utilizatorul curent.
Asta înseamnă că pentru embed scenarios, contextul utilizatorului final nu vine de la Azure AD (acel user nu e în Power BI), ci de la backendul aplicației tale. Documentația Microsoft RLS în embedded intră în detalii. Pentru produse SaaS B2B în 2027, e un mecanism matur, dar cere atenție la implementare și testing.
Greșeli reale, frecvent întâlnite
Câteva pattern-uri de eșec observate în implementări reale:
1. Tabel de mapare cu valori învechite. Maria a plecat acum 6 luni, tabelul nu a fost actualizat, Maria a fost transferată în alt departament dar mai are acces la datele vechi. Soluția: automatizare.
2. „Default deny” lipsă. Un user care nu apare în tabelul de mapare vede toate datele — pentru că filtrul nu returnează nimic, iar absența unui filtru înseamnă „no filter applied”. Trebuie un fallback explicit care întoarce FALSE() pentru utilizatori necunoscuți.
3. Testat doar pe admin. Contul de dev / admin nu e afectat de RLS, totul pare să funcționeze, deployment-ul trece, primul user real raportează că vede date pe care nu trebuia.
4. Relații bidirectional lăsate active. Pe modele complexe, bidirectional filtering interacționează prost cu RLS. Filtrul se propagă prin căi neașteptate, iar useri văd date pe care logica intenționată nu le permitea.
5. Date sensibile în column tooltips. RLS filtrează rândurile, dar dacă ai pus o coloană sensibilă (de exemplu, salariul individual) într-un tooltip al unui visual general, ea poate fi vizibilă chiar și utilizatorilor restricționați la nivel de rând. Best practice: nu pune coloane sensibile în model, nici dacă crezi că nu le folosești în vizuale.
Alternative la RLS pentru cazuri specifice
Există situații în care RLS nu e cea mai bună unealtă:
- Scenarii cu sute de roluri foarte diferite. Mai bine să creezi rapoarte separate per audiență decât să încărci un model cu RLS labirintic.
- Separare completă, fără overlap. Două echipe care nu trebuie să afle nimic despre cealaltă — workspace-uri complet separate cu rapoarte separate sunt mai sigure decât RLS pe același raport.
- Cerințe legale stricte. Pentru GDPR sau cerințe sectoriale (financiar, medical), separarea fizică a datelor poate fi cerută explicit. RLS, oricât de bun, rămâne o restricție la nivel de prezentare — datele sunt fizic acolo, în model.
Tema se leagă natural de discuția despre Power BI vs Tableau, unde am intrat în detaliu pe pattern-urile pe care le observăm în piață. În fond, Row-Level Security nu e doar un concept tehnic — este o decizie de business cu impact direct pe productivitatea echipei.
În rezumat
RLS în Power BI e un instrument bine pus la punct în 2027, după mai bine de un deceniu de utilizare. Funcționează curat dacă respecți câteva principii:
- Folosește dynamic RLS, nu static, dincolo de cazurile foarte simple
- Construiește un tabel de mapare alimentat automat din sursa de adevăr (HRIS, sistem intern)
- Include un default deny pentru utilizatori necunoscuți
- Testează cu utilizatori reali, nu doar pe contul de admin
- Documentează schema și procedura de modificare
- Audit trimestrial, ownership pe service account, nu pe persoană
Diferența dintre o implementare „demo” și una „producție” e exact aici — în detaliile pe care 12 minute de tutorial pe YouTube nu le acoperă. Pentru o companie care tratează datele cu seriozitate, RLS bine construit e diferența între autonomie a echipelor și incident de audit.
În practică, Row-Level Security a trecut de la subiect de roadmap la prioritate operațională pentru echipele care livrează rezultate de business — exact tipul de tracțiune pe care o vedem reflectată în deciziile reale de buget. Pentru cititorii care lucrează zilnic cu Row-Level Security, articolul rămâne deschis pentru update-uri pe măsură ce piața evoluează.
Întrebări frecvente
Ce face și ce nu face Row-Level Security?
Restricționează ce RÂNDURI vede fiecare utilizator în același raport. Nu oferă însă securitate la nivel de coloană — ascunderea anumitor coloane e o problemă diferită, pe care RLS nu o rezolvă.
Care e diferența dintre RLS static și dinamic?
La cel static definești roluri cu valori fixe — un rol „Nord” cu filtrul [Region] = „Nord”, un rol „Sud” cu [Region] = „Sud” — și mapezi utilizatorii sau grupurile Azure AD la roluri după publicare. Funcționează pentru companii sub 50 de utilizatori cu împărțiri simple. Cel dinamic folosește un singur rol care determină filtrul din identitatea utilizatorului curent.
Cum se face RLS dinamic?
Cu funcția DAX USERPRINCIPALNAME(), aplicată pe un tabel de mapare între emailuri și regiuni: filtrul [UserEmail] = USERPRINCIPALNAME(). Când utilizatorul deschide raportul, filtrul îi caută emailul în tabelul de mapare, găsește regiunea atribuită și o propagă prin relație până la tabelul de fapte. Două detalii strică implementarea: direcția de filtrare a relației și performanța pe modele mari.

