DAX row-level security – zabezpečenie dát v reportoch na úrovni riadkov pomocou jazyka DAX

Mnohokrát musíte riešiť zabezpečenie nielen samotných reportov Power BI, ale aj dát uložených v nich. Najmä v korporátnom prostredí je dosť častá požiadavka, aby užívateľ nevidel v reporte všetky dáta, ale iba tie dáta, ku ktorým má mať prístup. S touto požiadavkou nám vie pomôcť funkcionalita nazvaná „DAX row-level security“, čiže zabezpečenie dát na úrovni riadkov pomocou jazyka DAX.

Nie vždy je dobrý nápad dávať užívateľom prístup ku všetkým dátam. Niekedy je v tom obchodné hľadisko (nechcete, aby všetci zamestnanci mali prehľad o interných obchodných ukazovateľoch), inokedy právne hľadisko (GDPR, GPSR, a pod.), a niekedy aj pracovné vzťahy medzi zamestnancami (nechcete, aby obchodník X videl predaje a provízie obchodníka Y, aby nevznikali zbytočné hádky a emócie na pracovisku). Neznalí užívatelia Power BI implementujú túto funkcionalitu tak, že vytvoria samostatný report Power BI pre každého užívateľa, kde každý report je odfiltrovaný iba na dáta daného užívateľa. Tento prístup je však z dlhodobého hľadiska vstupenkou na psychiatriu. Zažil som ľudí, ktorí takto spravili 20 reportov pre 20 užívateľov. Keď sa potom mala robiť v reportoch nejaká zmena, tak ju bolo potrebné zopakovať vo všetkých 20 reportoch, následne otestovať a nasadiť všetkých 20 reportov, a popri tom sa nezblázniť. Pritom už dávno na to existuje elegantné riešenie.

Privítajte DAX row-level security

V Power BI, SSAS Tabulare a Azure Analysis Services je už takmer od ich prvých verzií dostupná funkcionalita s názvom „DAX row-level security“, čiže zabezpečenie dát na úrovni riadkov pomocou jazyka DAX. Je to funkcionalita dátového modelu. Táto funkcionalita vám umožňuje načítať do dátového modelu všetky dáta, ale zobraziť užívateľom iba tie dáta, pre ktoré majú oprávnenie.

Typický príklad je, že vytvoríte report pre všetkých zamestnancov, ale každý zamestnanec v ňom uvidí iba „svoje“ dáta (napr. jemu priradené objednávky, požiadavky, reklamácie, zákazníkov, a pod.). Takto máte iba jeden centrálny dátový model, v ktorom sú všetky dáta, ale každý v ňom vidí iba tie dáta, ku ktorým má mať prístup. Zmeny do dátového modelu potom stačí robiť na 1 mieste, a nie v 20 reportoch.

Vzorové dáta

Ukážku toho, ako nastaviť DAX row-level security, si ukážeme na nasledujúcich dátach. Majme v dátovom modeli takéto 2 tabuľky, ktoré nazveme „Objednavky“ a „Zamestnanci“:

V prvej z nich sú objednávky, ktoré sa odkazujú cez stĺpec „zamestnanec_id“ na rovnaký stĺpec v druhej tabuľke. Cez tieto stĺpce sú tabuľky aj prepojené. A tu by sme chceli nastaviť to, že keď si daný zamestnanec otvorí report s takýmito dátami, tak nech v ňom vidí iba svoje dáta.

Na začiatok si v reporte vytvoríme jednoduchú kontingenčku, kde zobrazíme sumu objednávok pre každého zamestnanca:

  1. do oblasti riadkov dáme stĺpec „meno“ z tabuľky „Zamestnanci“,
  2. do oblasti hodnôt dáme stĺpec „cena_bez_dph“ z tabuľky „Objednavky“.

Výsledná kontingenčka bude vyzerať takto:

Ako nastaviť DAX row-level security

Funkcionalita DAX row-level security sa nastavuje na dvoch miestach:

  1. v Power BI Desktope (alebo inom editore dátového modelu, napr. vo Visual Studiu), kde vytvoríme a nastavíme role zabezpečenia,
  2. na serveri (cloud Power BI, Power BI Report Server, server SSAS Tabular či AAS), kde nastavíme členstvo v roliach zabezpečenia.

