Skip to content

Native Dynamic Snowflake Access Pattern

Audience: System Administrators, Data Owners, and Data Users

Content Summary: This page describes the Native Dynamic Snowflake access pattern, through which Immuta applies policies directly in Snowflake, allowing you to use the Snowflake Web UI and your existing BI tools and have per-user policies dynamically applied at query time.


Native Dynamic Snowflake completely eliminates role bloat, as all views are accessible through the PUBLIC role and access controls are baked into the view, allowing customers to leverage Immuta's powerful set of attribute-based policies. Additionally, users can continue using roles to enforce compute-based policies through "warehouse" roles, without needing to grant each of those roles access to the underlying data or create multiple views of the data for each specific business unit.

Enable Native Dynamic Snowflake

Native Dynamic Snowflake is enabled the same way that Snowflake workspaces are enabled through the App Settings page.

Snowflake Configuration

Once Snowflake has been enabled on an instance, all future Snowflake data sources will also be created natively within the immuta database of the linked Snowflake instance. In addition to creating views, Immuta will also periodically sync user metadata to a system table within the Snowflake instance.

Sync Views and Data Sources

This access pattern leverages webhooks to keep Snowflake views up-to-date with the corresponding Immuta data sources. Whenever a data source is created, updated, or disabled, or whenever a data or subscription policy is added, modified, or removed, a webhook will be called that will create, modify, or delete the native Snowflake view.

The SQL that makes up all views includes a join to the secure view: immuta_system.user_profile. This view is a select from the immuta_system.profile table (which contains all Immuta users and their current groups, attributes, projects, and a list of valid tables they have access to) with a constraint immuta__userid = current_user() to ensure it only contains the profile row for the current user. This secure view is readable by all users and will only display the data that corresponds to the user executing the query.

Note: The immuta_system.profile table is updated through webhooks whenever a user's groups or attributes change, they switch projects, they acknowledge a purpose, or when their data source access is approved or revoked. The profile table can only be read and updated by the Immuta system account.

Secure and Non-Secure Views

When creating a native Snowflake data source, users have the option to use a regular view (traditional database view) or a secure view; however, according to Snowflake's documentation , "the Snowflake query optimizer, when evaluating secure views, bypasses certain optimizations used for regular views. This may result in some impact on query performance for secure views." Note: If HIPAA compliance is required, secure views must be used.

Snowflake Native View

Non-Secure View Policy Implications

When using a non-secure view, certain policies may leak sensitive information. In addition to the concerns outlined here, there is also a risk of someone exploiting the query optimizer to discover that a row exists in a table that has been excluded by row-level policies. This attack is mentioned here in the Snowflake documentation.

Policies that will not leak sensitive information

  • masking by making NULL, using a constant, or by rounding (date/numeric)
  • minimization row-level policies
  • date-based row-level policies
  • k-anonymization masking policies (these are generated as a whitelist)

Policies that could leak sensitive information

  • masking using a regex will show the regex being applied. In general this should be safe, but if you have a regex policy that removes a specific selector to redact (e.g., a regex of /123-45-6789/g to specifically remove a single SSN from a column), then someone would be able to identify columns with that value.
  • in conditional masking and custom WHERE clauses including “Right To Be Forgotten,” the custom SQL will be visible, so for a policy like "only show rows where COUNTRY NOT IN(‘UK’, ‘AUS’)," users will know that it’s possible there is data in that table containing those values.

Policies that will leak potentially sensitive information

These policies leak information sensitive to Immuta, but in most cases would require an attacker to reverse the algorithm. In general these policies should be used with secure views:

  • masking using hashing will include the salt used
  • numeric and categorical local differential privacy will include the salt used
  • reversible masking will include both a key and an IV
  • format preserving masking will include a tweak, key, an alphabet range, prefix, pad to length, and checksum id if used

Policy Enforcement

The data sources themselves have all the data policies baked into the SQL through a series of CASE statements that determine which view of the data a user will see. Row-level policies are applied as top-level WHERE clauses, and usage policies (purpose-based or subscription-level) are applied as WHERE clauses against the user_profile JOIN. The access_check function allows Immuta to throw custom errors similar to the Query Engine when a user lacks access to a data source because they are not subscribed to the data source, they are operating under the wrong project, or they cannot view any data because of policies enforced on the data source.

Snowflake Database Structure

By default, all native views are created within the immuta database, which is accessible by the PUBLIC role, so users acting under any Snowflake role can connect. All views within the database have the SELECT permission granted to the PUBLIC role as well, and access is enforced by the access_check function built into the individual views. Consequently, there is no need for users to manage any role-based access to any of the database objects managed by Immuta.


Immuta is unable to create a corresponding view in Snowflake for data sources

  • that have a differential privacy policy applied,
  • with an external policy handler, or
  • that are using the Advanced Rules DSL.

Certain interpolation functions can also block the creation of a native view, specifically @interpolatedComparison() and @iam.