Business Professionals
Power BI | Power Pivot | Power Query | DAX
Cloud Flows | RPA | AI Builder | Copilot
60+ Formulas | Data Stories | Advanced Reporting & Modeling
VB Programming | Report Automation |
MS-Office Automation
Techno-Business Professionals
Power BI | Power Query | Advanced DAX | SQL - Query &
Programming
Microsoft Fabric | Power BI | Power Query | Advanced DAX |
SQL - Query & Programming
Power BI | Power Apps | Power Automate | Copilot Studio | Power Pages | Dataverse
Microsoft Power Apps | Microsoft Power Automate
Power BI | Adv. DAX | SQL (Query & Programming) |
VBA | Python | Web Scrapping | API Integration
Power BI | Power Apps | Power Automate |
SQL (Query & Programming)
Power BI | Adv. DAX | Power Apps | Power Automate |
SQL (Query & Programming) | VBA | Python | Web Scrapping | API Integration
Power Apps | Power Automate | SQL | VBA | Python |
Web Scraping | RPA | API Integration
Technology Professionals
Power BI | DAX | SQL | ETL with SSIS | SSAS | VBA | Python
Power BI | SQL | Azure Data Lake | Synapse Analytics |
Data Factory | Databricks | Power Apps | Power Automate |
Azure Analysis Services
Microsoft Fabric | Power BI | SQL | Lakehouse |
Data Factory (Pipelines) | Dataflows Gen2 | KQL | Delta Tables | Power Apps | Power Automate
Power BI | Power Apps | Power Automate | SQL | VBA | Python | API Integration
Power BI | Advanced DAX | Databricks | SQL | Lakehouse Architecture
Business Professionals
Power BI | Power Pivot | Power Query | DAX
Cloud Flows | RPA | AI Builder | Copilot
60+ Formulas | Data Stories | Advanced Reporting & Modeling
VB Programming | Report Automation |
MS-Office Automation
Techno-Business Professionals
Power BI | Power Query | Advanced DAX | SQL - Query &
Programming
Microsoft Fabric | Power BI | Power Query | Advanced DAX |
SQL - Query & Programming
Power BI | Power Apps | Power Automate | Copilot Studio | Power Pages | Dataverse
Microsoft Power Apps | Microsoft Power Automate
Power BI | Adv. DAX | SQL (Query & Programming) |
VBA | Web Scrapping | API Integration
Power BI | Power Apps | Power Automate |
SQL (Query & Programming)
Power BI | Adv. DAX | Power Apps | Power Automate |
SQL (Query & Programming) | VBA | Web Scrapping | API Integration
Power Apps | Power Automate | SQL | VBA |
Web Scraping | RPA | API Integration
Technology Professionals
Power BI | DAX | SQL | ETL with SSIS | SSAS | VBA
Power BI | SQL | Azure Data Lake | Synapse Analytics |
Data Factory | Azure Analysis Services
Microsoft Fabric | Power BI | SQL | Lakehouse |
Data Factory (Pipelines) | Dataflows Gen2 | KQL | Delta Tables
Power BI | Power Apps | Power Automate | SQL | VBA | API Integration
Power BI | Advanced DAX | Databricks | SQL | Lakehouse Architecture
Power BI Row-Level Security in a Fabric world is no longer just about roles in a single semantic model. You can now design security once and reuse it across Lakehouse, Warehouse, and Power BI, instead of copy‑pasting DAX filters everywhere. This post walks through a practical pattern for centralizing RLS in Microsoft Fabric so your reports, Direct Lake models, and SQL queries all respect the same rules.
If you want to go beyond the basics and design end‑to‑end architectures, including medallion lakehouses and governed security, it’s worth investing in a more structured path like a focused Fabric & Power BI curriculum.
Fabric gives you multiple engines in one workspace:
If each of these has its own RLS logic:
The goal is simple:
Define security rules once, consume them everywhere.
That means:
Before we touch code, lock in a few principles.
Instead of hard‑coded filters like:
[Region] = "Poland" && USERPRINCIPALNAME() = "anna@contoso.com"
…create a security dimension:
DimUser
UserKey (surrogate key)UserUPNRegionKeyDepartmentKeyIsManager (bit)…and link it to your business dimensions (DimRegion, DimDepartment).
Your RLS then becomes "filter facts by what the user is allowed to see" instead of embedding business rules in DAX.
Pick one identity field as the canonical key:
UserUPN (e.g. anna@contoso.com).Use the same identity:
USERPRINCIPALNAME() mapping to UserUPN).Typical pattern:
You only push row filters into the Warehouse (SQL) when non‑Power‑BI tools need secure access.
We’ll start in the Lakehouse, because that’s where your curated Delta tables usually live.
At minimum, design:
sec.User – one row per user.sec.Role – logical roles (Region Manager, HR, Finance, etc.).sec.UserRole – bridge table (many‑to‑many).sec.UserRegion (or sec.UserEntity) – what data slices each user can see.Example SQL (Fabric Warehouse, but conceptually the same in Lakehouse SQL analytics endpoint):
CREATE SCHEMA sec;
CREATE TABLE sec.[User] (
UserKey INT IDENTITY(1,1) PRIMARY KEY,
UserUPN NVARCHAR(256) NOT NULL,
DisplayName NVARCHAR(256) NULL,
IsActive BIT NOT NULL DEFAULT 1
);
CREATE TABLE sec.[Role] (
RoleKey INT IDENTITY(1,1) PRIMARY KEY,
RoleName NVARCHAR(100) NOT NULL
);
CREATE TABLE sec.UserRole (
UserKey INT NOT NULL,
RoleKey INT NOT NULL,
CONSTRAINT PK_UserRole PRIMARY KEY (UserKey, RoleKey)
);
CREATE TABLE sec.UserRegion (
UserKey INT NOT NULL,
RegionKey INT NOT NULL,
CONSTRAINT PK_UserRegion PRIMARY KEY (UserKey, RegionKey)
);
Populate these from HR / AD exports using Dataflows Gen2 or notebooks.
If you have a user directory in Entra ID, you can sync it into Lakehouse with PySpark (simplified example):
from pyspark.sql.functions import col
# Assume df_ad_users loaded from Graph API or exported CSV
( df_ad_users
.select(
col("userPrincipalName").alias("UserUPN"),
col("displayName").alias("DisplayName")
)
.write
.format("delta")
.mode("overwrite")
.saveAsTable("sec.User_staging")
)
spark.sql("""
MERGE INTO sec.[User] AS tgt
USING sec.User_staging AS src
ON tgt.UserUPN = src.UserUPN
WHEN MATCHED THEN
UPDATE SET tgt.DisplayName = src.DisplayName,
tgt.IsActive = 1
WHEN NOT MATCHED THEN
INSERT (UserUPN, DisplayName, IsActive)
VALUES (src.UserUPN, src.DisplayName, 1);
""")
The important part: UserUPN is now the bridge between Fabric and AAD.
Once the security tables are in the Lakehouse, you have two options:
In Fabric, you can create a Warehouse that references Lakehouse tables via shortcuts or external tables. Then define views that encapsulate security logic.
Example: a view that returns only active users and their regions.
CREATE VIEW sec.vwUserRegion AS
SELECT
u.UserUPN,
r.RegionKey,
r.RegionName
FROM sec.[User] u
JOIN sec.UserRegion ur
ON u.UserKey = ur.UserKey
JOIN dim.Region r
ON ur.RegionKey = r.RegionKey
WHERE u.IsActive = 1;
This view:
In Power BI Desktop (or in the Fabric semantic model designer):
sec.vwUserRegion (or equivalent).vwUserRegion[RegionKey] → DimRegion[RegionKey] (single, filter both).vwUserRegion to fact tables.This keeps your security logic in dimensions, not facts.
Now we layer RLS on top of the security tables.
In the semantic model, create a role, e.g. RLS_Region, with a DAX filter on vwUserRegion:
-- Table: vwUserRegion
[UserUPN] = USERPRINCIPALNAME()
Because vwUserRegion filters DimRegion, and DimRegion filters your fact tables, the effect is:
vwUserRegion for their UPN.Nothing else needs a filter expression.
If you also have department‑level restrictions, you can:
vwUserDepartment.DimDepartment.-- Table: vwUserRegion
[UserUPN] = USERPRINCIPALNAME()
-- Table: vwUserDepartment
[UserUPN] = USERPRINCIPALNAME()
Now the effective RLS is the intersection:
Managers often need to see their team’s data. Model this as a separate mapping table:
sec.UserHierarchy:
ManagerUserKeyEmployeeUserKeyCreate a view that resolves the final allowed entities for each manager.
CREATE VIEW sec.vwManagerUserRegion AS
SELECT DISTINCT
m.UserUPN AS ManagerUPN,
r.RegionKey,
r.RegionName
FROM sec.UserHierarchy h
JOIN sec.[User] m
ON h.ManagerUserKey = m.UserKey
JOIN sec.[User] e
ON h.EmployeeUserKey = e.UserKey
JOIN sec.UserRegion ur
ON e.UserKey = ur.UserKey
JOIN dim.Region r
ON ur.RegionKey = r.RegionKey;
In the semantic model, you can then:
vwUserRegion (for direct permissions),vwManagerUserRegion (for manager views),RLS filter:
-- Table: vwEffectiveUserRegion
[UserUPN] = USERPRINCIPALNAME()
Where vwEffectiveUserRegion is a view that combines direct and manager‑derived rights.
The nice part of Fabric is that once your security tables live in Delta, you can reuse them across engines.
For Direct Lake models over a Lakehouse:
sec.*) are in the same Lakehouse as your facts/dims.Direct Lake respects RLS defined in the semantic model, so:
sec tables.If you have consumers querying the Warehouse directly (e.g. analysts using SSMS or applications using ODBC), you might need RLS at the SQL layer as well.
Pattern:
sec tables.Example: secured sales view using a function that maps the current user.
CREATE FUNCTION sec.fnUserRegionPredicate(@UserUPN NVARCHAR(256))
RETURNS TABLE
AS
RETURN
(
SELECT RegionKey
FROM sec.vwUserRegion
WHERE UserUPN = @UserUPN
);
GO
CREATE VIEW dbo.vwSales_Secured AS
SELECT s.*
FROM fact.Sales s
JOIN sec.fnUserRegionPredicate(SESSION_CONTEXT(N'UserUPN')) f
ON s.RegionKey = f.RegionKey;
You’d then need to set SESSION_CONTEXT('UserUPN') from the caller. In Fabric today this pattern is more realistic for controlled application access than ad‑hoc user queries; the key idea is that the same sec.vwUserRegion drives both SQL and Power BI.
If you apply RLS in both the Warehouse and semantic model, you can end up with:
Practical rule:
Centralizing RLS is only useful if it’s maintainable.
Put these under explicit ownership:
sec tables/views.In Power BI / Fabric semantic model designer:
Testing pattern:
sec.vwUserRegion via SQL.When a region is split or teams are reorganized:
sec tables should change (mappings, not DAX).This is the main payoff of centralization: business change becomes data change, not code change.
Pick a single high‑value Power BI dataset and move its RLS logic into a dedicated sec schema (tables + views) in your Lakehouse or Warehouse. Wire your semantic model to those tables and reduce your role definitions to simple UserUPN = USERPRINCIPALNAME() filters. Once that works end‑to‑end, you’ve got a proven pattern you can replicate across Fabric, instead of rewriting RLS separately for every model, Warehouse, and Lakehouse.
Power BI
New
Next Batches Now Live
Power BI
SQL
Power Apps
Power Automate
Microsoft Fabrics
Azure Data Engineering