|
| 1 | +--- |
| 2 | +title: Snowflake |
| 3 | +description: Query and inspect data in Snowflake |
| 4 | +--- |
| 5 | + |
| 6 | +import { BlockInfoCard } from "@/components/ui/block-info-card" |
| 7 | + |
| 8 | +<BlockInfoCard |
| 9 | + type="snowflake" |
| 10 | + color="#FFFFFF" |
| 11 | +/> |
| 12 | + |
| 13 | +{/* MANUAL-CONTENT-START:intro */} |
| 14 | +### Configure Snowflake OAuth |
| 15 | + |
| 16 | +An administrator with permission to create account integrations must create a custom Snowflake OAuth security integration for Sim. Replace the callback host and public key below with the values for your Sim deployment: |
| 17 | + |
| 18 | +```sql |
| 19 | +CREATE SECURITY INTEGRATION sim_oauth |
| 20 | + TYPE = OAUTH |
| 21 | + ENABLED = TRUE |
| 22 | + OAUTH_CLIENT = CUSTOM |
| 23 | + OAUTH_CLIENT_TYPE = 'CONFIDENTIAL' |
| 24 | + OAUTH_REDIRECT_URI = 'https://<your-sim-host>/api/auth/oauth2/callback/snowflake' |
| 25 | + OAUTH_ENFORCE_PKCE = TRUE |
| 26 | + OAUTH_ISSUE_REFRESH_TOKENS = TRUE |
| 27 | + OAUTH_CLIENT_RSA_PUBLIC_KEY = '<sim-oauth-public-key>'; |
| 28 | +``` |
| 29 | + |
| 30 | +Run `DESC SECURITY INTEGRATION sim_oauth` to find the generated OAuth client ID and public-key fingerprint. When connecting in Sim, provide: |
| 31 | + |
| 32 | +- Your account URL, such as `https://myorg-myaccount.snowflakecomputing.com` |
| 33 | +- Your account locator (not the account name) |
| 34 | +- The generated OAuth client ID |
| 35 | + |
| 36 | +The Sim deployment must configure the matching unencrypted PKCS#8 private key as `SNOWFLAKE_OAUTH_PRIVATE_KEY`. The private key is deployment-wide; only its public key is registered in each customer security integration. Sim uses an RS256 client assertion, PKCE, and refresh tokens, so customer OAuth client secrets are not collected or stored. |
| 37 | + |
| 38 | +Sim requests the `refresh_token` scope without a role scope. Snowflake therefore uses the connecting user's default role. Assign that role only the warehouses, databases, schemas, and operations workflows should be able to access. Snowflake blocks privileged roles by default. |
| 39 | + |
| 40 | +For key rotation, register the next public key in `OAUTH_CLIENT_RSA_PUBLIC_KEY_2`, update the Sim deployment to use the matching private key, verify connections, and then replace the old public key. Snowflake supports two active OAuth client public keys so this can be done without interruption. |
| 41 | + |
| 42 | +See Snowflake's [custom OAuth guide](https://docs.snowflake.com/en/user-guide/oauth-custom) and [`CREATE SECURITY INTEGRATION` reference](https://docs.snowflake.com/en/sql-reference/sql/create-security-integration-oauth-snowflake) for the authoritative setup and policy options. |
| 43 | + |
| 44 | +### Result handling |
| 45 | + |
| 46 | +Query, Execute, and Introspect submit exactly one statement and request Snowflake's minimum 16 MB result chunks. If Snowflake returns a pending statement, use **Get Statement** with its handle. Each operation returns at most one result partition; when `hasMore` is true, call **Get Statement** with the next zero-based partition number. Column metadata and the total row count are returned with the first partition and may be absent from later partitions. Sim does not automatically load all partitions into workflow memory. |
| 47 | + |
| 48 | +There is no Snowflake trigger. Snowflake does not document a compatible event or webhook trigger for this integration, so workflows should use schedules when polling is appropriate. |
| 49 | +{/* MANUAL-CONTENT-END */} |
| 50 | + |
| 51 | +## Usage Instructions |
| 52 | + |
| 53 | +Connect a Snowflake account with OAuth to run SQL, inspect database schemas, and retrieve asynchronous or partitioned statement results through the Snowflake SQL API. |
| 54 | + |
| 55 | + |
| 56 | + |
| 57 | +## Actions |
| 58 | + |
| 59 | +### Snowflake Query |
| 60 | + |
| 61 | +Run a SQL query in Snowflake and return the first bounded result partition |
| 62 | + |
| 63 | +#### Input |
| 64 | + |
| 65 | +| Parameter | Type | Required | Description | |
| 66 | +| --------- | ---- | -------- | ----------- | |
| 67 | +| `idToken` | string | No | Snowflake account URL stored with the OAuth credential | |
| 68 | +| `statement` | string | Yes | A single SQL query to run | |
| 69 | +| `warehouse` | string | No | Warehouse to use instead of the user default | |
| 70 | +| `database` | string | No | Database to use instead of the user default | |
| 71 | +| `schema` | string | No | Schema to use instead of the user default | |
| 72 | +| `timeout` | number | No | Statement timeout in seconds \(1-604800\) | |
| 73 | + |
| 74 | +#### Output |
| 75 | + |
| 76 | +| Parameter | Type | Description | |
| 77 | +| --------- | ---- | ----------- | |
| 78 | +| `status` | string | Statement status \(succeeded or running\) | |
| 79 | +| `message` | string | Snowflake status message | |
| 80 | +| `statementHandle` | string | Handle for later status/result requests | |
| 81 | +| `columns` | json | Result columns \(\[\{name, type, nullable\}\]\) | |
| 82 | +| `rows` | json | One bounded result partition as a 2D value array | |
| 83 | +| `rowCount` | number | Total rows reported by Snowflake | |
| 84 | +| `partitionCount` | number | Number of available result partitions | |
| 85 | +| `partition` | number | Partition returned by this operation | |
| 86 | +| `hasMore` | boolean | Whether another result partition is available | |
| 87 | +### Snowflake Execute |
| 88 | + |
| 89 | +Execute one SQL statement in Snowflake and return its status and bounded results |
| 90 | + |
| 91 | +#### Input |
| 92 | + |
| 93 | +| Parameter | Type | Required | Description | |
| 94 | +| --------- | ---- | -------- | ----------- | |
| 95 | +| `idToken` | string | No | Snowflake account URL stored with the OAuth credential | |
| 96 | +| `statement` | string | Yes | A single SQL statement to execute | |
| 97 | +| `warehouse` | string | No | Warehouse to use instead of the user default | |
| 98 | +| `database` | string | No | Database to use instead of the user default | |
| 99 | +| `schema` | string | No | Schema to use instead of the user default | |
| 100 | +| `timeout` | number | No | Statement timeout in seconds \(1-604800\) | |
| 101 | + |
| 102 | +#### Output |
| 103 | + |
| 104 | +| Parameter | Type | Description | |
| 105 | +| --------- | ---- | ----------- | |
| 106 | +| `status` | string | Statement status \(succeeded or running\) | |
| 107 | +| `message` | string | Snowflake status message | |
| 108 | +| `statementHandle` | string | Handle for later status/result requests | |
| 109 | +| `columns` | json | Result columns \(\[\{name, type, nullable\}\]\) | |
| 110 | +| `rows` | json | One bounded result partition as a 2D value array | |
| 111 | +| `rowCount` | number | Total rows reported by Snowflake | |
| 112 | +| `partitionCount` | number | Number of available result partitions | |
| 113 | +| `partition` | number | Partition returned by this operation | |
| 114 | +| `hasMore` | boolean | Whether another result partition is available | |
| 115 | + |
| 116 | +### Snowflake Introspect |
| 117 | + |
| 118 | +List tables, views, and columns from a Snowflake database information schema |
| 119 | + |
| 120 | +#### Input |
| 121 | + |
| 122 | +| Parameter | Type | Required | Description | |
| 123 | +| --------- | ---- | -------- | ----------- | |
| 124 | +| `idToken` | string | No | Snowflake account URL stored with the OAuth credential | |
| 125 | +| `database` | string | Yes | Database whose information schema should be inspected | |
| 126 | +| `schema` | string | No | Optional exact schema name to inspect | |
| 127 | +| `warehouse` | string | No | Warehouse to use instead of the user default | |
| 128 | +| `timeout` | number | No | Statement timeout in seconds \(1-604800\) | |
| 129 | + |
| 130 | +#### Output |
| 131 | + |
| 132 | +| Parameter | Type | Description | |
| 133 | +| --------- | ---- | ----------- | |
| 134 | +| `status` | string | Statement status \(succeeded or running\) | |
| 135 | +| `message` | string | Snowflake status message | |
| 136 | +| `statementHandle` | string | Handle for later status/result requests | |
| 137 | +| `columns` | json | Result columns \(\[\{name, type, nullable\}\]\) | |
| 138 | +| `rows` | json | One bounded result partition as a 2D value array | |
| 139 | +| `rowCount` | number | Total rows reported by Snowflake | |
| 140 | +| `partitionCount` | number | Number of available result partitions | |
| 141 | +| `partition` | number | Partition returned by this operation | |
| 142 | +| `hasMore` | boolean | Whether another result partition is available | |
| 143 | + |
| 144 | +### Snowflake Get Statement |
| 145 | + |
| 146 | +Check a statement and retrieve one bounded result partition by handle |
| 147 | + |
| 148 | +#### Input |
| 149 | + |
| 150 | +| Parameter | Type | Required | Description | |
| 151 | +| --------- | ---- | -------- | ----------- | |
| 152 | +| `idToken` | string | No | Snowflake account URL stored with the OAuth credential | |
| 153 | +| `statementHandle` | string | Yes | Statement handle returned by Query, Execute, or Introspect | |
| 154 | +| `partition` | number | No | Zero-based result partition to retrieve \(default: 0\) | |
| 155 | + |
| 156 | +#### Output |
| 157 | + |
| 158 | +| Parameter | Type | Description | |
| 159 | +| --------- | ---- | ----------- | |
| 160 | +| `status` | string | Statement status \(succeeded or running\) | |
| 161 | +| `message` | string | Snowflake status message | |
| 162 | +| `statementHandle` | string | Handle for later status/result requests | |
| 163 | +| `columns` | json | Result columns \(\[\{name, type, nullable\}\]\) | |
| 164 | +| `rows` | json | One bounded result partition as a 2D value array | |
| 165 | +| `rowCount` | number | Total rows reported by Snowflake | |
| 166 | +| `partitionCount` | number | Number of available result partitions | |
| 167 | +| `partition` | number | Partition returned by this operation | |
| 168 | +| `hasMore` | boolean | Whether another result partition is available | |
0 commit comments