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:
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"}
| Attribute | Notes |
|---|---|
| allowed_network_rules | Required, 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_secrets | Qualified names of the secrets the code may authenticate with. Mutually exclusive with allow_all_authentication_secrets. |
| allow_all_authentication_secrets | true maps to Snowflake's ALLOWED_AUTHENTICATION_SECRETS = ALL, which it reports in place of a list. |
| allowed_api_authentication_integrations | Names of the API authentication security integrations the code may use. They are account-level, so they are not schema-qualified. |
| enabled | Defaults to true. Snowflake requires it on CREATE either way, so Atlas always writes it. |
| comment | Free text, cleared with an empty string rather than an UNSET. |
| tag | Repeatable 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:
external_access_integration "OPEN_GATEWAY" { allowed_network_rules = [network_rule.EGRESS_A] allow_all_authentication_secrets = true}
Generated 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.
-- 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:
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.
-- 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:
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.