{"id":5751,"date":"2018-09-19T13:21:24","date_gmt":"2018-09-19T11:21:24","guid":{"rendered":"https:\/\/sii.pl\/blog\/?p=5751"},"modified":"2023-09-11T15:37:11","modified_gmt":"2023-09-11T13:37:11","slug":"row-level-security-w-modelu-tabular-analysis-services","status":"publish","type":"post","link":"https:\/\/sii.pl\/blog\/row-level-security-w-modelu-tabular-analysis-services\/","title":{"rendered":"Row Level Security w modelu Tabular Analysis Services"},"content":{"rendered":"\n<p>W tym artykule opisuj\u0119 proces wdro\u017cenia dynamicznego zabezpieczania dost\u0119pu do danych w modelu Tabular Analysis Services.<\/p>\n\n\n\n<p class=\"has-text-align-left\">Row Level Security umo\u017cliwia lepsz\u0105 \u2013 bardziej dopasowan\u0105 do u\u017cytkownika kontrol\u0119 dost\u0119pu do danych. Tworz\u0105c poziom zabezpieczenia danych w modelu Tabular nie ograniczamy dost\u0119pu tylko do poszczeg\u00f3lnych tabel, ale filtrujemy wiersze w tabelach okre\u015blaj\u0105c w ten spos\u00f3b poziom dost\u0119pu do danych dla zdefiniowanych r\u00f3l. Do danej roli s\u0105 przypisani poszczeg\u00f3lni u\u017cytkownicy. W ten spos\u00f3b definiujemy do jakiego zakresu danych poszczeg\u00f3lni u\u017cytkownicy b\u0119d\u0105 mieli dost\u0119p.<\/p>\n\n\n\n<p class=\"has-text-align-left\">Dodaj\u0105c u\u017cytkownika do danej roli okre\u015blamy, po jakich po\u015bwiadczeniach b\u0119dzie identyfikowany podczas \u0142\u0105czenia si\u0119 do modelu \u2013 w moim przyk\u0142adzie jest to login domenowy. U\u017cytkownicy b\u0119d\u0105 identyfikowani po loginie jakim pos\u0142uguj\u0105 si\u0119 loguj\u0105c do platformy, na kt\u00f3rej dany raport jest umieszczony (np. Reporting Services) lub \u0142\u0105cz\u0105c si\u0119 bezpo\u015brednio do modelu z poziomu Excela, gdzie przegl\u0105daj\u0105 dane przy u\u017cyciu tabeli przestawnej.<\/p>\n\n\n\n<p class=\"has-text-align-left\">To co musimy zrobi\u0107, aby stworzy\u0107 Row Level Security (RLS) to:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>doda\u0107 do modelu tabel\u0119 ze spisem login\u00f3w wszystkich u\u017cytkownik\u00f3w oraz zapewni\u0107 aby model by\u0142 filtrowany na podstawie dodanych atrybut\u00f3w tabeli,<\/li>\n\n\n\n<li>zapewni\u0107 aby u\u017cytkownik by\u0142 \u201erozpoznawany\u201d podczas logowania,<\/li>\n\n\n\n<li>stworzy\u0107 role z przypisanymi u\u017cytkownikami oraz zdefiniowa\u0107 dla ka\u017cdej z nich zakres filtrowania danych w modelu (okre\u015blaj\u0105c w ten spos\u00f3b poziom dost\u0119pu do danych).<\/li>\n<\/ul>\n\n\n\n<p class=\"has-text-align-left\">RLS wdra\u017camy do modelu z poziomu projektu w SQL Server Data Tools &#8211; Visual Studio.<\/p>\n\n\n\n<h2 class=\"wp-block-heading has-text-align-left\"><strong>Stworzenie tabeli ze spisem login\u00f3w u\u017cytkownik\u00f3w<\/strong><\/h2>\n\n\n\n<p class=\"has-text-align-left\">Do modelu musimy doda\u0107 tabel\u0119 ze spisem login\u00f3w oraz powi\u0105zanym im \u2018ID\u2019, po kt\u00f3rym u\u017cytkownicy b\u0119d\u0105 jednoznacznie identyfikowani. W moim przyk\u0142adowym modelu jest to tabela nazwana \u2018Security table\u2019 z atrybutami: \u2018SIIUSERLOGIN\u2019 (login) oraz \u2018ID Worker\u2019 (ID u\u017cytkownika). Atrybut \u2018ID Worker\u2019 jest wykorzystywany w ca\u0142ym modelu do identyfikowania u\u017cytkownik\u00f3w (pracownik\u00f3w). Nie musimy tworzy\u0107 relacji tabeli \u2018Security table\u2019 do innej tabeli w modelu, poniewa\u017c powi\u0105zanie zapewnimy za pomoc\u0105 odpowiednich funkcji DAX, definiuj\u0105c je podczas tworzenia roli.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter\"><a href=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2018\/07\/Rys.1-Tabela-u\u017cytkownik\u00f3w.png\"><img decoding=\"async\" width=\"786\" height=\"522\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2018\/07\/Rys.1-Tabela-u\u017cytkownik\u00f3w.png\" alt=\"Tabela u\u017cytkownik\u00f3w\" class=\"wp-image-5756\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2018\/07\/Rys.1-Tabela-u\u017cytkownik\u00f3w.png 786w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2018\/07\/Rys.1-Tabela-u\u017cytkownik\u00f3w-300x199.png 300w\" sizes=\"(max-width: 786px) 100vw, 786px\" \/><\/a><figcaption class=\"wp-element-caption\">Rys.1 Tabela u\u017cytkownik\u00f3w<\/figcaption><\/figure>\n\n\n\n<p>Po rozpoznaniu u\u017cytkownika na podstawie loginu w tabeli \u2018Security table\u2019 odpowiedni wiersz z atrybutu \u2018ID Worker\u2019 identyfikuj\u0105cy u\u017cytkownika b\u0119dzie powi\u0105zany z wybran\u0105 w modelu tabel\u0105 zawieraj\u0105c\u0105 atrybut \u2018ID Worker\u2019, a tabela ta b\u0119d\u0105ca cz\u0119\u015bci\u0105 modelu danych b\u0119dzie propagowa\u0142a filtr na pozosta\u0142e tabele, pokazuj\u0105c dane tylko dla wybranej warto\u015bci.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter\"><a href=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2018\/07\/Rys.2-Powi\u0105zanie-tabeli-z-modelem-1.png\"><img decoding=\"async\" width=\"786\" height=\"522\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2018\/07\/Rys.2-Powi\u0105zanie-tabeli-z-modelem-1.png\" alt=\"Powi\u0105zanie tabeli z modelem\" class=\"wp-image-5758\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2018\/07\/Rys.2-Powi\u0105zanie-tabeli-z-modelem-1.png 786w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2018\/07\/Rys.2-Powi\u0105zanie-tabeli-z-modelem-1-300x199.png 300w\" sizes=\"(max-width: 786px) 100vw, 786px\" \/><\/a><figcaption class=\"wp-element-caption\">Rys.2 Powi\u0105zanie tabeli z modelem<\/figcaption><\/figure>\n\n\n\n<p>Nale\u017cy te\u017c zwr\u00f3ci\u0107 uwag\u0119 na zaznaczenie opcji \u201eApply the Filter Direction when using Row Level Security\u201d w ustawieniach relacji dla tabeli odpowiedzialnej za propagowanie filtru na ca\u0142y model, aby filtrowanie RLS dzia\u0142a\u0142o.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter\"><a href=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2018\/07\/Rys.3-Ustawienia-relacji.png\"><img decoding=\"async\" width=\"976\" height=\"582\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2018\/07\/Rys.3-Ustawienia-relacji.png\" alt=\"Ustawienia relacji\" class=\"wp-image-5759\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2018\/07\/Rys.3-Ustawienia-relacji.png 976w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2018\/07\/Rys.3-Ustawienia-relacji-300x179.png 300w\" sizes=\"(max-width: 976px) 100vw, 976px\" \/><\/a><figcaption class=\"wp-element-caption\">Rys.3 Ustawienia relacji<\/figcaption><\/figure>\n\n\n\n<h2 class=\"wp-block-heading has-text-align-left\"><strong>Stworzenie roli na poziomie Visual Studio<\/strong><\/h2>\n\n\n\n<p>Aby utworzy\u0107 role otwieramy w Visual Studio okno \u201eRole Manager\u201d &#8211; z menu g\u00f3rnego paska Model -&gt; Roles -&gt;New. Nadajemy nazw\u0119 oraz okre\u015blamy poziom dost\u0119pu np. Permission -&gt;Read<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter\"><a href=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2018\/09\/Rys.4-Role-Manager-1.png\"><img decoding=\"async\" width=\"300\" height=\"198\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2018\/09\/Rys.4-Role-Manager-1-300x198.png\" alt=\"Role Manager\" class=\"wp-image-15158\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2018\/09\/Rys.4-Role-Manager-1-300x198.png 300w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2018\/09\/Rys.4-Role-Manager-1.png 757w\" sizes=\"(max-width: 300px) 100vw, 300px\" \/><\/a><figcaption class=\"wp-element-caption\">Rys.4 Role Manager<\/figcaption><\/figure>\n\n\n\n<p>W zak\u0142adce Row Filters u\u017cywamy funkcji Dax do okre\u015blenia zakresu filtrowania danych na poziomie wierszy w &nbsp;poszczeg\u00f3lnych tabelach. Okre\u015blamy&nbsp; w tym miejscu r\u00f3wnie\u017c powi\u0105zanie warto\u015bci z tabeli login\u00f3w i ID &#8211; \u2018Security table\u2019 do tabeli wybranej do propagowania filtru. Zapewniamy to wykorzystuj\u0105c funkcje DAX:<\/p>\n\n\n\n<p>LOOKUPVALUE() \u2013 przypisanie danej warto\u015bci z tabeli ze spisem login\u00f3w i ID&nbsp;\u2013 \u2018Security table\u2019 do tabeli odpowiedzialnej za filtrowanie modelu wed\u0142ug wyszukanej warto\u015bci. Wa\u017cne! U\u017cywaj\u0105c&nbsp; funkcji LOOKUPVALUE nie musimy tworzy\u0107 relacji pomi\u0119dzy przeszukiwan\u0105 tabel\u0105, a tabel\u0105 gdzie funkcj\u0119 stosujemy.<\/p>\n\n\n\n<p>USERNAME() \u2013 zwraca nazw\u0119 u\u017cytkownika z po\u015bwiadcze\u0144 dostarczonych do systemu w czasie po\u0142\u0105czenia.<\/p>\n\n\n\n<p>Zastosowanie razem funkcji LOOKUPVALUE oraz USERNAME \u2013 sczyta nazw\u0119 u\u017cytkownika z&nbsp; dostarczonych po\u015bwiadcze\u0144, a nast\u0119pnie przeszuka tabel\u0119 \u2018Security table\u2019 i po znalezieniu loginu przypisze odpowiadaj\u0105c\u0105 warto\u015b\u0107 atrybutu \u2018ID Worker\u2019, jako argument do tabeli \u2018Project by directworker\u2019, kt\u00f3ra zastosuje ten filtr na wszystkie dane w modelu (wg logiki utworzonych relacji w ca\u0142ym modelu).<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter\"><a href=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2018\/07\/Rys.5-Row-Filters.png\"><img decoding=\"async\" width=\"790\" height=\"237\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2018\/07\/Rys.5-Row-Filters.png\" alt=\"Row Filters\" class=\"wp-image-5761\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2018\/07\/Rys.5-Row-Filters.png 790w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2018\/07\/Rys.5-Row-Filters-300x90.png 300w\" sizes=\"(max-width: 790px) 100vw, 790px\" \/><\/a><figcaption class=\"wp-element-caption\">Rys.5 Row Filters<\/figcaption><\/figure>\n\n\n\n<p>W zak\u0142adce Members dodajemy u\u017cytkownik\u00f3w, dla kt\u00f3rych filtrowanie okre\u015blone dla danej roli b\u0119dzie mie\u0107 zastosowanie: Role Manager-&gt;Members-&gt;Add&#8230; (domena\\nazwa u\u017cytkownika)<\/p>\n\n\n\n<p>Tabele ze spisem login\u00f3w u\u017cytkownik\u00f3w \u2018Security table\u2019 mo\u017cemy ukry\u0107 w modelu oraz za pomoc\u0105 polecenia =FALSE() (na poziomie zak\u0142adki Row Filters ) zablokowa\u0107 mo\u017cliwo\u015b\u0107 przegl\u0105dania danych, tak \u017ceby cz\u0142onkowie danej roli nie mieli do niej wgl\u0105du.<\/p>\n\n\n\n<h2 class=\"wp-block-heading has-text-align-left\"><strong>Testowanie dzia\u0142ania filtru dla poszczeg\u00f3lnych roli<\/strong><\/h2>\n\n\n\n<p class=\"has-text-align-left\">Kiedy role zosta\u0142y utworzone nale\u017cy przetestowa\u0107 poprawno\u015b\u0107 dzia\u0142ania \u2013 filtrowania danych. W tym celu potrzebujemy po\u0142\u0105czy\u0107 si\u0119 do modelu jako u\u017cytkownik danej roli. Mo\u017cemy dokona\u0107 tego poprzez wybranie w Visual Studio z menu g\u00f3rnego paska opcji \u201eAnalyze in Excel\u201d. Nast\u0119pnie \u0142\u0105cz\u0105c si\u0119 z modelem z poziomu Excela mo\u017cemy przegl\u0105da\u0107 model z odpowiednio przefiltrowanymi danymi&nbsp; per u\u017cytkownik lub per rola.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter\"><a href=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2018\/07\/Rys.6-Analyze-in-Excel.png\"><img decoding=\"async\" width=\"381\" height=\"364\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2018\/07\/Rys.6-Analyze-in-Excel.png\" alt=\"Analyze in Excel\" class=\"wp-image-5762\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2018\/07\/Rys.6-Analyze-in-Excel.png 381w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2018\/07\/Rys.6-Analyze-in-Excel-300x287.png 300w\" sizes=\"(max-width: 381px) 100vw, 381px\" \/><\/a><figcaption class=\"wp-element-caption\">Rys.6 Analyze in Excel<\/figcaption><\/figure>\n\n\n\n<p>Per u\u017cytkownik:<\/p>\n\n\n\n<p>Model-&gt;Analyze in Excel, zaznaczamy opcje -&gt;Other Windows User<\/p>\n\n\n\n<p>Wpisujemy login (domena\\nazwa u\u017cytkownika) wybranego cz\u0142onka danej roli, nast\u0119pnie z poziomu Excela mamy wgl\u0105d w dane jakie s\u0105 widoczne dla tego u\u017cytkownika po zalogowaniu.<\/p>\n\n\n\n<p>Per rola:<\/p>\n\n\n\n<p>Model-&gt;Analyze in Excel, zaznaczamy opcje&nbsp; -&gt;Role<\/p>\n\n\n\n<p>Wybieramy dan\u0105 rol\u0119, kt\u00f3r\u0105 wcze\u015bniej stworzyli\u015bmy, nast\u0119pnie z poziomu Excela mamy wgl\u0105d w dane, jakie s\u0105 widoczne dla ka\u017cdego u\u017cytkownika tej roli.<\/p>\n\n\n<div class=\"kk-star-ratings kksr-auto kksr-align-left kksr-valign-bottom\"\n    data-payload='{&quot;align&quot;:&quot;left&quot;,&quot;id&quot;:&quot;5751&quot;,&quot;slug&quot;:&quot;default&quot;,&quot;valign&quot;:&quot;bottom&quot;,&quot;ignore&quot;:&quot;&quot;,&quot;reference&quot;:&quot;auto&quot;,&quot;class&quot;:&quot;&quot;,&quot;count&quot;:&quot;0&quot;,&quot;legendonly&quot;:&quot;&quot;,&quot;readonly&quot;:&quot;&quot;,&quot;score&quot;:&quot;0&quot;,&quot;starsonly&quot;:&quot;&quot;,&quot;best&quot;:&quot;5&quot;,&quot;gap&quot;:&quot;11&quot;,&quot;greet&quot;:&quot;&quot;,&quot;legend&quot;:&quot;0\\\/5 ( votes: 0)&quot;,&quot;size&quot;:&quot;18&quot;,&quot;title&quot;:&quot;Row Level Security w modelu Tabular Analysis Services&quot;,&quot;width&quot;:&quot;0&quot;,&quot;_legend&quot;:&quot;{score}\\\/{best} ( {votes}: {count})&quot;,&quot;font_factor&quot;:&quot;1.25&quot;}'>\n            \n<div class=\"kksr-stars\">\n    \n<div class=\"kksr-stars-inactive\">\n            <div class=\"kksr-star\" data-star=\"1\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" data-star=\"2\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" data-star=\"3\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" data-star=\"4\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" data-star=\"5\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n    <\/div>\n    \n<div class=\"kksr-stars-active\" style=\"width: 0px;\">\n            <div class=\"kksr-star\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n    <\/div>\n<\/div>\n                \n\n<div class=\"kksr-legend\" style=\"font-size: 14.4px;\">\n            <span class=\"kksr-muted\"><\/span>\n    <\/div>\n    <\/div>\n","protected":false},"excerpt":{"rendered":"<p>W tym artykule opisuj\u0119 proces wdro\u017cenia dynamicznego zabezpieczania dost\u0119pu do danych w modelu Tabular Analysis Services. Row Level Security umo\u017cliwia &hellip; <a class=\"continued-btn\" href=\"https:\/\/sii.pl\/blog\/row-level-security-w-modelu-tabular-analysis-services\/\">Continued<\/a><\/p>\n","protected":false},"author":168,"featured_media":5889,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"_editorskit_title_hidden":false,"_editorskit_reading_time":0,"_editorskit_is_block_options_detached":false,"_editorskit_block_options_position":"{}","inline_featured_image":false,"footnotes":""},"categories":[1316],"tags":[619,618],"class_list":["post-5751","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-development-na-miekko","tag-analysis-services-tabular","tag-row-level-security"],"acf":[],"aioseo_notices":[],"republish_history":[],"featured_media_url":"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2018\/07\/analytics-business-charts-257949.jpg","category_names":["Development na mi\u0119kko"],"_links":{"self":[{"href":"https:\/\/sii.pl\/blog\/wp-json\/wp\/v2\/posts\/5751"}],"collection":[{"href":"https:\/\/sii.pl\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/sii.pl\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/sii.pl\/blog\/wp-json\/wp\/v2\/users\/168"}],"replies":[{"embeddable":true,"href":"https:\/\/sii.pl\/blog\/wp-json\/wp\/v2\/comments?post=5751"}],"version-history":[{"count":2,"href":"https:\/\/sii.pl\/blog\/wp-json\/wp\/v2\/posts\/5751\/revisions"}],"predecessor-version":[{"id":24055,"href":"https:\/\/sii.pl\/blog\/wp-json\/wp\/v2\/posts\/5751\/revisions\/24055"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/sii.pl\/blog\/wp-json\/wp\/v2\/media\/5889"}],"wp:attachment":[{"href":"https:\/\/sii.pl\/blog\/wp-json\/wp\/v2\/media?parent=5751"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/sii.pl\/blog\/wp-json\/wp\/v2\/categories?post=5751"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/sii.pl\/blog\/wp-json\/wp\/v2\/tags?post=5751"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}