CertSafari
    Snowflake SnowPro Advanced: Administrator (ADA-C02)· Lessons

    Domain 2 · Lesson 9/24

    Snowflake Masking, External Tokenization and Row Access Policies

    Implement and manage data governance in Snowflake.

    15 min read
    6% of exam
    10 sources
    Published 6 Oct 2026
    Docs as of 4 Oct 2026

    What you will be able to do

    • Create a masking policy and attach it to table and view columns
    • Choose between Dynamic Data Masking and External Tokenization for a business requirement
    • Create a row access policy and add it to a table or view
    • Predict how attaching a row access policy changes query behaviour, CTAS, materialized views and policy evaluation order
    • Explain why policies are preferred over secure views for governing access
    • Identify tagging use cases: compliance tracking, classification, tag-based protection at scale, propagation, certification and auditing

    Key concept

    Query-time policy enforcement — Masking and row access policies are schema-level objects that you attach to columns or tables. The stored data is never changed. Snowflake checks the policy each time a query runs, so different roles see different results from the same table.

    1.Column-level security with Dynamic Data Masking

    Column-level Security in Snowflake has two features: Dynamic Data Masking and External Tokenization. Both use the same kind of object, the masking policy. A masking policy lives in a schema, so a database and schema must exist before you can apply one to a column. It has one data type, one or more conditions, and one or more masking functions. You write it once and can apply it to any number of columns with a matching data type, across databases and schemas.

    At query time Snowflake rewrites the query. The policy expression replaces the column everywhere it appears, including projections, joins, WHERE, ORDER BY and GROUP BY. Depending on the conditions, a user sees the plain-text value, a partial mask or a full mask. The input and output data types must match. A policy that takes a timestamp cannot return a string such as ***MASKED***.

    A masking policy: the ANALYST role sees the real email, every other role sees a fixed masksql
    CREATE OR REPLACE MASKING POLICY email_mask AS (val string) RETURNS string ->
      CASE
        WHEN CURRENT_ROLE() IN ('ANALYST') THEN val
        ELSE '*********'
      END;

    Snowflake recommends that a security or privacy officer, not the object owner, administer masking. In the docs this is a custom MASKING_ADMIN role. Three privileges divide the work. By default, object owners can neither unset a masking policy nor see the masked column data. That separation of duties is the point of the feature. It can even keep ACCOUNTADMIN or SECURITYADMIN from viewing data they don't need. To change a policy, run ALTER MASKING POLICY. You don't need to reapply it, and the columns stay protected while you edit it.

    Masking policy privileges and what each controls
    PrivilegeGranted onControls
    CREATE MASKING POLICYSchemaWho can create masking policies
    APPLY MASKING POLICYAccountWho can set or unset masking policies on columns; ACCOUNTADMIN has it by default
    APPLYMasking policyOptional; lets a policy owner delegate set/unset of that one policy to object owners

    Checkpoint 1 of 6· Fill the gap

    Which keyword attaches the policy to the column?

    ALTER TABLE IF EXISTS user_info MODIFY COLUMN email  ?  MASKING POLICY email_mask;

    Sources123

    2.External Tokenization and when to choose it

    External Tokenization uses the same policy structure, with one difference: the policy body calls an external function. A third-party tokenization provider tokenizes the data before it is loaded into Snowflake, so the table stores undecipherable tokens rather than plain text. At query time the external function makes a REST API call to the provider. The provider evaluates its own tokenization policy and returns tokenized or detokenized data. Roles must be mapped in both Snowflake and the provider for this to work.

    An External Tokenization policy: PAYROLL gets detokenized values from the external function ssn_unprotect, and everyone else gets the stored tokensql
    CREATE MASKING POLICY employee_ssn_detokenize AS (val string) RETURNS string ->
      CASE
        WHEN CURRENT_ROLE() IN ('PAYROLL') THEN ssn_unprotect(VAL)
        ELSE val -- sees tokenized data
      END;

    To decide between them, ask what the business needs to be true about the stored data. With Dynamic Data Masking, the table holds plain text and the policy hides it at query time. With External Tokenization, the data is tokenized before loading, so users never see the real value even on a column that has no policy. The cost is more moving parts: an API integration, an external function, and a provider that must stay in sync with your identity provider and roles. Integrating a tokenization provider with Snowflake External Tokenization requires Enterprise Edition or higher. The privileges are mostly the same as for masking. In addition, the policy owner needs USAGE on the external function, and the function's owner needs USAGE on the API integration it references. A tokenization policy can also be assigned to a tag.

    Dynamic Data Masking vs External Tokenization
    AspectDynamic Data MaskingExternal Tokenization
    What is stored in SnowflakePlain text; no static maskingTokens created by a provider before loading
    Function in the policy bodyBuilt-ins such as SHA2 or REGEXP_REPLACE, or UDFsExternal function that calls the tokenization provider
    Column with no policy attachedPlain text is visibleUsers still see only tokens
    Extra dependenciesNone outside SnowflakeAPI integration, external function, third-party provider

    Checkpoint 2 of 6· Check yourself

    A regulator requires that card numbers are never stored in Snowflake in readable form, even if someone removes a policy by mistake. Which approach meets this requirement?

    Sources43

    3.Configuring a row access policy

    Masking controls what a user sees in a column. A row access policy controls which rows come back at all. It is a schema-level object whose expression returns a BOOLEAN. It applies to SELECT and to the rows chosen by UPDATE, DELETE and MERGE. It does not stop inserts, and it does not stop visible rows from being updated or deleted. The simplest policy only checks the role, which costs almost nothing in performance.

    The simplest row access policy: only the it_admin role sees any rowssql
    CREATE OR REPLACE ROW ACCESS POLICY rap_it
    AS (empl_id varchar) RETURNS BOOLEAN ->
      'it_admin' = current_role()
    ;

    For more detailed entitlements, the policy can look up a mapping table, for example sales managers mapped to regions, inside an EXISTS subquery. Keep that mapping table in the same database as the protected table. Mapping-table lookups are slower than simple CASE logic, and replacing them with a memoizable function improves performance. If role hierarchy matters, use IS_ROLE_IN_SESSION or IS_DATABASE_ROLE_IN_SESSION instead of CURRENT_ROLE. Snowflake evaluates the expression with the privileges of the policy owner, so the querying user doesn't need access to the mapping table.

    You attach the policy with ADD ROW ACCESS POLICY … ON (column). This works in CREATE TABLE and CREATE VIEW, or later with ALTER TABLE and ALTER VIEW. The listed columns are bound to the policy's signature arguments. One policy can protect many tables and views at once.

    Adding a row access policy to an existing tablesql
    ALTER TABLE t1 ADD ROW ACCESS POLICY rap_t1 ON (empl_id);

    Checkpoint 3 of 6· Check yourself

    A row access policy restricts the EMPLOYEES table so that HR_ANALYST sees only the EMEA rows. Which action is still possible for HR_ANALYST, assuming the role has the privilege?

    Sources5

    4.What changes when a row access policy is attached

    Once a policy is attached, every row of the object is protected by it, and queries run differently. Snowflake wraps the object in a dynamic secure view. EXPLAIN shows this as the operation DynamicSecureView on the object "<object_name> (+ RowAccessPolicy)", but it doesn't show the policy's name or expression. Some shortcuts stop working. Without a policy, SELECT COUNT(*) returns in milliseconds from metadata. With a policy, Snowflake has to scan the table to count the rows the current context can see. Bound columns are scanned even when the query doesn't reference them, so a policy with fewer arguments performs better.

    Attaching a policy also affects other features:

    - With masking: the row access policy is evaluated first, and the same column can't appear in both a row access policy signature and a masking policy signature. - Nested policies: the table's policy runs first, then each view's policy from left to right. - Copies: CREATE TABLE … LIKE gives an empty table with no policy. CTAS gives filtered rows with no policy. A clone maps to the same policies as the source. - Materialized views: you can't add a policy to a table that already has a materialized view built on it, and you can't build a materialized view on a protected table. A dynamic table is the suggested alternative. - Time Travel: supported on tables and views with a row access policy. Snowflake evaluates the policy's mapping tables at the time of the query, so Time Travel does not affect the mapping table.

    Checkpoint 4 of 6· Put it in order

    Put Snowflake's query-runtime steps for a row-access-protected table in order

    1. 1.Create a dynamic secure view (a secure inline view) of the object
    2. 2.Bind the specified column values to the policy parameters and evaluate the expression
    3. 3.Return only the rows for which the policy evaluates to TRUE
    4. 4.Determine whether a row access policy is set on the database object

    Sources5

    5.Row access policies compared with secure views

    Before policies existed, the usual way to restrict rows or columns was a secure view per audience. Snowflake's column-security docs list two problems with that approach. First, secure views multiply: you need many views, each with its own BI dashboards. Second, secure views have no segregation of duties, because whoever owns the view decides what it exposes. The row access policy docs make the matching case for row filtering. A central data administrator, not the object owner, decides which objects to protect. The policy restricts even the object owner. You write it once and apply it across databases and schemas. If it uses a mapping table, you can change entitlements by editing the table, without touching the policy.

    Under the hood, a row access policy *is* applied as a dynamic secure view that Snowflake builds at runtime. So the choice isn't between two filtering engines. It is a choice between hand-maintaining many view objects and maintaining one governed policy. ALTER ROW ACCESS POLICY updates the expression in place, and the table stays protected while it changes.

    Secure views compared with row access policies
    ConcernSecure viewsRow access policy
    Who decides protectionThe view owner; no segregation of dutiesA central administrator; the object owner is also restricted
    ScaleMany views and BI dashboards to manageWrite once, attach to tables and views across databases and schemas
    Changing the ruleEdit or recreate each viewALTER ROW ACCESS POLICY, no reattachment; or edit the mapping table
    Runtime mechanismThe view you definedA dynamic secure view that Snowflake generates

    Checkpoint 5 of 6· Match them up

    Match each statement to the mechanism it describes

    Tap a term, then the definition that fits it.

    Sources35

    6.Tagging use cases: tracking, classifying and protecting data

    A tag is a Snowflake object that you set on a database, schema, table, view or column, with a string value such as governance.tags.pii = 'sensitive'. A tag on its own hides nothing. It labels data so that other governance features can find it, track it and act on it. The sources describe these use cases:

    - Tracking sensitive data for compliance: after tracing where sensitive data moves with access history, set tags so that the stages, tables and columns holding it can be tracked for compliance requirements. The Account Usage TAG_REFERENCES view shows which tags are set on a table or its columns. - Classification: sensitive data classification labels each sensitive column with the system tags SNOWFLAKE.CORE.SEMANTIC_CATEGORY (for example NAME) and SNOWFLAKE.CORE.PRIVACY_CATEGORY (IDENTIFIER, QUASI_IDENTIFIER or SENSITIVE). You can map your own tags to these, and then track sensitive data across your account by tracking the tags. - Protecting data at scale with tag-based policies: assign a masking policy to a tag, then set the tag. Set on a database or schema, tag inheritance protects the matching columns of every table and view in it, including tables and views added later. Combined with classification, columns are masked automatically when classification applies the tag. A masking policy set directly on a column still takes precedence over one that comes from a tag. - Following data downstream: a tag can be configured to propagate on object dependency, on data movement, or both. The tag-based policy then protects those downstream objects as well. - Certifying trusted data: the built-in system tag SNOWFLAKE.CORE.CERTIFICATION_STATUS = 'CERTIFIED' marks a table or view as the authoritative source. - Auditing: ACCESS_HISTORY records tag updates, such as setting a tag or changing its value, in the object_modified_by_ddl column.

    Step 1 of tag-based masking: assign a masking policy to a tagsql
    ALTER TAG my_tag SET MASKING POLICY my_masking_policy;
    Step 2: set the tag on an object; any column protected by the tag's policy followssql
    ALTER TABLE my_table SET TAG my_tag = 'protected';

    Checkpoint 6 of 6· Check yourself

    A data steward wants every table later added to the finance.accounting schema to be masked automatically, without anyone tagging or masking each new table. Which approach does this?

    Sources678910

    Exam traps

    Each one states something that sounds right. Open it to see what is actually true.

    1. 1.When a table has both a masking policy and a row access policy, the masking policy is applied first.Why is that wrong?

      The row access policy is always evaluated first. Also, the same column cannot appear in both policy signatures.

      Covered in What changes when a row access policy is attached

    2. 2.A table created with CTAS from a protected table inherits the row access policy.Why is that wrong?

      CTAS copies only the rows the creator could see. The new table has no policy.

      Covered in What changes when a row access policy is attached

    3. 3.External Tokenization with a provider integration works on any Snowflake edition, like basic external functions.Why is that wrong?

      Integrating a tokenization provider with Snowflake External Tokenization requires Enterprise Edition or higher.

      Covered in External Tokenization and when to choose it

    4. 4.If a column has its own masking policy and also gets a tag that carries a masking policy, the tag-based policy wins.Why is that wrong?

      The masking policy set directly on the column takes precedence over the one assigned to the tag.

      Covered in Tagging use cases: tracking, classifying and protecting data

    Sources

    Every claim above is drawn from one of these pages, quoted as it was written on the date shown.

    1. 1.
      “a database and schema must exist in Snowflake before a masking policy can be applied to a column”
      ↩︎ Column-level security with Dynamic Data Masking
    2. 2.
      “The column rewrite occurs at every place where the column specified in the masking policy appears in the query”
      ↩︎ Column-level security with Dynamic Data Masking
      “the input and output data types must match.”
      ↩︎ Column-level security with Dynamic Data Masking
    3. 3.
      “Object owners cannot view column data in which a masking policy applies.”
      ↩︎ Column-level security with Dynamic Data Masking
      “Snowflake uses the external function to make a REST API call to the tokenization provider”
      ↩︎ External Tokenization and when to choose it
      “secure views present management challenges due to large numbers of views and derived business intelligence (BI) dashboards from each view”
      ↩︎ Row access policies compared with secure views
      “masking policies as a schema-level object to protect sensitive data from unauthorized access while allowing authorized users to access sensitive data at query runtime”
      ↩︎ Key concept
      “Secure views do not have SoD, which is a profound limitation to their utility.”
      ↩︎ Checkpoint
    4. 4.
      “External Tokenization makes use of masking policies with external functions.”
      ↩︎ External Tokenization and when to choose it
      “if you choose to integrate your tokenization provider with Snowflake External Tokenization, you must upgrade to Enterprise Edition or higher.”
      ↩︎ Exam trap 3
      “even without applying a masking policy to a column in a table or view, users never see the real data value”
      ↩︎ Checkpoint
    5. 5.
      “Snowflake evaluates the policy expression by using the role of the policy owner, not the role of the operator who executed the query.”
      ↩︎ Configuring a row access policy
      “using mapping tables may result in decreased performance compared to the more simple example.”
      ↩︎ Configuring a row access policy
      “adding a row access policy means Snowflake must scan the table to count the number of rows that are accessible in the current context”
      ↩︎ What changes when a row access policy is attached
      “A row access policy cannot be added to a table if a materialized view has been created from that underlying table.”
      ↩︎ What changes when a row access policy is attached
      “The row access policy that is applicable to the table is always executed first.”
      ↩︎ What changes when a row access policy is attached
      “Snowflake supports time travel on tables and views with a row access policy.”
      ↩︎ What changes when a row access policy is attached
      “time travel does not affect the mapping table”
      ↩︎ What changes when a row access policy is attached
      “A central data administrator decides which objects to protect, not the object owner.”
      ↩︎ Row access policies compared with secure views
      “When a database object has both a row access policy and one or more masking policies, Snowflake evaluates the row access policy first.”
      ↩︎ Exam trap 1
      “The new table does not have a row access policy set on a column.”
      ↩︎ Exam trap 2
      “Row access policies do not currently prevent rows from being inserted, or prevent visible rows from being updated or deleted.”
      ↩︎ Checkpoint
      “the new table contains the filtered rows based on the row access policy definition”
      ↩︎ Prediction
      “Snowflake creates a dynamic secure view (i.e. a secure inline view) of the database object.”
      ↩︎ Checkpoint
    6. 6.
      “set tags to ensure stages, tables, and columns with sensitive data can be tracked for compliance requirements”
      ↩︎ Tagging use cases: tracking, classifying and protecting data
      “tag updates (e.g. set a tag, change a tag value) on the object or column”
      ↩︎ Tagging use cases: tracking, classifying and protecting data
    7. 7.
      “You can then track the data within your data estate by tracking the tags.”
      ↩︎ Tagging use cases: tracking, classifying and protecting data
      “SNOWFLAKE.CORE.SEMANTIC_CATEGORY: Tag used to identify the native or custom category of the data in a column.”
      ↩︎ Tagging use cases: tracking, classifying and protecting data
      “If you use tag-based masking to associate a masking policy with a user-defined tag, the data will be automatically masked”
      ↩︎ Tagging use cases: tracking, classifying and protecting data
    8. 8.
      “If you configure your tag to propagate to downstream objects, the tag-based policy protects those downstream objects automatically”
      ↩︎ Tagging use cases: tracking, classifying and protecting data
      “objects in all newly added tables and views are automatically protected”
      ↩︎ Checkpoint
    9. 9.
      “Query the Account Usage TAG_REFERENCES view to verify the existing tags set on a table or a column in a table.”
      ↩︎ Tagging use cases: tracking, classifying and protecting data
      “the directly assigned masking policy takes precedence over the masking policy assigned to the tag.”
      ↩︎ Exam trap 4
    10. 10.
      “Certify a specific table or view as the authoritative source after confirming the fully qualified name”
      ↩︎ Tagging use cases: tracking, classifying and protecting data

    Continue to page 2 of 2

    Snowflake Tagging, Classification, Access History and Trust Center

    Spotted a mistake, or was something unclear? Tell us.