Role zabezpečenia a ich nastavenie

Prvým krokom je vytvoriť role zabezpečenia. Role zabezpečenia sú pravidlá, ktoré určujú, ku ktorým riadkom v dátovom modeli sa dostanú budúci členovia danej role. Tieto pravidlá sa zadávajú pomocou filtrov jazyka DAX. Funguje to tak, že tam zvyčajne zadávate filtrovacie podmienky, vo formáte napr. „tabulka[stlpec] = hodnota“. Pre každú tabuľku môžete zadať síce iba 1 filtrovaciu podmienku, ale môže byť ľubovoľne komplexná, a vo väčšine prípadov môžete používať všetky funkcie a funkcionality z jazyka DAX. Členovia tejto role potom uvidia v tej tabuľke len tie riadky, ktoré spĺňajú túto podmienku. Nemusia to však vždy byť iba podmienky. Z technického hľadiska tam môžete zadať ľubovoľný vzorec. Funguje to potom tak, že ten vzorec sa vyhodnotí pre všetky riadky danej tabuľky, a členovia role uvidia iba tie riadky, pre ktoré vzorec vrátil hodnotu TRUE (čiže pravdu).

V Power BI Desktope sa k roliam zabezpečenia dostanete tak, že kliknete v hlavnom menu na záložku „Modelovanie“, a tam na tlačidlo „Spravovanie rol“:

DAX row-level security - ako sa dostať do Editora rolí

Otvorí sa okno s názvom „Správa rol zabezpečenia“, skrátene Editora rolí, kde na ľavej strane sa vytvárajú jednotlivé role zabezpečenia, a na pravej strane sa upravujú nastavenia vybranej role:

DAX row-level security - Editor rolí

Poznámka: vo verziách Power BI Desktopu pred polovicou roka 2024 sa nachádza staršia verzia tohto Editora, ktorá vyzerá mierne odlišne. Vo Visual Studiu vyzerá tento Editor úplne inak. Vo všetkých prípadoch však majú úplne identickú funkcionalitu, pričom vo Visual Studiu sú aj ďalšie možnosti, ktoré Power BI síce interne podporuje, ale nezobrazuje ich.

Začneme teda tým, že klikneme na tlačidlo „Nový“:

…čo nám vytvorí novú rolu s názvom „Bez názvu“. Poklikáme na jej názov 2x, aby sme ju premenovali, a zadáme ako nový názov tej role názov „Kazdy vidi iba svoje data“:

Napravo od tohto názvu sa nám zobrazí zoznam všetkých tabuliek v dátovom modeli, v stĺpci nazvanom „Vybrať tabuľky“. Kliknutím na názov konkrétnej tabuľky sa zobrazia filtre zabezpečenia nastavené pre túto tabuľku:

DAX row-level security - role zabezpečenia

Tento Editor je však len zjednodušeným editorom pre začiatočníkov, ktorí chcú jednoduchým spôsobom naklikať veľmi jednoduché, statické podmienky. V bežných prípadoch však potrebujete používať aj funkcie jazyka DAX, aby ste ľahko implementovali aj komplexné scenáre. Prepneme si teda tento Editor do režimu písania vzorcov v jazyku DAX, kliknutím na tlačidlo „Prepnúť na editor DAX“. Pravá časť Editora sa zmení na jednoduchý box, kde vieme zadať ľubovoľný vzorec v jazyku DAX:

My prejdeme na tabuľku „Zamestnanci“, a nastavíme k nej takúto filtrovaciu podmienku:

Zamestnanci[email] = USERPRINCIPALNAME()

Po zadaní vzorca nám Editor rolí bude zobrazovať ikonku lievika vedľa tabuľky „Zamestnanci“, indikujúc že na tejto tabuľke je nastavený filter zabezpečenia:

DAX row-level security - DAX podmienky pre filtre zabezpečenia

