Azure Functions の PowerShell ランタイムでマネージド ID (Managed Identity) を使用して SQL Database に接続をする方法についてまとめておきたいと思います。
Contents
事前準備
最初に事前準備として、Azure Functions のマネージド ID の設定と SQL Database のユーザーの作成を実施します。
今回は「fn-azurefunction01」という Azure Functions に対して作業を行います。
Azure Functions のマネージド ID の有効化については、該当の関数アプリの ID から、マネージド ID を「オン」にすることで、有効化を行うことができます。
マネージド ID の有効化を実施したら、Azure Functions 用のユーザーを SQL Database に作成します。
SQL Database に対して、マネージド ID を使用して接続を行うためのドキュメントについては次のようなものが公開されています
- App Service と Azure Functions でマネージド ID を使用する方法
- チュートリアル:マネージド ID を使用した App Service からの Azure SQL Database 接続のセキュリティ保護
- チュートリアル:Windows VM のシステム割り当てマネージド ID を使用して Azure SQL にアクセスする
- マネージド ID を使用して Azure SQL Database へのインデクサー接続を設定する
SQL Database にマネージド IDを使用して接続を行うためには、次のような作業を実施する必要があります。
- Azure Active Directory 認証でログイン (AAD 認証で SQL Database にログイン)
- クエリを実行するデータベースに マネージド ID を使用したユーザーを作成
今回は、SQL Database の「Azure Active Directory 管理者」に設定した AAD のユーザーで、クエリを実行したいデータベースに対してログインをし、次のようなクエリを実行しています。
[fn-azurefunction01] の箇所には、接続を行う Azure Functions の関数名を指定します。
CREATE USER [fn-azurefunction01] FROM EXTERNAL PROVIDER;
これで、マネージド ID を使用して、SQL Database に接続を行うための設定ができましたので、実際に接続をしてみます。
Azure Functions からの接続 (アクセストークンを使用)
Azure Functions からマネージド ID でアクセストークンを使用した接続ですが次の 2 ステップが必要となります。
- アクセストークンの取得
- 取得したアクセストークンを接続情報に指定して SQL Database に接続
アクセストークンの取得
マネージド ID を使用した SQL Database の接続については、アクセストークンを取得する必要があります。
取得の方法については次のドキュメントに記載されています。
今回はタイマートリガーを使用しているのですが、タイマートリガーからアクセストークンを取得する場合には、コード例 に記載されているような次のようなコードを実行します。
param($Timer) $resourceURI = "https://database.windows.net/" $tokenAuthURI = $env:IDENTITY_ENDPOINT + "?resource=$resourceURI&api-version=2019-08-01" $tokenResponse = Invoke-RestMethod -Method Get -Headers @{"X-IDENTITY-HEADER"="$env:IDENTITY_HEADER"} -Uri $tokenAuthURI $accessToken = $tokenResponse.access_token Write-Host $accessToken $con = New-Object System.Data.SqlClient.SqlConnection($ENV:SQLAZURECONNSTR_ConnectionString) $con.AccessToken = $accessToken
$resourceURI については、Azure リソースのマネージド ID をサポートするサービス に記載されている SQL Database のリソース URI を指定します。
アクセストークンを取得する際に要求を行う「$env:IDENTITY_ENDPOINT」ですが、Azure Functions ではこの環境変数が自動的に設定されており「http://127.0.0.1:41565/MSI/token/」が指定されている状態となりますので、環境変数に指定されている URI に対して、要求を行うことでアクセストークンが取得されます。
取得したアクセストークンを使用して SQL Database に接続を行います。
取得したアクセストークンを接続情報に指定して SQL Database に接続
今回、Azure Functions の「構成」の「接続文字列」には次のような設定を行っています。
種類を SQLAzure として設定した接続文字列については、関数内で「$ENV:SQLAZURECONNSTR_[名前]」として、環境変数経由で情報を取得することができます。
今回の設定例であれば「$ENV:SQLAZURECONNSTR_ConnectionString」として、設定している内容を取得することができます。
マネージド ID を使用して接続を行う場合必要となる情報はサーバー名とデータベース名のみとなり、資格情報 (ユーザー / パスワード) は設定する必要はありません。
「Server=xxxxxxx.database.windows.net;Database=xxxx」という接続文字列の情報のみが設定されていれば、接続を行うことができます。
先ほど取得したアクセストークンを使用してクエリを実行する場合は、次のようなスクリプトを実行することで、SQL Database に対してクエリを実行することができます。
$con = New-Object System.Data.SqlClient.SqlConnection($ENV:SQLAZURECONNSTR_ConnectionString) $con.AccessToken = $accessToken $con.Open() $cmd = New-Object System.Data.SqlClient.SqlCommand("SELECT @@VERSION", $con) $ret = $cmd.ExecuteScalar() Write-Host $ret $con.Close() $con.Dispose()
SqlConnection を作成する際には資格情報を指定していない接続文字列の情報でオブジェクトを作成します。
作成したオブジェクトの AccessToken プロパティに対して、前段で取得したアクセストークンを設定し、接続をオープンします。
以降の流れは通常の実行と同じです。
今回使用したスクリプトの全体が次の内容となります。
param($Timer) $resourceURI = "https://database.windows.net/" $tokenAuthURI = $env:IDENTITY_ENDPOINT + "?resource=$resourceURI&api-version=2019-08-01" $tokenResponse = Invoke-RestMethod -Method Get -Headers @{"X-IDENTITY-HEADER"="$env:IDENTITY_HEADER"} -Uri $tokenAuthURI $accessToken = $tokenResponse.access_token Write-Host $accessToken $con = New-Object System.Data.SqlClient.SqlConnection($ENV:SQLAZURECONNSTR_ConnectionString) $con.AccessToken = $accessToken $con.Open() $cmd = New-Object System.Data.SqlClient.SqlCommand("SELECT @@VERSION", $con) $ret = $cmd.ExecuteScalar() Write-Host $ret $con.Close() $con.Dispose()
Azure Functions からの接続 (接続文字列の利用)
Azure Functions からの接続 (アクセストークンを使用) で記載されていますが、「Authentication=Active Directory Managed Identity」を接続文字列に指定することでも MSI を使用したデータベースのアクセスを実施することができます。
こちらの場合は、アクセストークンを明示的に取得する必要がなく、シンプルな接続文字列で接続できますので、対応が楽かと思います。
PowerShell 7 の System.Data.SqlClient では、接続文字列に Authentication が使用できないため、この方法を使用するためには、Microsoft.Data.SqlClient を使用する必要がありますので、Azure Functions で Microsoft.Data.SqlClient が使用できるようにファイル配置が必要となり、手間が少しかかるかもしれません。
上述のアクセストークンについては、System.Data.SqlClient で使用できますので、PowerShell 7 で使用できる標準的なランタイムだけで対応することができます。
まとめ
マネージド ID を使用した場合は、資格情報をコード / 環境変数に埋め込むことなく、接続を行うことができます。
マネージド ID 対応サービスについては、積極的に使っていきたいですね。