Security and Governance: Balancing Control and Autonomy in Snowflake
In the modern data landscape, Data Governance and Data Security are the two key pillars. Every organization would want to protect their data and they can leverage masking policies, row access policies , classification tags and more. But there is a fundamental difference between simply “securing data” and “governing it”. Effective data strategy requires thinking with a governance mindset — ensuring that security measures are implemented in alignment with governance principles. This involves answering critical questions like “Who owns the policies in an organization? How can it be made consistent across the entire data platform? If made consistent, how can autonomy across different business domains be achieved?” to establish a clear separation of duties.
Governance Model Patterns
Below are the different governance patterns that can be adopted based on the organizational needs. Each model has its strengths and is suited to different scenarios — the right choice depends on your organization’s size, regulatory landscape, and team structure.
This blog will focus on implementing Hybrid Model — detailing the required RBAC Role Hierarchy and providing the necessary SQL scripts for creating tags, policies, and a classification profile for Snowflake’s Data Classification feature, illustrating how governance responsibilities are distributed differently across teams in each approach.
Disclaimer: Naming conventions are outside the scope of this post.Hybrid Model
The implementation will require the following steps with responsibilities split between the Central and Domain Teams :-
Step 1: Create Central Governance Database
-- -----------------------------------------------------------------
-- 1.1 Parameters Set-up
-- -----------------------------------------------------------------
SET GOV_DB = 'GOVERNANCE';
SET TAGS_SCHEMA_FQ = 'GOVERNANCE.TAGS';
SET POLICIES_SCHEMA_FQ = 'GOVERNANCE.POLICIES';
SET CLASSIFICATION_SCHEMA_FQ = 'GOVERNANCE.CLASSIFICATION';
SET AR_DATA_GOV_ADMIN = 'DATA_GOV_ADMIN_AR'; -- Access Role which will be mapped to Central Governance Admin Functional Role
SET FR_DATA_GOV_ADMIN = 'DATA_GOV_ADMIN_FR'; -- Functional Role created for central governance for tags/policies/classification
SET WH = 'COMPUTE_WH';
-- -----------------------------------------------------------------
-- 1.2 Create Central Governance Database and Schemas
-- -----------------------------------------------------------------
USE ROLE SYSADMIN;
CREATE DATABASE IF NOT EXISTS IDENTIFIER($GOV_DB);
CREATE SCHEMA IF NOT EXISTS IDENTIFIER($TAGS_SCHEMA_FQ) WITH MANAGED ACCESS;
CREATE SCHEMA IF NOT EXISTS IDENTIFIER($POLICIES_SCHEMA_FQ) WITH MANAGED ACCESS;
CREATE SCHEMA IF NOT EXISTS IDENTIFIER($CLASSIFICATION_SCHEMA_FQ) WITH MANAGED ACCESS;
-- -----------------------------------------------------------------------------
-- 1.3 Create Access Role
-- -----------------------------------------------------------------------------
USE ROLE USERADMIN;
CREATE ROLE IF NOT EXISTS IDENTIFIER($AR_DATA_GOV_ADMIN)
Comment = 'Access Role for creating and managing tags/policies/classification
profiles';
-- Grants appropriate permissions to the access role
USE ROLE SECURITYADMIN;
GRANT USAGE ON DATABASE IDENTIFIER($GOV_DB) TO ROLE IDENTIFIER($AR_DATA_GOV_ADMIN);
GRANT USAGE ON ALL SCHEMAS IN DATABASE IDENTIFIER($GOV_DB) TO ROLE IDENTIFIER($AR_DATA_GOV_ADMIN);
GRANT CREATE TAG ON SCHEMA IDENTIFIER($TAGS_SCHEMA_FQ) TO ROLE IDENTIFIER($AR_DATA_GOV_ADMIN);
GRANT CREATE MASKING POLICY ON SCHEMA IDENTIFIER($POLICIES_SCHEMA_FQ) TO ROLE IDENTIFIER($AR_DATA_GOV_ADMIN);
GRANT CREATE SNOWFLAKE.DATA_PRIVACY.CLASSIFICATION_PROFILE ON SCHEMA IDENTIFIER($CLASSIFICATION_SCHEMA_FQ) TO ROLE IDENTIFIER($AR_DATA_GOV_ADMIN);
GRANT CREATE SNOWFLAKE.DATA_PRIVACY.CUSTOM_CLASSIFIER ON SCHEMA IDENTIFIER($CLASSIFICATION_SCHEMA_FQ) TO ROLE IDENTIFIER($AR_DATA_GOV_ADMIN);
GRANT USAGE ON WAREHOUSE IDENTIFIER($WH) TO ROLE IDENTIFIER($AR_DATA_GOV_ADMIN);
-- Account-level privileges
USE ROLE ACCOUNTADMIN;
GRANT APPLY MASKING POLICY ON ACCOUNT TO ROLE IDENTIFIER($AR_DATA_GOV_ADMIN);
GRANT APPLY TAG ON ACCOUNT TO ROLE IDENTIFIER($AR_DATA_GOV_ADMIN);
GRANT DATABASE ROLE SNOWFLAKE.CLASSIFICATION_ADMIN
TO ROLE IDENTIFIER($AR_DATA_GOV_ADMIN);
-- -----------------------------------------------------------------
-- 1.4 Create Functional Role
-- -----------------------------------------------------------------
USE ROLE USERADMIN;
CREATE ROLE IF NOT EXISTS IDENTIFIER($FR_DATA_GOV_ADMIN)
Comment = 'Central Functional Role for Policy, Classification and Tag';
USE ROLE SECURITYADMIN;
GRANT ROLE IDENTIFIER($AR_DATA_GOV_ADMIN)
TO ROLE IDENTIFIER($FR_DATA_GOV_ADMIN);
GRANT ROLE IDENTIFIER($FR_DATA_GOV_ADMIN) TO ROLE SYSADMIN;Step 2: Create Tags
Note:The following tags and the allowed values in the tags is a template.
Ensure the tags and allowed values are tailored to meet the organization's
specific security requirements and business rules before implementation-- -----------------------------------------------------------------
-- 2.1 Parameters Set-up
-- -----------------------------------------------------------------
SET FR_DATA_GOV_ADMIN = 'DATA_GOV_ADMIN_FR'; -- Functional Role created for central governance for tags/policies
SET PII_EMAIL_TAG_FQ = 'GOVERNANCE.TAGS.PII_EMAIL';
SET SENSITIVITY_TAG_FQ = 'GOVERNANCE.TAGS.SENSITIVITY';
SET PII_LEVEL_TAG_FQ = 'GOVERNANCE.TAGS.PII_LEVEL';
SET DOMAIN_TAG_FQ = 'GOVERNANCE.TAGS.DOMAIN';
SET TAGS_FQ = 'GOVERNANCE.TAGS';
-- -----------------------------------------------------------------
-- 2.1 Create Classification Tags
-- -----------------------------------------------------------------
USE ROLE IDENTIFIER($FR_DATA_GOV_ADMIN) ;
-- PII Type Tags
CREATE OR REPLACE TAG IDENTIFIER($PII_EMAIL_TAG_FQ)
ALLOWED_VALUES 'TRUE'
COMMENT = 'Email Address';
-- Sensitivity Level Tag
CREATE OR REPLACE TAG IDENTIFIER($SENSITIVITY_TAG_FQ)
ALLOWED_VALUES 'PUBLIC', 'INTERNAL', 'CONFIDENTIAL', 'RESTRICTED'
COMMENT = 'Data sensitivity classification ';
-- PII Level Tag
CREATE TAG IF NOT EXISTS IDENTIFIER($PII_LEVEL_TAG_FQ)
ALLOWED_VALUES 'HIGH', 'MEDIUM', 'LOW'
COMMENT = 'PII sensitivity level';
-- DOMAIN Tag
CREATE TAG IF NOT EXISTS IDENTIFIER($DOMAIN_TAG_FQ)
ALLOWED_VALUES 'Finance', 'Marketing'
COMMENT = 'Business domains that owns the resource';
SHOW TAGS IN SCHEMA IDENTIFIER($TAGS_FQ);Step 3: Create Masking Policies
Note: The following email masking policy is a template.
Ensure the logic is tailored to meet the organization's specific security
requirements and business rules before implementation
In the example below, the policy uses SYSTEM$GET_TAG_ON_CURRENT_TABLE
to determine which domain the table belongs to, and applies
domain-specific masking rules accordingly with a single masking policy.
Each domain defines its own role-based access tiers.-- =============================================================================
-- 3.1 Create Masking Policy
-- =============================================================================
USE ROLE IDENTIFIER($FR_DATA_GOV_ADMIN);
CREATE OR REPLACE MASKING POLICY GOVERNANCE.POLICIES.MASK_EMAIL
AS (val STRING) RETURNS STRING ->
CASE
-- =====================================================================
-- DOMAIN: FINANCE
-- Tier 1 (Full Access): Finance Analysts see unmasked email
-- Tier 2 (No Access): All others see partially masked email
-- Tier 3 (Partial): Read-only consumers see fully masked email
-- =====================================================================
WHEN SYSTEM$GET_TAG_ON_CURRENT_TABLE('GOVERNANCE.TAGS.DOMAIN') = 'Finance'
THEN
CASE
WHEN IS_ROLE_IN_SESSION('ANALYST_FINANCE_FR') THEN val
WHEN IS_ROLE_IN_SESSION('READER_FINANCE_FR') THEN CONCAT('***', RIGHT(val, 4))
ELSE '*****'
END
-- =====================================================================
-- DOMAIN: MARKETING
-- Tier 1 (Full Access): Marketing BI users see unmasked email
-- Tier 2 (No Access): All others see fully masked email
-- =====================================================================
WHEN SYSTEM$GET_TAG_ON_CURRENT_TABLE('GOVERNANCE.TAGS.DOMAIN') = 'Marketing'
THEN
CASE
WHEN IS_ROLE_IN_SESSION('BI_MARKETING_FR') THEN val
ELSE '*****'
END
-- =====================================================================
-- DEFAULT: No domain tag set or unrecognized domain
-- Fully masks the value as a safety net
-- =====================================================================
ELSE '*****'
END;Step 4: Attach Policies to Tags
-- -----------------------------------------------------------------
-- 4.1 Parameters Set-up
-- -----------------------------------------------------------------
SET FR_DATA_GOV_ADMIN = 'DATA_GOV_ADMIN_FR';
-- Functional Role created for central governance for tags/policies/classification
SET PII_EMAIL_TAG_FQ = 'GOVERNANCE.TAGS.PII_EMAIL';
SET MASKING_POLICY_EMAIL = 'GOVERNANCE.POLICIES.MASK_EMAIL';
-- -----------------------------------------------------------------
-- 4.2 Attach Policy to Tag
-- -----------------------------------------------------------------
USE ROLE IDENTIFIER($FR_DATA_GOV_ADMIN);
-- Associate each policy with its respective tag
ALTER TAG IDENTIFIER($PII_EMAIL_TAG_FQ)
SET MASKING POLICY IDENTIFIER($MASKING_POLICY_EMAIL);Step 5: Create Classification Profile
-- -----------------------------------------------------------------
-- 5.1 Parameters Set-up
-- -----------------------------------------------------------------
SET FR_DATA_GOV_ADMIN = 'DATA_GOV_ADMIN_FR';
-- Functional Role created for central governance for tags/policies/classification
SET GOV_DB = 'GOVERNANCE';
SET CLASSIFICATION_SCHEMA = 'CLASSIFICATION';
-- -----------------------------------------------------------------
-- 5.2 Create Classification Profile
-- -----------------------------------------------------------------
USE ROLE IDENTIFIER($FR_DATA_GOV_ADMIN);
USE DATABASE IDENTIFIER($GOV_DB);
USE SCHEMA IDENTIFIER($CLASSIFICATION_SCHEMA);
USE WAREHOUSE COMPUTE_WH;
CREATE OR REPLACE SNOWFLAKE.DATA_PRIVACY.CLASSIFICATION_PROFILE
GOVERNANCE.CLASSIFICATION.STANDARD_PII_CLASSIFIER(
{
-- Classify tables immediately upon creation
'minimum_object_age_for_classification_days': 0,
-- Re-classify every 90 days
'maximum_classification_validity_days': 90,
-- Automatically apply tags to detected columns
'auto_tag': true,
-- Skip views; classify base tables only
'classify_views': false,
-- TAG: PII_EMAIL
-- Columns detected as EMAIL will be tagged for policy attachment
'tag_map': {
'column_tag_map': [
{'tag_name': 'GOVERNANCE.TAGS.PII_EMAIL',
'tag_value': 'TRUE',
'semantic_categories': ['EMAIL']},
-- TAG: PII_LEVEL (HIGH / MEDIUM / LOW)
-- Categorizes PII severity to drive tiered access controls
{'tag_name': 'GOVERNANCE.TAGS.PII_LEVEL', 'tag_value': 'HIGH',
'semantic_categories': ['US_SSN', 'US_PASSPORT','NATIONAL_IDENTIFIER']},
{'tag_name': 'GOVERNANCE.TAGS.PII_LEVEL', 'tag_value': 'MEDIUM',
'semantic_categories': ['NAME', 'EMAIL', 'PHONE_NUMBER',
'US_DRIVERS_LICENSE', 'DATE_OF_BIRTH',
'STREET_ADDRESS', 'POSTAL_CODE']},
{'tag_name': 'GOVERNANCE.TAGS.PII_LEVEL','tag_value': 'LOW',
'semantic_categories': ['GENDER', 'AGE', 'MARITAL_STATUS',
'ETHNICITY']},
-- TAG: SENSITIVITY (RESTRICTED / CONFIDENTIAL)
-- Broader data sensitivity classification aligned to organizational data tiers
{'tag_name': 'GOVERNANCE.TAGS.SENSITIVITY','tag_value': 'RESTRICTED',
'semantic_categories': ['US_DRIVERS_LICENSE','US_SSN', 'US_PASSPORT',
'NATIONAL_IDENTIFIER','SALARY']},
{'tag_name': 'GOVERNANCE.TAGS.SENSITIVITY','tag_value': 'CONFIDENTIAL',
'semantic_categories': ['NAME', 'EMAIL', 'PHONE_NUMBER',
'DATE_OF_BIRTH', 'STREET_ADDRESS', 'POSTAL_CODE']}
]}
}
);Step 6: Custom Classifiers (Optional)
When Snowflake’s built-in semantic categories don’t cover your data types, custom classifiers let you define regex-based detection rules for domain-specific sensitive data (e.g., payment cards, medical records).
Note: The following custom classifier is a template.
Ensure the logic is tailored to meet the organization's specific security
requirements and business rules before implementation
Each custom classifier uses:
>> SEMANTIC_CATEGORY. : A label for what the data represents
>> PRIVACY_CATEGORY. : The privacy tier (SENSITIVE, IDENTIFIER, etc.)
>> VALUE_REGEX. : Pattern to match against column value
>> COL_NAME_REGEX. : Pattern to match against column names (narrows scope)
>> THRESHOLD. : Confidence threshold (0–1) - fraction of
sampled values that must match for the column
to be classified-- 6.1 Create Custom Classifier
-- Custom Classifier Example 1: Credit Card Numbers
CREATE OR REPLACE SNOWFLAKE.DATA_PRIVACY.CUSTOM_CLASSIFIER
GOVERNANCE.CLASSIFICATION.CREDIT_CARD_CLASSIFIER();
CALL GOVERNANCE.CLASSIFICATION.CREDIT_CARD_CLASSIFIER!ADD_REGEX(
SEMANTIC_CATEGORY => 'PAYMENT_CARD',
PRIVACY_CATEGORY => 'SENSITIVE',
VALUE_REGEX => '^[0-9]{4}-[0-9]{4}-[0-9]{4}-[0-9]{1,4}$',
COL_NAME_REGEX => '.*CREDIT.*|.*CARD.*|.*PAYMENT.*',
DESCRIPTION => 'Credit card numbers with dashes (e.g., 4111-1111-1111-1111)',
THRESHOLD => 0.8
);
-- Custom Classifier Example 2: Medical Conditions
CREATE OR REPLACE SNOWFLAKE.DATA_PRIVACY.CUSTOM_CLASSIFIER
GOVERNANCE.CLASSIFICATION.MEDICAL_CONDITION_CLASSIFIER();
CALL GOVERNANCE.CLASSIFICATION.MEDICAL_CONDITION_CLASSIFIER!ADD_REGEX(
SEMANTIC_CATEGORY => 'MEDICAL_CONDITION',
PRIVACY_CATEGORY => 'SENSITIVE',
VALUE_REGEX => '.*(diabetes|hypertension|asthma|allerg|heart|arthritis|cancer|epilepsy|depression|anxiety).*',
COL_NAME_REGEX => '.*MEDICAL.*|.*CONDITION.*|.*DIAGNOSIS.*|.*HEALTH.*',
DESCRIPTION => 'Common medical conditions (healthcare compliance use case)',
THRESHOLD => 0.5
);
-- 6.2 Attach Custom Classifiers to the classification profile
-- =============================================================================
-- Once attached, the profile will use both built-in and custom classifiers
-- during automated scans. Any columns matching these patterns will receive
-- the appropriate semantic/privacy tags alongside the standard PII tags.
-- =============================================================================
CALL GOVERNANCE.CLASSIFICATION.STANDARD_PII_CLASSIFIER!SET_CUSTOM_CLASSIFIERS({
'CREDIT_CARD_CLASSIFIER': GOVERNANCE.CLASSIFICATION.CREDIT_CARD_CLASSIFIER!LIST(),
'MEDICAL_CONDITION_CLASSIFIER': GOVERNANCE.CLASSIFICATION.MEDICAL_CONDITION_CLASSIFIER!LIST()
});Once the custom classifiers are created, attach the custom classifiers with the classification profile. Once atatched, the profile will use both built-in and custom classifiers during automated scans. Any columns matching these patterns will recieve the appropriate semantic/privacy tags alongside the standard PII tags.
-- 6.2 Attach Custom Classifiers to the classification profile
CALL GOVERNANCE.CLASSIFICATION.STANDARD_PII_CLASSIFIER!SET_CUSTOM_CLASSIFIERS({
'CREDIT_CARD_CLASSIFIER': GOVERNANCE.CLASSIFICATION.CREDIT_CARD_CLASSIFIER!LIST(),
'MEDICAL_CONDITION_CLASSIFIER': GOVERNANCE.CLASSIFICATION.MEDICAL_CONDITION_CLASSIFIER!LIST()
});
-- 6.3 Confirm the profile is created and custom classifiers are attached
SHOW SNOWFLAKE.DATA_PRIVACY.CLASSIFICATION_PROFILE LIKE 'STANDARD_PII_CLASSIFIER';
SELECT STANDARD_PII_CLASSIFIER!DESCRIBE();Step 7: Create Domain Governance Role
The domain governance role enables individual business domains to apply tags and set classification profiles on their own databases/schemas without having the ability to create or modify the policies themselves.
-- -----------------------------------------------------------------
-- 7.1 Parameters Set-up
-- -----------------------------------------------------------------
SET AR_DOMAIN_DATA_GOV_ADMIN = 'DOMAIN_DATA_GOV_ADMIN_AR';
SET FR_DOMAIN_DATA_GOV_ADMIN = 'DOMAIN_DATA_GOV_ADMIN_FR';
SET GOV_DB = 'GOVERNANCE';
SET TAGS_SCHEMA_FQ = 'GOVERNANCE.TAGS';
SET CLASSIFICATION_SCHEMA_FQ = 'GOVERNANCE.CLASSIFICATION';
SET DOMAIN_TAG_FQ = 'GOVERNANCE.TAGS.DOMAIN';
SET DOMAIN_DB = 'FINANCE_DB';
SET DOMAIN_SCHEMA_FQ = 'FINANCE_DB.CORE';
SET WH = 'COMPUTE_WH';
-- ==========================================================================
-- 7.2 Create Domain Governance Access and Functional Role
-- ==========================================================================
USE ROLE USERADMIN;
-- Create Account Access Role
CREATE ROLE IF NOT EXISTS IDENTIFIER($AR_DOMAIN_DATA_GOV_ADMIN);
-- Create Functional Role
CREATE ROLE IF NOT EXISTS IDENTIFIER($FR_DOMAIN_DATA_GOV_ADMIN);
USE ROLE SECURITYADMIN;
-- Map Access Role → Functional Role → SYSADMIN (maintains role hierarchy)
GRANT ROLE IDENTIFIER($AR_DOMAIN_DATA_GOV_ADMIN) TO ROLE IDENTIFIER($FR_DOMAIN_DATA_GOV_ADMIN);
GRANT ROLE IDENTIFIER($FR_DOMAIN_DATA_GOV_ADMIN) TO ROLE SYSADMIN;
-- ===========================================================================
-- 7.3 Grant permissions to the Domain Access Role
-- Domain teams need:
-- Read access to central governance objects (tags, classification profiles)
-- Write access to their own domain database/schema (to apply tags & profiles)
-- ===========================================================================
USE ROLE SECURITYADMIN;
-- Grant Usage on Governance Database and Schemas
GRANT USAGE ON DATABASE IDENTIFIER($GOV_DB) TO ROLE IDENTIFIER($AR_DOMAIN_DATA_GOV_ADMIN);
GRANT USAGE ON SCHEMA IDENTIFIER($TAGS_SCHEMA_FQ) TO ROLE IDENTIFIER($AR_DOMAIN_DATA_GOV_ADMIN);
GRANT USAGE ON SCHEMA IDENTIFIER($CLASSIFICATION_SCHEMA_FQ) TO ROLE IDENTIFIER($AR_DOMAIN_DATA_GOV_ADMIN);
-- Write access to their domain database/schema
GRANT USAGE ON DATABASE IDENTIFIER($DOMAIN_DB) TO ROLE IDENTIFIER($AR_DOMAIN_DATA_GOV_ADMIN);
GRANT USAGE ON SCHEMA IDENTIFIER($DOMAIN_SCHEMA_FQ) TO ROLE IDENTIFIER($AR_DOMAIN_DATA_GOV_ADMIN);
GRANT MODIFY ON SCHEMA IDENTIFIER($DOMAIN_SCHEMA_FQ) TO ROLE IDENTIFIER($AR_DOMAIN_DATA_GOV_ADMIN);
-- Account-level privileges for tag application
USE ROLE ACCOUNTADMIN;
GRANT APPLY TAG ON ACCOUNT TO ROLE IDENTIFIER($AR_DOMAIN_DATA_GOV_ADMIN);
-- Classification privileges on the domain schema
GRANT EXECUTE AUTO CLASSIFICATION ON SCHEMA IDENTIFIER($DOMAIN_SCHEMA_FQ)
TO ROLE IDENTIFIER($AR_DOMAIN_DATA_GOV_ADMIN);
GRANT SNOWFLAKE.DATA_PRIVACY.CLASSIFICATION_PROFILE ROLE
GOVERNANCE.CLASSIFICATION.STANDARD_PII_CLASSIFIER!PRIVACY_USER
TO ROLE IDENTIFIER($AR_DOMAIN_DATA_GOV_ADMIN);
-- Warehouse access
GRANT USAGE ON WAREHOUSE IDENTIFIER($WH) TO ROLE IDENTIFIER($AR_DOMAIN_DATA_GOV_ADMIN);
-- =============================================================================
-- 7.4 DOMAIN TEAM APPLIES TAG AND CLASSIFICATION PROFILE
-- This is the step executed by the domain team using their role.
-- =============================================================================
USE ROLE IDENTIFIER($FR_DOMAIN_DATA_GOV_ADMIN);
-- Apply domain ownership tag to the database
ALTER DATABASE IDENTIFIER($DOMAIN_DB)
SET TAG IDENTIFIER($DOMAIN_TAG_FQ) = 'Finance';
-- Set the classification profile on the schema (triggers automated scanning)
ALTER SCHEMA IDENTIFIER($DOMAIN_SCHEMA_FQ)
SET CLASSIFICATION_PROFILE = 'GOVERNANCE.CLASSIFICATION.STANDARD_PII_CLASSIFIER';Step 8: Set Classification Profile & Validate (Domain Team)
Once the central team has created the governance infrastructure (tags, policies, classification profile) and the domain specific roles, then the domain teams can independently activate classification on their databases/schemas and verify the results.
Get Jayashree Suresh’s stories in your inbox
Join Medium for free to get updates from this writer.
This triggers automated scanning — any new or existing tables in the database or schema on which the classification profile is set will be classified and tagged according to the profile’s rules.
-- =============================================================================
-- 8.1 Set the classification profile on their schema
-- =============================================================================
USE ROLE FR_DOMAIN_DATA_GOV_ADMIN;
USE WAREHOUSE COMPUTE_WH;
-- Enable automated classification on the schema (The automated classification
-- can be set on a database as well)
ALTER SCHEMA FINANCE_DB.CORE
SET CLASSIFICATION_PROFILE =
'GOVERNANCE.CLASSIFICATION.STANDARD_PII_CLASSIFIER';
-- (Optional) Trigger immediate classification on a specific table
-- By default, auto-classification runs on a schedule;
-- use this for instant results to verify the results for a table
CALL SYSTEM$CLASSIFY('FINANCE_DB.CORE.CUSTOMERS',
'GOVERNANCE.CLASSIFICATION.STANDARD_PII_CLASSIFIER');
-- =============================================================================
-- 8.2 VERIFY: Check what tags were applied by the classification engine
-- Two approaches depending on latency tolerance:
-- • ACCOUNT_USAGE view: comprehensive but has 1-2 hour latency
-- • INFORMATION_SCHEMA function: real-time but scoped to a single table
-- =============================================================================
-- Method 1: ACCOUNT_USAGE (broad view, 1-2 hour latency)
SELECT
DATABASE_NAME, SCHEMA_NAME, TABLE_NAME,
STATUS, TRIGGER_TYPE, LAST_CLASSIFIED_ON, RESULT
FROM SNOWFLAKE.ACCOUNT_USAGE.DATA_CLASSIFICATION_LATEST
WHERE DATABASE_NAME = 'FINANCE_DB'
AND SCHEMA_NAME = 'CORE'
ORDER BY LAST_CLASSIFIED_ON DESC;
-- Method 2: INFORMATION_SCHEMA (real-time, per-table)
-- Shows both Snowflake system tags and user-defined tags applied by the profile
SELECT
COLUMN_NAME,
MAX(CASE WHEN TAG_NAME = 'SEMANTIC_CATEGORY' THEN TAG_VALUE END) AS SEMANTIC_CATEGORY,
MAX(CASE WHEN TAG_NAME = 'PRIVACY_CATEGORY' THEN TAG_VALUE END) AS PRIVACY_CATEGORY,
MAX(CASE WHEN TAG_NAME = 'PII_EMAIL' THEN TAG_VALUE END) AS PII_EMAIL,
MAX(CASE WHEN TAG_NAME = 'PII_LEVEL' THEN TAG_VALUE END) AS PII_LEVEL,
MAX(CASE WHEN TAG_NAME = 'SENSITIVITY' THEN TAG_VALUE END) AS SENSITIVITY
FROM TABLE(FINANCE_DB.INFORMATION_SCHEMA.TAG_REFERENCES_ALL_COLUMNS(
'FINANCE_DB.CORE.CUSTOMERS', 'TABLE'
))
GROUP BY COLUMN_NAME
ORDER BY PRIVACY_CATEGORY, COLUMN_NAME;Once classification tags are applied, the masking policies attached to those tags take effect automatically. This can be validated by querying the same table with different roles:
-- =============================================================================
-- 8.3 VALIDATION: Each role sees different data based on the masking policy
-- The policy attached to PII_EMAIL tag uses SYSTEM$GET_TAG_ON_CURRENT_TABLE
-- to apply domain-specific rules automatically.
-- =============================================================================
-- Tier 1 (Full Access): Finance Analysts see unmasked email
USE ROLE FR_ANALYST_FINANCE;
SELECT * FROM FINANCE_DB.CORE.CUSTOMERS;
-- Tier 2 (Partial Access): Read-only consumers see partially masked email
USE ROLE FR_READER_FINANCE;
SELECT * FROM FINANCE_DB.CORE.CUSTOMERS;
-- Tier 3 (No Access): All other roles see fully masked email
USE ROLE FR_DEVELOPER_FINANCE;
SELECT * FROM FINANCE_DB.CORE.CUSTOMERS;For domains that prefer to attach masking policies directly to columns (instead of relying on automated classification), the following approach can be used:
-- =============================================================================
-- 8.4 ALTERNATIVE: Attach masking policy directly to a column
-- Use this when:
-- • The domain doesn't use automated classification
-- • You need policy on a specific column that classification doesn't detect
-- • You want immediate, explicit control over which columns are masked
-- =============================================================================
USE ROLE IDENTIFIER($FR_DOMAIN_DATA_GOV_ADMIN);
-- Set the domain tag (required for domain-aware masking logic)
ALTER DATABASE MARKETING_DB SET TAG GOVERNANCE.TAGS.DOMAIN = 'Marketing';
-- Attach masking policy directly to the EMAIL column
ALTER TABLE MARKETING_DB.CORE.CUSTOMERS
MODIFY COLUMN EMAIL
SET MASKING POLICY GOVERNANCE.POLICIES.MASK_EMAIL;
-- Validate
USE ROLE FR_BI_MARKETING;
SELECT * FROM MARKETING_DB.CORE.CUSTOMERS;
USE ROLE FR_READER_MARKETING;
SELECT * FROM MARKETING_DB.CORE.CUSTOMERS;Conclusion
While the technical scripts provided here follow a Hybrid Model, the fundamental building blocks — RBAC, tags, masking policies, and classification — are universal. Whether you consolidate everything under a single team (Centralized) or replicate the infrastructure within each domain (Decentralized), the architecture remains the same. The real shift is in ownership.
As you design your strategy, focus on three pivotal questions:
- Where will your policies and tags live?
- Who is responsible for defining them?
- Who ensures they are attached to the data?
Ultimately, your choice should reflect your organization’s regulatory landscape, team structure, and operational maturity.