V tomto vzorci sme použili funkciu USERPRINCIPALNAME, ktorá vracia prihlasovacie meno užívateľa, ktorý si práve prezerá report Power BI, resp. ktorý je práve pripojený k dátovému modelu SSAS Tabularu. Prihlasovacie meno vracia zvyčajne vo formáte e-mailovej adresy užívateľa, čo sa v Active Directory technicky nazýva „user principal name“. Od toho je aj pomenovaná táto funkcia. Použitie takejto podmienky spôsobí, že sa viditeľné riadky v tejto tabuľke odfiltrujú len na ten riadok, kde e-mail zamestnanca je rovný prihlasovaciemu menu aktuálne prihláseného užívateľa. Takže ak je tento užívateľ v tejto tabuľke, tak tam uvidí iba „svoj“ riadok.

Poznámka: filtre zabezpečenia sa nedajú zrušiť pomocou funkcií jazyka DAX, ako napr. ALL alebo ALLEXCEPT. Čiže užívatelia to nevedia obísť pomocou vzorcov v jazyku DAX. Dátový model sa navonok tvári, ako keby v ňom boli iba dáta pre toho užívateľa. Samotná funkcionalita DAX row-level security je potom implementovaná v tzv. Formula Engine, ktorý do každého dotazu DAX ako keby pridal ako filtre všetky podmienky, ktoré ste uviedli v roliach zabezpečenia pre daného užívateľa.

Následne by sme potrebovali zabezpečiť aj druhú tabuľku – tabuľku „Objednavky“ – tak, aby užívateľ v nej videl iba svoje objednávky. Tu by nás mohlo napadnúť použiť napr. takýto vzorec:

RELATED(Zamestnanci[email]) = USERPRINCIPALNAME()

Čiže nech užívateľ vidí iba tie objednávky, kde hodnota v príslušnom riadku v tabuľke „Zamestnanci“ v stĺpci „email“ je prihlasovacie meno aktuálne prihláseného užívateľa. Táto podmienka bude fungovať, ale je ju zbytočné zadávať. Obe tabuľky sú totižto prepojené, a smer prúdenia filtrov (šípka na prepojení) je nastavený z tabuľky „Zamestnanci“ do tabuľky „Objednavky“:

Tento smer prúdenia filtrov funguje rovnako pre klasické filtre jazyka DAX pri výpočtoch, aj pre filtre zabezpečenia vo funkcionalite DAX row-level security. Ak totižto nastavíme filter zabezpečenia na jednej tabuľke, tak sa tento filter aplikuje v smere šípky na prepojení aj na prepojenú tabuľku, a automaticky tam vyfiltruje príslušné riadky. Čiže v našom prípade, keď nastavíme filter na tabuľke „Zamestnanci“ na aktuálne prihláseného užívateľa, tak tento filter okrem tabuľky „Zamestnanci“ automaticky vyfiltruje aj riadky v tabuľke „Objednavky“, ktorú odfiltruje len na príslušné riadky k viditeľným riadkom v tabuľke „Zamestnanci“. Čiže na objednávky toho 1 zamestnanca. Takto daný užívateľ v oboch tabuľkách uvidí iba „svoje“ dáta. Preto pre tabuľku „Objednavky“ nemusíme nastavovať žiadnu filtrovaciu podmienku.

Nie je to však také jednoduché. Ak nie sú nastavené žiadne filtre pre danú tabuľku, tak nastanú dve možnosti:

  1. ak sú nastavené filtre na prepojených tabuľkách, prepojených v smere šípky z tých tabuliek na túto tabuľku, tak sa táto tabuľka automaticky vyfiltruje len na príslušné riadky k tým vyfiltrovaným riadkom v prepojených tabuľkách (aj kaskádovito v smere šípok prepojení). Ak sa v tejto tabuľke zbehnú filtre zabezpečenia z 2 a viac tabuliek, tak sa medzi nimi automaticky použije logická operácia AND (logické „a súčasne“)
  2. ak nie je splnená podmienka z bodu 1), čiže ak zo žiadnej prepojenej tabuľky neprejdú do danej tabuľky filtre zabezpečenia, tak užívateľ uvidí v tabuľke všetky riadky.

Ak chcete, aby užívateľ nevidel v tabuľke žiadne riadky, tak to vyriešite napr. takouto podmienkou:

0 = 1

Takáto podmienka nebude splnená pre žiadny riadok tabuľky, takže užívateľ v nej nič neuvidí. Uvidí však stále tú tabuľku v ponuke, aj keď bez dát. Ak by ste ju chceli skryť z ponuky pre členov danej role, tak treba spraviť pomocou funkcionality Object-level security.

