CertSafari
    Snowflake SnowPro Advanced: Security Engineer (SEA-C01)· Lessons

    Domain 2 · Lesson 5/21

    External Tokenization, tag-based masking and row access policies

    Implement data security features.

    9 min read
    4.29% of exam
    6 sources
    Published 5 Oct 2026
    Docs as of 4 Oct 2026

    What you will be able to do

    • Build an External Tokenization masking policy that detokenizes through an external function
    • Protect columns at scale by assigning masking policies to tags, and predict which policy wins
    • Create, attach and replace row access policies, and explain how they interact with masking
    • Troubleshoot row access policy enforcement with EXPLAIN, POLICY_REFERENCES and POLICY_CONTEXT

    1.External Tokenization: detokenizing through an external function

    External Tokenization uses the same masking policy object as Dynamic Data Masking, but the data starts out differently. A third-party tokenization provider tokenizes the data before it is loaded, so Snowflake stores only tokens. Users never see the real values, even on a column that has no policy. The masking policy body calls an external function. At query runtime that function makes a REST API call to the provider, which evaluates its own tokenization policy and returns tokenized or detokenized data. Role mapping must exist on both sides, in Snowflake and at the provider.

    ANALYST sees detokenized emails through the de_email() external function; other roles see the stored tokensql
    create or replace masking policy email_de_token as (val string) returns string ->
      case
        when current_role() in ('ANALYST') then de_email(val)
        else val
      end;

    The privileges extend past the masking policy itself. The policy owner needs USAGE on the external function, and the function's owner needs USAGE on the API integration it references. Users who query the column need neither. External functions are available in every edition, but integrating your tokenization provider with Snowflake External Tokenization requires Enterprise Edition or higher. Because external functions can't run in the context of a share, mask shared data with Dynamic Data Masking instead.

    Checkpoint 1 of 5· Check yourself

    Which statement about External Tokenization is correct?

    Sources12

    2.Tag-based masking: one assignment, many columns

    Attaching policies column by column doesn't scale. A tag-based masking policy instead sets the masking policy on a tag with ALTER TAG. Any column carrying that tag, directly or through tag inheritance, is protected when its data type matches the policy signature. A tag holds at most one masking policy per data type, so a common pattern is one generic policy each for STRING, NUMBER and TIMESTAMP_LTZ. Policy bodies can also read the tag's string value through SYSTEM$GET_TAG_ON_CURRENT_COLUMN or SYSTEM$GET_TAG_ON_CURRENT_TABLE.

    Assigning a masking policy to a tagsql
    ALTER TAG security SET MASKING POLICY my_masking_policy;

    Where you set the tag decides the coverage. On a database or schema, columns in newly added tables and views are protected automatically. On a table, the tag covers all of its columns, including columns added later, much like future grants.

    The privileges differ by level. For a database or schema, the role needs global APPLY MASKING POLICY plus either global APPLY TAG or, if it owns the schema, APPLY on the tag. For tables and views, global APPLY MASKING POLICY is enough. A role with OWNERSHIP or APPLY on an already-policied tag can tag its own tables without APPLY MASKING POLICY.

    Limits to remember:

    - A masking policy can't be assigned to a system tag. - While the policy is assigned, neither the tag nor the policy (nor their parent schema and database) can be dropped. - A materialized view can't be created on a table protected by a tag-based policy. - A table moved or cloned into another schema loses protection from the source schema's tag-based policy.

    Checkpoint 2 of 5· Check yourself

    A STRING column has a masking policy assigned directly. Its table also carries a tag with a STRING masking policy. Which policy masks the column?

    Sources3

    3.Row access policies: design, attachment and precedence

    Masking controls what a value looks like. A row access policy controls whether the row appears at all. The body returns BOOLEAN for each row. Its conditions can check the user's active primary and secondary roles directly, look roles up in a mapping table, or do both. Snowflake recommends IS_ROLE_IN_SESSION for account roles and IS_DATABASE_ROLE_IN_SESSION for database roles. Keep a centralized mapping table in the same database as the protected table.

    You attach the policy to the columns named in its signature, either with CREATE TABLE/VIEW ... WITH ROW ACCESS POLICY or with ALTER TABLE/VIEW. A table or view can have only one row access policy at a time. To replace one, drop the old policy and add the new one in the same statement:

    Swapping row access policy versions in a single ALTER VIEWsql
    ALTER VIEW v1
      DROP ROW ACCESS POLICY rap_v1_version_1,
      ADD ROW ACCESS POLICY rap_v1_version_2 ON (empl_id);

    When an object has a row access policy and masking policies, the row access policy is evaluated first. A column can appear in a row access policy signature or in a masking policy signature, but not in both. Adding a policy fails if its body refers to a column or table that another policy already protects. A materialized view can't be created on a table that has a row access policy, and a row access policy can't be added to a table that already has a materialized view built on it. The table below shows what happens when you derive a new table from a protected one.

    How a row access policy on a source table affects derived tables
    StatementResult
    CREATE TABLE ... CLONEThe clone maps to the same policies; with a schema clone, local references point to the cloned policy
    CREATE TABLE ... LIKENo row access policy on the new table, which is empty
    CREATE TABLE ... AS SELECTThe new table holds only the filtered rows and has no row access policy

    Checkpoint 3 of 5· Fill the gap

    Which keyword attaches a row access policy to an existing table?

    ALTER TABLE t1  ?  ROW ACCESS POLICY rap_t1 ON (empl_id);

    Checkpoint 4 of 5· Exam question

    Support agents should see the full `email` value only when the row's `region` column equals 'EU'; everyone else must see a masked value. A masking policy `mask_email(val STRING, region STRING)` already exists. Which statement attaches it correctly?

    Sources45

    4.Troubleshooting row access policy enforcement

    When a user says rows are missing, or rows are visible that shouldn't be, start by confirming the policy is in play:

    - Run EXPLAIN on the query. At runtime Snowflake creates a dynamic secure view, so plan steps that invoke the policy show DynamicSecureView in the operation column and "<object_name> (+ RowAccessPolicy)" in the object column. Neither EXPLAIN nor Query History reveals the policy's name, signature or expression. - Call POLICY_REFERENCES, with either the policy name or an object name and domain, to see what is attached where. - Call POLICY_CONTEXT to replay the query as a particular role or context, without signing in as that user.

    Then check the usual causes:

    - CURRENT_DATABASE and CURRENT_SCHEMA inside a policy body refer to the protected table's location, not the session's. - Tag-based row access policies need the argument names and types to match the table's columns. Without a resolving signature alias, the policy is not enforced. - A row access policy assigned directly to the object overrides one inherited from a tag. - An external table can't serve as a mapping table, because database clones don't copy it.

    Checkpoint 5 of 5· Check yourself

    Analysts want to confirm a row access policy is filtering their query, but they have no access to policy metadata. What will they see?

    Sources56

    Exam traps

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

    1. 1.Masking policies run first, and the row access policy then filters the masked rows.Why is that wrong?

      The order is the reverse: the row access policy is evaluated before any masking policies on the object.

      Covered in Row access policies: design, attachment and precedence

    2. 2.A tag-based row access policy overrides a row access policy assigned directly to the table.Why is that wrong?

      Just as with masking, the directly assigned row access policy wins over the one assigned through a tag.

      Covered in Troubleshooting row access policy enforcement

    Sources

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

    1. 1.
      “Tokenization is the process of removing sensitive data by replacing it with an undecipherable token.”
      ↩︎ External Tokenization: detokenizing through an external function
      “are not necessary for the role of the user querying the column with a masking policy.”
      ↩︎ External Tokenization: detokenizing through an external function
      “if you choose to integrate your tokenization provider with Snowflake External Tokenization, you must upgrade to Enterprise Edition or higher.”
      ↩︎ External Tokenization: detokenizing through an external function
    2. 2.
      “At query runtime, Snowflake uses the external function to make a REST API call to the tokenization provider”
      ↩︎ External Tokenization: detokenizing through an external function
      “Data sharing only applies to Dynamic Data Masking because external functions cannot be invoked in the context of a share.”
      ↩︎ Checkpoint
    3. 3.
      “When the data type in the masking policy signature and the data type of the column match, the tagged column is automatically protected”
      ↩︎ Tag-based masking: one assignment, many columns
      “Assigning a tag-based masking policy to a table automatically applies the masking policy to any new table columns.”
      ↩︎ Tag-based masking: one assignment, many columns
      “A masking policy cannot be assigned to a system tag.”
      ↩︎ Tag-based masking: one assignment, many columns
      “the masking policy that is directly assigned to the column takes precedence over the tag-based masking policy.”
      ↩︎ Checkpoint
    4. 4.
      “A table or view can only be protected by one row access policy at a time.”
      ↩︎ Row access policies: design, attachment and precedence
    5. 5.
      “the same column cannot be specified in both a row access policy signature and a masking policy signature at the same time.”
      ↩︎ Row access policies: design, attachment and precedence
      “Snowflake recommends writing the policy conditions to call the IS_ROLE_IN_SESSION or the IS_DATABASE_ROLE_IN_SESSION function”
      ↩︎ Row access policies: design, attachment and precedence
      “Snowflake does not show users any row access policy information (i.e. policy name, policy signature, policy expression) or the objects accessed by the policy.”
      ↩︎ Troubleshooting row access policy enforcement
      “the function returns the database or schema that contains the protected table, not the database or schema in use for the session.”
      ↩︎ Troubleshooting row access policy enforcement
      “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 operation column includes the value DynamicSecureView.”
      ↩︎ Checkpoint
    6. 6.
      “By default, the name and data type of each policy argument must match a column on the table (case insensitive).”
      ↩︎ Troubleshooting row access policy enforcement
      “the directly assigned row access policy takes precedence over the row access policy assigned to the tag.”
      ↩︎ Exam trap 2

    Continue to page 3 of 3

    Projection, aggregation and differential privacy policies in Snowflake

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