What you will be able to do
- Explain how ABAC uses governed tags so that one policy protects many tables at once
- Explain how tag inheritance works for catalogs, schemas, tables and columns, and how has_tag() and has_tag_value() behave in table conditions versus column conditions
- Identify the scope, principals, action and conditions in an ABAC policy
- Decide when to use an ABAC policy and when to use a table-level row filter or column mask
Key concept
Attribute-based access control (ABAC) policy — An ABAC policy is a row filter or column mask rule attached to a catalog, schema or table. Instead of naming each object it protects, it matches tables and columns by their governed tags. Any object in scope that has the right tags is covered automatically, including tables created later.
1.From per-object rules to attribute-based rules
Row-level and column-level security usually begins one table at a time: someone writes a filter for this table and a mask for that column. This works for a handful of tables. It stops working when a catalog holds hundreds of tables owned by different teams. Unity Catalog's attribute-based access control (ABAC) works the other way round. Access is determined by evaluating attributes associated with securable objects. Those attributes are governed tags, and the policy conditions use the tags to decide which data a policy protects.
Policies are attached at a level of the Unity Catalog hierarchy and evaluated dynamically. Whenever an object has the attributes a policy targets, the policy takes effect on it automatically. That is why ABAC is the tool for *central* control of sensitive data. A security team writes the rule once, high in the hierarchy, and every matching table inherits the protection.
ABAC supports four policy types: row filter policies, column mask policies, GRANT policies and DENY policies (Beta). This lesson covers the first two, which carry row-level and column-level security. Row filter policies restrict which rows a user can see. Column mask policies control how column values are presented to users.
The practical way to tell the types apart is the UDF. Row filter and column mask policies require a user-defined function (UDF) to implement the filtering or masking logic. GRANT and DENY policies don't use UDFs: they grant or deny privileges when their tag-based condition matches the target object's attributes. Conditions normally match on resource tags. To match on the attributes of the user running the query instead, or on the context of a request such as the calling application, the docs point to identity attribute functions and context attribute functions. Identity attributes are in Beta.
Checkpoint 1 of 6· Check yourself
An ABAC policy masks every column tagged PII in tables within schemas tagged HR. Next week a team creates a new table in an HR schema and tags one of its columns PII. What has to happen for the new column to be masked?
ABAC policies are evaluated dynamically against tags. A newly created object that carries the targeted tags is covered without any new policy definition.
“As new data objects are created and tagged, the policy applies automatically without requiring separate policy definitions for each object.”Source: docs.databricks.com
2.Governed tags: the attributes policies match on
In Unity Catalog, attributes are implemented as governed tags. These are key-value pairs, such as pii : ssn or sensitivity : high. They are defined at the account level and applied to securable objects like catalogs, schemas, tables and columns. Because they are defined at the account level, one tag taxonomy can be shared across the whole data estate, even across multiple metastores.
Tags flow downward. By default, securables inherit tags from their parent catalog or schema, and you can override inherited tags at every level except one.
The exception is the column level: column tags do not inherit from the parent table and must be applied directly. Policies test tags with two built-in functions. has_tag('tag_key') checks that a tag is present. has_tag_value('tag_key', 'tag_value') also checks its value. Both functions behave differently depending on where you use them:
- In a table condition (WHEN), they check tags set directly on the table or inherited from its catalog or schema.
- In a column condition (MATCH COLUMNS), they check tags set directly on the column only.
Use the snake_case names. The older camelCase forms still work, but they are not recommended and are planned for deprecation when creating new policies.
Checkpoint 2 of 6· Check yourself
A schema is tagged sensitivity : high. One table in that schema carries its own direct tag sensitivity : low. Which statement about the table's tag is correct?
Inheritance is a default, not a lock. A table can override a tag it inherits from its catalog or schema. Columns are the exception: they never inherit, so there is nothing to override.
“You can override inherited tags at every level except the column level”Source: docs.databricks.com
Sources2
3.Anatomy of a policy: scope, principals, action, conditions
Every ABAC policy answers four questions. The example below masks columns tagged PII in tables tagged HR anywhere in catalog_a, for everyone except HR admins.
CREATE FUNCTION mask_pii(val STRING) RETURNS STRING
RETURN '***';
CREATE POLICY mask_pii_for_hr
ON CATALOG catalog_a
COLUMN MASK mask_pii
TO `account users` EXCEPT `HR admins`
FOR TABLES
WHEN has_tag('HR')
MATCH COLUMNS has_tag('PII') AS pii_col
ON COLUMN pii_col;| Part | Clause | What it decides |
|---|---|---|
| Scope | ON CATALOG / SCHEMA / TABLE (METASTORE is Beta) | Where the policy is attached. It evaluates against that object and all of its descendants. |
| Principals | TO ... EXCEPT ... | The users, groups or service principals the policy applies to, and those exempt from it |
| Action | ROW FILTER or COLUMN MASK | Whether a UDF filters rows or masks column values |
| Conditions | WHEN, MATCH COLUMNS | Tag-based expressions that pick which tables and columns are targeted |
Row filter and column mask policies can be attached at CATALOG, SCHEMA or TABLE scope. Metastore-level attachment is in Beta. Databricks recommends attaching policies at the highest applicable level, usually the catalog. Principals in the EXCEPT list are not subject to the policy and see the full, unmodified data.
Creating, editing or deleting a policy requires MANAGE on the securable object, or ownership of it. Policies can be managed in the Catalog Explorer UI (the Policies tab on a catalog, schema or table), with SQL statements such as CREATE POLICY, DROP POLICY, SHOW POLICIES and DESCRIBE POLICY, or through REST APIs, SDKs and Terraform.
Checkpoint 3 of 6· Match them up
Match each clause to the job it does in an ABAC policy
Tap a term, then the definition that fits it.
Scope comes from ON, principals from TO and EXCEPT, and the table-level tag condition from WHEN.
“The TO clause specifies the users, groups, or service principals subject to the policy.”Source: docs.databricks.com
Checkpoint 4 of 6· Exam question
In Unity Catalog, what is the defining characteristic of an ABAC (attribute-based access control) policy compared to a standard `GRANT` statement on an object?
Correct answer: A — ABAC policies evaluate governed tags attached to catalogs, schemas, tables, or columns to decide row visibility and masking at query time.
- A. This is correct: ABAC policies key off governed tags rather than fixed object names, so Databricks re-evaluates row filtering and column masking dynamically as tags on catalogs, schemas, tables, or columns change. This is what lets one policy govern many objects at once.
- B. This is incorrect. ABAC policies govern row-level and column-level visibility for principals who already have access; identity-based `GRANT`/`REVOKE` privileges still control whether a principal can access a securable object at all.
- C. This is incorrect. ABAC policies are designed to scale across many principals and objects through `TO`/`EXCEPT` group clauses and tag matching, which is the opposite of requiring one policy per individual user.
- D. This is incorrect. ABAC policies are evaluated dynamically against current tag state at query time, so they automatically pick up newly tagged objects without any manual recreation.
4.Why ABAC gives central control: comparing it with table-level filters and masks
Unity Catalog offers two ways to apply row-level and column-level security. Both sit on top of ordinary GRANTs. The difference is where the restriction is defined and who controls it. A table-level filter or mask is set with ALTER TABLE on one table, and the table owner can modify or remove it. An ABAC policy lives on the catalog or schema and is evaluated by Unity Catalog before the query reaches the runtime. Individual table owners can't remove, modify or bypass it. This is the property that lets a security team impose one rule on tables owned by many different teams.
| Consideration | ABAC policies | Table-level row filters and column masks |
|---|---|---|
| SQL syntax | CREATE POLICY ... ON CATALOG/SCHEMA/TABLE | ALTER TABLE ... SET ROW FILTER / ALTER TABLE ... ALTER COLUMN ... SET MASK |
| Scope | All tables in scope and its descendants; new tagged tables covered automatically | A single table, configured individually |
| Dynamic matching | Yes, by governed tags with has_tag() and has_tag_value() | No; bound to specific tables and columns |
| Targeted principals | TO/EXCEPT clauses, plus identity functions in the UDF | Identity functions like current_user() in the UDF |
| Governance | Set by catalog or schema owners; table owners cannot override them | Managed by table owners, who can modify or remove them |
| Effective policies | SHOW EFFECTIVE POLICIES shows which policies apply to a given table and user | Directly visible on the table definition |
| Auditability | DESCRIBE POLICY and SHOW POLICIES to inspect policy definitions | INFORMATION_SCHEMA.ROW_FILTERS and INFORMATION_SCHEMA.COLUMN_MASKS |
Choose ABAC when you need consistent rules across many tables, schemas or catalogs; when policy authors and the data stewards who tag data are separate people; or when a growing estate should be covered as soon as new tables are tagged. Table-level filters and masks suit a small, stable set of tables with specific logic that owners manage themselves.
The two approaches can co-exist on the same table, but only one distinct row filter can apply, and only one distinct column mask can be resolved per column. Databricks detects a conflict by comparing the functions applied, not their output.
Dynamic views are a third option. They implement row-level and column-level security by embedding identity functions such as current_user() and is_account_group_member() in the view definition. They fit fine-grained access control that spans multiple source tables or reshapes data for sharing, and they support query optimization and predicate pushdown. The cost is a new object: the logic lives in a view you must create and maintain. Row filters and column masks, whether set by ABAC policies or at table level, control access on individual tables without introducing new objects. A dynamic view also has no tag-based matching, so it does not give you the policy that follows new tagged tables around.
Checkpoint 5 of 6· Check yourself
For the same user and table, an ABAC policy applies mask function mask_a to a column and a table-level mask applies a different function, mask_b, to the same column. Both return '***'. What happens when the user queries the table?
Conflict is judged by the function, not the result. Two different functions on one column for one user is a conflict, and Databricks blocks access.
“If they apply different functions, Databricks blocks access and returns an error, even if those functions produce identical data output.”Source: docs.databricks.com
Checkpoint 6 of 6· Exam question
A retail company tags many tables across a catalog with `sensitivity = high` and tags the relevant column in each of those tables with `geo_region`. The governance team wants European customer rows hidden from the `us_analysts` group everywhere this pattern occurs, without editing every individual table. Which approach satisfies this requirement?
Correct answer: A — Create one ABAC row filter policy on the catalog using `WHEN has_tag_value('sensitivity','high')` and `MATCH COLUMNS has_tag('geo_region')`, scoped `TO us_analysts`.
- A. This is correct: attaching one ABAC row filter policy at the catalog level, scoped with `WHEN` to only tagged tables and `MATCH COLUMNS` to the tagged region column, applies the filter everywhere the tag pattern exists without touching individual tables.
- B. This is incorrect. Writing and attaching a row filter per table works but is exactly the per-table maintenance burden the governance team wants to avoid, and it does not scale as new tagged tables are added.
- C. This is incorrect. Blocking access to entire tables that contain any European rows removes visibility into legitimate non-European rows in the same table, which does not meet the row-level filtering requirement.
- D. This is incorrect. Building and maintaining a filtering view per table reintroduces per-table object management and requires re-pointing grants to views, which is the overhead the team is trying to eliminate.
Sources4
Exam traps
Each one states something that sounds right. Open it to see what is actually true.
1.Tagging a table or schema
PIImeansMATCH COLUMNS has_tag('PII')will match its columns through inheritance.Why is that wrong?Catalogs, schemas and tables inherit tags, but columns do not. A column condition matches only tags applied directly to the column.
2.Naming a group in an ABAC policy's TO clause gives that group access to the matched tables.Why is that wrong?
ABAC row filter and column mask policies only restrict data. Users still need object-level privileges granted separately before they can query at all.
Covered in Why ABAC gives central control: comparing it with table-level filters and masks
3.A table owner can remove a catalog-level ABAC policy from their own table in the same way they can drop their own table-level row filter.Why is that wrong?
A policy set at a higher level is outside the table owner's control. Only table-level filters and masks are managed by table owners.
Covered in Why ABAC gives central control: comparing it with table-level filters and masks
Sources
Every claim above is drawn from one of these pages, quoted as it was written on the date shown.
- 1.
“access is determined by evaluating attributes associated with securable objects”
↩︎ From per-object rules to attribute-based rules“a single policy can enforce consistent access rules across an entire metastore, catalog, or schema”
↩︎ Key concept - 2.
“Row filter policies restrict which rows a user can see. Column mask policies control how column values are presented to users.”
↩︎ From per-object rules to attribute-based rules“GRANT and DENY policies don't use UDFs, and instead grant or deny privileges when their tag-based condition matches”
↩︎ From per-object rules to attribute-based rules“Governed tags are key-value pairs defined at the account level and applied to Unity Catalog securable objects”
↩︎ Governed tags: the attributes policies match on“By default, securables inherit tags from their parent catalog or schema.”
↩︎ Governed tags: the attributes policies match on“For row filter and column mask policies, supported policy scopes are CATALOG, SCHEMA, or TABLE.”
↩︎ Anatomy of a policy: scope, principals, action, conditions“Databricks recommends attaching policies at the highest applicable level, usually the catalog, to maximize governance efficiency.”
↩︎ Anatomy of a policy: scope, principals, action, conditions“column tags do not inherit from the parent table and must be applied directly.”
↩︎ Exam trap 1“As new data objects are created and tagged, the policy applies automatically without requiring separate policy definitions for each object.”
↩︎ Checkpoint“Tags don't propagate from tables to columns.”
↩︎ Prediction“You can override inherited tags at every level except the column level”
↩︎ Checkpoint“The TO clause specifies the users, groups, or service principals subject to the policy.”
↩︎ Checkpoint - 3.
“Modifying policies (create, edit, delete) requires MANAGE on the securable object or object ownership.”
↩︎ Anatomy of a policy: scope, principals, action, conditions - 4.
“The policy lives on the catalog and is evaluated by Unity Catalog before the query reaches the runtime.”
↩︎ Why ABAC gives central control: comparing it with table-level filters and masks“Only one distinct row filter can apply.”
↩︎ Why ABAC gives central control: comparing it with table-level filters and masks“Use row filters and column masks when you want to control access on individual tables without introducing new objects.”
↩︎ Why ABAC gives central control: comparing it with table-level filters and masks“You must grant base table access separately through object-level permissions (GRANT).”
↩︎ Exam trap 2“individual table owners can't remove, modify, or bypass it.”
↩︎ Exam trap 3“Neither approach grants access to data on its own”
↩︎ Prediction“If they apply different functions, Databricks blocks access and returns an error, even if those functions produce identical data output.”
↩︎ Checkpoint