Keď už máme nastavené všetky filtre zabezpečenia, tak klikneme v Editore rolí na tlačidlo „Uložiť“, a potom na tlačidlo „Zavrieť“:

Tým uložíme zmeny v týchto nastaveniach, a zavrieme tento Editor.

Otestovanie rolí zabezpečenia

Nikdy nie je vhodné spoliehať sa na žiadnu funkcionalitu Power BI bez jej riadneho otestovania. A preto nám aj Power BI Desktop ponúka možnosť otestovať to, ako sa budú role zabezpečenia správať z pohľadu budúcich užívateľov. Vieme si dať zobraziť report tak, ako keby sme patrili do jednej alebo viacerých rolí. Robí sa to tak, že v hlavnom menu, na záložke „Modelovanie“, kliknete na tlačidlo „Zobraziť ako“:

Otvorí sa okno s názvom „Zobraziť ako roly“. Tam vyberieme jednu alebo viacero rolí, pomocou začiarknutia jej názvu. V našom prípade vyberieme rolu „Kazdy vidi iba svoje data“, a stlačíme tlačidlo „OK“:

DAX row-level security - výber testovanej role

Potom nám Power BI Desktop nasimuluje, ako sa bude zobrazovať report pre členov tejto role. Napríklad, ak sme prihlásení ako prvý zamestnanec v tabuľke „Zamestnanci“, tak sa nám bude report zobrazovať takto:

DAX row-level security - zobrazenie dát užívateľa

Všimnite si, že nad reportom sa zobrazuje žltá lišta z názvom „Teraz sa zobrazuje s použitím roly: Kazdy vidi iba svoje data“. Ak sme už hotoví s testovaním a kontrolami, tak sa môžeme prepnúť naspäť na zobrazovanie všetkých dát, kliknutím na tlačidlo „Prestať zobrazovať“ na konci tej lišty:

DAX row-level security - návrat naspäť na zobrazovanie všetkých dát

Lišta potom zmizne, a bude nám to opäť zobrazovať všetky dáta v reporte.

Pridanie členov do rolí zabezpečenia

Keď už máme vytvorené, nastavené a otestované role zabezpečenia, tak do týchto rolí musíme pridať členov. Čiže konkrétnych užívateľov, na ktorých sa budú aplikovať filtre zabezpečenia zadefinované v týchto roliach. Na to však musíme vypublikovať report, resp. dátový model. V prípade reportov Power BI musíme nasadiť/vypublikovať report buď do cloudu Power BI, alebo na vnútropodnikový Power BI Report Server. V nastaveniam členstva v roliach sa dostaneme potom nasledovne:

1) v cloude Power BI – prejdeme do pracovného priestoru, kam sme vypublikovali report. Tam si nájdeme dátový model za týmto reportom. Vedľa tohto dátového modelu klikneme na 2 bodky, a potom na položku „Zabezpečenie“,

2) vo vnútropodnikovom Power BI Report Serveri – prejdeme do adresára, kam sme vypublikovali report. Vedľa reportu klikneme na 3 bodky, a tam vyberieme položku „Manage“. Otvorí sa ďalšia stránka, kde vyberieme v ľavom menu položku „Row-level security“.

V oboch prípadoch by sme teraz niekde na ľavej strane mali vidieť všetky role zabezpečenia, ktoré sme zadefinovali v Power BI Desktope:

DAX row-level security - pridanie členov do role zabezpečenia

Teraz už len vyberieme danú rolu, a priradíme do nej buď užívateľov, alebo skupiny užívateľov. Nezabudnite po výbere užívateľa alebo skupiny kliknúť na tlačidlo „Pridať“ a potom na „Uložiť“.

