Azure SQL Database External REST Endpoints Integration Public Preview でアナウンスがありましたが、SQL Database で、SQL から REST API をコールすることができる sp_invoke_external_rest_endpoint というストアドプロシージャがプレビューで提供されました。
SQL 単体で、REST をコールして情報を取得することができる機能となります。
呼び出しができるエンドポイントについては、許可されているエンドポイント に記載されている次のエンドポイントに限定され、これ以外のエンドポイントについては、サポートされるエンドポイントでラップして呼び出す必要があります。
本機能の使用方法のサンプルについては Azure SQL DB sp_invoke_external_rest_endpoint samples が提供されているのですが、この中で触れられていない Microsoft Graph を使用して、本機能を確認してみました。
SQL Database から Graph REST API を呼び出すための準備
SQL Database から Graph REST API を呼び出すために、SQL Database の論理サーバーの Managed Identity から API を呼び出すための権限を付与しておきます。(呼び出し方法についてはいくつかのパターンを採用できると思いますが今回は Managed Identity を使用しています)
権限の付与ですが、今回は チュートリアル: セキュリティで保護された .NET アプリからアプリとして Microsoft Graph にアクセスする の方法を使用しています。
このチュートリアルでは、Azure AD PowerShell が使用されており、本投稿でもそれを利用していますが、Azure Active Directory の PowerShell モジュール / MSOnline / AzureAD PowerShell から Graph PowerShell SDK への移行について 1_概要 等でアナウンスされているとおり、今後は Graph PowerShell SDK への移行が推奨されていますので、2023/3/31 以降は Graph PowerShell を利用したほうが良いかと思います。
また、PowerShell 7 で AzureAD PowerShell を実行しようとすると powershell login error のエラーになるかもしれませんので、Windows PowerShell で実行したほうが簡単かと思います。
SQL Database の Managed Identity に Grapu REST API からユーザーの読み取りを実行する場合は次のようなスクリプトを実行します。
$TenantID="<Tenant ID>" $objectId = "<Managed Identity object id>" Connect-AzureAD -TenantId $TenantID $PermissionName = "User.Read.All" $GraphServicePrincipal = Get-AzureADServicePrincipal -SearchString "Microsoft Graph" | Select-Object -first 1 $AppRole = $GraphServicePrincipal.AppRoles | ` Where-Object {$_.Value -eq $PermissionName -and $_.AllowedMemberTypes -contains "Application"} New-AzureAdServiceAppRoleAssignment -ObjectId $objectId -PrincipalId $objectId -ResourceId $GraphServicePrincipal.ObjectId -Id $AppRole.Id # 削除する場合は以下を実行 $srAssignment = Get-AzureADServiceAppRoleAssignment -ObjectId $GraphServicePrincipal.ObjectId | ? PrincipalId -eq $objectId Remove-AzureADServiceAppRoleAssignment -ObjectId $GraphServicePrincipal.ObjectId -AppRoleAssignmentId $srAssignment.ObjectId
このようなスクリプトを実行すると Microsoft Graph に対して、Managed Identity が読み取りのアクセスが付与されます。
AAD のポータルで設定状況を確認する場合は、次の情報になるのではないでしょうか。
- [エンタープライズアプリケーション] -> [すべてのアプリケーション] -> [アプリケーションの種類のフィルターを削除] -> [Microsoft Graph] で、アプリケーション ID [00000003-0000-0000-c000-000000000000] のアプリケーションを選択し、[ユーザーとグループ]
- [エンタープライズアプリケーション] -> [すべてのアプリケーション] -> [アプリケーションの種類のフィルターを削除] -> [SQL Database の論理サーバー名を入力] -> [アクセス許可]
Managed Identity に対して次のような権限が付与されていれば、事前の準備は完了です。
SQL Database から Graph API を呼び出す
それでは実際に呼び出してみたいと思います。事前に CREATE MASTER KEY でデータベースマスターキーの作成は完了しているという前提でのクエリです。
IF EXISTS (SELECT * FROM sys.database_scoped_credentials WHERE name = 'https://graph.microsoft.com/v1.0/users') BEGIN DROP DATABASE SCOPED CREDENTIAL [https://graph.microsoft.com/v1.0/users]; END CREATE DATABASE SCOPED CREDENTIAL [https://graph.microsoft.com/v1.0/users] WITH IDENTITY = 'Managed Identity' , SECRET = '{"resourceid":"https://graph.microsoft.com/"}'; GO DECLARE @response nvarchar(max) EXEC sp_invoke_external_rest_endpoint @url = 'https://graph.microsoft.com/v1.0/users' , @method='GET' , @response = @response OUTPUT , @credential = [https://graph.microsoft.com/v1.0/users] IF (SELECT JSON_VALUE(@response, '$.response.status.http.code')) <> 200 BEGIN SELECT [key],[value] FROM OPENJSON(@response, '$.response.headers') UNION ALL SELECT [key],[value] FROM OPENJSON(@response, '$.result.error') END ELSE BEGIN SELECT JSON_VALUE(value, '$.displayName') AS displayName , JSON_VALUE(value, '$.userPrincipalName') AS userPrincipalName FROM OPENJSON(@response, '$.result.value') END
軽く試した感じでは、このようなクエリを実行することで、Graph API を SQL で呼び出し、ユーザーの一覧を取得することができました。
実際に使用している自分のテナントの情報なので、白塗りが多くて何をとっているのかわからないですが、ユーザー情報の取得が行えています。
どのような処理を SQL Database 側で実装すると効率が良いのかは悩ましいところではありますが、面白い機能なのではないでしょうか。