SnowPro Advanced Architect study materials
SnowPro Advanced Architect study resources

Tag-Based Masking, Residual Grants, and Audit Evidence

SnowPro Advanced Architect · Put your knowledge to work in context.

All case studies

Tag-Based Masking, Residual Grants, and Audit Evidence

HealthCo holds 60 TB in one database with HIPAA-regulated columns: MEMBER_SSN, MEMBER_DOB, and DIAGNOSIS_CODE. Three roles matter: ANALYST must see SSN and DOB masked; CLINICAL must see full values but only for its own REGION; BREAK_GLASS needs full data for a maximum of four hours per incident. A tag named PII carries a tag-based masking policy. Several older tables also carry column-level masking policies written before the tag existed. Last week a new column, MEMBER_SSN_RAW, was added to a table by an engineer and is currently returning unmasked values to ANALYST. Separately, CLINICAL users can see other regions' rows through a view that is supposed to filter by region. Auditors want an inventory of every object holding member data, plus evidence that BREAK_GLASS use is logged and time-limited.

1. Why is MEMBER_SSN_RAW unmasked, and what governance change prevents the next one?

Read the worked answer

Tag-based masking is only as strong as tag coverage. A new column does not inherit a tag, and no masking policy is attached to it, so it returns raw values. The tag is a label on a column, not a rule about column names.

There is a second trap worth checking first: when a column carries both a column-level masking policy and a tag with a tag-based policy, the column-level policy takes precedence. The legacy policies on older tables mean HealthCo is effectively running two masking systems, and which one wins depends on the column. That is unmaintainable and it hides gaps.

Prevention plan:

  • Collapse to one mechanism. Inventory existing column-level policies against POLICY_REFERENCES, migrate their logic into the tag-based policy, then drop the redundant column policies so behavior is predictable.
  • Automate detection. Run Snowflake's sensitive data classification on a schedule over the database; it identifies likely PII columns and can propagate tags. Alert on any column in a PII-bearing table that lacks the PII tag or a mask.
  • Gate the change. Add ALTER TABLE ... SET TAG to the table-creation template and to CI checks, so a column added outside the template fails review rather than silently exposing data.
  • Report weekly. A query over TAG_REFERENCES joined to COLUMNS that lists untagged columns in tables where any sibling column is PII-tagged. MEMBER_SSN_RAW would have surfaced the day it was created.

2. CLINICAL can see other regions' rows through a view that is supposed to filter by region. What is the likely cause and the durable fix?

Read the worked answer

A region filter implemented as a WHERE clause in one view is a control on a path, not on the data. The classic cause is that CLINICAL also holds direct SELECT on the base table - granted for an earlier project - so members simply query the table and bypass the view entirely. Other paths that produce the same symptom: a second view created before the filter was added, a clone of the table made for testing, or a role hierarchy where CLINICAL inherits a role with broader access.

Diagnose before fixing: SHOW GRANTS ON TABLE <base_table> and SHOW GRANTS TO ROLE CLINICAL to enumerate inherited roles, plus POLICY_REFERENCES to confirm which tables actually carry a row access policy.

The durable fix is to move enforcement down to the base table with a row access policy whose body maps CURRENT_ROLE() (or CURRENT_USER()) to a region set via a small mapping table. Then every path - direct query, view, clone, future view written by someone who has never heard of the rule - is filtered identically. Afterwards, revoke direct SELECT from CLINICAL so the policy is the only thing standing between the role and the rows, and note that multiple row access policies on different columns combine with AND, which is fine here but will surprise you if a second policy is added later.

Watch the failure mode: if the mapping lookup returns no row for a role, the policy filters everything and the role sees zero rows. That is the correct, safe direction - document it so the first support ticket is not diagnosed as an outage.

3. How would you produce the auditor's inventory and prove BREAK_GLASS access is logged and time-bound?

Read the worked answer

Inventory. Three sources, triangulated:

  • TAG_REFERENCES for every column carrying the PII tag, including inherited database and schema tags.
  • Sensitive data classification results for columns that should be tagged and are not - this is the coverage argument, and it is what auditors actually care about.
  • POLICY_REFERENCES for which masking and row access policies are attached where, so you can show there are no unprotected copies.

Read evidence. ACCESS_HISTORY gives column-level read records - who queried MEMBER_SSN, under which role, at what time, and from which query - retained for up to 365 days. Pair it with LOGIN_HISTORY for session context. This is the only defensible answer to 'prove nobody read this outside the approved group.'

Time-bound BREAK_GLASS. Snowflake has no native expiring grant, so compose it:

  • A session policy limiting session duration and idle time, so an unlocked session cannot persist indefinitely.
  • An authentication policy requiring MFA for the role.
  • Automation - a scheduled task or external workflow triggered by an ITSM ticket - that revokes the role after the authorized window, with the revocation itself logged.
  • An alert on any ACCESS_HISTORY row for BREAK_GLASS, routed to security, so use is reviewed rather than merely recorded.

Present the auditor with a control narrative: the role is locked by default, unlocking is ticketed, sessions expire, and every access attempt is queryable. That is stronger evidence than a policy document.