Od tohto momentu sa budú na týchto užívateľov vzťahovať filtre zabezpečenia definované v danej roli zabezpečenia. A keďže pri viacerých užívateľoch a viacerých roliach môžu nastať viaceré možnosti, tak to bude fungovať takto:

  1. ak užívateľ patrí do 1 alebo viacerých rolí, tak sa mu skumulujú oprávnenia zo všetkých rolí kam patrí; inak povedané: sčítajú sa; ešte inak povedané: použije sa logická operácia OR (logické „alebo“) medzi jednotlivými rolami,
  2. ak užívateľ nepatrí do žiadnej role, tak:
    1. ak používate cloud Power BI a užívateľ má vyzdieľaný report, tak uvidí všetky dáta v reporte,
    2. ak používate vnútropodnikový Power BI Report Server, a užívateľ má vyzdieľaný report, tak buď mu vôbec nezobrazí report, alebo report síce otvorí, ale všetky vizualizácie vyhlásia chybu (závisí od verzie servera).
  3. ak užívateľ nemá vyzdieľaný report, resp. nemá žiaden prístup/oprávnenia k reportu, tak sa funkcionalita DAX row-level security vôbec nepoužije a užívateľ sa nedostane k reportu.

Pri cloude Power BI si dajte veľký pozor na bod 2b) uvedený vyššie. Ak užívateľ nie v žiadnej roli, ale má sprístupnený report, tak v ňom uvidí všetky dáta. Pre niekoho je to želaný scenár (napr. ak chcete top manažmentu dať prístup ku všetkým dátam jednoduchým spôsobom), a pre niekoho to je neželaný scenár (ak to nechcete). Takže ak to nechcete, tak si dajte pozor, aby ste report zdieľali len tým užívateľom, ktorí sú uvedení aj v roliach zabezpečenia. Aj preto sa odporúča zdieľať report aj pridávať do rolí zabezpečenia iba skupiny užívateľov, a nie konkrétnych užívateľov. To minimalizuje riziko, že report vyzdieľate nejakému užívateľovi a pozabudnete ho pridať do niektorej role zabezpečenia.

Kedy DAX row-level security funguje a kedy nie

Nie je však všetko také ružové. Aby to zafungovalo, tak musia byť splnené nejaké podmienky. Napríklad, pri cloudovej verzii Power BI je vyžadovaná licencia Power BI Pro a vyššia, alebo uloženie reportu v pracovnom priestore Power BI Premium. Pri vnútrofiremnom Power BI Report Serveri netreba žiadne licencie pre užívateľov.

Táto funkcionalita funguje spolu s funkcionalitou Direct Query. Nefunguje však pri použití niektorých funkcionalít, ako napríklad:

  1. verejné reporty – ak report vyzdieľate komukoľvek na svete
  2. ak ste vlastník reportu/dátového modelu, alebo správca pracovného priestoru kde je uložený, alebo administrátor databázy SSAS Tabularu
  3. ostatné podmienky nájdete v oficiálnej dokumentácii

Obrovskou výhodou je to, že tým že je to funkcionalita implementovaná na úrovni dátového modelu, tak to automaticky bude aplikované všade, kde je použitý tento dátový model – aj v Exceli, v nalinkovaných reportoch Power BI či všade inde kde je použitý tento dátový model. Takto zadefinujete oprávnenia na jednom mieste v dátovom modeli, a užívatelia vo všetkých reportovacích nástrojoch, ktoré pripojíte k tomuto dátovému modelu, automaticky uvidia len tie dáta, ktoré majú vidieť. Nie je to teda definované na úrovni reportu, a teda to potom ani nemusíte opakovať v každom reporte ktorý napojíte na tento dátový model.

Na záver

Toto je teda funkcionalita DAX row-level security, čiže zabezpečenia dát na úrovni riadkov pomocou jazyka DAX. Pomocou nej viete elegantne obmedziť, ktoré dáta zobrazíte ktorému užívateľovi, a nemusíte len kvôli tomu vyrábať samostatný report pre každého užívateľa.

Navonok jednoduchá funkcionalita má však aj svoje úskalia, a spolu s niektorými bugmi vedia riadne potrápiť. Najmä pri implementácii pokročilejších požiadaviek. Ako všade inde, tak aj tu platí, že to treba vedieť správne nastaviť. Bežné podnikové nasadenie vyžaduje oveľa komplexnejšie pravidlá zabezpečenia dát. Napríklad, že manažér má vidieť svoje dáta a dáta svojich podriadených. Takéto a rôzne ďalšie scenáre si však už ukážeme na samostatnom webinári venovanému tejto téme 🙂