Azure Private Link を使用する Snowflake への接続を試してみる

Azure Private Link を使用する Snowflake への接続を試してみる

2025.10.14

はじめに

Azure の仮想ネットワーク(Vnet)内のインスタンス(VM)から Azure Private Link 経由での Snowflake への接続を試してみましたので、その内容をまとめてみます。

前提条件

以下の環境で検証しています。

  • Snowflake
    • クラウドサービス:Microsoft Azure
    • リージョン:japaneast
  • ストレージ アカウントのリージョン:japaneast
  • 以下の構成は作成済みとします
    • リソースグループ
    • 仮想ネットワーク(Vnet)
      • プライベートサブネットへの VM(Windows Server)の作成
      • VM には Azure Bastion 経由で Azure ポータル上からログインします
  • 以下の Azure Private Link の接続を行います
    • Snowflake サービス
    • 内部ステージ
    • ※ここでは以下へのプライベート接続は扱いません
      • Streamlit in Snowflake
      • Snowpark Container Services

下図のような構成を目指します。

image

構成手順は以下に記載があります。本記事でもこちらの内容に沿って進めます。

https://docs.snowflake.com/ja/user-guide/privatelink-azure

Azure プライベート エンドポイントの構成

Azure Private Link の構成には、Azure アカウント側でプライベート エンドポイントを作成します。プライベート エンドポイントは何らかのサブネットに作成するので、ここではプライベート エンドポイント用のサブネットを作成しました。

image 1

あわせてサブネットには、デフォルトのネットワークセキュリティグループ(NSG)を割り当てました。今回はデフォルトのままで明示的に設定していませんが、ポート 443 および 80 からのインバウンド接続が許可されている必要があります。

image 2

プライベート エンドポイント作成時は、Snowflake アカウント側の Azure ネットワークの Private Link サービスの識別子が必要です。そのため、Snowflake 側で SYSTEM$GET_PRIVATELINK_CONFIG を実行し、以下を実行し出力のprivatelink-pls-id の値を控えておきます。

			
			SELECT SYSTEM$GET_PRIVATELINK_CONFIG();

		
			
			"privatelink-pls-id":"sf-xxxxx.privatelinkservice",

		

プライベート エンドポイント作成時は、既存のリソース グループを指定し、「接続方法」で「リソース ID またはエイリアスを使って Azure リソースに接続します。」を選択し、privatelink-pls-idの値を指定します。

image 3

サブネットには、先の手順で作成した、プライベート エンドポイント用のサブネットを指定しました。

image 4

作成後の「接続状態」は「Pending」となっています。

image 5

プライベート エンドポイント作成後、Snowflake 側での承認作業に必要なので、リソース ID を確認します。

image 6

続けて Azure アカウント側で Snowflake アカウント側で利用できる一時的なアクセストークンを生成します。ここでは、クラウドシェルで以下を実行しました。SubscriptionIDは、プライベート エンドポイント作成時のサブスクリプションの ID です。

			
			az account get-access-token --subscription <SubscriptionID>

		

出力は以下のようになるので、accessToken の値を控えておきます。こちらは有効期限があるので注意します。

			
			$ az account get-access-token --subscription xxxxx
{
  "accessToken": "xxxxx",
  "expiresOn": "2025-10-13 03:14:08.000000",
  "expires_on": 1760325248,
  "subscription": "xxxxx",
  "tenant": "xxxxx",
  "tokenType": "Bearer"
}

		

Snowflake 側でプライベート エンドポイントのリソース ID とaccessToken の値を使用し、SYSTEM$AUTHORIZE_PRIVATELINK 関数を実行します。これにより、Snowflake アカウント側のサービスへのプライベート接続が有効となります。

			
			USE ROLE ACCOUNTADMIN;

SELECT SYSTEM$AUTHORIZE_PRIVATELINK (
  '<プライベート エンドポイントのリソース ID>',
  '<accessToken>'
  );

		

image 7

上記実行後、Azure アカウント側でもプライベート エンドポイントのステータスが変更されていることを確認できます。

image 8

DNS 構成

Private Link の構成後、Vnet 内から Snowflake へのリクエストが、プライベート エンドポイント経由するように(プライベート IP アドレスで解決できるように) DNS の構成を行います。

