

- Description
- Vue à travers un trou de serrure : on n'aperçoit que ce que l'ouverture laisse voir, ici un dôme au loin.
- Source
- Galen Crout · original page
- Licence
- CC0 Public domain
RLS Security and Access
This topic measures control over who sees what: row-level security (RLS, static and dynamic), object-level security (OLS), workspace permissions, sharing, access to…
In short
This topic measures control over who sees what: row-level security (RLS, static and dynamic), object-level security (OLS), workspace permissions, sharing, source access, and above all proof that security works (role tests, logs). Compliance (GDPR, classification) is covered in the PD matrix.
Level: 🟢→🔴 · Theme code: RLS
1. Why this topic#
A data leak in a report is a security incident, not a display bug. RLS in a semantic model applies only to users with reader role: a member with write permissions on the workspace bypasses RLS (documented behavior; recheck by version, status 2026-10). RLS filters, but does not prevent inferences (an unfiltered total, a row count, a decomposition visual). Cost of ignoring it: exposure of business data (margins, competitors) or personal data.
2. What this topic measures#
- Axis: from open sharing to designed, tested, and audited security.
- Key indicators: share of models containing sensitive data protected by role; number of roles tested automatically; number of users with unjustified write permissions; rights removal lead time.
- Units: %, days.
3. The 5 levels#
| Level | Short name | Promise | Typical indicator (orders of magnitude) |
|---|---|---|---|
| 1 | Open | Anyone with the link sees everything. | No roles; link sharing |
| 2 | Static roles | Each user group sees only its declared scope. | Roles by scope; Entra groups |
| 3 | Dynamic | Each user sees their scope without creating one role per person. | 1 dynamic role + security table |
| 4 | Tested and logged | A badly written security rule is detected before production; access is traceable. | Automated “view as” test; audit |
| 5 | Proven | Security is demonstrable to an auditor, including against common bypasses. | Independent review; 0 deviations over 12 months |
4. Milestones by level#
| ID | Milestone | Verifiable evidence |
|---|---|---|
| BI-RLS-1.1 | Report access is limited to people in the organization (no web publish) | Tenant settings verified |
| BI-RLS-1.2 | Workspaces have identified owners | Admin list |
| BI-RLS-1.3 | Sensitive data is identified | Inventory of sensitive columns |
| BI-RLS-2.1 | RLS roles defined on scope dimension tables | Roles in the model |
| BI-RLS-2.2 | Role members are groups (Entra), not individual accounts | Assignments in the service |
| BI-RLS-2.3 | Workspace permissions follow least privilege (Reader by default) | Workspace role review |
| BI-RLS-2.4 | “Link-based” shares are inventoried and limited | Sharing audit report |
| BI-RLS-3.1 | Dynamic filter by USERPRINCIPALNAME() on a security table |
Role expression + table |
| BI-RLS-3.2 | Security filter direction verified (propagation to facts; bidirectional documented) | Model review |
| BI-RLS-3.3 | Sensitive measures do not disclose through totals or inferences | Inference test cases |
| BI-RLS-3.4 | A “all / none / multiple scopes” case is handled | Set of security cases |
| BI-RLS-3.5 | “Virtual” users (administrator, leadership) are handled explicitly | Documented role or exception |
| BI-RLS-4.1 | “View as” tests rerun with every release | Role test log |
| BI-RLS-4.2 | OLS to hide sensitive columns/tables when needed | OLS role implemented and tested |
| BI-RLS-4.3 | Activity logs are used (access, exports) | Audit query |
| BI-RLS-4.4 | Permissions removed when a user leaves, within a defined timeframe | Measured lead time |
| BI-RLS-5.1 | Annual independent security review | Report |
| BI-RLS-5.2 | The security table is fed automatically from the HR/organization source of truth | Feed pipeline |
| BI-RLS-5.3 | Sensitivity labels propagated to exports | Labels verified downstream |
| BI-RLS-5.4 | No known bypass: write permissions, exports, query API | Bypass matrix tested |
5. Detailed reading by level#
🟢 Level 1 — Open#
- Signs: “everyone sees everything,” reports shared by link, unrestricted exports.
- Benefit: zero friction. Does not guarantee: confidentiality.
- Difficulty: 1/5 · Effort: 1/5.
🟢 Level 2 — Static roles#
-- Rôle « Région Nord » sur DIM_COMMERCIAL
[Region] = "Nord"
- Signs: one role per scope, members = groups. Simple, readable, costly to maintain when scopes change.
- Benefit: first real barrier.
- Limit: explosion in number of roles; errors during staff changes.
- Difficulty: 2/5 · Effort: 2/5.
🟡 Level 3 — Dynamic#
-- Rôle unique « Périmètre » sur la table de sécurité SEC_USER_PERIMETRE
[Email] = USERPRINCIPALNAME ()
The security table links a user to their sales reps/sectors; the SEC → dimension relationship propagates the filter to facts. Depending on the model, a bidirectional relationship with Apply security filter in both directions is required, which can have side effects: document each case.
- Benefit: maintenance through data, not deployment.
- Limit: totals can differ between users (intended) but still surprise: an executive sees a higher total than a manager.
- Difficulty: 3/5 · Effort: 3/5.
SFA thread: a sales rep sees their customers; a manager sees their team's customers, including those whose ownership rotates during the year. The security table carries a validity period; a period filter is added to the role expression.
Symptom: a measure counting dimensions (e.g., number of customers) varies unexpectedly by user. Cause: back-filtering from facts to dimensions under RLS. Fix: test each counting measure under each role; adjust filter direction or the measure.
Symptom: an administrator sees everything in testing and thinks security works. Cause: write permissions ignore RLS. Fix: test with a real reader account or with “view as.”
🟡 Level 4 — Tested and logged#
- Signs: “view as” is a release test; audit queries have an owner; OLS hides sensitive columns (margins) from unauthorized roles.
- Benefit: a wrong rule is caught before production.
- Limit: OLS can break reports that reference the hidden column; test it.
- Difficulty: 4/5 · Effort: 4/5.
Automate testing with a DAX query executed with effective identity (EffectiveUserName on the XMLA side, or testing via the query execution API with impersonation) and compare the result to an expected value: “user X should only see N customers.”
🔴 Level 5 — Proven#
- Signs: security table fed from the HR source, independent security review, bypass matrix (exports, subscriptions, API, direct access to database or lakehouse) tested. Model RLS does not protect the source: direct SQL or OneLake access must be covered separately.
- Benefit: enforceable proof.
- Limit: maintenance and coordination cost with HR and security.
- Difficulty: 5/5 · Effort: 5/5.
Put security as close to the source as possible when feasible (SQL RLS, OneLake security), and keep model RLS as a second layer: one layer = one single point of failure.
An assistant can draft a role expression or generate test cases; it does not assess the impact of filter direction on your totals. Risk: exposing data to an AI service without a framework; check the organization's policy (see PD — security).
6. Partial achievement and rating#
Common rule. A “partial 5”: independent review done once but not renewed (BI-RLS-5.1 = 0.5), security table fed automatically (5.2 = 1), sensitivity labels set on half the models (5.3 = 0.5), bypasses tested on exports but not on direct source access (5.4 = 0.5). A security milestone at 0 blocks level attainment, regardless of the average: this is intentional.
7. Moving to the next level#
Possible means (optional):
| Transition | Possible levers |
|---|---|
| 1 → 2 | Inventory of sensitive data; roles by group; least privilege |
| 2 → 3 | Security table; single role; set of edge cases |
| 3 → 4 | “View as” tests in pipeline; OLS; activity logs |
| 4 → 5 | Automatic HR feed; external review; bypass matrix; source-level security |
Pitfalls:
- False positive: “RLS is in place” but admins and the project team never test it with a reader account.
- Goodhart: counting roles; an “All” role that filters nothing makes the metric meaningless.
- Confusing confidentiality and masking: hiding a visual does not secure the underlying data.
8. See also#
- Related topics: MOD · TST · GOV · IND
- Other matrices: PD — Security, Privacy, and Compliance · DL — Security
- Content: SQL Server in SaaS — Challenges and Pitfalls · OneLake + SaaS Mobile Apps: Challenges and Pitfalls · Power BI Reporting Project Checklists
✻ Written by Claude Sonnet 5.5