ささみ学習帳 - sasami's study book

ささみ学習帳

Microsoft365 や Power Platform について学んだこと・アイデアのメモ

Microsoft365関連の未使用ライセンス数が指定値を下回ったらTeamsチャネルに通知するPowershellスクリプト

Microsoft365関連のライセンス残が閾値を超えたらTeamsチャネルに通知するPowershellスクリプトです。数年前に MSOnlineモジュールを使って見様見真似で作成していたのですが、MSOnlineは廃止される予定となっていますので Microsoft Graph Powershell SDK を使ったスクリプトに書き換えてみました。

 

2023/6/8追記

PowerAutomateクラウドフロー版も作ってみました。

→「Microsoft365関連の未使用ライセンス数が指定値を下回ったらTeamsチャネルに通知するPowerAutomateクラウドフロー

 

 

このスクリプトで実現できること

Microsoft365関連ライセンスの未使用数が指定した条件を下回ったら、Teamsのチャネルで通知する

 

準備するもの

Microsoft Graph PowerShellのインストール

管理者アカウントPowershellを起動し下記コマンドでインストール

Install-Module Microsoft.Graph

Teams側でIncoming WebHook の構成

このスクリプトは Incoming WebHook でTeams のチャネルに通知します。

下記手順でアプリをインストールしIncoming Webhook のURLを取得してください。

1.通知したいチームのチャネルで「…」→「コネクタ」

2.「Incoming Webhook」を追加

※チームにIncoming Webhookが追加済みの場合は「構成」ボタンに変わります。その場合は3へ

3.再度 通知したいチームのチャネルで「…」→「コネクタ」

4.「Incoming Webhook」の構成ボタンをクリック

5.名前を画像を設定して「作成」

ここで設定した名前と画像でメッセージが投稿されます。

5.「作成」ボタンをクリックすると、URLが表示されますので、これをどこかにコピーしておきます。

6.「完了」ボタンをクリックすると、チャネルに下記のように投稿されます。

 

スクリプト全体(v1) AzureADアプリ登録なし

Import-Module -Name Microsoft.Graph.Users

# m365接続。
Connect-MgGraph -Scopes "Organization.Read.All"

# 残りライセンス数が10未満を抽出
$warningUnits = Get-MgSubscribedSku | 
  Select-Object -Property Sku*, ConsumedUnits -ExpandProperty PrepaidUnits | 
  Select-Object *, @{Name = "RemainedUnits"; Expression = {$_.Enabled - $_.ConsumedUnits}} | 
  Where-Object {$_.RemainedUnits -lt 10} 

#通知メッセージを作成
$warningUnits | %{
  $licenseName = $_.SkuPartNumber
  # ライセンス名を置き換える
  $licenseName = $licenseName -replace "DEVELOPERPACK_E5","Microsoft 365 E5 Developer"
  $licenseName = $licenseName -replace "FLOW_FREE","Microsoft Power Automate Free"
  $licenseName = $licenseName -replace "Win10_VDA_E3","Windows10 Enterprise E3"
  $licenseName = $licenseName -replace "EXCHANGESTANDARD","Exchange Online (プラン1)"
  $licenseName = $licenseName -replace "POWER_BI_STANDARD","Power BI"
  $licenseName = $licenseName -replace "SPE_E3","Microsoft 365 E3"
  $licenseName = $licenseName -replace "EXCHANGEARCHIVE_ADDON","Exchange Online Archiving for Exchange Online"

  $remainingText += $licenseName + " が 残り" + $_.RemainedUnits + " ライセンスです。"
  $remainingText += "<br>"
}

# Teamsチャネルに通知
$WebHookURI = 'ここにIncoming Webhook の URLをコピペ';

$Payload = @{ 
    title = 'Microsoft365関連の残ライセンス数アラート';
  text = $remainingText;
}
$body = ConvertTo-Json $Payload
#UTF8に文字コードを変換する
$body = [System.Text.Encoding]::UTF8.GetBytes($body)
Invoke-RestMethod -Uri $WebHookURI -Method Post -Body $body


# m365切断
Disconnect-MgGraph

 # ライセンス名を置き換える の部分は、Powershellで取得できる名称のままでは分かりづらいため、わかりやすい名前に置換しています。

製品名との対応はこちらのページにありますので、必要なライセンスの分を追加変更してください。

learn.microsoft.com

実行イメージ

このスクリプトを実行すると、サインインのダイアログが表示されます。管理者アカウントでサインインする事で処理が実行されます。

上記にスクリプトではライセンスが残り10を切った場合に通知するようになっています。

  Where-Object {$_.RemainedUnits -lt 10} 

