7
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

誰がどのMicrosoft 365のライセンスを持っているか、Graph APIをPower Automateから使って一覧取得する

Last updated at Posted at 2024-06-30

こんな人向けの記事です

Microsoft 365を活用している企業では、ライセンス管理はコストに直結するのでとても大切です。Microsoft 365管理センターからライセンス数は見えるし、誰にライセンスが付与されているかも確認したりダウンロードはできるけれど、それを自動化したい方向けの記事です。

定期的にCSVなどで決まった場所に出力することで、誰にいつ付けた、外した、付与済みユーザーの推移は?などの分析するためのデータを作ることができます。

マイクロソフトやサービスプロバイダーから年間契約でライセンスを購入したライセンスは在庫。必要なユーザーに対して割り当てますが、たとえば500ライセンスを購入しているのに、実際に割り当てられているユーザーが100人しかいなければ残りの400は使われないまま消えてゆく不良在庫。あー怖い。

瞬間のデータが取れれば推移が取れ、アクションが打てます。経費削減に直結し、Power BIで傾向分析と削減効果を見える化なんてしてみれば、あなたの評価は爆上げでしょう w。

PowerShellを使う場合は

こちらの記事が参考になります。とっても簡単です。

まずはおさらいから・・・

ユーザーからみた「持ってるライセンスは何?」

Microsoft 365管理センター> ユーザー> アクティブなユーザー と進んで、適当なユーザー名をクリックして開き、「ライセンスとアプリ」の項目を開くと、そのユーザーに割り当てられているライセンスがわかります。
image.png

私のテナントは開発者プログラムを使って作ったテストテナントなので、ライセンスの種類は少ないですが、一般的にはライセンスの欄にずらりと様々なライセンスが並んでいることでしょう。

下のほうにある「アプリ」に並んでいるのは、上部のライセンスの中身に含まれるもっと細かい「サービスプラン」と呼ばれる項目です。社内のユーザーにはMicrosoft 365 の機能の一部を使わせたくないような場合に、「サービスプラン」をオフにしたりします。

ライセンスから見た「持ってるユーザーは誰?」

こんどは、どんなライセンスがあって、そこに誰が割り当てられているのかという視点から見てみます。こちらも開発者プランのテナントなので少ないですが、種類がユーザーの項目に表示されていたものと同じですね?
私のテナントの場合、25個のMicrosoft 365 E5ライセンスを持っていて、その中から18個がユーザーにすでに割り当てられていて、残り7個を誰かに必要なら割り当てる余裕のあることがわかります。
image.png

Microsoft 365 E5のライセンスを開いてみると、このライセンスが誰に割り当たっているのか一覧表示ができます。ユーザーのエクスポートもできるので、一覧がとれるじゃないか! ということなのですが。毎月誰かが手作業でダウンロードするのは面倒だし忘れちゃいますよね? ということで、Power Automateのクラウドフローを使って自動取得しようというのが今回の趣旨です。

image.png

URLでSKUIDが取得できます

Microsoft 365 管理センターで誰にライセンスが割り当てられているか取得できるわけですが、この画面のURLに注目です。/licensedetailpage/ の後ろにある文字列。これがSKUIDです。
image.png

ちなみにKawasakiSEさんの記事で紹介されているこちらの記事のようにPowerShellで確認すると、Microsoft管理センターのURLに表示されている文字列と一致していることが確認できました。
image.png

Get-MgSubscribedSku | Select-Object SkuPartNumber,ConsumedUnits,SkuId

Graph Explorerで確認してみる

では、みんな大好きGraph Explorerで取得していきましょう。
Graph Explorer

