Row-Level Security in Power BI: The Guide I Wish I'd Had Before I Shipped It to 400 Users
Row-Level Security (RLS) in Power BI restricts which rows a user can see in a semantic model, but it does not protect columns/tables (that's OLS), underlying data sources, or users with edit permissions Static RLS hardcodes filters per role (simple but high maintenance), while Dynamic RLS uses USERPRINCIPALNAME() to resolve filters at query time from a mapping table (scalable and recommended for changing groups) The most common security leak occurs when RLS filters fail to propagate through rela
Analysis
TL;DR
- Row-Level Security (RLS) in Power BI restricts which rows a user can see in a semantic model, but it does not protect columns/tables (that's OLS), underlying data sources, or users with edit permissions
- Static RLS hardcodes filters per role (simple but high maintenance), while Dynamic RLS uses USERPRINCIPALNAME() to resolve filters at query time from a mapping table (scalable and recommended for changing groups)
- The most common security leak occurs when RLS filters fail to propagate through relationships due to incorrect bi-directional relationship directions, silently showing users data they shouldn't see
- RLS only applies to Viewers and app/shared link recipients; workspace Admins, Members, and Contributors bypass RLS entirely when accessing through edit permissions
- Proper testing requires validating the complete filter propagation path from the security table through all relationships to every fact table before deployment
Why It Matters
This guide addresses a critical gap in Power BI security implementation that affects organizations deploying row-level access controls at scale. The article reveals that RLS failures are silent and compliance-related rather than error-driven, making them dangerous because they go undetected until users report data leaks. For AI practitioners and data professionals building semantic models with sensitive data, understanding these pitfalls prevents costly security breaches and ensures proper governance of row-level access.
Technical Details
- RLS Scope Limitations: RLS filters rows only within the semantic model; it does not provide column/table security (Object-Level Security requires Tabular Editor), protect underlying warehouse/lakehouse data, or restrict users with workspace edit permissions (Admins, Members, Contributors)
- Static vs Dynamic Implementation: Static RLS uses hardcoded DAX filters like
DimRegion[RegionName] = "East"per role, requiring model republishing for changes; Dynamic RLS usesUSERPRINCIPALNAME()in filters likeDimUser[UserEmail] = USERPRINCIPALNAME()with a mapping table, making additions a data change rather than model change - Filter Propagation Architecture: The RLS filter must travel through the relationship chain (e.g., DimUser → DimRegion → FactSales) using proper 1:* relationships; if any relationship breaks the propagation path, the filter silently stops and users see unrestricted data
- USERPRINCIPALNAME() vs USERNAME(): USERPRINCIPALNAME() returns the UPN (email) consistently across both Power BI Desktop and Service, while USERNAME() returns DOMAIN\user format in Desktop, causing inconsistent behavior
- Default Behavior for Unmapped Users: Users not present in the DimUser mapping table see nothing, which is the secure default but generates support tickets; this should be deliberately documented
Industry Insight
- Organizations should audit workspace roles immediately to ensure sensitive data consumers are assigned Viewer permissions rather than Contributor/Admin roles, as edit permissions bypass RLS entirely
- Dynamic RLS with USERPRINCIPALNAME() and a mapping table should be the default architecture for any deployment with more than a handful of security groups or frequent personnel changes, reducing maintenance overhead and deployment risk
- Security testing must validate the complete relationship propagation path before production deployment; implement automated testing that simulates multiple user identities to verify filter boundaries are correctly enforced across all fact tables
Disclaimer: The above content is generated by AI and is for reference only.