Skip to main content

RLS Persona Tester

Automated row-level security (RLS) testing for Power BI & Fabric semantic models.

Point it at a published model, declare what each role is supposed to see, and it answers — automatically, in CI, before you ship — the question BI teams still answer by hand:

Does every persona see exactly what it should — no more, no less?

An RLS leak means the wrong users see the wrong data: a security, compliance and audit failure waiting to surface in front of an auditor or a customer. Today teams catch it with spare "test accounts" and eyeballing View as role — manual, partial, and easy to skip under deadline. This tool makes it a one-command regression test that blocks the release pipeline when a role leaks.


Install

pip install rls-persona-tester            # core engine (stdlib only)
pip install 'rls-persona-tester[rest]'    # + live testing against a real model (msal, requests)

Try it in 30 seconds — free, no login

The offline demo runs against a built-in model seeded with two deliberately buggy roles, so you can watch the checks fire:

rls-test -c examples/demo_config.json
EMEA_leaky   scope_leak    FAIL   Sees Region outside allowed scope: ['North', 'South']
EMEA_leaky   value_scope   FAIL   Total Sales=800 but allowed scope should total 300
Empty_role   empty_view    FAIL   Role sees no data on any key measure (over-restrictive / broken RLS)
...
[FAIL] 47 checks — 12 failed, 35 passed     # exit 1 → a CI gate would block the deploy

Machine-readable and CI outputs:

rls-test -c examples/demo_config.json -f junit -o results.xml   # JUnit → CI gate
rls-test -c examples/demo_config.json -f json                   # JSON

The offline demo and --preflight diagnostics are free forever.

Test your real model (licensed)

Run the same checks against a published Power BI / Fabric semantic model over the executeQueries REST API — cross-platform (macOS/Linux/Windows/CI), no Power BI Desktop, no .NET, no Fabric notebook required:

rls-test --preflight -c your_model.json          # connectivity + permission diagnostics (free)
rls-test -c your_model.json --license <KEY>      # live RLS test (licensed)
# or set it once:  export RLS_TESTER_LICENSE_KEY=...

A valid license unlocks live runs against your own models. Get a license → · $99/year.


What it checks

Five checks, from zero-config to declared-intent:

Check Needs Catches
empty_view nothing broken / over-restrictive RLS (a role sees nothing)
exceeds_unrestricted nothing hard leak (a role totals more than the whole model)
scope_leak role → allowed members a role sees dimension members outside its lane
value_scope role → allowed members a role's measure ≠ the measure over its allowed scope
reconciliation a partition of roles the roles don't tile the unrestricted total exactly once

It passes a correctly-restricted role and fails a leaky one — the complete regression signal, with a non-zero exit code so release pipelines stop on a leak.

Config

{
  "connector": "rest",
  "security_table": "Geography",
  "security_column": "Region",
  "measures": ["Total Sales", "Order Count"],
  "connection": { "dataset_id": "<guid>", "group_id": "<workspace-guid>", "client_id": "<app-guid>" },
  "roles": [
    { "name": "North", "as_user": "north-tester@yourco.com", "allowed": ["North"],
      "expected": { "measures": { "Total Sales": 250 }, "visible": ["North"] } }
  ],
  "partition_roles": ["North", "South", "EMEA"]
}
  • allowed — the members this role should see on security_column (its intent).
  • as_user — a UPN that is a member of this role in the model's Security settings (executeQueries impersonates a user; it can't activate a role by name — that needs XMLA).
  • partition_roles — roles that together should tile the whole model exactly once.
  • connector: "simulated" runs the free offline demo with no connection block.

See examples/ for ready-to-edit configs and docs/SETUP_FABRIC.md for the one-time Fabric/Power BI setup (test users, tenant setting, permissions).

Knows the Direct Lake + SSO trap

A Direct Lake model whose source connection uses SSO is incompatible with executeQueries impersonation — every impersonation fails with PowerBIEntityNotFound, even impersonating the owner. It's a very common Fabric setup and an opaque failure. This tool auto-detects that signature and tells you the fix (bind the Direct Lake source to a dedicated cloud connection with fixed credentials, SSO off) instead of leaving you guessing.

Requirements (live testing)

  • Model on Premium / PPU / Fabric capacity (the Fabric trial covers it).
  • Tenant setting "Dataset Execute Queries REST API" = ON.
  • Build permission on the model; a test user per role, assigned in Security.
  • User auth (MSAL device-code) — service principals aren't allowed on RLS datasets.

Pricing & license

  • Free: the offline demo + --preflight diagnostics, forever.
  • $99/year: live RLS testing against your own semantic models, plus updates.
  • One license covers a developer's machines and CI. Buy →

A commercial license governs use — see LICENSE.

Support

Questions, a model shape that doesn't fit, or a false positive? Reach us through your Polar customer portal (linked on your receipt). Built by Green Analytics Ltd.

Roadmap

  • XMLA/ADOMD connector (activate roles by name; unattended CI at scale)
  • sempy_labs notebook connector (Direct Lake-native impersonation)
  • HTML report; GitHub Action / Azure DevOps task wrapper
  • Excel "source of truth" reconciliation

Metadata

Release files for rls-persona-tester 0.1.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for rls-persona-tester 0.1.1
File Size Uploaded
rls_persona_tester-0.1.1.tar.gz 21.1 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for rls-persona-tester 0.1.1
File Interpreter ABI Platform
rls_persona_tester-0.1.1-py3-none-any.whl Python 3 none any Details

Total release size: 45.3 kB

Release files / rls_persona_tester-0.1.1.tar.gz

Download URL rls_persona_tester-0.1.1.tar.gz
Size 21.1 kB
Tags Source
SHA-256 checksum
How to use checksums
ab5e126af92e5000cdf61579fdac897b7661389a38a488b0f8f5cb3aeee8633a
BLAKE2b-256 checksum
How to use checksums
9d0d30becdfa9be152e34c2ad28cb2b5a4a609886da7e6195a2b28f42b540f69
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.0

Release files / rls_persona_tester-0.1.1-py3-none-any.whl

Download URL rls_persona_tester-0.1.1-py3-none-any.whl
Size 24.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
9504dd5230ac8326258fa7db1661a03fd0ff121d00b53ce06f3ed3228e67fa41
BLAKE2b-256 checksum
How to use checksums
3a6b30932d42941e8eae55e6079c896c130239f91bc2eecce743d666ba105649
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.0

Release history Release notifications | RSS feed

This release

0.1.1 This release

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page