の数字を変更することで調整できます。

 

Disconnect-MgGraph を実行しないと認証情報はキャッシュされるが…

Connect-MgGraph でサインインすると認証情報はキャッシュされ、Disconnect-MgGraph を実行するまで保持する動作をするようです。この為、Windowsのスタートアップにこのスクリプトを追加すれば、毎日自動実行ができてしまいそうです。

キャッシュはC:\Users\<User>.graph\*cache.bin3 ファイルとして保持される

しかし、このキャッシュに有効期限があるのか不明な事や、Microsoft Graph Powershellを使う際にはキャッシュされた管理者権限でサインインしてしまうリスク、他の作業で別テナントに接続しなおすとこのスクリプトの動作が影響受けてしまう等の懸念もあります。

自動で定期実行させるのであれば、Disconnect-MgGraph はスクリプト内でちゃんと実行した上で、↓のスクリプト(V2)の手段とした方がよさそうです。

冒険はせずにサポートされてる手段を使う方がいろいろ安心です。

 


スクリプト(V2) - AzureADアプリ登録あり

以前のMSOnlineでは、パスワードをファイルに保持することで認証ステップを省略する事が出来ていましたが、Microsoft Graph Powershell では AzureADにアプリケーション登録必要があります。

AzureADにアプリ登録

1.Microsoft Entra 管理センター にアクセス(管理者アカウントでサインイン)

https://entra.microsoft.com/#view/Microsoft_AAD_IAM/

2.Azure Active Directory→アプリケーション→アプリの登録→新規登録

3.アプリの新規登録画面

  • 名前
    • 適切な名前を設定
  • サポートされているアカウントの種類
  • リダイレクトURI
    • 省略

「登録」ボタンをクリックします

 

4.概要に表示される [アプリケーション (クライアント) ID] と [ディレクトリ (テナント) ID] の値をコピーしておきます

 

5.[API のアクセス許可] – [+アクセス許可の追加] をクリック

 

6.[Microsoft Graph] – [アプリケーションの許可] をクリック

 

7.[Organization.Read.All]  を選択して [アクセス許可の追加] をクリック

 

8.[<テナント名> に管理者の同意を与えます] をクリック

確認が表示されるので [はい] をクリック

 

9.PowerShellを起動し下記のコマンドを実行して自己証明書を作成

$mycert = New-SelfSignedCertificate -Subject "CN=SelfSignedCert" -CertStoreLocation "Cert:\CurrentUser\My"  -KeyExportPolicy Exportable -KeySpec Signature

#エクスポート先のパスに合わせて ".\SelfSignedCert.cer"を変更
$mycert | Export-Certificate -FilePath ".\SelfSignedCert.cer"     
$mycert | Select Thumbprint

Thumbprint の値をコピーしておきます。

 

10. Entra管理センターに戻り、[証明書とシークレット]→[証明書をアップロード]をクリックし、9 で作成した証明書をアップロード

以上でアプリ登録は完了です。

 

コピーしておいた

  • [アプリケーション (クライアント) ID]
  • [ディレクトリ (テナント) ID] 
  • Thumbprintの値

は、スクリプトに反映します。

 

スクリプト(V1)からの差分

スクリプト(V1)との差分は、冒頭の Connect-MgGraph の部分のみです。

# m365に接続。
Connect-MgGraph -Clientid "[アプリケーション(クライアント)ID]" -TenantId "[ディレクトリID]" -CertificateThumbprint "[Thumbprintの値]"

 

実行イメージ

AzureADに登録したアプリケーションの権限で動作する為、このスクリプトではサインインは求められません。出力される内容はスクリプト(V1)と変化ありません。

 

さいごに

Microsoft Graph Powershell SDK を使ってみる練習台として、数年前に MSOnlineで作成したスクリプトを Micrsoft Graph Powershell SDK に置き換えてみましたが、構成は大きく変えずに対応できました。AzureAD に登録しないとサインインを求められてしまう仕様は少しハードルが上がりましたが、セキュリティという観点では必要な対応なのかもしれません。

ちなみに、このフローの後続処理としてPowerAutomateクラウドフローを組み合わせ、チャネルにメッセージ通知が来たらTeams承認フローを開始しm365管理者に通知、m365管理者が承認したら担当営業にライセンス追加の見積もり依頼メールを自動送信する、ところまで作っています。

 

※Get-MgSubscribedSku で取得できる情報の中にWarningという値がありました。もしかして標準機能でライセンス残を通知する機能があるのだろうか...

 

 

参考にしたページ

learn.microsoft.com

 

jpazureid.github.io