Copilot StudioでSnowflakeナレッジを追加する手順

Copilot Studioでは、外部のデータソースをナレッジとして登録できます。代表的な例としてSharePointやDataverse等がありますが、Snowflakeもパブリックプレビューとしてナレッジソースに追加できるようになりました。

本記事では、接続に必要な情報の取得からSnowflake側の設定、Copilot Studioへの追加までを一連の流れで整理します。

概要

SnowflakeをCopilot Studioのナレッジソースに追加すると、テーブル内のデータを自然言語でクエリすることが出来るようになります。しかし、SnowflakeとCopilot Studioの接続にはOAuth認証やSnowflakeロールの設定など多くの事前準備が必要となります。

本記事では、SnowflakeとCopilot Studioの接続に必要な情報を整理し、設定・接続手順を取りまとめます。

前提条件

本手順を実行するにあたり、必要な前提条件は以下のとおりです。

権限

  • Microsoft Entra IDロール:クラウドアプリケーション管理者
  • Snowflake:ACCOUNTADMINロール

実行環境

  • Azure Cloud Shell(PowerShell)を実行できる環境

※Copilot Studio側の詳細な前提条件は本記事の主題ではないため、「Copilot Studio上でエージェントを作成できる状態である」ことを前提とします。

ナレッジ接続のための準備

必要な接続情報

はじめに、Snowflakeナレッジを追加するために必要な接続情報について整理します。ナレッジを追加する際、接続情報として下記の項目の入力を求められます。

  • Authentication type:接続の認証方式。本手順では「Service principal(Microsoft Entra ID application)」を前提とした接続を行います。
  • Snowflake SaaS URL:接続先のSnowflakeアカウントURL。画面の注記どおり「https://」は付けず、アカウント識別子を含むホスト名部分を入力します。
  • Snowflake database:接続対象のデータベース名。参照したいテーブルが格納されているデータベースを指定します。
  • Warehouse name:SQL実行に使用するウェアハウス名。
  • Role:接続時に利用するSnowflakeロール名。このロールに、対象データベースへの参照権限やウェアハウス利用権限を付与しておく必要があります。
  • Schema:接続対象のスキーマ名。データ参照のスコープとなる対象のスキーマを指定します。
  • Tenant:Microsoft Entra IDのテナントID。
  • Client ID:Microsoft Entra IDで登録するサービスプリンシパルのクライアントID。
  • Client Secret:上記サービスプリンシパルで発行するクライアントシークレット。
  • Resource URL:Snowflake側で定義するOAuthのResource URL。

以降の手順で、これらの値を取得するために必要な設定手順を説明していきます。

アプリ登録

Copilot StudioからSnowflakeをサービスプリンシパルで接続する場合、Entra IDで「トークンの宛先(Resource)」と「トークンを取得するクライアント(Client)」を定義するためのアプリ登録が必要になります。

アプリ登録の手順は以下のSnowflake公開情報を参考にします。