はじめに Snowflake 側で SYSTEM$GET_PRIVATELINK_CONFIG を実行します。公式ドキュメントの手順で整形しつつ出力を確認すると、2025/10/13 時点では以下のようになります。

			
			>select key, value from table(flatten(input=>parse_json(SYSTEM$GET_PRIVATELINK_CONFIG())));
+--------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------+
| KEY                                  | VALUE                                                                                                                                            |
|--------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------|
| app-service-privatelink-url          | "*.xxxxx.privatelink.snowflake.app"                                                                                                             |
| privatelink-account-name             | "<アカウント識別子>.japan-east.privatelink"                                                                                                                 |
| privatelink-account-url              | "<アカウント識別子>.japan-east.privatelink.snowflakecomputing.com"                                                                                          |
| privatelink-dashed-urls-for-duo      | "[app-<組織名>-<アカウント名>.privatelink.snowflakecomputing.com, <組織名>-<アカウント名>.privatelink.snowflakecomputing.com]"                 |
| privatelink-internal-stage           | "/subscriptions/xxxxx/<ストレージ アカウント名>" |
| privatelink-pls-id                   | "sf-xxxxx.privatelinkservice"                                               |
| privatelink_ocsp-url                 | "ocsp.<アカウント識別子>.japan-east.privatelink.snowflakecomputing.com"                                                                                     |
| regionless-privatelink-account-url   | "<組織名>-my_azure_account.privatelink.snowflakecomputing.com"                                                                                    |
| regionless-privatelink-ocsp-url      | "ocsp.<組織名>-my_azure_account.privatelink.snowflakecomputing.com"                                                                               |
| regionless-snowsight-privatelink-url | "app-<組織名>-my_azure_account.privatelink.snowflakecomputing.com"                                                                                |
| snowpark-connect-privatelink-url     | "*.snowpark.xxxxx.privatelink.snowflakecomputing.com"                                                                                           |
| snowsight-privatelink-url            | "app.japan-east.privatelink.snowflakecomputing.com"                                                                                              |
| spcs-auth-privatelink-url            | "sfc-endpoint-login.xxxxxx.privatelink.snowflakecomputing.com"                                                                                   |
| spcs-registry-privatelink-url        | "<組織名>-<アカウント名>.registry.privatelink.snowflakecomputing.com"                                                                           |
+--------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------+

		

このうち、ここでは以下の値を使用します。

			
			+--------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------+
| KEY                                  | VALUE                                                                                                                                            |
|--------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------|
| privatelink-account-url              | "<アカウント識別子>.japan-east.privatelink.snowflakecomputing.com"                                                                                          |
| privatelink_ocsp-url                 | "ocsp.<アカウント識別子>.japan-east.privatelink.snowflakecomputing.com"                                                                                     |
| snowsight-privatelink-url            | "app.japan-east.privatelink.snowflakecomputing.com"                                                                                              |
| regionless-privatelink-account-url   | "<組織名>-<アカウント名>.privatelink.snowflakecomputing.com"                                                                                    |
| regionless-privatelink-ocsp-url      | "ocsp.<組織名>-<アカウント名>.privatelink.snowflakecomputing.com"                                                                               |
| regionless-snowsight-privatelink-url | "app-<組織名>-<アカウント名>.privatelink.snowflakecomputing.com"                                                                                |
| privatelink-dashed-urls-for-duo      | "[app-<組織名>-<アカウント名>.privatelink.snowflakecomputing.com, <組織名>-<アカウント名>.privatelink.snowflakecomputing.com]"                 |
+--------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------+

		

Snowflake にアクセスする際は、アカウント識別子を使用するものと組織名・アカウント名を使用するものの 2 種類の URL を使用できます。プライベートアクセス用の URL も同様に 2 種類用意されています。

privatelink-dashed-urls-for-duoは特に MFA に Duo を使用する際に、アカウント名にアンダースコア(_)が含まれている場合、追加の DNS 設定(レコード登録)が必要になります。この際に、この DNS レコードを使用できます。
具体的にはアカウント名のアンダースコアがハイフン(-)に置き換えたられた値となっており、今回の設定では、アカウント名にアンダースコアが含まれていたので、こちらも後述する手順で登録します。

https://docs.snowflake.com/en/release-notes/bcr-bundles/2025_01/bcr-1875

プライベート DNS ゾーンの作成

上記のエンドポイント値がプライベート IP アドレスに解決されるように、 DNS の構成を行います。以下の構成で Azure プライベート DNS ホストゾーンを作成します。

  • 名前:privatelink.snowflakecomputing.com

image 9

各エンドポイントのレコードを追加します。はじめにレコード値を確認します。レコード値は、プライベート エンドポイントの IP アドレスです。

image 10

GUI の場合、対象のホストゾーンの「DNSの管理 > レコードセット」より各レコードを作成できます。ここでは、レコードが複数あるので、クラウドシェルで以下を実行することで、各種の A レコードを作成しました。

			
			# 変数を定義
RESOURCE_GROUP="<リソースグループ名>"
PRIVATE_DNS_ZONE="privatelink.snowflakecomputing.com"
IP_ADDRESS="<プライベートエンドポイントのIPアドレス>"

RECORD_SET_ACCOUNT="<アカウント識別子>.japan-east"
RECORD_SET_OCSP="ocsp.<アカウント識別子>.japan-east"
RECORD_SET_SNOWSIGHT="app.japan-east"
RECORD_SET_REGIONLESS_ACCOUNT="<組織名>-<アカウント名>"
RECORD_SET_REGIONLESS_SNOWSIGHT="app-<組織名>-<アカウント名>"
RECORD_SET_REGIONLESS_OCSP="ocsp.<組織名>-<アカウント名>"

# Duo用
RECORD_SET_REGIONLESS_ACCOUNT_DUO="<組織名>-<アカウント名>"
RECORD_SET_REGIONLESS_SNOWSIGHT_DUO="app-<組織名>-<アカウント名>"

		
			
			# すべてのAレコードを作成
az network private-dns record-set a add-record \
  --resource-group $RESOURCE_GROUP \
  --zone-name "$PRIVATE_DNS_ZONE" \
  --record-set-name "$RECORD_SET_ACCOUNT" \
  --ipv4-address "$IP_ADDRESS"

az network private-dns record-set a add-record \
  --resource-group $RESOURCE_GROUP \
  --zone-name "$PRIVATE_DNS_ZONE" \
  --record-set-name "$RECORD_SET_OCSP" \
  --ipv4-address "$IP_ADDRESS"

az network private-dns record-set a add-record \
  --resource-group $RESOURCE_GROUP \
  --zone-name "$PRIVATE_DNS_ZONE" \
  --record-set-name "$RECORD_SET_SNOWSIGHT" \
  --ipv4-address "$IP_ADDRESS"

az network private-dns record-set a add-record \
  --resource-group $RESOURCE_GROUP \
  --zone-name "$PRIVATE_DNS_ZONE" \
  --record-set-name "$RECORD_SET_REGIONLESS_ACCOUNT" \
  --ipv4-address "$IP_ADDRESS"

az network private-dns record-set a add-record \
  --resource-group $RESOURCE_GROUP \
  --zone-name "$PRIVATE_DNS_ZONE" \
  --record-set-name "$RECORD_SET_REGIONLESS_SNOWSIGHT" \
  --ipv4-address "$IP_ADDRESS"

az network private-dns record-set a add-record \
  --resource-group $RESOURCE_GROUP \
  --zone-name "$PRIVATE_DNS_ZONE" \
  --record-set-name "$RECORD_SET_REGIONLESS_OCSP" \
  --ipv4-address "$IP_ADDRESS"

# duo用レコードの作成
az network private-dns record-set a add-record \
  --resource-group $RESOURCE_GROUP \
  --zone-name "$PRIVATE_DNS_ZONE" \
  --record-set-name "$RECORD_SET_REGIONLESS_ACCOUNT_DUO" \
  --ipv4-address "$IP_ADDRESS"

az network private-dns record-set a add-record \
  --resource-group $RESOURCE_GROUP \
  --zone-name "$PRIVATE_DNS_ZONE" \
  --record-set-name "$RECORD_SET_REGIONLESS_SNOWSIGHT_DUO" \
  --ipv4-address "$IP_ADDRESS"

		

実行後、Azure ポータルからも確認できます。

image 11

プライベート DNS ゾーンを仮想ネットワークにリンク

対象のプライベート DNS ゾーンの「DNSの管理 > 仮想ネットワーク リンク」から、VM を構築した VNet とのリンクを追加します。

image 12

VM から接続

プライベートサブネットに構築した VM(Windows Server)からプライベート接続用のエンドポイントで Snowflake アカウントに接続します。

image 13

ログインできました。

image 14

クエリも実行できます。

image 15

アカウント識別子、組織名・アカウント名のいずれでもアクセスできます。

注意点としてプライベート接続経由で Notebook や Streamlit in Snowflake は機能しません。

image 16

この場合、追加の構成が必要です。

https://docs.snowflake.com/ja/developer-guide/streamlit/privatelink

内部ステージへのアクセスを構成

次に、Vnet 内のインスタンスから Snowflake の内部ステージ(Blob)へのアクセスを構成します。こちらの手順は以下に記載があります。

https://docs.snowflake.com/ja/user-guide/private-internal-stages-azure

また、詳細な手順は公式のナレッジベースの記事が参考になります。

https://community.snowflake.com/s/article/HOW-TO-configure-private-connectivity-to-azure-internal-stages

構成前

事前に構成前の状況を確認してみます。Snowflake 側で以下を実行します。

			
			SELECT SYSTEM$ALLOWLIST();

		

出力の内、以下は内部ステージへの URL となります。

			
			{"host":"<ストレージアカウント名>.blob.core.windows.net","port":443,"type":"STAGE"}

		

VNet 内のインスタンスから名前解決を行うと、この時点ではパブリック IP アドレスに解決されます。

			
			> Test-NetConnection -ComputerName <ストレージアカウント名>.blob.core.windows.net -Port 443                                                                                                                                                                                                                                                                  
ComputerName     : <ストレージアカウント名>.blob.core.windows.net
RemoteAddress    : 20.xx.xx.xx
RemotePort       : 443
InterfaceAlias   : Ethernet
SourceAddress    : 10.0.1.5
TcpTestSucceeded : True

		

Snowflake 側で以下を実行し、内部ステージへのプライベート接続を有効化します。

			
			USE ROLE ACCOUNTADMIN;
ALTER ACCOUNT SET ENABLE_INTERNAL_STAGES_PRIVATELINK = TRUE;

		

内部ステージのストレージ アカウント名を取得

Snowflake 側で以下を実行し、privatelink-internal-stage値を確認します。

			
			USE ROLE ACCOUNTADMIN;
SELECT KEY, VALUE::VARCHAR INTERNAL_STAGE
FROM TABLE(FLATTEN(INPUT=>PARSE_JSON(SYSTEM$GET_PRIVATELINK_CONFIG())))
WHERE KEY = 'privatelink-internal-stage';

		

出力は以下のようになっており、一番最後の文字列が内部ステージのストレージ アカウント名となります。

			
			/subscriptions/xxxxx/storageAccounts/<ストレージアカウント名>

		

内部ステージ向けのプライベート エンドポイントの構成

内部ステージへのアクセスがプライベート IP アドレス経由とするために、新しいプライベート エンドポイントを作成します。ここでは、先と同様に、プライベート エンドポイント用のサブネットに作成しました。

image 17

「リソース」に関する設定では「リソース ID またはエイリアスを使って Azure リソースに接続します。」とし、リソース ID には先の手順で取得したprivatelink-internal-stageの値を指定します。また、対象サブリソースには「blob」と指定します。

2025-10-14_09h30_11

プライベート エンドポイント接続を承認

プライベート エンドポイント作成後、「設定」メニューより「リソース ID」を控えておきます。

image 19

Snowflake 側で以下を実行し、プライベート エンドポイント接続を承認します。

			
			USE ROLE ACCOUNTADMIN;
SELECT SYSTEM$AUTHORIZE_STAGE_PRIVATELINK_ACCESS('<プライベートエンドポイントのリソースID>');

		

image 20

その後 Azure ポータルでステータスを確認すると「承認済み」となります。

image 21

DNS 構成

先の手順と同様に、Private Link の構成後、Vnet 内から内部ステージへのリクエストが、プライベート エンドポイント経由するように(プライベート IP アドレスで解決できるように) DNS の構成を行います。

ここでは以下の情報を事前に用意しておきます。

  • 内部ステージのストレージ アカウント名
    • 上記の手順で確認済みの値
    • このストレージ アカウント名を「.blob.core.windows.net」や「.privatelink.blob.core.windows.net」の先頭に追加することで、ストレージ アカウント URL の一部として利用できます
  • 内部ステージ向けのプライベート エンドポイントの IP アドレス

内部ステージ向けのプライベート DNS ゾーンの作成

以下の構成で内部ステージ向けの Azure プライベート DNS ホストゾーンを作成します。

  • 名前:privatelink.blob.core.windows.net

image 22

内部ステージのストレージアカウント名を、プライベート エンドポイントの IP アドレスにマッピングする A レコードを登録します。

			
			# 変数を定義
RESOURCE_GROUP="<リソースグループ名>"
PRIVATE_DNS_ZONE="privatelink.blob.core.windows.net"
IP_ADDRESS="<内部ステージ向けプライベートエンドポイントのIPアドレス>"
STORAGE_ACCOUNT="<ストレージアカウント名>"

		
			
			# Aレコードを作成
az network private-dns record-set a add-record \
  --resource-group $RESOURCE_GROUP \
  --zone-name "$PRIVATE_DNS_ZONE" \
  --record-set-name "$STORAGE_ACCOUNT" \
  --ipv4-address "$IP_ADDRESS"

		

実行後、Azure ポータルで下図のように確認できます。

image 23

プライベート DNS ゾーンを仮想ネットワークにリンク

先と同様にプライベート DNS ゾーンの「DNSの管理 > 仮想ネットワーク リンク」から、VM を構築した VNet とのリンクを追加します。

プライベート エンドポイントとプライベート DNS ゾーンをリンク

作成したプライベート DNS ゾーンを、プライベートエンドポイントが配置されている VNet にリンクさせます。

このリンクにより、VNet 内のリソースからの DNS クエリが、まずこのプライベート DNS ゾーンを参照するようにできます。(ここでは VM から <ストレージアカウント名>.blob.core.windows.net のような内部ステージの URL にアクセスしようとした際、その DNS クエリがプライベート DNS ゾーンにルーティングされ、プライベートIPアドレスが返されるようになります。)

プライベート エンドポイントの「DNS の構成 > 構成の追加」より設定できます。

image 24

下図のように設定しました。

image 25

プライベート DNS ゾーンでの名前解決失敗時にパブリックな解決が行われてないように、「パブリック解決へのフォールバックを有効にする」は無効としました。

設定完了後、指定の VNet 内のリソースは、Azure Storage の URL を自動的にプライベート IP アドレスに解決できるようになります。

接続のテスト

VM から内部ステージへの名前解決を試してみます。

			
			> Test-NetConnection -ComputerName <ストレージアカウント名>.blob.core.windows.net -Port 443
ComputerName     : <ストレージアカウント名>.blob.core.windows.net
RemoteAddress    : 10.0.3.5
RemotePort       : 443
InterfaceAlias   : Ethernet
SourceAddress    : 10.0.1.5
TcpTestSucceeded : True

> Test-NetConnection -ComputerName <ストレージアカウント名>.privatelink.blob.core.windows.net -Port 443
ComputerName     : <ストレージアカウント名>.privatelink.blob.core.windows.net
RemoteAddress    : 10.0.3.5
RemotePort       : 443
InterfaceAlias   : Ethernet
SourceAddress    : 10.0.1.5
TcpTestSucceeded : True

		

特にはじめの通常のストレージアカウント URL による接続テストについて、<ストレージアカウント名>.blob.core.windows.net というパブリック URL は、パブリック IP アドレスではなく、プライベート エンドポイントの IP アドレスに解決しています。

パブリックサブネットに NATGateway を追加、SnowSQL をインストールし、Vnet 内の VM からPUTコマンドでファイルをアップロードしてみます。

			
			>snowsql -a <組織名>-<アカウント名>.privatelink
User: admin
Password:
* SnowSQL * v1.4.5
Type SQL statements or !help

>SELECT current_ip_address();
+----------------------+
| CURRENT_IP_ADDRESS() |
|----------------------|
| 10.0.1.5             |
+----------------------+

>put file://./test.csv @my_int_stage;
+----------+-------------+-------------+-------------+--------------------+--------------------+----------+---------+
| source   | target      | source_size | target_size | source_compression | target_compression | status   | message |
|----------+-------------+-------------+-------------+--------------------+--------------------+----------+---------|
| test.csv | test.csv.gz |          16 |          47 | NONE               | GZIP               | UPLOADED |         |
+----------+-------------+-------------+-------------+--------------------+--------------------+----------+---------+
1 Row(s) produced. Time Elapsed: 0.359s

		

問題なくアップロードできました。

パブリックアクセスのブロック

Private Link の構成ができたので、パブリックアクセスをブロックしてみます。こちらはそれぞれ以下に記載があります。

https://docs.snowflake.com/ja/user-guide/privatelink-azure#blocking-public-access-recommended

https://docs.snowflake.com/ja/user-guide/private-internal-stages-azure#blocking-public-access-recommended

検証用ユーザーを作成

Snowflake サービスへのブロックは、ユーザーレベルで行うこととし、検証用のユーザーを作成しました。

			
			CREATE USER test_user 
	PASSWORD='<パスワード>'
	DEFAULT_ROLE = public;

		

ネットワークルール・ネットワークポリシーの作成

ここでは、Azure プライベート エンドポイント の LinkID でネットワークアクセス制御を試してみます。

はじめに、SYSTEM$GET_PRIVATELINK_AUTHORIZED_ENDPOINTS を実行し、アカウントに関連付けられた LinkID を取得します。LinkID は、出力のlinkIdentifierの値です。

			
			SELECT SYSTEM$GET_PRIVATELINK_AUTHORIZED_ENDPOINTS();
[
	{
		"endpointId":"xxxxx",
		"endpointIdType":"Azure Endpoint Connection Id",
		"linkIdentifier":"<AZURELINKID>"
	}
]

		

以下の内容で、Snowflake サービスへのネットワークポリシーを作成し、検証用ユーザーに適用しました。

			
			--AZURELINKIDアドレスから Snowflakeサービストラフィックを許可またはブロックするために使用されるネットワークルールを作成
CREATE NETWORK RULE azure_vnet
  TYPE = AZURELINKID
  VALUE_LIST = ('<AZURELINKID>')
  MODE = INGRESS
  COMMENT ='azure privatelink endpoint';

--パブリックアクセスをブロックするネットワークルール
CREATE NETWORK RULE block_public_access
  MODE = INGRESS
  TYPE = IPV4
  VALUE_LIST = ('0.0.0.0/0');

--ネットワークポリシーを作成
----ユーザーアクセス用
CREATE OR REPLACE NETWORK POLICY test_user_net_policy
    ALLOWED_NETWORK_RULE_LIST = ('azure_vnet')
    BLOCKED_NETWORK_RULE_LIST=('block_public_access')
 ;

ALTER USER test_user SET NETWORK_POLICY = test_user_net_policy;
--ALTER USER test_user UNSET NETWORK_POLICY;

		

ネットワークルール設定時の注意点として「異なるタイプの識別子が自動的にブロックされるわけではない」ためご注意ください。例えば上記のようにネットワークルールのタイプとしてAZURELINKID を指定したものを作成し、ポリシーのALLOWED_NETWORK_RULE_LIST に割り当てたとしても、タイプの異なる IPV4 アドレスでのアクセスは可能なままとなります。IPV4 アドレスからのアクセスも制限する場合は、タイプ IPV4 とするネットワークルールを追加する必要があります。(ここでは明示的にブロックするルールを作成)

https://docs.snowflake.com/ja/user-guide/network-policies#interaction-between-allowed-lists-and-blocked-lists

設定後、接続テストを行います。

はじめに、手元のネットワークから通常のアカウント URL でアクセスすると、意図した通り、ブロックされます。

image 26

続けて、VM からプライベート接続用の URL にアクセスします。

image 27

問題なく接続でき、検証用ユーザーに MFA を設定したので、追加の認証を行い、ログインできました。

image 28

image 29

内部ステージの保護

Azure Private Link 構成時の内部ステージの保護を試してみます。

後の検証用に、GET_PRESIGNED_URL による事前署名付き URL を内部ステージに配置済みのファイルに対して発行しておきます。

			
			SELECT GET_PRESIGNED_URL(@my_int_stage, 'test.csv');

		

注意点として、Azure Private Link における内部ステージの保護は、パブリックアクセスの制御とは異なります。ネットワークポリシーではなく、 SYSTEM$BLOCK_INTERNAL_STAGES_PUBLIC_ACCESS 関数を使用します。これにより、 すべてのパブリック IP アドレスがブロックされます。

※一部のパブリック IP アドレスをブロックしながら他のアドレスを許可するなどの構成はできません

内部ステージへの Private Link 構成を完了しているので、以下を実行し、内部ステージへのパブリック IP アドレスによるアクセスをブロックします。

			
			SELECT SYSTEM$BLOCK_INTERNAL_STAGES_PUBLIC_ACCESS();

		

