pbPassingBI
/
Service & governance advanced 9 min

Row-level security

Static and dynamic roles, USERPRINCIPALNAME, and testing before release.

What you'll be able to do
  • Create a role with a DAX filter
  • Implement dynamic RLS with an entitlement table
  • Test roles before publishing

Static roles

In Power BI Desktop: Modeling → Manage roles. Create a role and give it a DAX filter on a table:

[Region] = "East"

After publishing, assign users or security groups to that role in the Service under dataset Security. The filter applies automatically for anyone in it.

Static roles work fine when there are a handful of fixed groupings. They don't scale — one role per region means editing the model every time the org changes.

Dynamic RLS

The scalable pattern uses the signed-in user's identity. USERPRINCIPALNAME() returns their UPN — usually their email — and is the function to use; USERNAME() behaves differently between Desktop and Service.

Create a UserAccess table mapping UPNs to entities:

email              | region
[email protected]    | East
[email protected]    | North
[email protected]    | West

Relate it to your dimension, then define one role with the filter:

[email] = USERPRINCIPALNAME()

One role covers everyone. Access changes become data edits, not model edits.

Making the filter propagate

A filter on the UserAccess table only helps if it flows through to the fact table. Check the relationship path: UserAccess → Region dimension → Sales.

If the propagation doesn't reach, you may need bidirectional filtering on that specific relationship — one of the few legitimate uses — or you can apply the filter directly on the dimension. Test it rather than assuming.

Testing

In Desktop, View as lets you preview a role and even specify a user. In the Service, dataset Security has Test as role.

Always test three cases: a user with one entitlement, a user with several, and a user with none. That last case should show an empty report, and it's the one people forget — an unassigned user seeing everything is the failure mode that matters.

Note that workspace Admins and Members bypass RLS on datasets they can edit. Viewers get RLS applied. This surprises people during testing.

Key points
  • Use USERPRINCIPALNAME(), not USERNAME(), for dynamic RLS
  • An entitlement table scales; one role covers every user
  • Workspace Admins/Members bypass RLS — test as a Viewer
Check yourself