Azure AD グループ単位のライセンス割り当てを今すぐ実行

皆さんこんにちは。国井です。

Azure ADユーザーに対して、Office 365やMicrosoft 365のライセンス割り当てを行うときって必ずあると思います。そのときユーザーひとりずつ割り当てを行うのは面倒なので、Azure AD Premium P1のライセンスを持っているテナントであれば、グループにライセンス割り当てをしておいて、ユーザーはそのグループのメンバーになれば、自動的にユーザーに対してライセンス割り当てができると思います。

image

ただし、この機能はAzure AD内部で[再処理]というプロセスが実行されたときに割り当てられるので、だいたい1時間ぐらいのタイムラグが生じます。(もちろんグループのプロパティで[再処理]ボタンを押せばよいのですが、それを行うのが面倒って場合もあるでしょう)

グループの[再処理]ボタンを押すって処理、PowerShellでやりたいと思ってスクリプトを作ろうとしたら意外に大変なのね..

ってことで今日はその備忘録を残しておきます。
全部の手順を書くとめっちゃ大変なので、一部設定は他の投稿を引用しながら進めます。

なぜ大変なのか?

Azure AD PowerShell コマンドレットに[再処理]ボタンを押すオプションがありません。
そのため、Microsoft Graph経由での操作になるのですが、グループに対する[再処理]を実行するAPIはなく、ユーザー単位で[再処理]を実行するAPIを呼び出さなければならないのです。

image

ただ、このボタンを押したいだけなのに。

Microsoft Graph経由で再処理を実行

Graphを実行するための [アプリの登録] を作成します。
(※アプリの登録の作成方法はこちらで解説しています)
アプリの登録でアクセス許可を与えるAPIは
・Directory.ReadWrite.All
・User.ReadWrite.All

の2つです。どちらもアプリケーションのアクセス許可として割り当ててください。

image

PowerShellスクリプトの作成と実行

こちらのPowerShellスクリプトも以前の投稿、[Microsoft Graph APIでAzure ADを管理]から流用しました。
ポイントを解説すると、
まず最初の5行にあるパラメーターは
$tenantId の項目に Azure AD のテナント ID
(Azure AD 管理センターのトップページで確認できます)
$clientID の項目に[アプリの登録]を作成すると生成されるクライアントID
(アプリの登録ページで確認できます)
$thumbprint の項目にアプリの登録に登録した証明書の拇印
(証明書の作り方・登録方法についてはこちらで解説しています)
$serviceprincipal の項目にはアプリの登録に対応するエンタープライズアプリケーションのオブジェクトID
をそれぞれ入力してください。

また、最後のほうにある Invoke-RestMethod コマンドレットですが、
ここが再処理を実行しろ!という命令をしているところです。

Invoke-RestMethod -Uri "$resource/v1.0/users/<ユーザーのオブジェクトID>/reprocessLicenseAssignment" –Method POST -Headers $headerParams -ContentType "application/json"

ユーザーのオブジェクトIDはGet-AzureADUserコマンドレットを使えば取得できるので、Connect-AzureADコマンドレットをあらかじめ実行し、その上でGet-AzureADUserコマンドレットを実行して、それぞれのユーザーのオブジェクトIDを取得し、それぞれのユーザーで再処理を行うよう、ForEach コマンドレットを使ってループ実行します。

ここまでができると、ユーザーはライセンス割り当てされたグループのメンバーであれば、即座にユーザーに対するライセンス割り当てが完了します。
これをひとまとめにしたPowerShellスクリプトがこちら。

##
## Authorization & resource Url
##
$tenantId = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
$resource = https://graph.microsoft.com
$clientID = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
$thumbprint = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
$serviceprincipal = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"

##
## Download NuGet.exe
##
$sourceNugetExe = "https://dist.nuget.org/win-x86-commandline/latest/nuget.exe"
$targetNugetExe = ".\nuget.exe"
Remove-Item .\Tools -Force -Recurse -ErrorAction Ignore
Invoke-WebRequest $sourceNugetExe -OutFile $targetNugetExe
Set-Alias nuget $targetNugetExe -Scope Global -Verbose

##
## Download Microsoft.IdentityModel.Clients.ActiveDirectory.dll
##
./nuget install Microsoft.IdentityModel.Clients.ActiveDirectory -O .\Tools
md .\Tools\Microsoft.IdentityModel.Clients.ActiveDirectory
$prtFolder = Get-ChildItem ./Tools | Where-Object {$_.Name -match 'Microsoft.IdentityModel.Clients.ActiveDirectory.'}
move .\Tools\$prtFolder\lib\net45\*.* .\Tools\Microsoft.IdentityModel.Clients.ActiveDirectory
Remove-Item .\Tools\$prtFolder -Force -Recurse

##
## Remove NuGet.exe
##
Remove-Item nuget.exe

##
## MS Graph Access
##
Add-Type -Path ".\Tools\Microsoft.IdentityModel.Clients.ActiveDirectory\Microsoft.IdentityModel.Clients.ActiveDirectory.dll"

##
## Authorization & resource Url
##
$authUrl = "https://login.microsoftonline.com/$tenantId/"

##
## Create AuthenticationContext for acquiring token
##
$authContext = New-Object Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext $authUrl, $false

##
## Create credential for client application
##
$clientCred = New-Object Microsoft.IdentityModel.Clients.ActiveDirectory.ClientCredential $clientID, $clientSecret

##
## Acquire the authentication result
##
$authResult = $authContext.AcquireTokenAsync($resource, $clientCred).Result

##
## Give User Account Administrator permission to service principal
##
Get-AzureADDirectoryRole | Where-Object {$_.DisplayName -eq "User Account Administrator"}
$userAdminRole = Get-AzureADDirectoryRole | Where-Object {$_.DisplayName -eq "User Account Administrator"}
Add-AzureADDirectoryRoleMember -ObjectId $userAdminRole.ObjectId -RefObjectId $serviceprincipal

##
## Get users data
##
Connect-AzureAD  -CertificateThumbprint $thumprint -TenantId $tenantId -ApplicationId $serviceprincipal
$users=Get-AzureADUser

##
## Execute Reprocess
##
ForEach($userObj in $users.ObjectID) {
$headerParams = @{'Authorization' = "$($authResult.AccessTokenType) $($authResult.AccessToken)"}
Invoke-RestMethod -Uri "$resource/v1.0/users/$userObj/reprocessLicenseAssignment" –Method POST -Headers $headerParams -ContentType "application/json"
}

もうめちゃくちゃ面倒!
だったら、Azure AD管理センターに行って、グループのライセンス項目にある[再処理]ボタンを押すわ!というのがお分かりいただけたと思います。