Skip to content

Library · Data Practice OS

Governance on Snowflake: Horizon

Reference guide · Published · Source reviewed

Snowflake Horizon Catalog is the umbrella name for the governance features built into Snowflake. Nothing is installed separately. The work is deciding the model and putting it in code.

The model: roles for who, tags for what

  1. Functional roles describe people: analyst_registrations, engineer_safety, cssc_staff.
  2. Access roles describe privileges on objects: registrations_gold_read. Functional roles inherit them.
  3. Tags describe the data: classification = OFFICIAL | SENSITIVE, pii_type = name | address | licence_no | dob.
  4. Policies attach to tags, not to individual columns. Tag a column and the policy follows it.

This is Attribute-based access control in practice. One masking policy for each kind of personal information, attached to its tag, covers every table, including new ones.

Classification

Run automatic sensitive-data classification on bronze and silver schemas to suggest tags. Then have a data steward confirm them. Classification output is a suggestion, not a control.

-- Tags that mirror the security classification labels and the kinds of personal information
CREATE TAG governance.tags.classification ALLOWED_VALUES 'OFFICIAL', 'SENSITIVE', 'PROTECTED';
CREATE TAG governance.tags.pii_type       ALLOWED_VALUES 'name', 'address', 'licence_no', 'dob', 'contact';

Masking and row access

CREATE MASKING POLICY governance.policies.mask_pii AS (val STRING) RETURNS STRING ->
  CASE
    WHEN IS_ROLE_IN_SESSION('PII_FULL')    THEN val
    WHEN IS_ROLE_IN_SESSION('PII_PARTIAL') THEN REGEXP_REPLACE(val, '.(?=.{3})', '*')
    ELSE '***MASKED***'
  END;

ALTER TAG governance.tags.pii_type SET MASKING POLICY governance.policies.mask_pii;

-- Regional staff see only their region's rows
CREATE ROW ACCESS POLICY governance.policies.region_rap AS (region STRING) RETURNS BOOLEAN ->
  IS_ROLE_IN_SESSION('ALL_REGIONS')
  OR EXISTS (SELECT 1 FROM governance.mapping.role_region m
             WHERE m.region = region AND IS_ROLE_IN_SESSION(m.role_name));

Policies also apply to Cortex. Cortex Analyst, Cortex Agents and Snowflake Intelligence and AI SQL functions run under the caller's role, so masked data stays masked in AI answers. This is one of Snowflake's strongest arguments for keeping AI inside the platform. See AI on Snowflake - Cortex.

Lineage, audit and quality

  • Access history records which user, through which role, read which columns. Use it for privacy audits and to find unused data.
  • Lineage in Snowsight shows table- and column-level flows, including through dbt models.
  • Data metric functions attach freshness, null-count and custom quality checks to tables on a schedule. They complement dbt tests (Data quality and observability).
  • Object dependencies let you see what breaks before you drop or change something.

Iceberg and external engines

For Iceberg tables shared with Databricks, Horizon can act as an Iceberg REST catalog, or you can publish through Snowflake Open Catalog (Apache Polaris). Either way, decide which engine writes each table and treat that catalog as the catalog of record (ADR-004: One catalog of record per table). Masking and row policies do not travel with the files: an external engine reading Iceberg directly sees raw values. Share SENSITIVE data through governed views or secure sharing, not raw Iceberg. See Catalogs and the catalog of record.

Put it in code

Manage roles, grants, tags, policies and their attachments with Terraform (the Snowflake provider) or versioned SQL migrations in CI. Monthly drift detection should flag any grant made by hand.

Pitfalls

  • Granting to PUBLIC, including the default Cortex role. Revoke it on day one.
  • Using ACCOUNTADMIN for daily work. Use it only through a break-glass procedure.
  • Masking in views only. The base table is still readable by anyone who can reach it. Put policies on the table.
  • Treating classification as done. New sources arrive monthly. Schedule classification and steward review.

Worked example

The licensing silver schema holds names, dates of birth, addresses and licence numbers. Classification proposes pii_type tags and a steward confirms them in a pull request to the governance repo. Terraform applies the tags, and the tag-based policy masks all four types for everyone except PII_FULL (the licensing operations team). The row access policy limits regional staff to their own region. Quarterly, access history produces the report the privacy officer needs under the applicable privacy law.

Verify the current Horizon feature set and edition requirements (some policy features need Enterprise or Business Critical) in the Horizon documentation. See Governance, security and trust for the practice-wide model.