Bird
Raised Fist0
Snowflakecloud~30 mins

Column-level security with masking policies in Snowflake - Mini Project: Build & Apply

Choose your learning style10 modes available
Column-level security with masking policies
📖 Scenario: You work for a company that stores sensitive customer data in Snowflake. You want to protect the email column so that only authorized users can see the full email addresses. Others should see masked values.
🎯 Goal: Create a masking policy in Snowflake that hides the email column for unauthorized users by replacing it with a masked string.
📋 What You'll Learn
Create a table called customers with columns id, name, and email
Create a masking policy called email_masking_policy that masks the email column
Apply the masking policy to the email column in the customers table
Use a condition in the masking policy to show full email only to users with role FULL_ACCESS
💡 Why This Matters
🌍 Real World
Companies use masking policies to protect sensitive data like emails, phone numbers, or social security numbers in cloud data warehouses.
💼 Career
Understanding column-level security and masking policies is essential for data engineers and cloud security professionals working with Snowflake or similar platforms.
Progress0 / 4 steps
1
Create the customers table
Create a table called customers with columns id as integer, name as string, and email as string.
Snowflake
Hint

Use CREATE OR REPLACE TABLE customers (id INT, name STRING, email STRING);

2
Create the masking policy email_masking_policy
Create a masking policy called email_masking_policy that takes a string input email and returns the original email if the current role is FULL_ACCESS. Otherwise, return the string '***masked***'.
Snowflake
Hint

Use CREATE OR REPLACE MASKING POLICY email_masking_policy AS (email STRING) RETURNS STRING -> CASE WHEN CURRENT_ROLE() = 'FULL_ACCESS' THEN email ELSE '***masked***' END;

3
Apply the masking policy to the email column
Alter the customers table to set the masking policy email_masking_policy on the email column.
Snowflake
Hint

Use ALTER TABLE customers ALTER COLUMN email SET MASKING POLICY email_masking_policy;

4
Verify the masking policy is applied
Write a query to select id, name, and email from the customers table to verify the masking policy is applied.
Snowflake
Hint

Use SELECT id, name, email FROM customers; to verify the masking policy

Practice

(1/5)
1. What is the main purpose of a masking policy in Snowflake's column-level security?
easy
A. To create backups of sensitive columns
B. To hide or mask sensitive column data based on user roles
C. To encrypt the entire database automatically
D. To delete sensitive data permanently from a column

Solution

  1. Step 1: Understand masking policy purpose

    Masking policies control how sensitive data is shown without changing the original data.
  2. Step 2: Identify role-based data visibility

    They mask or reveal data depending on the user's role or permissions.
  3. Final Answer:

    To hide or mask sensitive column data based on user roles -> Option B
  4. Quick Check:

    Masking policy = role-based data masking [OK]
Hint: Masking policies control data visibility by user roles [OK]
Common Mistakes:
  • Thinking masking deletes data
  • Confusing masking with encryption
  • Assuming masking backs up data
2. Which of the following is the correct syntax to create a masking policy in Snowflake?
easy
A. CREATE MASKING POLICY policy_name AS CASE WHEN CURRENT_ROLE() IN ('ANALYST') THEN val ELSE '****' END RETURNS STRING;
B. CREATE MASKING POLICY policy_name (val STRING) RETURNS STRING AS CASE WHEN CURRENT_ROLE() IN ('ANALYST') THEN val ELSE '****' END;
C. CREATE MASKING POLICY policy_name AS (val STRING) RETURNS STRING AS (CASE WHEN CURRENT_ROLE() IN ('ANALYST') THEN val ELSE '****' END);
D. CREATE MASKING POLICY policy_name RETURNS STRING AS (val STRING) CASE WHEN CURRENT_ROLE() IN ('ANALYST') THEN val ELSE '****' END;

Solution

  1. Step 1: Recall correct syntax structure

    Snowflake masking policy syntax starts with CREATE MASKING POLICY name AS (input parameter) RETURNS type.
  2. Step 2: Match syntax with options

    CREATE MASKING POLICY policy_name AS (val STRING) RETURNS STRING AS (CASE WHEN CURRENT_ROLE() IN ('ANALYST') THEN val ELSE '****' END); correctly uses AS (val STRING) RETURNS STRING followed by the CASE expression.
  3. Final Answer:

    CREATE MASKING POLICY policy_name AS (val STRING) RETURNS STRING AS (CASE WHEN CURRENT_ROLE() IN ('ANALYST') THEN val ELSE '****' END); -> Option C
  4. Quick Check:

    Correct syntax = CREATE MASKING POLICY policy_name AS (val STRING) RETURNS STRING AS (CASE WHEN CURRENT_ROLE() IN ('ANALYST') THEN val ELSE '****' END); [OK]
