Fine-Grained Access Control: Privileges, Row Filters, and Column Masks
Who this is for:
Architecture / Concept Overview: Fine-Grained Access Control: Privileges, Row Filters, and Column Masks
Fine-grained access control in Unity Catalog operates at three levels: object privileges control who can access which objects, row filters control which rows a user sees, and column masks control what values appear in specific columns.
%%{init: {"theme":"base","themeVariables":{"background":"#0B0E14","primaryTextColor":"#E0E6ED","lineColor":"#5D6470","darkMode":true,"primaryColor":"#2E4A4A","secondaryColor":"#374151","secondaryTextColor":"#E0E6ED","tertiaryColor":"#111827","tertiaryTextColor":"#E0E6ED","edgeLabelBackground":"#1f2937"}}}%%
flowchart LR
classDef source fill:#3F4B59,stroke:#9CA3AF,stroke-width:2px,rx:8,ry:8,color:#E0E6ED
classDef ingestion fill:#5A4B36,stroke:#C9A86B,stroke-width:2px,rx:8,ry:8,color:#E0E6ED
classDef processing fill:#535072,stroke:#8E82B4,stroke-width:2px,rx:8,ry:8,color:#E0E6ED
classDef storage fill:#2E4A4A,stroke:#5FAFA8,stroke-width:2px,rx:8,ry:8,color:#E0E6ED
classDef serving fill:#3D5550,stroke:#6BB7AA,stroke-width:2px,rx:8,ry:8,color:#E0E6ED
classDef governance fill:#5A3F52,stroke:#C28BB0,stroke-width:2px,rx:8,ry:8,color:#E0E6ED
QUERY[User Query] --> PRIV[Privilege Check<br/>Does user have SELECT?]
PRIV -->|Yes| RF[Row Filter<br/>Which rows can they see?]
RF --> CM[Column Mask<br/>What values do they see?]
CM --> RESULT[Filtered & Masked Results]
PRIV -->|No| DENIED[Access Denied]
QUERY:::source
PRIV:::governance
RF:::governance
CM:::governance
RESULT:::serving
DENIED:::source
*Figure 1 — Three-layer access enforcement: privilege check, row filter application, column mask application — evaluated in sequence for every query.*
Row filters and column masks are SQL functions registered in Unity Catalog and attached to tables.
%%{init: {"theme":"base","themeVariables":{"background":"#0B0E14","primaryTextColor":"#E0E6ED","lineColor":"#5D6470","darkMode":true,"primaryColor":"#2E4A4A","secondaryColor":"#374151","secondaryTextColor":"#E0E6ED","tertiaryColor":"#111827","tertiaryTextColor":"#E0E6ED","edgeLabelBackground":"#1f2937"}}}%%
graph TD
classDef source fill:#3F4B59,stroke:#9CA3AF,stroke-width:2px,rx:8,ry:8,color:#E0E6ED
classDef ingestion fill:#5A4B36,stroke:#C9A86B,stroke-width:2px,rx:8,ry:8,color:#E0E6ED
classDef processing fill:#535072,stroke:#8E82B4,stroke-width:2px,rx:8,ry:8,color:#E0E6ED
classDef storage fill:#2E4A4A,stroke:#5FAFA8,stroke-width:2px,rx:8,ry:8,color:#E0E6ED
classDef serving fill:#3D5550,stroke:#6BB7AA,stroke-width:2px,rx:8,ry:8,color:#E0E6ED
classDef governance fill:#5A3F52,stroke:#C28BB0,stroke-width:2px,rx:8,ry:8,color:#E0E6ED
TBL[Table: customers] --> RF[Row Filter Function<br/>region_filter]
TBL --> CM1[Column Mask: email<br/>email_mask]
TBL --> CM2[Column Mask: ssn<br/>ssn_mask]
RF --> LOGIC1[Returns TRUE/FALSE<br/>based on IS_MEMBER or current_user]
CM1 --> LOGIC2[Returns masked value<br/>e.g. j***@example.com]
CM2 --> LOGIC3[Returns masked value<br/>e.g. ***-**-1234]
TBL:::storage
RF:::governance
CM1:::governance
CM2:::governance
LOGIC1:::processing
LOGIC2:::processing
LOGIC3:::processing
*Figure 2 — Row filter and column mask functions bound to a table, each encoding access logic based on user identity or group membership.*
Key Terms
Prerequisites and Setup
- Unity Catalog enabled with schemas containing the target tables
MODIFYprivilege on the table (to attach row filters and column masks)CREATE FUNCTIONprivilege on the schema (to create filter/mask functions)- Premium or Enterprise tier (row filters and column masks require Premium)
Step-by-Step Implementation
Configuration Reference
| Privilege | Scope | Description |
|---|---|---|
SELECT | Table/View | Read data |
MODIFY | Table | Insert, update, delete data |
CREATE TABLE | Schema | Create new tables |
ALL PRIVILEGES | Any securable | Full control (use sparingly) |
USE CATALOG | Catalog | Required to access any child object |
USE SCHEMA | Schema | Required to access any table in the schema |
| Row filter | Table | SQL function returning BOOLEAN per row |
| Column mask | Column | SQL function returning the column's data type |