Azure FunctionsでMicrosoft Graph PowerShell SDKを使う(powershell)

2022年9月16日

ローカルだと楽勝ですが、Azure Functionsだとひと工夫必要です。

モジュール読み込み

ローカル環境の場合

まずMicrosoft Graph PowerShell SDKを使うためにモジュールをダウンロードして利用できるようにする必要があります。

Install the Microsoft Graph PowerShell SDK | Microsoft Docs

Install-Module Microsoft.Graph -Scope CurrentUser

Azure Functionsの場合

このブログが神でした。

Azure Functions 用に Save-Module する

Kudu > Debug console > PowerShellに進んで

[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
Install-PackageProvider nuget -Force -Scope CurrentUser
Save-Module Microsoft.Graph -Path .\modules 

とすることで、modules以下に必要なモジュールがダウンロードされ、Azure functions関数起動時に読み込まれます。

※ 実際にMicrosoft.Graphのすべてをダウンロードすると多すぎるので、Microsoft.Graph.Devices.ServiceAnnouncementのように限定する

これ、ヒントはAzure Functions の PowerShell 開発者向けリファレンス | Microsoft Docsの一番下に書いてあるのですが、ちょっとわからなかったです。上記ブログを読むまではprofile.ps1で何とかするのかなと思ってました。

認証

ローカル環境の場合(対話的な認証)

Connect-MgGraphコマンドを利用して、実行したいコマンドに必要な権限を付与する必要があります。

Connect-MgGraph -Scopes 'User.Read.All'

このコマンドを普通にするとブラウザで認証画面が立ち上がります。

ローカル環境のコマンドラインで取得する際はこの対話型で認証すればいいですが、Azure Functionsで自動的に実行するとなるとそうはいきません。

Azure Functionsのため、対話的な認証以外の方法を模索

対話型ではなくアプリケーション権限で認証させることで、非対話的な処理で操作者の応答なく関数を実行できます。

やり方ですが、アプリケーション権限での認証を行うこと。

Use app-only authentication with the Microsoft Graph PowerShell SDK | Microsoft Docs

このためには証明書が必要なようです。自己証明書(オレオレ証明書)でOK。

証明書作るの面倒、と思って従来型のシークレットとキーで出来ないかと調べたけど、Connect-MgGraph自体にそんなオプションはない様子でした。

Connect-MgGraph (Microsoft Graph)

ローカル環境での証明書認証(コンピューターの証明書ストアに証明書が格納されている場合)

ローカル環境では以下の通りに実行することで、証明書の拇印だとか、CN名を指定すれば証明書認証が可能でした。

Connect-MgGraph -Clientid "<登録したアプリのアプリケーション (クライアント) ID>" -TenantId "<アプリを登録したテナントのディレクトリ (テナント) ID>" -CertificateThumbprint "<証明書の拇印>"

しかしこれは、証明書ストアが参照できるローカルコンピューター(証明書を作成したコンピューター)の場合。Azure Functionsは別マシンなのでこの方法は使えません。

秘密鍵をエクスポートして、X509Certificate2 オブジェクトで証明書として読み込む

考えたのは「秘密鍵はファイルとしてエクスポートできる。それを読み込んで認証させる方式ならAzure Functionsでも同じことができるんじゃね?」でした。

まずは、ローカル環境にエクスポートした秘密鍵を保存して、X509Certificate2 オブジェクトを指定して実行します。

$password= "mypassword"
$passwordSecure = ConvertTo-SecureString -AsPlainText -Force $password

$cert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2("C:\d\20220905_cert\secret1.pfx", $passwordSecure)

Connect-MgGraph -ClientID "クライアントID" -TenantId "テナントID" -Certificate $cert

上手くいきました。

こちらのやり方は以下の記事にも書いてあります。

open Unable to authenticate using Connect-MgGraph with certificate on Windows Server or Azure HybridWoker error is "certificate was not found or has expired." · Issue #675 · microsoftgraph/msgraph-sdk-powershell

Azure Functionsで実行しようとした(失敗)

同じやり方ならAzure Functionsでいけるやろ!と思ったら失敗しました。

まず、事前に秘密鍵をKudo経由でAzure functionsにアップロードします。アップロード場所は C:\home\site\wwwroot\certfile\secret1.pfx です。

そして、以下のコードを入力するとエラーが出ました。

$password= "mypassword"
$passwordSecure = ConvertTo-SecureString -AsPlainText -Force $password

$cert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2("C:\home\site\wwwroot\certfile\secret1.pfx", $passwordSecure)

Connect-MgGraph -ClientID "クライアントID" -TenantId "テナントID" -Certificate $cert

いろいろ調べたのですが、Azure Functionsで証明書を利用するにはお作法があるようです。ということで、次回に続きます。

備考

Microsoft Graph PowerShell SDKを使わずにHTTPSでやる方法はこちらです。

PowerShellでMicrosoft Graph APIを実行し、Azure ADのユーザー情報を更新する – Qiita

ただ、せっかく新しいモジュールがリリースされていて、これからは主流になると思うので、勉強のためにこちらで実装しています。

Posted by tera