Atlas now manages Snowflake row access policies as a first-class resource. Declare the policy signature and body in HCL or SQL, and Atlas inspects, diffs, and migrates them with CREATE, ALTER, and DROP ROW ACCESS POLICY.
A row access policy in Snowflake is a schema-level object that returns a boolean per row, deciding which rows a query is allowed to see. Atlas now manages its full lifecycle as a first-class resource alongside your tables, views, and tags, in both the declarative and versioned workflows.
Enabling the Feature
Policy management with Atlas is opt-in. To enable it, set policies = true inside the mode "snowflake" block of your env to include row access policies in inspect, diff, and apply:
env "prod" {url = "snowflake://user:pass@account_identifier/database"dev = "snowflake://user:pass@dev_account_identifier/database"schema {src = "file://schema.hcl"mode "snowflake" {policies = true}}}
Defining a Policy
Use the row_access_policy block to declare a policy in your HCL schema. The signature is declared as one arg block per argument, and the boolean expression as the as attribute; comment and tags are optional:
schema "public" {}row_access_policy "sales_policy" {schema = schema.publicarg "sales_region" {type = VARCHAR(100)}as = "current_role() = 'ADMIN' or sales_region = 'US'"comment = "Restrict rows by sales region"}
Inspection works in the other direction, too. Atlas lists the policies in each schema and recovers their signature and body, so the policies already in your account round-trip into HCL with atlas schema inspect.
Generated SQL
Atlas generates CREATE, ALTER, and DROP ROW ACCESS POLICY statements based on the diff between your desired and current state:
-- Create row access policy "sales_policy"CREATE ROW ACCESS POLICY "public"."sales_policy" AS ("sales_region" VARCHAR(100)) RETURNS BOOLEAN -> current_role() = 'ADMIN' or sales_region = 'US' COMMENT = 'Restrict rows by sales region';
A changed body, comment, or tag is handled in place with ALTER ROW ACCESS POLICY SET, without recreating the policy:
-- Modify row access policy "sales_policy"ALTER ROW ACCESS POLICY "public"."sales_policy" SET BODY -> current_role() = 'ADMIN' or sales_region in ('US', 'EU');-- Modify row access policy "sales_policy"ALTER ROW ACCESS POLICY "public"."sales_policy" SET COMMENT = 'Restrict rows by sales region (NA + EU)';
-- Changing the signature requires a recreate (Snowflake limitation)DROP ROW ACCESS POLICY "public"."sales_policy";CREATE ROW ACCESS POLICY "public"."sales_policy" AS ("sales_region" VARCHAR(100), "dept" VARCHAR(100)) RETURNS BOOLEAN -> sales_region = 'US' and dept = 'SALES';
Every change carries its inverse. A CREATE reverses to DROP, and a SET BODY back to the previous body, so plans stay reversible and atlas migrate down works on them.
Policies That Query a Mapping Table
In addition to comparing against current_role(), a policy body looks the caller up in a mapping table. Snowflake resolves the body at CREATE time, so that table has to exist first. Atlas reads the body for the objects it names and orders the plan accordingly:
table "REGION_MAP" {schema = schema.publiccolumn "ROLE_NAME" {type = VARCHAR(100)}column "REGION" {type = VARCHAR(100)}}row_access_policy "mapped_policy" {schema = schema.publicarg "sales_region" {type = VARCHAR(100)}as = "EXISTS (SELECT 1 FROM REGION_MAP WHERE ROLE_NAME = current_role() AND REGION = sales_region)"}
The mapping table is created before the policy, without any annotation. For references the body parser cannot see, such as a policy that reaches through a UDF, declare them with depends_on.
Tags
Policies participate in Snowflake tagging like other schema objects, so a policy can be classified alongside the tables it protects:
tag "cost_center" {schema = schema.public}row_access_policy "tagged_policy" {schema = schema.publicas = "TRUE"tag {ref = tag.cost_centervalue = "finance"}}
Tag changes are diffed and applied with ALTER ROW ACCESS POLICY ... SET TAG / UNSET TAG, like any other tagged resource. Tags are gated by their own mode flag, so add tags = true next to policies = true to manage them together:
mode "snowflake" {policies = truetags = true}
Row access policies are available in the Snowflake driver today. See the row_access_policy reference for the full list of attributes, and Snowflake Database Security as Code for how policies fit next to the roles and grants that Atlas already manages.