参考:Snowflake公式ガイド(https://www.snowflake.com/en/developers/guides/getting-started-with-microsoft-copilot-studio-and-cortex-agents/#configure-oauth

まずは、以下のPowerShellスクリプトを.ps1ファイルとして保存します。このスクリプトの実行により、SnowflakeをEntra IDのサービスプリンシパル認証で接続するためのAzure側設定をし、最後にSnowflake側で実行するSQLと接続情報を出力します。

※注意:コード内の< tenant id >はアプリ登録をするMicrosoftテナントIDに置き換える必要があります。

$modules = @(
    @{ Name = "Microsoft.Graph.Authentication"; InstallCommand = "Install-Module -Name Microsoft.Graph.Authentication -Force -Scope CurrentUser -Verbose" },
    @{ Name = "Microsoft.Graph.Applications"; InstallCommand = "Install-Module -Name Microsoft.Graph.Applications -Force -Scope CurrentUser -Verbose" },
    @{ Name = "Microsoft.Graph.Identity.SignIns"; InstallCommand = "Install-Module -Name Microsoft.Graph.Identity.SignIns -Force -Scope CurrentUser -Verbose" }
)

foreach ($module in $modules) {
    if (-not (Get-Module -ListAvailable -Name $module.Name)) {
        try {
            Invoke-Expression $module.InstallCommand
        } catch {
            Write-Host "Warning: Failed to install $($module.Name). Continuing..."
        }
    }
}

# 必要なスコープを指定してMicrosoft Graphに接続
Connect-MgGraph -Scopes "Application.ReadWrite.All", "Directory.ReadWrite.All" -TenantId "< tenant id >"
 
$resourceAppName = Read-Host "Enter Resource App Name"
$clientAppName = Read-Host "Enter Client App Name"
$roleName = Read-Host "Enter App Role Name"
$tenantId = Read-Host "Enter Tenant ID"

# リソースアプリケーションを作成
$resourceAppParams = @{
    DisplayName = $resourceAppName
    SignInAudience = "AzureADMyOrg"
}
$resourceApp = New-MgApplication @resourceAppParams
Start-Sleep -Seconds 10
$resourceAppId = $resourceApp.AppId
$resourceObjectId = $resourceApp.Id

Write-Host "Resource App created: $resourceAppId"

# クライアントアプリケーションを作成
$clientAppParams = @{
    DisplayName = $clientAppName
    SignInAudience = "AzureADMyOrg"
}
$clientApp = New-MgApplication @clientAppParams
Start-Sleep -Seconds 10
$clientAppId = $clientApp.AppId
$clientObjectId = $clientApp.Id
Write-Host "Client App created: $clientAppId"

# リソースアプリケーションの識別子URIを設定
$identifierUri = "api://$resourceAppId"
Update-MgApplication -ApplicationId $resourceApp.Id -IdentifierUris @($identifierUri)

# クライアントシークレットを作成
$passwordCredential = @{
    DisplayName = "SnowflakeSecret"
    EndDateTime = (Get-Date).AddYears(1)
}
$secret = Add-MgApplicationPassword -ApplicationId $clientApp.Id -PasswordCredential $passwordCredential
Write-Host "Secret created = $($secret.SecretText)"

# アプリケーションロールを作成
$appRole = @{
    AllowedMemberTypes = @("Application")
    Description = "Snowflake app role"
    DisplayName = $roleName
    Id = [Guid]::NewGuid()
    IsEnabled = $true
    Value = "session:role:$roleName"
}

# 既存のアプリロールを取得して新しいロールを追加
$existingApp = Get-MgApplication -ApplicationId $resourceApp.Id
$appRoles = $existingApp.AppRoles + $appRole
Update-MgApplication -ApplicationId $resourceApp.Id -AppRoles $appRoles

# API権限スコープを作成
$scope = @{
    Id = [Guid]::NewGuid()
    Value = "session:scope:$roleName"
    AdminConsentDescription = "Can administer the Snowflake account"
    AdminConsentDisplayName = "Account Admin"
    IsEnabled = $true
    Type = "Admin"
}

$api = @{
    Oauth2PermissionScopes = @($scope)
}
Update-MgApplication -ApplicationId $resourceApp.Id -Api $api

# サービスプリンシパルを作成
$resourceSP = New-MgServicePrincipal -AppId $resourceAppId
Start-Sleep -Seconds 10

$clientSP = New-MgServicePrincipal -AppId $clientAppId
Start-Sleep -Seconds 10

# アプリロールを割り当て
$appRoleAssignment = @{
    PrincipalId = $clientSP.Id
    ResourceId = $resourceSP.Id
    AppRoleId = $appRole.Id
}
New-MgServicePrincipalAppRoleAssignment -ServicePrincipalId $clientSP.Id -BodyParameter $appRoleAssignment

# OAuth2権限を付与
$permissionGrant = @{
    ClientId = $clientSP.Id
    ConsentType = "AllPrincipals"
    ResourceId = $resourceSP.Id
    Scope = $scope.Value
}
New-MgOauth2PermissionGrant -BodyParameter $permissionGrant

# 必要なリソースアクセスを構成
$requiredResourceAccess = @{
    ResourceAppId = $resourceAppId
    ResourceAccess = @(
        @{
            Id = $scope.Id
            Type = "Scope"
        },
        @{
            Id = $appRole.Id
            Type = "Role"
        }
    )
}
Update-MgApplication -ApplicationId $clientApp.Id -RequiredResourceAccess @($requiredResourceAccess)

# アクセストークンを取得
$tokenUrl = "https://login.microsoftonline.com/$tenantId/oauth2/v2.0/token"
$body = @{
    client_id = $clientAppId
    client_secret = $secret.SecretText
    scope = "$resourceAppId/.default"
    grant_type = "client_credentials"
}

$tokenResponse = Invoke-RestMethod -Method Post -Uri $tokenUrl -Body $body
$accessToken = $tokenResponse.access_token
Write-Host "Access Token: $accessToken"

# トークンをデコード
$tokenParts = $accessToken -split '\.'
$payload = $tokenParts[1]
# ペイロードにパディングを追加
switch ($payload.Length % 4) {
    2 { $payload += '==' }
    3 { $payload += '=' }
}
$decodedPayload = [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($payload))
$payloadObject = $decodedPayload | ConvertFrom-Json
$sub = $payloadObject.sub

# 出力をファイルに保存
$desktopPath = [System.Environment]::GetFolderPath("Desktop")
$outputFile = "snowflakeinfo.txt"

$outputContent = @"
============================================================================================================================
Snowflake power platform connection info
============================================================================================================================
Tenant: $TenantId
Client ID: $clientAppId
Client Secret: $($secret.SecretText)
Resource URL: $resourceAppId

============================================================================================================================
Snowflake SQL Commands. Please execute these commands on Snowflake for adding Security Integration and Creating User, Role
============================================================================================================================
create security integration external_azure
    type = external_oauth
    enabled = true
    external_oauth_any_role_mode = 'ENABLE'
    external_oauth_type = azure
    external_oauth_issuer = 'https://sts.windows.net/$TenantId/'
    external_oauth_jws_keys_url = 'https://login.microsoftonline.com/$TenantId/discovery/v2.0/keys'
    external_oauth_audience_list = ('$resourceAppId')
    external_oauth_token_user_mapping_claim = (upn,sub)
    external_oauth_snowflake_user_mapping_attribute = 'login_name';

ALTER ACCOUNT SET EXTERNAL_OAUTH_ADD_PRIVILEGED_ROLES_TO_BLOCKED_LIST = FALSE;

CREATE OR REPLACE USER AAD_SP_USER
    LOGIN_NAME = '$sub' 
    DISPLAY_NAME = 'AAD_SP_USER' 
    COMMENT = 'Snowflake User';

CREATE ROLE IF NOT EXISTS $roleName;

GRANT ROLE $roleName TO USER AAD_SP_USER;
"@

$outputContent | Out-File -FilePath $outputFile -Encoding UTF8
Write-Host "Info saved to: $outputFile"

保存後、このスクリプトを対象テナントのAzure Cloud ShellのPowerShellモードで実行します。実行時に、アプリ登録に必要な情報の入力を求められます。各項目の入力内容は以下のとおりです。

  • リソースアプリ名:<任意>
  • クライアントアプリ名:<任意>
  • 接続時に利用するSnowflakeロール名:<任意> ※このロール名が接続情報のRoleの値となります。本手順では「ANALYST」というロール名に設定します。
  • テナントID:<アプリ登録をするEntraテナントID>

実行が完了すると、アプリ登録が完了し、接続に必要な値や外部OAuth用のセキュリティ統合を作るためのSQLテンプレートが記載されたテキストファイル「snowflakeinfo.txt」が出力されるのでダウンロードします。

snowflakeinfo.txtには、接続に必要なTenantClient IDClient SecretResource URLの4つの値が記載されています。

以上でアプリ登録の手順は終了です。

Snowflake設定

次に、接続に必要なSnowflake側の設定について説明します。

まずは、接続に必要なセキュリティ統合、接続用ユーザー、接続ユーザー用ロールの作成を行うため、アプリ登録の手順でダウンロードしたsnowflakeinfo.txt内のSQLステートメント部分をSnowflakeのSQLワークシート上で実行します。

加えて、ナレッジ対象とするデータベースへの参照権限とウェアハウス利用権限をロールへ付与し、そのロールを接続用ユーザーのデフォルトロールとして設定をするため下記のSQLを実行します。

-- ANALYSTロールにCOMPUTE_WHウェアハウスの使用権限を付与
GRANT USAGE ON WAREHOUSE COMPUTE_WH TO ROLE ANALYST;

-- ANALYSTロールにSNOWFLAKE_SAMPLE_DATAデータベースのIMPORTED PRIVILEGESを付与
GRANT IMPORTED PRIVILEGES ON DATABASE SNOWFLAKE_SAMPLE_DATA TO ROLE ANALYST;

-- AAD_SP_USERのデフォルトロールをANALYSTに設定
ALTER USER AAD_SP_USER SET DEFAULT_ROLE = ANALYST;

今回の例では、サンプルとして提供されているデータベース「SNOWFLAKE_SAMPLE_DATA」に含まれるテーブルをナレッジとして利用します。

※ 既存のデータベースを利用したい場合、対象のデータベース、スキーマのUSAGE権限、そしてテーブルに対するSELECT権限をロールに対して付与する必要があります。

ここでロールに対する権限を付与したデータベース名が接続情報のSnowflake databaseの値となり、そのデータベース内のナレッジ対象としたいスキーマ名が接続情報のSchemaとなります。

最後に、Snowflakeの[アカウント] > [アカウントの詳細を表示する] > [アカウント/サーバーURL]からSnowflake SaaS URLの値を取得することが出来ます。

以上までの手順で、接続に必要な情報は全て揃いました。

ナレッジ接続

Copilot Studioへアクセスし、Snowflakeナレッジを追加したいエージェントを開きます。その後、[概要] > [ナレッジ] > [ナレッジの追加]と進み、「Snowflake」と検索するとSnowflakeナレッジが表示されます。

すると、以下のようにSnowflakeへの接続が求められるため「新しい接続を作成する」を押下します。

ここで、Snowflakeへの接続に必要な情報を求められるため入力していきます。入力が完了すると、指定したSchema内に含まれるテーブルが一覧表示されます。検索対象としたいテーブルにチェックをし[エージェントに追加する]を押下します。

これにより、テーブル内のデータをナレッジとして活用することが出来るようになります。

以上で、Copilot StudioでSnowflakeナレッジを追加する手順は終了となります。

まとめ

本記事ではSnowflakeをCopilot Studioにナレッジとして接続する手順を紹介しました。

これにより、Snowflakeのデータを活用したエージェント構築が可能になります。ぜひ参考にしてください。

執筆担当者プロフィール
薩田 凱斗

薩田 凱斗(日本ビジネスシステムズ株式会社)

Data&AI本部 ソリューション部所属 Azureに関する技術を中心に発信します。

担当記事一覧