Hint: Syntax: CREATE MASKING POLICY name AS (param) RETURNS type [OK]
Common Mistakes:
  • Placing RETURNS before AS
  • Missing parentheses around input parameter
  • Incorrect order of clauses
3. Given this masking policy:
CREATE MASKING POLICY mask_ssn AS (val STRING) RETURNS STRING AS (CASE WHEN CURRENT_ROLE() IN ('HR') THEN val ELSE 'XXX-XX-XXXX' END);

What will a user with role 'SALES' see when querying the masked SSN column?
medium
A. 'XXX-XX-XXXX'
B. NULL
C. The actual SSN value
D. An error message

Solution

  1. Step 1: Analyze masking policy logic

    The policy shows the real value only if CURRENT_ROLE() is 'HR'. Otherwise, it masks with 'XXX-XX-XXXX'.
  2. Step 2: Determine output for 'SALES' role

    Since 'SALES' is not 'HR', the user sees the masked string 'XXX-XX-XXXX'.
  3. Final Answer:

    'XXX-XX-XXXX' -> Option A
  4. Quick Check:

    Role not HR = masked value [OK]
Hint: If role not allowed, masking policy returns mask string [OK]
Common Mistakes:
  • Assuming user sees actual data
  • Expecting NULL instead of mask
  • Thinking it causes an error
4. You created a masking policy but users still see unmasked data. What is the most likely cause?
medium
A. The masking policy was not attached to the column
B. The masking policy syntax has a typo
C. The user has the role that bypasses masking
D. The table is missing a primary key

Solution

  1. Step 1: Check masking policy attachment

    Masking policies must be assigned to columns to take effect.
  2. Step 2: Consider user roles and syntax

    While roles can bypass masking, if all users see unmasked data, likely the policy is not attached.
  3. Final Answer:

    The masking policy was not attached to the column -> Option A
  4. Quick Check:

    Policy attached = masking works [OK]
Hint: Attach masking policy to column to activate it [OK]
Common Mistakes:
  • Ignoring policy attachment step
  • Blaming user roles without checking
  • Confusing table keys with masking
5. You want to create a masking policy that shows full email addresses to 'ADMIN' role, partially masks emails for 'SUPPORT' role (showing only domain), and masks completely for others. Which policy logic correctly implements this?
hard
A. CASE WHEN CURRENT_ROLE() = 'SUPPORT' THEN val WHEN CURRENT_ROLE() = 'ADMIN' THEN CONCAT('***@', SPLIT_PART(val, '@', 2)) ELSE '****' END
B. CASE WHEN CURRENT_ROLE() = 'ADMIN' THEN '****' WHEN CURRENT_ROLE() = 'SUPPORT' THEN val ELSE CONCAT('***@', SPLIT_PART(val, '@', 2)) END
C. CASE WHEN CURRENT_ROLE() IN ('ADMIN', 'SUPPORT') THEN val ELSE '****' END
D. CASE WHEN CURRENT_ROLE() = 'ADMIN' THEN val WHEN CURRENT_ROLE() = 'SUPPORT' THEN CONCAT('***@', SPLIT_PART(val, '@', 2)) ELSE '****' END

Solution

  1. Step 1: Identify role conditions and outputs

    'ADMIN' sees full email (val), 'SUPPORT' sees masked local part but full domain, others see full mask.
  2. Step 2: Match logic to requirements

    CASE WHEN CURRENT_ROLE() = 'ADMIN' THEN val WHEN CURRENT_ROLE() = 'SUPPORT' THEN CONCAT('***@', SPLIT_PART(val, '@', 2)) ELSE '****' END shows full val for ADMIN, partial mask for SUPPORT using CONCAT and SPLIT_PART, else full mask.
  3. Final Answer:

    CASE WHEN CURRENT_ROLE() = 'ADMIN' THEN val WHEN CURRENT_ROLE() = 'SUPPORT' THEN CONCAT('***@', SPLIT_PART(val, '@', 2)) ELSE '****' END -> Option D
  4. Quick Check:

    Role-based partial/full masking = CASE WHEN CURRENT_ROLE() = 'ADMIN' THEN val WHEN CURRENT_ROLE() = 'SUPPORT' THEN CONCAT('***@', SPLIT_PART(val, '@', 2)) ELSE '****' END [OK]
Hint: Order CASE by roles from most to less privileged [OK]
Common Mistakes:
  • Swapping ADMIN and SUPPORT logic
  • Showing full email to all roles
  • Incorrect string functions usage
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard