
Snowflake Cortex Agents の Microsoft Teams・Microsoft 365 Copilot 連携を試してみた
はじめに
Snowflake では、Cortex Agents を Microsoft Teams と Microsoft 365 Copilot から利用できる連携機能が提供されています。
Teams からエージェントに問い合わせるまでのセットアップと、ユーザーの紐づけやネットワークポリシーの挙動を確認した際の内容を記事としました。
Cortex Agents の Microsoft Teams 連携の概要
本機能については以下に記載があります。
Cortex Agents を Microsoft Teams と Microsoft 365 Copilot に組み込み、チャットから自然言語で Snowflake のデータに問い合わせできる機能です。回答はテキスト・表・グラフで返ります。Teams では専用の Bot アプリとして、Microsoft 365 Copilot では Copilot 内のエージェントとして利用できます。
認証には Microsoft Entra ID による External OAuth を使用します。Entra ID が発行したトークンをもとに Snowflake ユーザーへ紐づけられ、そのユーザーのデフォルトロールでエージェントが実行される仕組みです。
データ処理について、Bot のバックエンドは Snowflake の Azure East US 2 リージョンで動作しています。そのため、Snowflake アカウントがどのリージョンにある場合も、この連携の利用時には Azure East US 2 での中間処理が行われます。Azure East US 2 以外のリージョンのアカウントでは、Teams アプリと Snowflake アカウントの接続時にこの点への同意が必要です。
全体の流れは以下のようになります。
Teams の Bot に問い合わせ
→ Entra ID にサインイン
→ Entra ID がトークン(JWT)を発行
→ Bot がトークンを付けて Cortex Agents API を呼び出し
→ Snowflake のセキュリティ統合がトークンを検証し、Snowflake ユーザーに紐づけ
→ ユーザーのデフォルトロールでエージェントを実行
主な前提・制限事項は以下の通りです。
- Entra ID のユーザーと Snowflake ユーザーを1対1で対応させる必要がある
- エージェントの実行はユーザーのデフォルトロールに依存する。ACCOUNTADMIN などの管理系ロールはデフォルトロールにできない
- Private Link 構成のアカウントでは利用できない
前提条件
検証環境
以下の環境を使用しています。
- Snowflake
- Enterprise Edition(AWS 東京リージョン)
- Cortex Agent・セマンティックビューなどの関連オブジェクトは作成済み
- クロスリージョン推論(
CORTEX_ENABLED_CROSS_REGION)はAWS_APJ
- Microsoft 365
- Microsoft 365 Business Standard の試用版で検証用のテナントを用意し、ユーザーに Teams Essentials のライセンスを割り当て
- Entra ID のグローバル管理者で作業
Microsoft 365 Business Standard の試用
はじめに、以下より Microsoft 365 Business Standard の試用版を開始します。
試用版を開始できたら、Microsoft Entra 管理センターの「概要」から Entra ID のテナント ID を控えておきます。テナント ID は、後ほど Snowflake のセキュリティ統合の作成と、Entra ID の管理者同意で使用します。

Cortex Agent の作成
Snowflake 側では、以下の記事の内容で作成したエージェントを使用します。エージェントはyasuhara_devロールで使用します。
Teams ライセンスの割り当て
Microsoft 365 管理センターから「その他の製品の追加」を選択します。

ここでは Microsoft Teams Essentials を追加しました。

ライセンスを追加したら、対象のユーザーを選択し「ライセンスとアプリ」タブで「Microsoft Teams Essentials」にチェックを入れて、変更を保存します。

保存後、対象ユーザーでライセンスが有効になっていることを確認します。

続けて、検証ユーザーで https://teams.microsoft.com を開き、サインインします。

問題なければ、下図のように Teams の画面が表示されます。

Snowflake 側の設定
セキュリティ統合の作成
はじめに、ACCOUNTADMIN で External OAuth のセキュリティ統合を作成します。公式ドキュメントのテンプレートをベースに、一部変更しています。
USE ROLE ACCOUNTADMIN;
CREATE OR REPLACE SECURITY INTEGRATION entra_id_cortex_agents_integration
TYPE = EXTERNAL_OAUTH
ENABLED = TRUE
EXTERNAL_OAUTH_TYPE = AZURE
EXTERNAL_OAUTH_ISSUER = 'https://login.microsoftonline.com/<tenant-id>/v2.0'
EXTERNAL_OAUTH_JWS_KEYS_URL = 'https://login.microsoftonline.com/<tenant-id>/discovery/v2.0/keys'
EXTERNAL_OAUTH_AUDIENCE_LIST = ('5a840489-78db-4a42-8772-47be9d833efe')
EXTERNAL_OAUTH_TOKEN_USER_MAPPING_CLAIM = 'email'
EXTERNAL_OAUTH_SNOWFLAKE_USER_MAPPING_ATTRIBUTE = 'EMAIL_ADDRESS'
EXTERNAL_OAUTH_ANY_ROLE_MODE = 'ENABLE'
EXTERNAL_OAUTH_ALLOWED_ROLES_LIST = ('YASUHARA_DEV');
<tenant-id>には、先ほど控えたテナント ID を指定します。その他のポイントは以下の通りです。
EXTERNAL_OAUTH_AUDIENCE_LIST- Snowflake が用意している「Snowflake Cortex Agents Bot OAuth Resource」アプリの ID で固定値です
EXTERNAL_OAUTH_TOKEN_USER_MAPPING_CLAIM- 今回はメールアドレスでの紐づけに絞りました
EXTERNAL_OAUTH_ALLOWED_ROLES_LIST- Teams 経由で使用できるロールを限定しています
なお、EXTERNAL_OAUTH_BLOCKED_ROLES_LISTは指定していません。指定しない場合も、既定で ACCOUNTADMIN・ORGADMIN・GLOBALORGADMIN・SECURITYADMIN がブロックされます。
Snowflake ユーザーの作成
続けて、Teams にサインインするユーザーに対応する Snowflake ユーザーを作成します。ポイントとしてEMAILは Entra ID のユーザー名と一致させます。External OAuth でのみログインするため、パスワードは設定していません。
また、このユーザーは後ほど Teams アプリと Snowflake アカウントの接続(管理者の操作)にも使用します。そのためDEFAULT_SECONDARY_ROLES = ('ALL')とし、後から付与する ACCOUNTADMIN をセカンダリロールとして使用できるようにしています。
USE ROLE USERADMIN;
CREATE OR REPLACE USER teams_test_user
TYPE = PERSON
EMAIL = '<user>@<tenant>.onmicrosoft.com'
DEFAULT_ROLE = 'YASUHARA_DEV'
DEFAULT_WAREHOUSE = 'COMPUTE_WH'
DEFAULT_SECONDARY_ROLES = ('ALL');
USE ROLE SECURITYADMIN;
GRANT ROLE yasuhara_dev TO USER teams_test_user;
デフォルトロールのYASUHARA_DEVには、エージェント・セマンティックビュー・ウェアハウスなどの使用権限と、SNOWFLAKE.CORTEX_AGENT_USERデータベースロールを付与済みです。
Entra ID の管理者同意
次に、Entra ID 側で Snowflake のアプリに対する管理者同意を行います。グローバル管理者で以下の2つの URL をブラウザで開き、それぞれ同意します。<tenant-id>にはテナント ID を指定します。
https://login.microsoftonline.com/<tenant-id>/adminconsent?client_id=5a840489-78db-4a42-8772-47be9d833efe
https://login.microsoftonline.com/<tenant-id>/adminconsent?client_id=bfdfa2a2-bce5-4aee-ad3d-41ef70eb5086
1つ目が OAuth Resource です。Snowflake の API を表すアプリで、確認画面が1回表示されます。

2つ目が OAuth Client です。Teams アプリのバックエンドを表すアプリで、こちらは確認画面が2回表示されます。


同意後、ブラウザに以下のエラーが表示されますが、ドキュメントにある通り同意は完了しています。URL にadmin_consent=Trueが含まれていることも確認できます。
{
"error": {
"code": "ServiceError",
"message": "Missing required query string parameter: code. Url = https://unitedstates.token.botframework.com/.auth/web/redirect?admin_consent=True&tenant=<tenant-id>"
}
}
同意後、Entra 管理センターの「エンタープライズ アプリケーション」で以下の2つが表示されていれば問題ありません。
- Snowflake Cortex Agents Bot OAuth Resource
- Snowflake Cortex Agents Bot OAuth Client

