Row-Level Security at Scale

Case study · Access control

A public-sector reporting platform where security was the hard part: every person had to see their own slice of the data and nothing beyond it. I designed the entitlement layer that decided which rows any given user could reach.

At a glance

The problem

Reporting for a public administration carries security requirements that are not negotiable: a user sees the data they are responsible for and nothing else. Geography was the usual boundary, with a team accountable for certain regions seeing only those.

The organisation already knew who everyone was. An identity store held the users, their groups, and which applications each group could reach. What did not exist was the link to the analytics: nothing said which rows a group was entitled to. Filling that gap by hand, per workbook, would have been laborious and impossible to trust.

The architecture

How an entitlement resolves

From an account in the identity store to the rows a person is allowed to see. The shaded columns are the part I designed and built.

Designed and built by meIdentityAutomationIAM storeEntitlement layerTableauResultuser accounts: Keyed by email addressuser accountsserver metadata: Projects and groups read from Tableau Serverserver metadatascheduled sync: Script on a VM, run on a schedulescheduled syncusersusersgroupsgroupsapplications: One per reporting projectapplicationsgroup × dimension: Which dimension values each group may seegroup × dimensionapp × folder: Which Tableau folder each application maps toapp × foldersecured model: Data model with the entitlement join appliedsecured modelwhat the user sees: Only the rows their group is entitled towhat the user sees

Names are simplified placeholders.

What I designed

The surrounding platform was a team effort: a scheduled script on a virtual machine pulled accounts into the identity store, and the server's own projects and groups were read back out to keep both sides in step.

My part was the layer that turns identity into data access. Two mappings do the work: one binds each user group to the dimension values it may see, the other binds each application to the folder its content lives in. Both resolve inside the data models I had built, so group membership decides a user's rows without any workbook implementing a rule.

How it resolves

User groupRows it may see
Group ARegion 1
Group BRegion 1, Region 2
Group CAll regions

Illustrative values. A user inherits their group's entitlement and the model returns only matching rows, so the same workbook shows different data to different people.

Design decisions