Row Level Security
Introduction
What is RLS ?
RLS, or Row-Level Security, is a method of restricting data access in a database or business intelligence environment based on the characteristics of the user. Essentially, it allows administrators to control who can see what data within the same table or report. This is particularly valuable in environments where you have sensitive or private data that should only be accessible by certain users.
How is it different from RBAC ?
RLS in Power BI allows you to control access to rows of data based on the user viewing the report. This means you can create filters within roles defined in Power BI Desktop, and when users log into Power BI, they will only see data relevant to these filters.
RBAC, on the other hand, is broader and controls access at higher levels of the Power BI environment, not just at the data level. RBAC helps manage who has access to workspaces, reports, dashboards, and what kind of operations they can perform (like read, write, share, or delete).
How to enable RLS.
What you will need ?
The 'user table'
The users table is a table that maps all the users that will have access to the data, to the data they can see. It should be structured in the following way :
user_id: the unique identifier of the user, which can be mapped back to an item of the Power BI authentication payload.scope: the scope of the data available to the user. This is a string that will be used to filter the reporting data.
How to configure the RLS ?
The RLS is implemented by adding the user_table to your Power BI dashboard and by (inner) joining it onto the reporting table. The user_table can then be used to filter down data from the reporting table the user has been granted access to.
To do so, you will need to create a new role in your Power BI dashboard, and add a filter to the reporting table that will filter down the data based on the scope of the user.
- Ensure that your data model has the necessary columns to define RLS filters. Basically, you need a set of dimensions you want to apply RLS to, to be available in both the reporting table and the
user_table. Theuser_tableshould also include a column acting as a primary mean of identification for the user (in the example, we will be using theemailcolumn). - Import the
user_tableinto your Power BI dashboard, and create a relationship between theuser_tableand the reporting tables. The join must be done on the scope column. - Create and manage a role:
- In Power BI Desktop, click on the
Modeltab, then click onManage Roles. - Click on
Createto create a new role. - In the
Manage rolesdialog box, enter a name for the role, and then click onAdd Table Filter. - In the
Table Filter DAX Expressiondialog box, enter a DAX expression that filters the data based on the user's email address. This is done to filter the users table to the current dashboard viewer. For example, if you want to filter the data based on the user's email address, you can use the following DAX expression:
'user_table'[email] = USERPRINCIPALNAME()- Click on
OKto save the DAX expression. - Click on
Saveto save the role. - Click on
Closeto close theManage rolesdialog box. - Publish the report to the Power BI service.
- In Power BI Desktop, click on the
Example : implementing RLS at the school level
In this example, we will implement RLS to restrict access to the data based on the user's email address, so that each user can only see the data for the school they are associated with.
Step 1 : Create the users table
The users table should have the following columns:
email: the email address of the userschool: the school the user is associated with
Step 2 : Implementing RLS in Power BI
- Import the
userstable into your Power BI dashboard, and create a relationship between theuserstable and the reporting tables. The join must be done on theschoolcolumn. This is the big deal: if your reporting table DOES NOT contain aschoolcolumn, you won't be able to join theuser_tabletable, and you won't be able to apply RLS to this table. - Create a role :
- In Power BI Desktop, click on the
Modeltab, then click onManage Roles. - Click on
Createto create a new role. - In the
Manage rolesdialog box, enter a name for the role, and then click onAdd Table Filter. - In the
Table Filter DAX Expressiondialog box, enter a DAX expression that filters the data based on the user's email address. This is done to filter the users table to the current dashboard viewer. For example, if you want to filter the data based on the user's email address, you can use the following DAX expression:
user_table['email'] = USERPRINCIPALNAME()- Click on
OKto save the DAX expression. - Click on
Saveto save the role. - Click on
Closeto close theManage rolesdialog box. - Publish the report to the Power BI service.
- In Power BI Desktop, click on the
Why is it working ?
Here is what happens when a user is viewing the report, deep inside the Power BI engine:
- The user logs with his email into Power BI and the report is displayed.
- Power BI sets
USERPRINCIPALNAME()to the user's email. - The DAX expression in the role is evaluated, and the
user_tableis filtered to the user's email. - The tables joined on the
user_tableare now filtered to the user's email, and the user can only see the data for the school they are associated with.
A note about USERPRINCIPALNAME()
USERPRINCIPALNAME() is a DAX function that returns the currently authenticated user's email address. This function is only available in Power BI service, and not in Power BI Desktop. When you publish the report to the Power BI service, the USERPRINCIPALNAME() function will return the email address of the user viewing the report. This is useful for filtering the data based on the user's email address.
My customer wants RLS to work at school level, but also at class level. How can I do that?
Since Power BI doesn't handle multiple-column joins (it's only been half a century since we walked on the moon after all), you will have to concatenate the columns you want to join on into a single column. This is done by creating a new column in all your reporting and user_table tables. Creating one column for multiple columns can be done by simply concatenating the columns you want to join on. Of course, the concatenation order must be exactly the same in both your user_table and your reporting table (otherwise the join won't work). If you want to show off how smart you are, you can do it in SQL BEFORE importing your data and use the hash of the concatenation as the join column instead of the concatenation itself (to save some tiny bits of precious memory).