Teams から問い合わせる
Teams アプリの接続
Teams の「アプリ」から「Snowflake Cortex Agents」を検索します。

「追加」を選択し、アプリを追加します。

追加すると、下図のように Bot とのチャット画面が開きます。


組織で初めてアプリを利用するユーザーは、Snowflake アカウントをアプリに接続する必要があります。この操作には、Snowflake 側で ACCOUNTADMIN または SECURITYADMIN ロールを持っている必要があります。
ここでは、先ほど作成したユーザーに ACCOUNTADMIN を付与しました。前述の通りデフォルトロールはYASUHARA_DEVのままとし、ACCOUNTADMIN はセカンダリロールとして使用される形です。
USE ROLE ACCOUNTADMIN;
GRANT ROLE ACCOUNTADMIN TO USER teams_test_user;
Bot に話しかけるとサインインを求められるので、「Sign in」から Entra ID のアカウントでサインインします。

初回は Snowflake アカウントの接続設定が必要なため、管理者であること(I'm the Snowflake administrator)を選択します。

Snowflake のアカウント URL(<org>-<account>.snowflakecomputing.com)を指定し、接続します。

今回のアカウントは AWS 東京リージョンのため、Azure East US 2 での中間処理(データの保存はしない)に関する同意を求められます。内容を確認し、同意します。

接続できたら、利用するエージェントを選択できます。

この状態で「売上データの日次サマリーレポートを作成してください。」と問い合わせてみます。
下図のように、表やグラフを含む形で回答が返ってきました。



管理者以外のユーザーで問い合わせる
続けて、管理者権限を持たないユーザーを Entra ID・Snowflake の双方に追加し問い合わせてみます。
はじめに Microsoft 365 管理センターでユーザーを追加し Teams のライセンスを割り当てます。


Snowflake 側では以下のクエリでユーザーを追加しました。ここでも Snowflake ユーザーのEMAILは Entra ID 側のメールアドレス(今回はユーザー名と同じ<user2>@<tenant>.onmicrosoft.com)と一致させます。
USE ROLE USERADMIN;
CREATE USER IF NOT EXISTS teams_min_user
TYPE = PERSON
EMAIL = '<user2>@<tenant>.onmicrosoft.com'
DEFAULT_ROLE = 'YASUHARA_DEV'
DEFAULT_WAREHOUSE = 'COMPUTE_WH'
DEFAULT_SECONDARY_ROLES = ();
USE ROLE SECURITYADMIN;
GRANT ROLE yasuhara_dev TO USER teams_min_user;
こちらはセカンダリロールを空にし、デフォルトロールの権限のみで動作するようにしています。
追加したユーザーで Teams にサインインします。

先と同じ手順で Snowflake Cortex Agents アプリを追加し、Bot からサインインします。

管理者が接続した Snowflake アカウントがそのまま使用でき、エージェントはロールの権限の範囲のものが表示され、管理者向けの設定も表示されませんでした。


同様の問い合わせで、回答が返ることを確認できました。

ネットワークポリシーの挙動
ネットワークアクセス制御について、ドキュメントでは以下に記載があります。
今回の検証も踏まえた主な特徴は以下の通りです。
- 既存のネットワークポリシーが適用される。ただし、セキュリティ統合に設定したネットワークポリシーは適用されないため、ユーザー単位またはアカウント単位で設定する
- 判定には、Entra ID のトークンに含まれる
ipaddrクレーム(Microsoft にサインインした時点の IP)が使用される - Bot からサインアウトして再度サインインするまで、判定に使用される IP は更新されない
- Microsoft への接続が IPv6 の場合は、
TYPE = IPV6のネットワークルールを追加する必要がある- IPv6 のネットワークルールは、執筆時点で AWS 上の Snowflake アカウントのみ対応
こちらの挙動を試してみます。先ほどの管理者以外のユーザーに、ユーザー単位でネットワークポリシーを設定しました。手元の IPv4 アドレスと IPv6 の範囲を許可しています。
USE ROLE SECURITYADMIN;
CREATE NETWORK RULE IF NOT EXISTS <db>.<schema>.teams_test_allow_rule
MODE = INGRESS
TYPE = IPV4
VALUE_LIST = ('<手元の IPv4 アドレス>/32');
CREATE OR REPLACE NETWORK RULE <db>.<schema>.teams_test_allow_rule_v6
MODE = INGRESS
TYPE = IPV6
VALUE_LIST = ('<手元の IPv6 プレフィックス>::/64');
CREATE OR REPLACE NETWORK POLICY teams_test_policy
ALLOWED_NETWORK_RULE_LIST = ('<db>.<schema>.teams_test_allow_rule', '<db>.<schema>.teams_test_allow_rule_v6');
ALTER USER teams_min_user SET NETWORK_POLICY = teams_test_policy;
この上で、許可したものとは別のネットワークから接続します。ブロックされた際は、下図のようなエラーが Teams に表示されます。

エラーに表示された IP は、Entra 管理センターのサインイン ログ(「監視と正常性」→「サインイン ログ」)に記録された IPv6 アドレスと一致していました。一方、同じ PC・回線から Snowsight にログインした場合は IPv4 で記録されます。
これは、検証環境の回線が IPv4 と IPv6 の両方に対応しており、接続先によって使用されるアドレスが異なるためです。Microsoft のエンドポイントは IPv6 に対応している一方で、Snowsight(app.snowflake.com)は IPv4 で接続されていました。どちらになるかは利用者のネットワーク環境に依存するため、IPv4 のみの社内ネットワークなどでは、Teams 経由でも IPv4 で判定されると考えられます。
また、Teams 経由のログインはLOGIN_HISTORYに記録されますが、CLIENT_IPはすべて0.0.0.0となっていました。判定に使用された IP は、ログイン履歴からは確認できませんでした。
上記のように許可した範囲からは問題なく問い合わせでき、許可した範囲外からはブロックされることを確認できました。
一方で、いくつかのパターンを試す中で以下の2点は注意が必要と思いました。
ネットワークポリシーはネットワーク識別子の種類(IPv4 / IPv6)ごとに適用される
許可リストのルールで制限されるのは、そのルールと同じ種類の識別子のみです。IPv4 のルールのみのポリシーを設定した状態では、IPv6 で判定される Teams からの問い合わせは制限されず、成功しました。IPv6 のルールを追加すると、IPv6 での接続も許可リストで判定され、許可した範囲外はブロックされるようになります。
そのため、IPv4 の許可ルールのみで運用している場合、Teams 経由の IPv6 での接続は制限されません。IP で制限する場合は、利用者が Microsoft に接続する際の IP を Entra のサインイン ログで確認した上で、IPv4 と IPv6 の両方のルールを設定する必要があります。
Bot は最初にサインインした時点の IP を保持する
最初にサインインした回線から別の回線に切り替え、Teams でログアウトして再度サインインしてから問い合わせてみました。この場合も、判定には最初の回線の IP が使用されていました。
具体的には、最初の回線の範囲のみを許可した状態では、別の回線からでも問い合わせできました。反対に、別の回線の範囲のみを許可した状態ではブロックされ、エラーには最初の回線の IP が表示されていました。Entra のサインイン ログには別の回線の IP も記録されていましたが、Bot が使用するトークンは更新されていなかったようです。
ドキュメントにもある通り、判定は「現在どこから使っているか」ではなく「Microsoft にサインインした時点の IP」で行われます。社内でサインインした後に社外へ持ち出した場合も、トークンが更新されるまでは許可され続ける可能性があります。場所に基づく制御を厳密に行いたい場合は、Entra ID の条件付きアクセスとの組み合わせも検討が必要と思いました。
Microsoft 365 Copilot から問い合わせる
最後に、同じ設定のまま Microsoft 365 Copilot からも問い合わせてみます。Snowflake 側・Entra ID 側で追加の設定は不要でした。

Copilot からサインインすると、Teams と同様にエージェントを選択でき、問い合わせも可能でした。


さいごに
Cortex Agents の Microsoft Teams 連携と、ネットワークポリシーの挙動を確認してみました。セットアップ自体はシンプルで、普段使いのチャットツールから Snowflake のエージェントを利用できる点は便利と思いました。認証も Entra ID による OAuth ベースのため、利用者は普段の Microsoft アカウントでサインインするだけで使用でき、Snowflake 側のパスワードは不要です。
こちらの内容がどなたかの参考になれば幸いです。








