This guide walks you through connecting your Snowflake warehouse to Openbridge using a Programmatic Access Token (PAT). PAT authentication is simpler than OAuth — there is no recurring token refresh or manual re-authentication. You generate a token, provide it to Openbridge, and it remains valid until it expires. Token lifetime is controlled by your authentication policy; this guide configures a maximum of 365 days. When the token approaches expiration, you generate a new one (see Token Renewal).
Prerequisites
Before you begin, make sure you have:
An active Snowflake account with ACCOUNTADMIN privileges
An AWS account to create S3 buckets and IAM roles
Openbridge handles the rest automatically once your destination is configured.
Step 1: Configure Your S3 Bucket
Openbridge uses an S3 bucket as a staging area to load data into Snowflake. You have two options:
Option A: Use the CloudFormation Template (Recommended)
Use the Openbridge-provided CloudFormation template to automatically create and configure your S3 bucket with the correct permissions.
Option B: Use an Existing Bucket
If you prefer to use an existing S3 bucket, add the following IAM policy to grant Openbridge read/write access. Openbridge writes to the root of the bucket, so we recommend using a dedicated bucket rather than sharing one with other applications.
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::791778434480:role/zeroadmin-production"
},
"Action": [
"s3:GetObject",
"s3:PutObject",
"s3:DeleteObject",
"s3:ListBucket"
],
"Resource": [
"arn:aws:s3:::YOUR_BUCKET_NAME",
"arn:aws:s3:::YOUR_BUCKET_NAME/*"
]
}
]
}⚠ Important: Your S3 bucket's AWS region must match the region configured for your Snowflake storage integration.
Step 2: Create an IAM Policy and Role for Snowflake
Snowflake needs an IAM role in your AWS account to access your S3 bucket. This step creates the policy and role.
2a: Create the IAM Policy
In the IAM left navigation, select Policies.
Click Create Policy.
Select the JSON tab in the policy editor.
Paste the following policy, replacing
YOUR_BUCKET_NAMEwith your S3 bucket name:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:PutObject",
"s3:GetObject",
"s3:GetObjectVersion",
"s3:DeleteObject",
"s3:DeleteObjectVersion"
],
"Resource": "arn:aws:s3:::YOUR_BUCKET_NAME/*"
},
{
"Effect": "Allow",
"Action": [
"s3:ListBucket",
"s3:GetBucketLocation"
],
"Resource": "arn:aws:s3:::YOUR_BUCKET_NAME"
}
]
}Click Next.
Enter a policy name (e.g.,
openbridge_snowflake_s3_access).Click Create policy.
2b: Create the IAM Role
In the IAM left navigation, select Roles.
Click Create role.
Select AWS account as the trusted entity type.
Select Another AWS account.
In the Account ID field, enter your own AWS account ID (this is temporary — you will update it in Step 5).
Check Require external ID and enter a placeholder value like
0000(this will also be updated in Step 5).Click Next.
Search for and select the policy you created in Step 2a (e.g.,
openbridge_snowflake_s3_access).Click Next.
Enter a role name (e.g.,
openbridge_snowflake_role).Click Create role.
Open the role you just created and copy the Role ARN from the summary page (format:
arn:aws:iam::123456789012:role/openbridge_snowflake_role).
Save this Role ARN — you will need it in the next step.
Step 3: Run the Openbridge Setup Script
Open a Snowflake worksheet and log in as ACCOUNTADMIN. Copy and customize the script below by replacing the placeholder variables at the top.
Variables to Customize
Variable | Description | Format |
| Name for the Openbridge database | UPPERCASE |
| Name for the schema | UPPERCASE |
| Username for the Openbridge service account | UPPERCASE |
| Name for the Openbridge role | UPPERCASE |
| Name for the external stage | UPPERCASE |
| Name for the warehouse | UPPERCASE |
| Warehouse type | UPPERCASE |
| Warehouse size | UPPERCASE |
| IAM Role ARN from Step 2 | Exact casing |
| Your S3 bucket name | Exact casing |
Setup Script
-- ============================================
-- SET THESE VARIABLES BEFORE RUNNING
-- ============================================
SET db_name = 'OPENBRIDGE';
SET schema_name = 'OPENBRIDGE_SCHEMA';
SET user_name = 'OPENBRIDGE_USER';
SET role_name = 'OPENBRIDGE_ROLE';
SET stage_name = 'OPENBRIDGE_STAGE';
SET warehouse_name = 'OPENBRIDGE_WH';
SET warehouse_type = 'STANDARD';
SET warehouse_size = 'XSMALL';
SET aws_role_arn = 'arn:aws:iam::XXXXXXXXXXXX:role/your-role-name';
SET s3_bucket_name = 'your-bucket-name';
SET default_ns = $db_name || '.' || $schema_name;
SET s3_url = 's3://' || $s3_bucket_name || '/';
-- ============================================
-- CREATE ROLE
-- ============================================
USE ROLE ACCOUNTADMIN;
CREATE ROLE IF NOT EXISTS IDENTIFIER($role_name);
-- Grant the role to your current user (for testing purposes)
SET current_username = CURRENT_USER();
GRANT ROLE IDENTIFIER($role_name) TO USER IDENTIFIER($current_username);
-- ============================================
-- CREATE WAREHOUSE
-- ============================================
CREATE WAREHOUSE IF NOT EXISTS IDENTIFIER($warehouse_name)
WAREHOUSE_SIZE = $warehouse_size
WAREHOUSE_TYPE = $warehouse_type
AUTO_SUSPEND = 60
AUTO_RESUME = TRUE
INITIALLY_SUSPENDED = TRUE;
GRANT USAGE ON WAREHOUSE IDENTIFIER($warehouse_name) TO ROLE IDENTIFIER($role_name);
-- ============================================
-- CREATE DATABASE AND SCHEMA
-- ============================================
CREATE DATABASE IF NOT EXISTS IDENTIFIER($db_name);
GRANT USAGE ON DATABASE IDENTIFIER($db_name) TO ROLE IDENTIFIER($role_name);
USE DATABASE IDENTIFIER($db_name);
CREATE SCHEMA IF NOT EXISTS IDENTIFIER($schema_name);
GRANT ALL PRIVILEGES ON SCHEMA IDENTIFIER($schema_name) TO ROLE IDENTIFIER($role_name);
GRANT CREATE TABLE, CREATE VIEW, CREATE STAGE, CREATE FILE FORMAT ON SCHEMA IDENTIFIER($schema_name) TO ROLE IDENTIFIER($role_name);
USE SCHEMA IDENTIFIER($default_ns);
-- ============================================
-- CREATE USER
-- Service users cannot have passwords — authentication
-- is handled exclusively via the PAT created in Step 6.
-- ============================================
CREATE USER IF NOT EXISTS IDENTIFIER($user_name)
TYPE = SERVICE
DEFAULT_ROLE = $role_name
DEFAULT_WAREHOUSE = $warehouse_name
DEFAULT_NAMESPACE = $default_ns;
GRANT ROLE IDENTIFIER($role_name) TO USER IDENTIFIER($user_name);
-- ============================================
-- CREATE S3 STORAGE INTEGRATION AND STAGE
-- (STORAGE_AWS_ROLE_ARN, STORAGE_ALLOWED_LOCATIONS, and URL
-- do not support session variable substitution)
-- ============================================
DECLARE
role_arn VARCHAR DEFAULT $aws_role_arn;
s3_uri VARCHAR DEFAULT $s3_url;
stage VARCHAR DEFAULT $stage_name;
sql_str VARCHAR;
BEGIN
sql_str := 'CREATE OR REPLACE STORAGE INTEGRATION openbridge_s3 TYPE = EXTERNAL_STAGE STORAGE_PROVIDER = ''S3'' ENABLED = TRUE STORAGE_AWS_ROLE_ARN = ''' || :role_arn || ''' STORAGE_ALLOWED_LOCATIONS = (''' || :s3_uri || ''')';
EXECUTE IMMEDIATE :sql_str;
sql_str := 'CREATE STAGE IF NOT EXISTS ' || :stage || ' STORAGE_INTEGRATION = openbridge_s3 URL = ''' || :s3_uri || ''' FILE_FORMAT = (TYPE = ''PARQUET'')';
EXECUTE IMMEDIATE :sql_str;
END;
GRANT ALL PRIVILEGES ON STAGE IDENTIFIER($stage_name) TO ROLE IDENTIFIER($role_name);
GRANT USAGE ON INTEGRATION openbridge_s3 TO ROLE IDENTIFIER($role_name);
-- ============================================
-- CREATE NETWORK POLICY
-- ============================================
USE ROLE ACCOUNTADMIN;
-- These are the Openbridge production IP addresses.
-- Current IPs: https://docs.openbridge.com/en/articles/11822520-snowflake-warehouse-with-oauth-authentication
-- If these IPs ever change, update the network rule:
-- ALTER NETWORK RULE openbridge_network_rule
-- SET VALUE_LIST = ('NEW_IP_1/32', 'NEW_IP_2/32');
CREATE NETWORK RULE IF NOT EXISTS openbridge_network_rule
TYPE = IPV4
MODE = INGRESS
VALUE_LIST = ('52.2.68.68/32', '52.54.227.22/32');
CREATE NETWORK POLICY IF NOT EXISTS openbridge_network_policy
ALLOWED_NETWORK_RULE_LIST = ('openbridge_network_rule');
ALTER USER IDENTIFIER($user_name)
SET NETWORK_POLICY = openbridge_network_policy;
-- ============================================
-- CREATE AUTHENTICATION POLICY FOR PAT
-- ============================================
CREATE AUTHENTICATION POLICY IF NOT EXISTS openbridge_pat_policy
PAT_POLICY = (
NETWORK_POLICY_EVALUATION = ENFORCED_REQUIRED,
MAX_EXPIRY_IN_DAYS = 365
);
ALTER USER IDENTIFIER($user_name)
SET AUTHENTICATION POLICY openbridge_pat_policy;
-- ============================================
-- GRANT PAT MANAGEMENT TO OPENBRIDGE ROLE
-- ============================================
GRANT MODIFY PROGRAMMATIC AUTHENTICATION METHODS ON USER IDENTIFIER($user_name)
TO ROLE IDENTIFIER($role_name);
-- Test 1: Create a table
CREATE OR REPLACE TABLE test_table (
id INT AUTOINCREMENT PRIMARY KEY,
name STRING,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP()
);
-- Test 2: Insert data into the table
INSERT INTO test_table (name) VALUES
('Alice'),
('Bob'),
('Charlie');
-- Test 3: Query data from the table
SELECT * FROM test_table;
-- Test 4: Update data in the table
UPDATE test_table
SET name = 'Alice Updated'
WHERE name = 'Alice';
-- Test 5: Delete data from the table
DELETE FROM test_table
WHERE name = 'Bob';
-- Test 6: Drop the table
DROP TABLE test_table;
Need full ownership? The script above grants usage and specific privileges, which is safe for shared databases. If this is a dedicated Openbridge database and you want the Openbridge role to have full control, replace the database/schema grants with:
GRANT OWNERSHIP ON DATABASE IDENTIFIER($db_name) TO ROLE IDENTIFIER($role_name);
GRANT OWNERSHIP ON SCHEMA IDENTIFIER($schema_name) TO ROLE IDENTIFIER($role_name);
GRANT OWNERSHIP transfers full control of the database and schema to the Openbridge role, which can revoke access for other roles. Only use it for a dedicated Openbridge database.
Step 4: Retrieve IAM Values for Trust Policy
Run the following command in your Snowflake worksheet:
DESC INTEGRATION openbridge_s3;
From the output, copy these two values:
Property | Description |
| The AWS IAM user ARN created by Snowflake |
| The external ID for the trust relationship |
You will need these in the next step.
Step 5: Update Your IAM Role Trust Policy
Now you need to update the IAM role from Step 2 so that Snowflake (not your own AWS account) is the trusted entity.
In the AWS Management Console, navigate to IAM > Roles.
Select the role you created in Step 2 (e.g.,
openbridge_snowflake_role).Click the Trust relationships tab.
Click Edit trust policy.
Replace the entire policy document with the following, substituting the values from Step 4:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "",
"Effect": "Allow",
"Principal": {
"AWS": "STORAGE_AWS_IAM_USER_ARN_FROM_STEP_4"
},
"Action": "sts:AssumeRole",
"Condition": {
"StringEquals": {
"sts:ExternalId": "STORAGE_AWS_EXTERNAL_ID_FROM_STEP_4"
}
}
}
]
}Replace
STORAGE_AWS_IAM_USER_ARN_FROM_STEP_4with theSTORAGE_AWS_IAM_USER_ARNvalue from Step 4.Replace
STORAGE_AWS_EXTERNAL_ID_FROM_STEP_4with theSTORAGE_AWS_EXTERNAL_IDvalue from Step 4.Click Update policy.
If you ever recreate the storage integration in Snowflake, it will generate new ARN and external ID values. You would need to repeat this step with the new values.
Step 6: Generate a Programmatic Access Token
The setup script in Step 3 granted PAT management privileges to your Openbridge role. Switch to that role and generate the token.
Replace <YOUR_ROLE_NAME> and <YOUR_USER_NAME> below with the values you set in Step 3:
USE ROLE <YOUR_ROLE_NAME>;
ALTER USER <YOUR_USER_NAME>
ADD PROGRAMMATIC ACCESS TOKEN openbridge_pat
DAYS_TO_EXPIRY = 365
ROLE_RESTRICTION = <YOUR_ROLE_NAME>;
For example, if you used the default values from Step 3:
USE ROLE OPENBRIDGE_ROLE;
ALTER USER OPENBRIDGE_USER
ADD PROGRAMMATIC ACCESS TOKEN openbridge_pat
DAYS_TO_EXPIRY = 365
ROLE_RESTRICTION = OPENBRIDGE_ROLE;
⚠ Important: This command returns the token only once. Copy and save it in a secure location immediately. You will not be able to retrieve it again.
Step 7: Find Your Snowflake Account Identifier
Log in to your Snowflake account.
Click the account selector in the bottom-left corner.
Hover over your account and click the link icon to copy your Account Identifier.
Your Account Identifier should be in the format ORGNAME-ACCOUNTNAME (e.g., MYORG-MYACCOUNT).
If you are unsure of your Account Identifier, run the following in a Snowflake worksheet:
SELECT CURRENT_ORGANIZATION_NAME() || '-' || CURRENT_ACCOUNT_NAME();
Use the result as your Account Identifier.
Step 8: Configure Your Destination in Openbridge
In the Openbridge app, navigate to your Snowflake destination settings.
Enter the following details:
Field | Value |
Account Identifier | From Step 7 |
Username | The |
Programmatic Access Token | The token from Step 6 |
Database | The |
Schema | The |
Warehouse | The |
Stage | The |
Role | The |
S3 Bucket | Your S3 bucket name |
Bucket Region | The AWS region of your S3 bucket |
Save the destination.
Token Renewal
Your Programmatic Access Token expires based on the DAYS_TO_EXPIRY value set during generation (up to 365 days). Before it expires, revoke the old token, generate a new one, and update it in your Openbridge destination settings.
Check token expiration
SHOW PROGRAMMATIC ACCESS TOKENS FOR USER <YOUR_USER_NAME>;
Revoke the expiring token
ALTER USER <YOUR_USER_NAME>
REMOVE PROGRAMMATIC ACCESS TOKEN openbridge_pat;
Generate a new token
USE ROLE <YOUR_ROLE_NAME>;
ALTER USER <YOUR_USER_NAME>
ADD PROGRAMMATIC ACCESS TOKEN openbridge_pat
DAYS_TO_EXPIRY = 365
ROLE_RESTRICTION = <YOUR_ROLE_NAME>;
⚠ Important: This command returns the token only once. Copy and save it immediately.
Update Openbridge
Edit your destination in the Openbridge app and replace the token. All other fields are prepopulated.
Replace <YOUR_USER_NAME> and <YOUR_ROLE_NAME> with the values from Step 3 (e.g., OPENBRIDGE_USER, OPENBRIDGE_ROLE).
Troubleshooting
"Authentication policy does not allow programmatic access tokens"
If your account has an existing authentication policy that restricts authentication methods, you need to add PAT as an allowed method:
ALTER AUTHENTICATION POLICY your_existing_policy
SET AUTHENTICATION_METHODS = ('OAUTH', 'PASSWORD', 'PROGRAMMATIC_ACCESS_TOKEN');
"Network policy required"
The authentication policy requires a network policy. Verify the network policy from Step 3 was created and applied to the user successfully:
DESCRIBE USER OPENBRIDGE_USER
Look for NETWORK_POLICY in the output. If empty, re-run the network policy section from Step 3.
Token is not working after policy change
If an admin changed the MAX_EXPIRY_IN_DAYS to a value shorter than your token's remaining lifetime, the token is automatically invalidated. Generate a new token with Step 6.
Snowflake cannot assume the IAM role
If Snowflake fails to access your S3 bucket after completing all steps, AWS Security Token Service (STS) may be disabled for your region. To fix this:
In the AWS Management Console, navigate to IAM.
In the left navigation, select Account settings.
Under Security Token Service (STS) in Endpoints, find the AWS region where your Snowflake account is hosted.
If the status is Inactive, toggle it to Active.
