Back to changelog
New
2 minute read

Snowflake: External Access Integrations

Atlas now manages Snowflake external access integrations, the account-level object that grants a UDF or procedure outbound network access.

A UDF or procedure in Snowflake cannot reach the network on its own. An external access integration is the account-level allow-list that grants it, by naming the HOST_PORT egress network rules the code may reach and the secrets it may authenticate with. Atlas now manages its full lifecycle.

Declaring an Integration

The new external_access_integration block requires allowed_network_rules and accepts allowed_authentication_secrets, allowed_api_authentication_integrations, enabled, and comment:

schema.hcl
network_rule "EGRESS_A" {  schema     = schema.PUBLIC  type       = HOST_PORT  mode       = EGRESS  value_list = ["example.com:443"]}
external_access_integration "GATEWAY" {  allowed_network_rules                   = [network_rule.EGRESS_A, "OTHER_DB.PUBLIC.ELSEWHERE"]  allowed_authentication_secrets          = ["PUBLIC.VENDOR_TOKEN"]  allowed_api_authentication_integrations = ["API_AUTH"]  enabled                                 = false  comment                                 = "gateway"}
AttributeNotes
allowed_network_rulesRequired, and must name at least one HOST_PORT egress rule. Snowflake's CREATE rejects an empty list, so a desired state with none is refused at plan time rather than applied.
allowed_authentication_secretsQualified names of the secrets the code may authenticate with. Mutually exclusive with allow_all_authentication_secrets.
allow_all_authentication_secretstrue maps to Snowflake's ALLOWED_AUTHENTICATION_SECRETS = ALL, which it reports in place of a list.
allowed_api_authentication_integrationsNames of the API authentication security integrations the code may use. They are account-level, so they are not schema-qualified.
enabledDefaults to true. Snowflake requires it on CREATE either way, so Atlas always writes it.
commentFree text, cleared with an empty string rather than an UNSET.
tagRepeatable block associating a Snowflake tag with the integration. Set in a follow-up ALTER, since CREATE takes no inline WITH TAG.

Both lists take a reference to the block of an object Atlas manages, or a qualified string for one it does not, and a single list may hold both. A name written by hand is folded and quoted the way Snowflake stores it, so it matches an inspected reference instead of diffing against it forever.

Snowflake also accepts ALLOWED_AUTHENTICATION_SECRETS = ALL in place of a list, which is written as allow_all_authentication_secrets:

schema.hcl
external_access_integration "OPEN_GATEWAY" {  allowed_network_rules            = [network_rule.EGRESS_A]  allow_all_authentication_secrets = true}

Generated SQL

migration.sql
-- create external access integration "GATEWAY"CREATE EXTERNAL ACCESS INTEGRATION "GATEWAY"  ALLOWED_NETWORK_RULES = (PUBLIC.EGRESS_A, OTHER_DB.PUBLIC.ELSEWHERE)  ALLOWED_AUTHENTICATION_SECRETS = (PUBLIC.VENDOR_TOKEN)  ALLOWED_API_AUTHENTICATION_INTEGRATIONS = (API_AUTH)  ENABLED = false COMMENT = 'gateway';
-- create external access integration "OPEN_GATEWAY"CREATE EXTERNAL ACCESS INTEGRATION "OPEN_GATEWAY"  ALLOWED_NETWORK_RULES = (PUBLIC.EGRESS_A)  ALLOWED_AUTHENTICATION_SECRETS = ALL ENABLED = true;

Snowflake takes several properties per SET, so a change to any combination of them becomes a single statement. A list or a comment is cleared with = none and = '' rather than UNSET. Every statement carries its inverse, so migrate down works.

migration.sql
-- modify external access integration "GATEWAY"ALTER EXTERNAL ACCESS INTEGRATION "GATEWAY" SET  ALLOWED_NETWORK_RULES = (PUBLIC.EGRESS_B),  ENABLED = false, COMMENT = 'gateway';
-- clearing a list and a commentALTER EXTERNAL ACCESS INTEGRATION "GATEWAY" SET  ALLOWED_AUTHENTICATION_SECRETS = none, COMMENT = '';

Tags

An integration takes repeatable tag blocks, like the other objects that support Snowflake tags:

schema.hcl
external_access_integration "GATEWAY" {  allowed_network_rules = [network_rule.EGRESS_A]  tag {    ref   = tag.DATA_DOMAIN    value = "integrations"  }}

Snowflake's CREATE EXTERNAL ACCESS INTEGRATION takes no inline WITH TAG clause, so Atlas sets tags in a follow-up ALTER. Removing one emits an UNSET TAG, and a tag change on its own leaves the integration's properties untouched, with no property SET in the plan.

migration.sql
-- create external access integration "GATEWAY"CREATE EXTERNAL ACCESS INTEGRATION "GATEWAY"  ALLOWED_NETWORK_RULES = (PUBLIC.EGRESS_A) ENABLED = true;ALTER EXTERNAL ACCESS INTEGRATION "GATEWAY" SET TAG PUBLIC.DATA_DOMAIN = 'integrations';
-- removing itALTER EXTERNAL ACCESS INTEGRATION "GATEWAY" UNSET TAG PUBLIC.DATA_DOMAIN;

Ordering

An integration is only valid once the objects it names exist, so Atlas orders it after them on create and before them on drop. A network rule is never removed while an integration still allows it, a tag is created before the SET TAG that uses it, and the whole set can be added or removed in a single plan.

Getting Started

External access integrations are opt-in. Enable them in the mode "snowflake" block of your env, together with the objects they reference:

atlas.hcl
env "snow" {  schema {    mode "snowflake" {      external_access_integrations = true      network_rules                = true    }  }}

Snowflake support is part of Atlas Pro. Run atlas login to get started.

featuresnowflakeexternal-access-integrationnetwork-rulesecurity