From 4a21061677a0a26abf2ae8e6079ae28b69b78d6a Mon Sep 17 00:00:00 2001 From: Ray Harris Date: Wed, 2 Jul 2025 13:10:30 -0700 Subject: [PATCH 1/2] preview --- .../gpt_action_snowflake_direct.ipynb | 130 +++++++++++++----- 1 file changed, 94 insertions(+), 36 deletions(-) diff --git a/examples/chatgpt/gpt_actions_library/gpt_action_snowflake_direct.ipynb b/examples/chatgpt/gpt_actions_library/gpt_action_snowflake_direct.ipynb index d2494a6037..6d7ba6785c 100644 --- a/examples/chatgpt/gpt_actions_library/gpt_action_snowflake_direct.ipynb +++ b/examples/chatgpt/gpt_actions_library/gpt_action_snowflake_direct.ipynb @@ -99,7 +99,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## ChatGPT Steps" + "## 1. Configure the Custom GPT" ] }, { @@ -107,7 +107,7 @@ "metadata": {}, "source": [ "\n", - "### Custom GPT Instructions\n", + "### Set GPT Instructions\n", "\n", "Once you've created a Custom GPT, copy the text below in the Instructions panel. Have questions? Check out [Getting Started Example](https://platform.openai.com/docs/actions/getting-started) to see how this step works in more detail." ] @@ -217,7 +217,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## Authentication Instructions" + "## 2. Configure Snowflake Integration" ] }, { @@ -231,16 +231,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "### Pre-Action Steps" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Before you set up authentication in ChatGPT, please take the following steps in Snowflake.\n", - "\n", - "### 1. Optional: Configure IP Whitelisting for ChatGPT\n", + "### Configure IP Whitelisting for ChatGPT\n", "Snowflake accounts with network policies that limit connections by IP, may require exceptions to be added for ChatGPT.\n", "* Review the Snowflake documentation on [Network Policies](https://docs.snowflake.com/en/user-guide/network-policies)\n", "* Go to the Snowflake Worksheets\n", @@ -258,26 +249,11 @@ }, "outputs": [], "source": [ - "## Example with ChatGPT IPs as of October 23, 2024\n", - "## Make sure to get the current IP ranges from https://platform.openai.com/docs/actions/production\n", + "## ChatGPT IP ranges available at https://openai.com/chatgpt-actions.json\n", "CREATE NETWORK RULE chatgpt_network_rule\n", " MODE = INGRESS\n", " TYPE = IPV4\n", - " VALUE_LIST = ('23.102.140.112/28',\n", - " '13.66.11.96/28',\n", - " '104.210.133.240/28',\n", - " '70.37.60.192/28',\n", - " '20.97.188.144/28',\n", - " '20.161.76.48/28',\n", - " '52.234.32.208/28',\n", - " '52.156.132.32/28',\n", - " '40.84.220.192/28',\n", - " '23.98.178.64/28',\n", - " '51.8.155.32/28',\n", - " '20.246.77.240/28',\n", - " '172.178.141.0/28',\n", - " '172.178.141.192/28',\n", - " '40.84.180.128/28');\n", + " VALUE_LIST = ('23.102.140.112/28',...,'40.84.180.128/28');\n", "\n", "CREATE NETWORK POLICY chatgpt_network_policy\n", " ALLOWED_NETWORK_RULE_LIST = ('chatgpt_network_rule');" @@ -287,14 +263,14 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Network policies can be applied at the account, security integration, and user level. The most specific network policy overrides the more general network policies. Depending on how these policies are applied, you may need to alter the policies for individual users in addition to the security integration. If you face this issue, you may encounter Snowflake's error code 390422." + "Network policies can be applied at the account, security integration, and user level. The most specific network policy overrides the more general network policies. Depending on how these policies are applied, you may need to alter the policies for individual users in addition to the security integration. If you face this issue, you may encounter Snowflake's error code 390422 or a generic \"Invalid Client\" error." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "### 2. Set up the Security Integration\n", + "### Create the Security Integration\n", "* Review the Snowflake OAuth Overview: [https://docs.snowflake.com/en/user-guide/oauth-snowflake-overview](https://docs.snowflake.com/en/user-guide/oauth-snowflake-overview)\n", "* Create new OAuth credentials through a [Security Integration](https://docs.snowflake.com/en/sql-reference/sql/create-security-integration-oauth-snowflake) - you will need a new one for each OAuth app/custom GPT since Snowflake Redirect URIs are 1-1 mapped to Security Integrations" ] @@ -324,7 +300,89 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "\n", + "
\n", + " Automate Network Rule Configuration\n", + " \n", + " There are now over 100 egress IP addresses used by ChatGPT. The list updates irregularly and without announcement. To keep up to date with it, we can fetch the list on a daily basis and apply it to our network rule.\n", + "\n", + " ### Network rule to allow outbound traffic to OpenAI\n", + " ```sql\n", + " CREATE OR REPLACE NETWORK RULE chatgpt_actions_rule\n", + " MODE = EGRESS -- outbound\n", + " TYPE = HOST_PORT\n", + " VALUE_LIST = ('openai.com:443');\n", + " ```\n", + " ### Access Integration to apply the rule\n", + " ```sql\n", + " CREATE OR REPLACE EXTERNAL ACCESS INTEGRATION chatgpt_actions_integration\n", + " ALLOWED_NETWORK_RULES = (chatgpt_actions_rule)\n", + " ENABLED = TRUE;\n", + " ```\n", + "\n", + " ### UDF to Fetch the IP ranges\n", + " ```sql\n", + " CREATE OR REPLACE FUNCTION getChatGPTActionsAddresses()\n", + " RETURNS ARRAY -- array\n", + " LANGUAGE PYTHON\n", + " RUNTIME_VERSION = 3.10\n", + " PACKAGES = ('requests')\n", + " EXTERNAL_ACCESS_INTEGRATIONS = (chatgpt_actions_integration)\n", + " HANDLER = 'get_ip_address_ranges'\n", + "AS\n", + "$$\n", + "import requests\n", + "\n", + "def get_ip_address_ranges():\n", + " resp = requests.get(\"https://openai.com/chatgpt-actions.json\", timeout=10)\n", + " resp.raise_for_status()\n", + " data = [entry[\"ipv4Prefix\"] for entry in resp.json().get(\"prefixes\", []) if \"ipv4Prefix\" in entry]\n", + " return data\n", + "$$;\n", + " ```\n", + " ### Procedure to update the network rule\n", + " ```sql\n", + " CREATE OR REPLACE PROCEDURE update_chatgpt_network_rule()\n", + " RETURNS STRING\n", + " LANGUAGE SQL\n", + "AS\n", + "$$\n", + "DECLARE\n", + " ip_list STRING;\n", + "BEGIN\n", + " -- Properly quote the IPs for use in VALUE_LIST\n", + " ip_list := '''' || ARRAY_TO_STRING(getChatGPTActionsAddresses(), ''',''') || '''';\n", + "\n", + " -- Run the dynamic SQL to update the rule\n", + " EXECUTE IMMEDIATE\n", + " 'ALTER NETWORK RULE chatgpt_network_rule SET VALUE_LIST = (' || ip_list || ')';\n", + "\n", + " RETURN 'chatgpt_network_rule updated with ' || ARRAY_SIZE(getChatGPTActionsAddresses()) || ' entries';\n", + "END;\n", + "$$;\n", + " ```\n", + "\n", + " ### Call the procedure\n", + " ```sql\n", + " CALL update_chatgpt_network_rule();\n", + " ```\n", + "\n", + " ### Run the procedure every day at 6AM Pacific Time\n", + " ```sql\n", + " CREATE OR REPLACE TASK auto_update_chatgpt_network_rule\n", + " WAREHOUSE = COMPUTE_WH\n", + " SCHEDULE = 'USING CRON 0 6 * * * America/Los_Angeles'\n", + "AS\n", + " CALL update_chatgpt_network_rule();\n", + " ```\n", + "
" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Configure GPT Action Authentication\n", + "### Gather key information from Snowflake\n", "* Retrieve your OAuth Client ID, Auth URL, and Token URL\n" ] }, @@ -391,7 +449,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "### In ChatGPT" + "### Set OAuth Values in GPT Action Authentication" ] }, { @@ -407,11 +465,11 @@ "| Client Secret | OAUTH_CLIENT_SECRET from SHOW_OAUTH_CLIENT_SECRETS |\n", "| Authorization URL | OAUTH_AUTHORIZATION_ENDPOINT from DESCRIBE SECURITY INTEGRATION |\n", "| Token URL | OAUTH_TOKEN_ENDPOINT from DESCRIBE SECURITY INTEGRATION |\n", - "| Scope | session:role:your_role* |\n", + "| Scope | session:role:CHATGPT_INTEGRATION_ROLE* |\n", "| Token Exchange Method | Default (POST Request) |\n", "\n", "\n", - "*Snowflake scopes pass the role in the format `session:role:` for example `session:role:CHATGPT_INTEGRATION_ROLE`. It's possible to leave this empty and specify the role in the instructions, but by adding it here it becomes included in OAuth Consent Request which can sometimes be more reliable. " + "*Snowflake scopes pass the role in the format `session:role:` for example `session:role:CHATGPT_INTEGRATION_ROLE`. You can optionally leave this field empty and specify the role in the GPT instructions, but by adding it here it becomes included in OAuth Consent Request which can sometimes be more reliable. " ] }, { From f9916852a6aaf5c9f02fa9f0876d397423a3d95c Mon Sep 17 00:00:00 2001 From: Ray Harris Date: Wed, 2 Jul 2025 13:15:59 -0700 Subject: [PATCH 2/2] little more --- .../gpt_action_snowflake_direct.ipynb | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/examples/chatgpt/gpt_actions_library/gpt_action_snowflake_direct.ipynb b/examples/chatgpt/gpt_actions_library/gpt_action_snowflake_direct.ipynb index 6d7ba6785c..cc1c692a9f 100644 --- a/examples/chatgpt/gpt_actions_library/gpt_action_snowflake_direct.ipynb +++ b/examples/chatgpt/gpt_actions_library/gpt_action_snowflake_direct.ipynb @@ -235,7 +235,7 @@ "Snowflake accounts with network policies that limit connections by IP, may require exceptions to be added for ChatGPT.\n", "* Review the Snowflake documentation on [Network Policies](https://docs.snowflake.com/en/user-guide/network-policies)\n", "* Go to the Snowflake Worksheets\n", - "* Create a network rule with the ChatGPT IP egress ranges listed [here](https://platform.openai.com/docs/actions/production/ip-egress-ranges)\n", + "* Create a network rule with the ChatGPT IP egress ranges listed [here](https://platform.openai.com/docs/actions/production/ip-egress-ranges#ip-egress-ranges)\n", "* Create a corresponding Network Policy" ] }, @@ -301,7 +301,7 @@ "metadata": {}, "source": [ "
\n", - " Automate Network Rule Configuration\n", + " Optional: Automate Network Rule Configuration\n", " \n", " There are now over 100 egress IP addresses used by ChatGPT. The list updates irregularly and without announcement. To keep up to date with it, we can fetch the list on a daily basis and apply it to our network rule.\n", "\n", @@ -381,7 +381,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## Configure GPT Action Authentication\n", + "## 3. Configure GPT Action Authentication\n", "### Gather key information from Snowflake\n", "* Retrieve your OAuth Client ID, Auth URL, and Token URL\n" ] @@ -404,7 +404,7 @@ "metadata": {}, "source": [ "\n", - "You’ll find the required information in these 3 columns:" + "You’ll find the required information in these 3 rows:" ] }, { @@ -476,7 +476,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "### Post-Action Steps" + "### 4. Update the Snowflake Integration Redirect URI" ] }, {