Microsoft Entra ID(旧 Azure AD)の動的セキュリティ グループを「任意のライセンスを1つでも持つ有効ユーザー」に限定したいのに、条件式でエラーになったり、共有メールボックスや失効ライセンスを持つユーザーまで入ってしまう……という悩みはよくあります。本記事では、このニッチな要件を確実に満たす動的グループの作り方を、実務目線で詳しく解説します。
シナリオ整理:動的グループで実現したいこと
今回のゴールは、Microsoft Entra ID の動的セキュリティ グループに、次の条件を満たすユーザーだけを自動登録することです。
- 有効なユーザー アカウント(user.accountEnabled = true)
- 1つでもライセンス(サービス プラン)が割り当てられている
- ただし、共有メールボックス化した元ユーザーや、失効済みライセンスだけを持つユーザーは除外したい
- 特定のプラン ID ではなく、「どのプランでも良い」=任意のライセンスを条件にしたい
特定のサービス プラン ID を指定する動的ルールはよく紹介されていますが、「任意のライセンスを持つユーザー」という抽象度で書こうとすると、次のようなつまずきが発生します。
- servicePlanId をワイルドカードにしようとしてエラーになる
- -any / -all の挙動がわかりづらく、意図しないユーザーが含まれてしまう
- 共有メールボックスに変換した元ユーザーが、いつまでもグループから外れない
ここをきちんと理解するには、まず assignedPlans と capabilityStatus というプロパティの意味を押さえておく必要があります。
前提知識:assignedPlans と capabilityStatus を理解する
ライセンス関連の動的メンバーシップは、主に次のプロパティを使って評価されます。
| プロパティ | 概要 | よくある値の例 |
|---|---|---|
user.accountEnabled | ユーザー アカウントが有効かどうか。 サインイン可能なユーザーを対象にする場合は true でフィルタする。 | true / false |
user.assignedPlans | ユーザーに割り当てられたサービス プランの配列。 各要素に servicePlanId や capabilityStatus などが含まれる。 | 複数の要素を持つ JSON 配列イメージ |
assignedPlan.servicePlanId | 1つのサービス プランを識別する GUID。 Exchange Online や SharePoint Online など、プランごとに異なる。 | f8a1db68-be16-40ed-86d5-cb42ce701560 など |
assignedPlan.capabilityStatus | そのプランの状態。 有効 / 無効 / 一時停止 などを表す。 | "Enabled", "Suspended", "Deleted" など |
ポイントは、ライセンスを外したつもりでも assignedPlans の履歴がすぐには消えないケースがあることです。共有メールボックス化したユーザーや、サブスクリプション失効後のユーザーなどで、構造自体は残っていることがあります。
そのため、assignedPlans の有無だけで判断すると、「過去にライセンスを持っていたが、今は有効なサービスはない」ユーザーを拾ってしまうことがあります。このときに効いてくるのが、capabilityStatus = "Enabled" です。
-any と -all の違いをおさらい
動的メンバーシップ ルールでは、配列型のプロパティ(assignedPlans など)に対して -any と -all を使って条件を表現します。
| 演算子 | 意味 | イメージ |
|---|---|---|
-any (条件) | 配列の中に「条件を満たす要素が1つでもあれば true」 | 「いずれか1つでも OK なら true」 |
-all (条件) | 配列の要素が「すべて条件を満たすなら true」 | 「1つでも条件を満たさない要素があれば false」 |
not (… -all (条件)) | 「すべて条件を満たす」の否定。 = 1つでも条件を満たさない要素があれば true | 「全部Aではない」=「Bが1つでもあれば true」 |
この記事で使うテクニックは、not と -all の組み合わせで「1つでも null でないプランがある」状態を表現することです。
おすすめのルール パターン 3種類
ここから、実際に使える 3 つのルール パターンを紹介します。
| パターン | ルール | 想定用途 |
|---|---|---|
| A. 推奨(not + -all) | servicePlanId がすべて null ではない | 任意のライセンスを1つでも持つ有効ユーザーを広く拾いたいとき |
| B. シンプル(-any + -ne) | servicePlanId が null でないものが1つでもある | まず動かしてみたいラボ環境向け。共有メールボックスなどの混入リスクあり |
| C. 厳密(capabilityStatus = Enabled) | Enabled なプランが1つでもある | 共有メールボックスや失効ライセンスを本気で避けたい本番運用向け |
A. 推奨パターン:「not + -all」で任意ライセンス保有を判定
最も扱いやすく、公式コミュニティでも「解決済み」とされることが多いのがこのパターンです。
(user.accountEnabled -eq true)
and not (user.assignedPlans -all (assignedPlan.servicePlanId -eq null))
この式を日本語にすると、次のようになります。
user.accountEnabled -eq true
→ アカウントが有効なユーザーだけを対象にするuser.assignedPlans -all (assignedPlan.servicePlanId -eq null)
→ 「すべての assignedPlans の servicePlanId が null」の場合に truenot (…)
→ 上記の否定。「すべて null ではない」=「1つでも null でない servicePlanId がある」
つまり、「アカウントが有効」かつ「少なくとも1つは null でない servicePlanId を持つ」ユーザーだけがメンバーになります。
| メリット | デメリット / 注意点 |
|---|---|
特定プラン ID を意識せず、「任意のライセンス」を条件にできる -all の否定で、「1つでも存在する」をスマートに表現できる ルール自体は短く、メンテナンスしやすい | ライセンス履歴が残っている特殊ケースでは、意図せぬユーザーを含む可能性がある 「有効なプランだけ」に限定したい場合は、Cパターンに比べるとやや粗い |
まずは A パターンで運用し、問題が出てきた場合に C パターンへ切り替える、というステップアップ方式も現実的です。
B. シンプルな代替案:「-any + -ne」で直感的に書く
-all の否定がどうもピンと来ない場合は、-any と -ne を組み合わせたパターンも使えます。
(user.accountEnabled -eq true)
and (user.assignedPlans -any (assignedPlan.servicePlanId -ne null))
こちらは、感覚的に理解しやすい式です。
assignedPlans -any (assignedPlan.servicePlanId -ne null)で
「servicePlanId が null ではない要素が1つでもあれば true」- つまり、「何かしらのライセンス情報を持つ」ユーザーを拾う
ただし、この書き方にはいくつかの落とし穴があります。
- 共有メールボックス化した元ユーザー
Exchange Online のメールボックスを Shared に変換しても、assignedPlansに情報が残るケースがあり、そのままだとグループに残ってしまうことがあります。 - 失効ライセンスを持つユーザー
テナントのサブスクリプションが終了した場合など、capabilityStatusが"Deleted"等になっていても、servicePlanId自体は存在するため条件に一致してしまうことがあります。
| こんなときに B パターン |
|---|
| 検証環境で、とりあえず「ライセンス持ちユーザー」をざっくり集めたい -all / not の組み合わせに不慣れで、まずは直感的な条件から始めたい 共有メールボックスや失効ライセンスがそれほど問題にならない規模の環境 |
本番環境では、C パターン(capabilityStatus で絞る)を検討することを強くおすすめします。
C. 厳密フィルタ:capabilityStatus = “Enabled” のプランだけに限定
共有メールボックスや失効ライセンスを確実に除外したいなら、capabilityStatus = "Enabled" まで条件に入れたパターンが安心です。
(user.accountEnabled -eq true)
and (user.assignedPlans -any (
not (assignedPlan.servicePlanId -eq null)
and (assignedPlan.capabilityStatus -eq "Enabled")
))
この式の意味は次の通りです。
not (assignedPlan.servicePlanId -eq null)
→ servicePlanId が null ではない(実在するプランである)assignedPlan.capabilityStatus -eq "Enabled"
→ そのプランの状態が有効である-any (…)
→ 上記を満たすプランが 1 つでもあれば、そのユーザーはグループに含める
これにより、次のようなユーザーを避けることができます。
- 共有メールボックス化しており、実質的にライセンスが外れているユーザー
- 削除済み・一時停止状態のプランだけが紐づいているユーザー
| メリット | デメリット / 注意点 |
|---|---|
| 「有効なプランを1つ以上持っているユーザー」に絞り込める ライセンス履歴や特殊な状態に左右されにくい 本番運用での誤配属リスクを大きく減らせる | 式がやや長く、初見の人には読みづらい トラブルシューティング時には assignedPlans の中身を確認する必要がある |
ライセンス付与に応じて自動でグループに加入させ、そのグループを条件付きアクセスやアプリ割り当てに使う場合は、C パターンを採用しておくと安心度が高くなります。
特定プランを含めない / 含める条件の追加例
上記のパターンに、特定のサービス プラン ID を「含めない」「含める」といった条件を追加することもできます。
特定プランを除外したい場合の例
たとえば、Enabled なプランを持つユーザーに限定しつつ、あるプラン ID を除外したいとします。
(user.accountEnabled -eq true)
and (user.assignedPlans -any (
not (assignedPlan.servicePlanId -eq null)
and (assignedPlan.capabilityStatus -eq "Enabled")
and not (assignedPlan.servicePlanId -eq "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx")
))
"xxxxxxxx-..."の部分に除外したいサービス プランの GUID を指定します。- 複数除外したい場合は、
and not (…)を複数追加するか、OR 条件を組み合わせます。
特定プランを必須にしたい場合の例
逆に、「任意のライセンスを1つ以上持っている」ユーザーの中でも、特定プランを持っているユーザーだけを抽出したい場合は、C パターンの一部を差し替えます。
(user.accountEnabled -eq true)
and (user.assignedPlans -any (
assignedPlan.servicePlanId -eq "yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy"
and (assignedPlan.capabilityStatus -eq "Enabled")
))
このように、ベースとなるパターン(A/B/C)を決めたうえで、必要に応じて servicePlanId を追加条件として組み込むと、運用方針にフィットしたルールを作れます。
Azure ポータルからの具体的な作成手順
ここまで紹介したルールを、実際に Microsoft Entra ID の動的セキュリティ グループとして作成する手順を解説します。
- Azure ポータルにサインインし、左メニューから 「Microsoft Entra ID」 を開きます。
- 左メニューで 「グループ」 を選択し、上部の 「新しいグループ」 をクリックします。
- グループの種類 に 「セキュリティ」 を選択します。
- グループ名、グループの説明 をわかりやすく入力します。例:
- グループ名:
SG-LicensedUsers-AnyPlan - 説明:
任意の有効なライセンスを1つ以上持つ有効ユーザーを自動登録
- グループ名:
- メンバーシップの種類 を 「動的ユーザー」 に変更します。
- メンバーシップの種類の下に表示される 「動的クエリを追加」 をクリックします。
- ルールの構文 のテキスト ボックスに、A / B / C のいずれかのルールを貼り付けます。
- 「クエリを検証」 または 「メンバーシップの有効性を確認」 を使用して、想定通りのユーザーが含まれるかを確認します。
- 問題なければ 「保存」 → 「作成」 をクリックします。
作成後、動的グループのメンバーシップが完全に反映されるまでには時間差があります。通常は数分〜数時間ですが、最大 24 時間程度のラグがあり得る前提で設計しておくと安全です。
メンバーシップの検証とトラブルシューティング
ルールが意図通りに動いているかを確認するには、グループ画面から行える次の機能を活用します。
- メンバーシップの有効性を確認
対象となるユーザーを指定して、「このユーザーがルールに一致するか」を即座に判定できます。
想定ユーザーが「一致しない」場合は、ユーザーのassignedPlansやcapabilityStatusを見直しましょう。 - メンバー タブ
しばらく時間をおいてから、実際にどのユーザーがメンバーになっているかを確認します。
想定外のユーザーが入っている場合は、ルールの条件を見直します。
トラブルシューティングの際は、次の観点をチェックすると原因を特定しやすくなります。
- ユーザーが本当に accountEnabled = true になっているか
- ユーザーの assignedPlans に、どの servicePlanId と capabilityStatus が含まれているか
- テナントのサブスクリプション状態により、プランの capabilityStatus が変化していないか
共有メールボックスや退職ユーザーを確実に除外するコツ
運用が長くなるほど、「もう使っていないはずのユーザー」が動的グループに残り続けるケースが増えてきます。特に注意したいのが次のパターンです。
- ユーザーを共有メールボックス(Shared)に変換したケース
- 退職ユーザーのライセンスを外したが、履歴が残っているケース
これらを確実に除外するには、次のような工夫が有効です。
- 可能であれば、C パターン(capabilityStatus = “Enabled”)を採用する
- 退職ユーザー向けには、別の属性(department、companyName、extensionAttribute など)でフィルタリングする
- 共有メールボックス専用の命名規則(例:
sh-xxx)がある場合は、userPrincipalNameやdisplayNameに対する-notContains条件を追加する
例えば、C パターンに「UPN が @shared.contoso.com を含むアカウントは除外」という条件を足すこともできます。
(user.accountEnabled -eq true)
and (user.userPrincipalName -notContains "@shared.contoso.com")
and (user.assignedPlans -any (
not (assignedPlan.servicePlanId -eq null)
and (assignedPlan.capabilityStatus -eq "Enabled")
))
このように、ライセンス条件だけに頼らず、命名規則や属性値と組み合わせることで、現場の運用にあった精度の高いグループを作れます。
条件付きアクセスやアプリ割り当てと組み合わせる
「任意のライセンスを持つ有効ユーザー」グループは、次のような用途で特に威力を発揮します。
- 条件付きアクセス ポリシーの対象
たとえば、「ライセンス保有ユーザーには MFA を必須にするが、共有メールボックスなどは対象外にしたい」といった要件に対応しやすくなります。 - アプリケーションのユーザー/グループ割り当て
Enterprise アプリケーション側で、このグループをベースにアクセス制御を行うことで、ライセンス付与とアプリ利用権限をほぼ自動的にリンクさせることができます。 - Microsoft 365 グループや Teams のゲートキーパー
「ライセンスを持っているユーザーだけが、特定のチームに参加できる」といった制御のベースとしても利用可能です。
このように、「任意のライセンスを持つ有効ユーザー」グループは、単なる情報整理に留まらず、ID 管理とアクセス制御をつなぐ共通コンポーネントとして設計しておくと、あとから大きく効いてきます。
運用上の注意点とベストプラクティス
最後に、動的セキュリティ グループをライセンス条件で運用する際の注意点と、ベストプラクティスをまとめます。
| 項目 | ポイント |
|---|---|
| 反映までの時間差 | ライセンス付与・削除直後は、動的グループへの反映に時間がかかる場合があります。 運用設計としては、最大 24 時間のラグがあり得る前提でフローを組むのがおすすめです。 |
| ルールの複雑化 | 条件を盛り込みすぎると、トラブルシュートが困難になります。 「ベースのルール(A/B/C)+少数の追加条件」に抑え、コメントやドキュメントで補足するようにしましょう。 |
| 命名規則 | グループ名・説明欄に、どのパターンのルールをベースにしているかを明記しておくと、あとから見直すときに楽になります。 例:説明に「BaseRule: Pattern-C (Enabled Plans Only)」と記載するなど。 |
| 検証用グループ | いきなり本番グループを切り替えず、テスト用の動的グループを別に作って挙動を確認してから、本番に適用する運用が安全です。 |
| 定期レビュー | テナントの契約プラン変更や、組織改編に伴い、想定外のユーザーが含まれるようになることがあります。 半年〜1年に一度は、メンバー構成とルール内容を棚卸しすることをおすすめします。 |
まとめ:まずはベース パターンを決めてからチューニングする
Microsoft Entra ID の動的セキュリティ グループで「任意のライセンスを持つ有効ユーザーだけを自動登録」したい場合、次のステップで考えると整理しやすくなります。
- A / B / C のどのパターンをベースにするか決める
- シンプルに始めるなら:A パターン
- まず挙動を見てみたい検証環境なら:B パターン
- 本番でしっかり絞り込みたいなら:C パターン
- 組織固有の要件(共有メールボックス命名規則、退職ユーザー属性など)を追加条件として盛り込む
- テスト用グループで十分に検証し、「メンバーシップの有効性を確認」で個別ユーザーをチェックする
- 本番グループに適用し、条件付きアクセスやアプリ割り当てに活用する
一度きちんと設計しておくと、「ライセンスを付与したら自動的に必要な権限が付く」「ライセンスを外したら自動的にアクセスも消える」といった、理想的なライフサイクル管理に近づけます。本記事の 3 パターンと応用例をベースに、自社の運用にフィットするルールを作り込んでみてください。

コメント