開いたばかりの状態だとまだ自テナントにサインインできていないので、右側にあるユーザーマークをクリックしてサインインしましょう。(サインインしない場合もサンプルデータで確認できます)
初期状態でURLの入力欄には [https://graph.microsoft.com/v1.0/me] と入っていると思います。そのまま「Run Query」ボタンをクリックすると、サインインしているユーザー自身の情報が表示されます。
image.png

この状態だと情報過多なので、必要な情報だけを表示するように絞ります。これには $selectを使用します。

?$select=id,mail,desiplayname を加えてみました。ずいぶんすっきりしました。
image.png

さらに項目を追加します。今回知りたいのはライセンス情報なので、URLの入力欄の$selectの対象として licenseの文字を入力すると、取得できる候補が現れます。Graph Explorerを使うと、実際にどんな項目を取得できるのかが探せるのが素晴らしいですね。せっかくなので一つずつ試してみましょう。
image.png

ライセンス関係の$Select項目

licenseAssignmentStates

各SKUIDとアクティブかどうか、最後に更新された日時が表示されました。
image.png

注目すべきは"disabledPlans"の項目です。 ためしにWhiteboardのサービスプランをOFFにしてみてから再度取得すると、"disabledPlans"にWhiteboardのSKUIDが表示されました。つまり、フルにライセンスを付与したなかのオフにしたサービスプランがこの項目に表示されるようです。引き算の考え方ですね。

image.png

licenseDetails

ライセンスの詳細のようですが、何にも表示されないですね。謎なので次に行きましょう。
image.png

assignedLicenses

これはシンプルですね。私に付与されているライセンスのSKUIDが3つ並んでます。
image.png

Microsoft 365管理センターのユーザーから確認して比較するとイメージしやすいですね。
image.png

他のユーザーについて調べるには?

今回のテーマは、特定のライセンスを誰が付与されているかの一覧を取ることでした。さきほどまでGraph Explorerに入力していたURL(エンドポイント)のmeの部分を usersに変更すると、他のユーザーについて取得できます。 users/<ユーザーのオブジェクトID> とすると特定のユーザーについて調べられます。ユーザーのオブジェクトIDを指定しない場合は、すべてのユーザーについて取得します。

さっそく試してみると、エラーが出ました。権限が足りないのでタブから許可してと書いてあります。

Forbidden - 403 - 1164 ms. Either the signed-in user does not have sufficient privileges, or you need to consent to one of the permissions on the Modify permissions tab

image.png

自分の情報ならば見られましたが、他人の情報を見るには明示的に許可をしてやる必要があります。Graph Explorerもアプリなので、このアプリに他人の情報を見る許可を与えます。

「Modify permissions」を開くと許可できる項目が現れます。「Administrator consent required」がYesになっている項目は、とても強い権限なので管理者のOKがなければ与えられない権限です。Noとなっているものは、ユーザー自身が特別な許可がなくても閲覧できる部分に対するアクセスの許可です。こういうのを「委任」といいます。
image.png

「ユーザーの代わりに、アプリで組織内の他のユーザーのプロファイル プロパティの基本的なセットの読み取りを実行できるようにします。表示名、氏名、メール アドレス、写真が含まれます。」

「Modify permissions」の中から「User.ReadBasic.All」の「Consent」をクリックしましょう。この項目は説明書きがあるように以下のような操作に対する許可です。

この操作をしているのが全体管理者の場合は、Consent on behalf of your organization のチェックは入れないようにしましょう。誰でも許可した項目を使えるようになってしまいますので慎重に。

アプリに対する「User.ReadBasic.All」の許可を与えた後で、再度クエリーを実行してみると、自分だけではなく他のユーザーについてもライセンスの情報を取得することができているのがわかります。
image.png

いよいよ Power Automateの出番です。

Power AutomateからHTTP要求をするアクションを使います。Graph APIを操作するのに使えるのは、HTTP With Microsoft Entra ID(preauthorized)です。ややこしいのですが、(preauthorized)が以前のHTTP With Microsoft Entra IDでした。改名して括弧がつき、新たに登場したのがHTTP with Microsoft EntraID(無印)です。 無印のほうはあらかじめテナントの管理者がユーザーが利用できる要求のスコープを決めて利用させなければいけません。(この関係の公式文章はまた探しておきます)

image.png

ただし、こちらのHTTP要求はプレミアムコネクタです。プレミアム無しでもGraph APIが利用できる方法についてはこちらの記事が参考になります。

HTTP要求ができるアクションはEntra ID、Outlook、Office365Users,Teams,Groups と複数みつかります。 よっ! HTTP要求そろい踏み! 以下のエンドポイントに対してぜんぶ同時に試してみます。

https://graph.microsoft.com/v1.0/users?$select=id,mail,displayname,assignedLicenses

image.png

今回のエンドポイントの場合だとOffice 365 Usersのアクションが取得できましたので、これをつかうことにします。(一番左のEntra ID(preauthorized)もいけるはずなのにおかしいな?)
image.png

Office 365 Users の HTTP要求アクションを選択しましょう。
image.png

特定のライセンスにしぼって取得する

取得されるのはユーザーのメールアドレスと、その人がどのライセンスをもっているかのセットです。
すべてのライセンスとユーザーをいっぺんに抽出してもよいのですが、ラインセンスの種類が多いと出力されるデータも膨大になります。

そこで、指定した特定のライセンスだけに出力をしぼるようにエンドポイントのフィルターを追加します。HTTP要求の前に文字列変数を初期化してフィルターとエンドポイントURLの値を設定します。

フィルターには以下のような文字列を設定することで指定の値について絞り込むことができます。

参考:https://learn.microsoft.com/ja-jp/graph/filter-query-parameter?tabs=http#any-operator

&$filter=assignedLicenses/any(x:x/skuId eq <取得したいSKUID>)

フィルタの文字列をエンドポイントURLの後ろに変数としてくっつけます。エンドポイントURLに直接フィルタ部分も書いてやってよさそうなものですが、なぜかその場合エラーが出ました。こちらは原因不明。
image.png

テスト実行してみると、確かに指定したユーザーのメールアドレスが取得できています。
image.png

CSVにしてSharePointに保存

指定したSKUIDをもつユーザーをJSONで取得することができました。シンプルにCSVファイルにしてSharePoint Onlineのドキュメントライブラリに保存してみましょう。「開始」には下記のように指定します。

body('HTTP_要求を送信します')?['value']

image.png

テスト実行してみると、指定した名前でCSVファイルが保存されています。
image.png

CSVファイルにはエンドポイントURLに指定した$selectの項目を出力することができました!
image.png

まとめ

Graph Apiを使って特定のライセンスをもつユーザーの一覧を取得することができました。assignedLicensesの項目の中にはdisabledPlansの配列も含まれていますので、さらに細かくサービスプランの管理まで行うことも工夫次第でできそうです。

HTTP要求は複数の標準コネクタのアクションに含まれていますが、使うAPIの種類によって得意不得意な分野があるようです。プレミアムを使えなくてもつけるコネクタを見つけるには、今回やってみたような総当たりでチェックすると良いかと思います。

今回の方法で取得できるのは、ある時点のライセンスの状態ですから、定期的にファイル名に日付でも指定して実行し、Power BIを使えば時系列での分析もできます。

取得したライセンス一覧とアクセスログを突き合わせて、棚卸をするのもよいかもしれません。SKUIDの文字列さえ変更すれば複数のライセンスにも対応可能です。取得するSKUIDをリスト化してApply to eachで今回のフィルタ変数のID部分を差し替えてやれば一撃です。

みなさんのライセンス管理のお役に立てればうれしいです。

余談ですが

もしも取得した一覧を配列にしたいなら動作が遅いApply to eachを使わずに、「選択」を使った高速変換の方法があります。詳しくはこちらのブログをどうぞ。

選択の「開始」にはHTTP要求のValueを式で指定します。

body('HTTP_要求を送信します')?['value']

image.png
選択をマップモードにした状態で、マップにはメール項目だけを抜き出すように以下を設定します。

item()?['mail']

image.png

実行してみると、特定のSKUID(ライセンス)をもつユーザーのメールアドレスだけが抽出できました。
image.png

7
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?