image 30

この状態で、手元のネットワークから先の事前署名付き URL にアクセスすると、下図の表示になり、アクセスがブロックされていることを確認できます。

image 31

一方で、VM(Vnet)のブラウザからアクセスすると、対象のファイルをダウンロードできます。

image 32

さらに、手元のネットワークからPUT操作を試してみます。

			
			>PUT file://C:/Users/<users>/test2.csv @my_int_stage;
+-----------+--------------+-------------+-------------+--------------------+--------------------+--------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| source    | target       | source_size | target_size | source_compression | target_compression | status | message                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   |
|-----------+--------------+-------------+-------------+--------------------+--------------------+--------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| test2.csv | test2.csv.gz |           0 |           0 | NONE               | GZIP               | ERROR  | HTTPError('403 Client Error: This request is not authorized to perform this operation. for url: https://<ストレージアカウント名>.blob.core.windows.net/stageszzfdc7ac2f-e25c-4fa9-ac63-a381514430c6/test2.csv.gz?sv=2021-04-10&se=2025-10-13T13%3A02%3A04Z&skoid=611b7611-69a7-45d7-9ee1-a5d976ab5c2d&sktid=3a79d845-29c1-4bd4-ac94-846e44c04a93&skt=2025-10-13T11%3A02%3A04Z&ske=2025-10-20T11%3A01%3A04Z&sks=b&skv=2021-04-10&sr=c&sp=racwdl&sig=j9elNWHZK9yKl2LaDa6gPuKppsHqrSvKEtShrofsseA%3D') |
+-----------+--------------+-------------+-------------+--------------------+--------------------+--------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 Row(s) produced. Time Elapsed: 3.027s

		

こちらもエラーとなりました。

VM(Vnet)のからは、引き続き問題なくアップロードできます。

			
			>put file://./test3.csv @my_int_stage;
+-----------+--------------+-------------+-------------+--------------------+--------------------+----------+---------+
| source    | target       | source_size | target_size | source_compression | target_compression | status   | message |
|-----------+--------------+-------------+-------------+--------------------+--------------------+----------+---------|
| test3.csv | test3.csv.gz |          16 |          48 | NONE               | GZIP               | UPLOADED |         |
+-----------+--------------+-------------+-------------+--------------------+--------------------+----------+---------+
1 Row(s) produced. Time Elapsed: 0.239s

		

内部ステージへのパブリックアクセスのブロックのステータスについては、SYSTEM$INTERNAL_STAGES_PUBLIC_ACCESS_STATUS で確認できます。

image 33

パブリックアクセスのブロック解除は、SYSTEM$UNBLOCK_INTERNAL_STAGES_PUBLIC_ACCESS 関数で可能です。

			
			SELECT SYSTEM$UNBLOCK_INTERNAL_STAGES_PUBLIC_ACCESS();

		

image 34

解除後は、手元のネットワークからから再度PUTできます。

			
			>PUT file://C:/Users/<user>/test2.csv @my_int_stage;
+-----------+--------------+-------------+-------------+--------------------+--------------------+----------+---------+
| source    | target       | source_size | target_size | source_compression | target_compression | status   | message |
|-----------+--------------+-------------+-------------+--------------------+--------------------+----------+---------|
| test2.csv | test2.csv.gz |           0 |          32 | NONE               | GZIP               | UPLOADED |         |
+-----------+--------------+-------------+-------------+--------------------+--------------------+----------+---------+
1 Row(s) produced. Time Elapsed: 2.745s

		

さいごに

Azure Private Link 経由での Snowflake への接続を試してみました。
こちらの内容が何かの参考になれば幸いです。

参考

本検証にあたり、以下の記事を参考とさせていただきました。

https://community.snowflake.com/s/article/Azure-Private-Link-and-Snowflake-detailed-troubleshooting-Guide

https://zenn.dev/falcode/articles/b8e0e2edbb8e31

https://zenn.dev/hanabusashun/articles/833a0f591d01a1

https://interworks.com/blog/2023/12/05/configure-azure-private-link-connectivity-with-snowflake/

https://interworks.com/blog/2024/02/13/configure-azure-private-endpoints-for-snowflake-internal-stages/

この記事をシェアする

FacebookHatena blogX

関連記事