What you will be able to do
- Explain how Databricks Data Classification detects PII and how detection differs from automatic tagging
- Identify the privileges needed to enable classification, enable auto-tagging, and create masking policies
- Write an ABAC column mask policy that matches columns by governed tag and applies a masking UDF
- Use the control-tag pattern so that new tables stay fully masked until a steward has reviewed them
Key concept
Governed tags link detection to enforcement — Detection writes governed tags such as class.us_ssn onto columns. ABAC policies attached at a catalog or schema then mask whatever carries those tags, so protection follows the tag instead of a list of tables.
1.Detecting PII with Data Classification
A pipeline can't mask PII that nobody has found. In Unity Catalog, Databricks Data Classification does the finding. It uses an agent, helped by a large language model, to classify the tables in a catalog. Scanning is incremental, so new data is classified without manual setup. Scans also go beyond plain Delta tables. By default Data Classification covers tables, streaming tables and materialized views, so one detector handles both what batch jobs write and what streaming pipelines publish. New tables and columns are usually scanned within 24 hours of being created.
Detections are expressed as class.* system governed tags, for example class.name, class.email_address and class.us_ssn. The tags are grouped by compliance framework (PII, PCI DSS, GDPR, HIPAA and others), and there are regional tags such as class.uk_nino and class.in_aadhaar. You don't need any custom tags for column-level detection.
The results page lists every classification with its detected columns, its auto-tagging status, its compliance frameworks, and an Unmasked user access (last 7d) metric that shows how exposed the data is. Clicking Review opens the detected columns with sample values. Use the Exclude icon on any false positive, and only then enable automatic tagging. Tagging is not instant: after you enable it, tags populate in the next scan, within about 24 hours, so a detected column stays untagged (and unmasked by any tag-based policy) until then. Auto-tagging can be set at metastore level or catalog level, and the catalog setting overrides the metastore one. For a single catalog, the same panel also lets you create an ABAC policy straight from a classification.
The privileges differ for each action. One default is a common trap: only account admins hold MANAGE and ASSIGN on the data classification system governed tags until they grant them to other users, service principals or groups.
| Action | Required privileges |
|---|---|
| Enable data classification on a catalog | Own the catalog, or MANAGE on it |
| Enable automatic tagging (catalog level) | USE CATALOG and APPLY TAG on the catalog, plus ASSIGN on the tag |
| Enable automatic tagging (metastore level) | Be a metastore admin and have ASSIGN on the tag |
| View classification results | MANAGE, or READ METADATA, or USE CATALOG + USE SCHEMA + SELECT on the catalog |
| MANAGE and ASSIGN on data classification system governed tags | Account admins by default; they can grant them for individual governed tags to other users, service principals, or groups |
Checkpoint 1 of 6· Check yourself
A Lakeflow pipeline publishes a streaming table into a catalog that has Data Classification enabled, and view scanning is not turned on. Is the streaming table scanned?
Streaming tables and materialized views are part of the default scan scope. The preview only adds regular Unity Catalog views.
“By default, Data Classification scans tables, streaming tables, and materialized views.”Source: docs.databricks.com
Checkpoint 2 of 6· Exam question
A platform team must guarantee that every column classified as an email address, in every schema of the `analytics` catalog, is masked for anyone outside the `pii_readers` account group — and that the rule applies automatically to new tables data engineers create next quarter without a follow-up change. Which two actions correctly use Unity Catalog ABAC to meet this requirement? (Select 2)(Select 2)
Correct answers: A, B — Define a governed tag such as `pii_category=email` and create a catalog-level column mask policy with `FOR COLUMNS` matching that tag, so it attaches once and enforces on every current and future tagged column automatically.; Tag each qualifying column directly with `pii_category=email`, since Unity Catalog column-level tags are not automatically inherited from the parent table even when the table itself already carries the same tag.
- A. This is the core ABAC pattern: a governed tag identifies the attribute, and a policy scoped with `FOR COLUMNS` at the catalog level automatically evaluates against every matching column across current and future descendants, which is exactly what "applies without a follow-up change" requires.
- B. Governed tags applied to a table are not automatically inherited by that table's columns, unlike catalog and schema tags which do cascade down to child objects. Tagging the columns explicitly is necessary for a column-scoped ABAC policy to match them.
- C. Manually altering each table's mask is the per-object approach ABAC is meant to replace, and it explicitly fails the "applies automatically to new tables" requirement since every future table needs its own manual statement.
- D. A DENY policy revokes a privilege outright rather than transforming a value, so it would block access to the column entirely instead of masking it, and matching on column name substrings ignores the governed-tag mechanism the requirement calls for.
- E. ABAC policies attach at the catalog or schema level specifically so narrower, more specific tag conditions can refine enforcement across descendants; defining everything at the metastore level does not match how ABAC policy scoping is described, and metastore-wide scope is not the recommended pattern here.
- F. Unity Catalog row filters and column masks cannot be applied to views, and building a parallel dynamic-view layer duplicates enforcement logic per schema instead of using the reusable, auto-applying governed-tag and policy mechanism ABAC provides.
2.Turning tags into masks with ABAC policies
A tag by itself hides nothing. Enforcement comes from an ABAC policy. The policy is attached to a securable (catalog, schema or table; metastore-level attachment is in Beta), selects columns by their tags, and runs a masking function on them. Creating a policy needs Databricks Runtime 16.4 or above or serverless compute, MANAGE on (or ownership of) the securable the policy attaches to, and EXECUTE on the UDF that holds the masking logic. Here is the documented column mask policy:
CREATE FUNCTION ssn_to_last_nr (ssn STRING, nr INT) RETURNS STRING
RETURN right(ssn, nr);
CREATE POLICY mask_ssn
ON SCHEMA prod.customers
COLUMN MASK ssn_to_last_nr
TO us_analysts EXCEPT admins
FOR TABLES
MATCH COLUMNS has_tag_value('pii', 'ssn') AS ssn
ON COLUMN ssn
USING COLUMNS (4);Here is what each clause does. TO names the principals the policy applies to, and EXCEPT exempts principals, who then see unmodified data. An optional WHEN clause decides which tables the policy applies to, based on table tags. MATCH COLUMNS then selects columns with has_tag / has_tag_value. A policy can have up to three of these expressions, and all of them must match for the policy to apply. That is different from combining conditions with AND, OR and NOT inside a single expression, which decides whether one column matches. ON COLUMN chooses which matched alias to mask. USING COLUMNS passes arguments to the UDF, here the constant 4.
The masking method lives in the UDF, and its return type must be castable to the column's type. The sources show two approaches. The first is partial suppression, like right(ssn, nr) above. The second is the built-in system.data_classification.mask_value, a type-aware masking function that returns 0 for integers, DATE '1970-01-01' for dates and a SHA-256 hash for strings.
Checkpoint 3 of 6· Check yourself
A policy uses two MATCH COLUMNS expressions: has_tag_value('pii','ssn') and has_tag('class.us_ssn'). When does the policy apply?
A policy can have up to three MATCH COLUMNS expressions, and every one must match for the policy to apply. Table selection is the job of WHEN. Use OR inside a single expression when you mean 'either'.
“A policy can include up to 3 MATCH COLUMNS expressions, and all must match for the policy to apply.”Source: docs.databricks.com
Streaming and pipeline workloads add a wrinkle: there are two identity contexts. When a pipeline refreshes a materialized view or streaming table, ABAC policies are evaluated with the pipeline owner's or run-as identity. If that identity is subject to a policy, the table permanently contains masked or filtered data. To avoid this, add the pipeline owner or run-as identity to the EXCEPT clause of the policies on every table the pipeline reads, and use TO to say who receives masked data. Only exempt trusted identities such as ETL service principals, because exempted principals see unmasked data. At query time it is different: functions that check user context, such as CURRENT_USER and IS_MEMBER, are evaluated using the invoker's context, so each analyst gets their own masking.
You can also mask directly in a streaming table definition, for example when ingesting from cloud files or from another streaming table. This per-table form is managed through CREATE OR REFRESH:
CREATE OR REFRESH STREAMING TABLE customers_silver (
id int COMMENT 'This is the customer ID',
name string,
region string,
ssn string MASK catalog.schema.ssn_mask_fn COMMENT 'SSN masked for privacy'
)
WITH ROW FILTER catalog.schema.us_filter_fn ON (region)
AS SELECT * FROM STREAM(customers_bronze)Checkpoint 4 of 6· Exam question
A Lakeflow Spark Declarative Pipeline publishes a streaming table `silver.customers` from a bronze source. The `email` column has a Unity Catalog column mask whose SQL UDF calls `is_account_group_member('pii_readers')` to decide whether to reveal or hash the value. After deploying the pipeline, every analyst who queries `silver.customers` — regardless of their own group membership — sees the exact same masking outcome, and it only changes after the next scheduled pipeline refresh. What explains this behavior? ```sql CREATE FUNCTION mask_email(email STRING) RETURN CASE WHEN is_account_group_member('pii_readers') THEN email ELSE sha2(email, 256) END; ```
Correct answer: A — Row filter and column mask functions attached to a streaming table run with the pipeline owner's rights during each refresh, so `is_account_group_member()` resolves against the owner's groups, baking the masked value in until the next refresh.
- A. During a Lakeflow refresh, row filter and column mask functions execute with the pipeline owner's identity, so user-context calls like `is_account_group_member()` are evaluated once against the owner's group memberships rather than per querying analyst. The resulting masked or unmasked value is materialized into the streaming table and stays fixed for all viewers until the next refresh recomputes it.
- B. This is incorrect: Lakeflow Spark Declarative Pipelines support row filters and column masks on streaming tables and materialized views, and the mask function does execute during the refresh. The scenario's symptom (one fixed outcome for everyone) is consistent with the mask running, not being skipped.
- C. There is no such split between batch and streaming consumers for column mask enforcement — the mask is evaluated when the table is refreshed by the pipeline, not selectively per downstream query engine. This distinction does not reflect how Unity Catalog masking is applied to streaming tables.
- D. Row filters and column masks are independent controls that can both be attached to the same table; one does not silently override or disable the other. Nothing in the scenario indicates a row filter is even present, so this does not explain the observed behavior.
3.Closing the gap: secure new tables by default
There's still a window of exposure. A new table can take up to 24 hours to be scanned, and tags from auto-tagging populate in the next scan, so until it's tagged, any user with SELECT on the schema can read its raw PII. Databricks' control-tag pattern closes that window. You create a governed tag review_status with the values pending and reviewed, then set review_status = 'pending' on the schema. Every table created in that schema inherits the tag. A first policy masks every column of any table still marked pending. Remember that by default only account admins have MANAGE and ASSIGN on the classification system tags, so make sure whoever enables auto-tagging has been granted ASSIGN on them.
Checkpoint 5 of 6· Fill the gap
Which token makes this policy mask every column of a pending table, whatever its tags?
CREATE POLICY review_pending_policy
ON SCHEMA abac_tutorial.secure_default
COLUMN MASK system.data_classification.mask_value
TO `account users`
FOR TABLES
WHEN has_tag_value('review_status', 'pending')
MATCH COLUMNS ? AS m ON COLUMN m;MATCH COLUMNS TRUE matches every column regardless of tags. The WHEN clause restricts the policy to tables tagged pending.
Source: docs.databricks.comData Classification scans in the background and, once auto-tagging is on, applies class.* tags. A steward reviews those tags and corrects false positives. The steward then sets review_status to reviewed on the table itself, which overrides the tag inherited from the schema. A second policy now applies and masks only the classified columns:
CREATE POLICY review_complete_policy
ON SCHEMA abac_tutorial.secure_default
COLUMN MASK system.data_classification.mask_value
TO `account users`
FOR TABLES
WHEN has_tag_value('review_status', 'reviewed')
MATCH COLUMNS (
has_tag('class.name')
OR has_tag('class.email_address')
OR has_tag('class.us_ssn')
OR has_tag('class.phone_number')
OR has_tag('class.credit_card')
OR has_tag('class.date_of_birth')
) AS m
ON COLUMN m;Checkpoint 6 of 6· Put it in order
Put the lifecycle of a new table under the control-tag pattern in order
- 1.Table is created and inherits review_status = pending from the schema
- 2.A steward reviews the classifications and corrects false positives
- 3.The steward sets review_status to reviewed on the table, and only class.*-tagged columns stay masked
- 4.Data Classification applies class.* tags to detected sensitive columns
- 5.All columns are masked by the pending policy
The schema tag protects the table from the moment it exists. Classification and review come next, and the table-level reviewed tag hands control to the second policy.
“After a data steward reviews the classifications and corrects any false positives, they flip review_status to reviewed at the table level.”Source: docs.databricks.com
Exam traps
Each one states something that sounds right. Open it to see what is actually true.
1.As soon as Data Classification detects PII, the column is tagged and ready for ABAC policies.Why is that wrong?
Detection and tagging are separate. You review the detections, then enable automatic tagging for each classification. Only after that are existing and future detections tagged.
Covered in Detecting PII with Data Classification
2.Several MATCH COLUMNS expressions in one policy are ORed, so a column that matches any of them is masked.Why is that wrong?
Every MATCH COLUMNS expression must match for the policy to apply. To mean 'either', combine the conditions with OR inside one expression, as review_complete_policy does.
Covered in Turning tags into masks with ABAC policies
3.A pipeline's service principal needs no exemption, because masking is applied per analyst at query time anyway.Why is that wrong?
Pipeline refreshes evaluate ABAC policies with the pipeline owner's or run-as identity. If that identity is masked, the streaming table or materialized view permanently stores masked data, so exempt it with EXCEPT.
Covered in Turning tags into masks with ABAC policies
Sources
Every claim above is drawn from one of these pages, quoted as it was written on the date shown.
- 1.
“Databricks Data Classification uses an agent to automatically classify and tag tables in your catalog.”
↩︎ Detecting PII with Data Classification“New tables and columns in a catalog are typically scanned within 24 hours of being created.”
↩︎ Detecting PII with Data Classification“To enable data classification, you must own the catalog or have the MANAGE privilege on it.”
↩︎ Detecting PII with Data Classification“Catalog-level settings take precedence over the metastore-level setting.”
↩︎ Detecting PII with Data Classification“By default, only account admins have MANAGE and ASSIGN permissions on data classification system governed tags.”
↩︎ Detecting PII with Data Classification“By default, only account admins have MANAGE and ASSIGN permissions on data classification system governed tags.”
↩︎ Closing the gap: secure new tables by default“When automatic tagging is enabled, all existing and future detections of this classification are tagged.”
↩︎ Exam trap 1“When automatic tagging is enabled, all existing and future detections of this classification are tagged.”
↩︎ Prediction“By default, Data Classification scans tables, streaming tables, and materialized views.”
↩︎ Checkpoint - 2.https://docs.databricks.com/aws/en/data-governance/unity-catalog/abac/secure-by-defaultOfficial docs
“Tags populate in the next scan (within 24 hours).”
↩︎ Detecting PII with Data Classification“For example, it returns 0 for integers, DATE '1970-01-01' for dates, and a SHA-256 hash for strings.”
↩︎ Turning tags into masks with ABAC policies“a schema-level review_status = pending tag causes every new table in the schema to be fully masked by default.”
↩︎ Closing the gap: secure new tables by default“MATCH COLUMNS TRUE matches every column regardless of tags.”
↩︎ Closing the gap: secure new tables by default“After a data steward reviews the classifications and corrects any false positives, they flip review_status to reviewed at the table level.”
↩︎ Checkpoint - 3.
“you must have MANAGE on the securable object where the policy is attached”
↩︎ Turning tags into masks with ABAC policies“Exempt principals are not subject to filtering or masking.”
↩︎ Turning tags into masks with ABAC policies“A policy can include up to 3 MATCH COLUMNS expressions, and all must match for the policy to apply.”
↩︎ Exam trap 2“A policy can include up to 3 MATCH COLUMNS expressions, and all must match for the policy to apply.”
↩︎ Checkpoint - 4.
“the materialized view or streaming table permanently contains masked or filtered data”
↩︎ Turning tags into masks with ABAC policies“the materialized view or streaming table permanently contains masked or filtered data”
↩︎ Exam trap 3 - 5.https://docs.databricks.com/aws/en/ldp/unity-catalogOfficial docs
“are evaluated using the invoker's user context”
↩︎ Turning tags into masks with ABAC policies
Also cited
“apply automatically to tables and columns based on governed tags”
↩︎ Key concept