PowerShellでPIMロールを有効化できない原因と対処法|MfaRuleエラーとamr=mfaクレームの解説

Microsoft Entra ID(旧 Azure AD)の PIM ロールを PowerShell から有効化しようとしたところ、MfaRule が原因で RoleAssignmentRequestPolicyValidationFailed やサインイン エラー 500186 になり、手詰まりになっていないでしょうか。ポータルからは問題なく有効化できるのに、スクリプトだけが失敗する場合、多くは「条件付きアクセスや PIM ポリシーの MFA 要求」と「PowerShell で取得したトークンの中身」が噛み合っていないことが原因です。この記事では、原因の仕組みを分解しながら、PowerShell(Microsoft Graph PowerShell)で PIM ロールを安定して有効化する具体的な対処方法を詳しく解説します。

目次

PowerShell から PIM ロールを有効化しようとすると何が起きているのか

まずは、よく見られる症状を整理します。次のような状況で困っているケースが多いはずです。

状況具体的な症状・メッセージ
PowerShell から PIM ロール有効化New-MgRoleManagementDirectoryRoleAssignmentScheduleRequest を実行すると失敗 エラー: RoleAssignmentRequestPolicyValidationFailed メッセージ: The following policy rules failed: ["MfaRule"]
サインイン ログサインイン エラー コード 500186 内容: ポリシー条件により許可されない / 多要素認証が必要
ユーザーの体感PowerShell 実行時、MFA の追加確認が求められない Microsoft Authenticator に通知も来ない 同じユーザーで、Entra 管理センター(ポータル)から PIM ロールを手動有効化すると成功する

つまり、ポータルからは通るのに PowerShell からだと MfaRule でブロックされるという状態です。

MfaRule と amr=mfa クレームの関係

なぜこのような差が出るのかを理解するには、トークンのクレーム、とくに amr クレームについて知っておく必要があります。

用語意味
条件付きアクセス(CA)ユーザー/アプリ/操作の条件に応じて「MFA 必須」などを強制するポリシー。
PIM ポリシーPIM ロールの有効化時に「MFA が必須」「理由の入力必須」などを定義するロール専用ポリシー。
MfaRule「この操作は MFA 済みトークンでなければダメ」というポリシー ルール。
amr クレームAuthentication Methods References。認証方法の実績が入るクレーム。MFA を実施すると通常 amr に mfa が含まれる。
amr=mfaトークン内に「このサインインは MFA を伴った」という証跡が含まれている状態。

条件付きアクセスや PIM の MfaRule は、「現在使っているトークンに amr=mfa があるかどうか」をチェックしています。
ポータルから PIM を操作するときは、ブラウザー上でのサインインに対して自然に MFA が走るため、得られるトークンに amr=mfa が入り、問題なく MfaRule を満たせます。

ところが PowerShell から Graph に接続する場合、サインインの流れが少し違います。

根本原因:PowerShell のトークンに amr=mfa が含まれていない

今回のようなエラーの本質的な原因は、次の 2 点に集約できます。

  1. 条件付きアクセスや PIM ポリシーで「MFA が必須」になっている
  2. しかし、PowerShell で取得したアクセストークンに amr=mfa が含まれていない

ここでポイントになるのが「トークン キャッシュ」です。

  • Connect-MgGraph を一度実行すると、そのプロセスの中でアクセストークンがキャッシュされる
  • 同じプロセスで再度 Connect-MgGraph を実行すると、MFA なしで既存トークンが silently 再利用されることがある
  • その結果、MFA をしていない古いトークンで PIM API を呼びにいき、MfaRule に引っ掛かる

つまり、ユーザーの感覚としては「毎回サインイン画面が出ていたから、MFA も通っているはず」と思っていても、実際にはトークン使い回しで amr=mfa が付いていない、というギャップが生じているわけです。

ポータル操作と PowerShell 操作の違い

ブラウザーからポータル(Entra 管理センター)にアクセスした場合と、PowerShell(Graph PowerShell)でサインインした場合の違いをざっくり比較すると、次のようになります。

項目ポータル(ブラウザー)PowerShell(Graph PowerShell)
サインイン UIブラウザー内。MFA プロンプトも同じブラウザー/アプリで誘導。デバイスの既定ブラウザーでサインイン画面を開くが、トークンは PowerShell プロセス内でキャッシュ。
MFA 実施の強制条件付きアクセスが直接ブラウザー セッションに適用される。トークン キャッシュが生きていると、再認証なしでトークン再利用されることがある。
amr=mfa の付きやすさMFA プロンプト後のトークンにはほぼ確実に含まれる。MFA していない古いトークンを掴んでいると amr=mfa が付かない。
PIM ロール有効化問題なく MfaRule を満たして有効化できる。MfaRule により RoleAssignmentRequestPolicyValidationFailed になる。

解決策:Connect-MgGraph で MFA を強制するクレームを付与する

最もシンプルで汎用性が高い解決策は、サインイン時に「MFA を強制するクレーム」を要求してからコマンドを実行することです。具体的には、Connect-MgGraph に -ExtraQueryParameters を指定し、amr=mfa を要求します。

基本パターンのスクリプト例

# 既存セッションの切断(念のため)
Disconnect-MgGraph 2>$null

# MFA 実施を強制するクレームを付けてサインイン
Connect-MgGraph `
  -Scopes "RoleManagement.ReadWrite.Directory","Directory.Read.All" `
  -ContextScope Process `
  -ExtraQueryParameters @{claims='{"access_token":{"amr":{"values":["mfa"]}}}'}

# 例:PIM(ディレクトリ ロール)の自己有効化リクエスト
New-MgRoleManagementDirectoryRoleAssignmentScheduleRequest `
  -Action "SelfActivate" `
  -PrincipalId "<あなたのユーザー オブジェクトID>" `
  -RoleDefinitionId "<対象ロールの定義ID>" `
  -DirectoryScopeId "/" `
  -Justification "自動化ジョブの実行のため" `
  -ScheduleInfo @{
      startDateTime = (Get-Date).ToUniversalTime().ToString("o")
      expiration    = @{ type = "AfterDuration"; duration = "PT1H" }  # 例:1時間
    }

ここで重要なポイントは -ExtraQueryParameters に指定している claims 引数です。

@{claims='{"access_token":{"amr":{"values":["mfa"]}}}'}

このクレームにより、サインイン時に必ず MFA の追加認証が発生し、得られるアクセストークンに amr=mfa が含まれるようになります。結果として、PIM 側の MfaRule の検証を通過できるようになります。

Connect-MgGraph 実行時の挙動

修正後の Connect-MgGraph を実行すると、次のような挙動が確認できます。

  • ブラウザーが開き、通常のサインイン画面が表示される
  • サインイン後、MFA の追加認証(Authenticator 通知やコード入力など)が必ず発生する
  • 認証完了後、PowerShell 側で Account や Scopes が設定された状態で接続が完了する

これにより、PIM API を呼び出す際には、MFA 実施済みのトークンが必ず使われることになります。

-ContextScope Process を付ける意味

上記の例では、あえて -ContextScope Process を付けています。これには次のような狙いがあります。

設定意味 / 効果
-ContextScope Process ありトークンが「プロセス単位」で管理される 別の PowerShell セッション間でトークンが共有されにくくなる 古いトークンがどこからか再利用されるリスクを抑えられる
-ContextScope 指定なし環境によってはより広いスコープでキャッシュされることがある 意図せず過去のセッションのトークンを再利用してしまうことがある

特に PIM のように「MFA 実施済みトークン」であることが重要な操作では、プロセスを分けて都度クリーンな状態で接続するのがおすすめです。
「PIM 用 PowerShell」は、他と混ぜずに専用ウィンドウで実行する運用にしておくとトラブルを減らせます。

代替手段:MSAL を直接使ってクレーム付きトークンを取得する

PowerShell 7 のみを使っていたり、独自のサインイン フローを組みたい場合は、MSAL(Microsoft Authentication Library)を直接使ってトークンを取得する方法もあります。

MSAL.PS を使う例

まず、MSAL.PS モジュールをまだ入れていない場合はインストールします。

Install-Module MSAL.PS -Scope CurrentUser

次に、クレーム付きでトークンを取得し、そのトークンを使って Graph に接続します。

$tenantId = "<テナントID>"
$clientId = "<パブリッククライアントID>"   # 例:Azure AD PowerShell 用などの公開クライアント ID

# MFA を強制するクレーム
$claims = '{"access_token":{"amr":{"values":["mfa"]}}}'

# インタラクティブにトークンを取得
$token = Get-MsalToken `
  -TenantId $tenantId `
  -ClientId $clientId `
  -Interactive `
  -Scopes "https://graph.microsoft.com/.default" `
  -Claims $claims

# 取得したアクセストークンで Graph に接続
Connect-MgGraph -AccessToken $token.AccessToken

# あとは同様に PIM API を実行
New-MgRoleManagementDirectoryRoleAssignmentScheduleRequest ...

この方法でも、MSAL にクレームを渡すことで MFA を強制し、amr=mfa 付きのトークンを得ることができます。
Connect-MgGraph の動きに依存したくない場合や、複数の API(Graph 以外)を同一トークンで呼びたい場合に有効です。

トークン再利用(キャッシュ)による問題の抑止策

今回のようなトラブルを再発させないためには、「トークンキャッシュが何をしているか」を少し意識しておくと安心です。

推奨される運用パターン

シナリオ推奨パターン
PIM ロールを手動で有効化するスクリプト専用の PowerShell ウィンドウでのみ実行 開始時に Disconnect-MgGraph 2>$null を実行 Connect-MgGraph -ContextScope Process -ExtraQueryParameters @{claims=...} を必ず通す
管理者がインタラクティブに操作するバッチスクリプトの冒頭で Connect-MgGraph ... を呼び出す スクリプトの最後に Disconnect-MgGraph を実行
自動化ジョブ(非対話)基本的に「人の MFA」を前提にした自動実行は避ける サービスプリンシパル+証明書認証などを検討しつつ、条件付きアクセスの設計を見直す

特に注意したいのが、Disconnect-MgGraph を実行しても「同一プロセス」のキャッシュが残ることがあるという点です。そのため、「セッションを切り離したつもりでも、実は古いトークンを使っていた」という落とし穴にハマりがちです。
最も安全なのは、「PIM を触るときは新しく PowerShell を開き直す」というシンプルな運用ルールを徹底することです。

切り分けチェックリスト

トラブルシューティング時に確認したいポイントをチェックリスト形式でまとめます。

チェック項目確認内容
サインイン ログのエラーコードEntra ID のサインイン ログで、エラーコード 500186 が出ているか 詳細に「多要素認証が必要」「ポリシー条件によりアクセス不可」などと表示されているか
条件付きアクセスの設定対象ユーザー/アプリ/操作に対し、MFA 必須のポリシーが適用されていないか 認証強度(多要素認証/フィッシング耐性 MFA 等)のポリシーが有効になっていないか
PIM ロール設定対象ロールの PIM ポリシーで「アクティベーション時に MFA 必須」となっているか ポータル操作では問題なく有効化できるか(比較のため)
ユーザーの認証方法設定Microsoft Authenticator または許可された MFA 方法が登録されているか 認証方法ポリシーでブロックされていないか
PowerShell セッション状態新しい PowerShell ウィンドウで試しているか Connect-MgGraph 前に古いセッションを切断しているか
Graph PowerShell モジュールMicrosoft.Graph モジュールが最新に近いバージョンになっているか 古い AzureAD / AzureADPreview モジュールを前提としたスクリプトが残っていないか

上記を一通り確認し、特に「条件付きアクセス」「PIM ポリシー」「トークン取得方法」の 3 点が噛み合っているかをチェックすることで、原因の切り分けがしやすくなります。

よくある落とし穴とその回避策

Disconnect-MgGraph だけでは足りないことがある

前述の通り、Disconnect-MgGraph はセッションの切断には有効ですが、同一プロセス内のトークンキャッシュを完全に消さないことがあります。
そのため、次のような運用が安全です。

  • PIM 用スクリプトは「新しい PowerShell ウィンドウ」で起動する
  • スクリプト冒頭で Disconnect-MgGraph 2>$null を呼ぶ
  • Connect-MgGraph -ContextScope Process -ExtraQueryParameters @{claims=...} を必ず通す

旧 AzureAD モジュールを使い続けている

すでに非推奨となった AzureAD / AzureADPreview モジュールは、今後の更新やサポートが期待できません。
PIM を含む管理系操作は、Microsoft Graph PowerShell と MSAL ベースの認証を前提に設計し直すことをおすすめします。

  • 新規スクリプトは必ず Microsoft.Graph.* モジュールを使用
  • 既存スクリプトも段階的に Graph API ベースへ移行
  • MFA 必須の操作は、今回紹介したようなクレーム付きサインインに集約

認証強度ポリシーと amr=mfa のギャップ

条件付きアクセスの「認証強度(Authentication Strength)」を使っている環境では、amr=mfa だけでは不十分なことがあります。
例えば、「フィッシング耐性 MFA」が必須になっている場合、単なるスマホ通知型 MFA では条件を満たせません。

このようなケースでは、

  • 要求されている認証強度の内容を確認する
  • ユーザーがその強度を満たせる認証方法を登録しているか確認する
  • テスト目的で一時的にポリシーを緩め、問題の切り分けを行う

といったステップを踏むことで、「MFA の種類が足りない」のか「トークンに証跡が載っていないだけなのか」を明確にできます。

実運用を意識した PIM ロール有効化スクリプト例

最後に、実運用で使いやすいように少し整理したサンプル スクリプトを紹介します。
特定の PIM ロールを自己有効化し、一定時間だけアクティブにするシナリオを想定しています。

param(
    [Parameter(Mandatory)]
    [string]$RoleDefinitionId,          # 対象ロールの定義 ID

    [Parameter(Mandatory)]
    [string]$Justification,            # 理由(監査ログに残る)

    [string]$Duration = "PT1H"         # 有効化時間 (ISO 8601 形式, 例: PT1H)
)

# ===== 共通設定 =====
$scopes = @(
    "RoleManagement.ReadWrite.Directory",
    "Directory.Read.All"
)

# ===== サインイン(MFA を強制) =====
Write-Host "Microsoft Graph にサインインしています(MFA 必須)..."

Disconnect-MgGraph 2>$null

$claims = '{"access_token":{"amr":{"values":["mfa"]}}}'

Connect-MgGraph `
    -Scopes $scopes `
    -ContextScope Process `
    -ExtraQueryParameters @{ claims = $claims }

# ===== ユーザー情報の取得 =====
$ctx = Get-MgContext
$me  = Get-MgUser -UserId $ctx.Account

Write-Host "サインイン ユーザー:" $me.DisplayName "("$me.Id")"

# ===== PIM ロールの自己有効化要求 =====
$start = (Get-Date).ToUniversalTime().ToString("o")

Write-Host "PIM ロールを有効化しています..."

$request = New-MgRoleManagementDirectoryRoleAssignmentScheduleRequest `
    -Action "SelfActivate" `
    -PrincipalId $me.Id `
    -RoleDefinitionId $RoleDefinitionId `
    -DirectoryScopeId "/" `
    -Justification $Justification `
    -ScheduleInfo @{
        startDateTime = $start
        expiration    = @{
            type     = "AfterDuration"
            duration = $Duration
        }
    }

Write-Host "要求 ID:" $request.Id
Write-Host "状態   :" $request.Status

if ($request.Status -ne "Provisioned" -and $request.Status -ne "PendingApproval") {
    Write-Warning "ロール有効化要求の状態が想定外です。サインイン ログおよび PIM 画面で詳細を確認してください。"
}

このテンプレートをベースに、

  • ロール定義 ID を環境ごとに管理する
  • ジョブ名やチケット番号を $Justification に含める
  • 有効化時間($Duration)をジョブ内容に応じて変更する

など、自社の運用に合わせたカスタマイズを行うことで、「毎回ポータルを開かなくても、安全に PIM ロールを有効化できる仕組み」を作ることができます。

まとめ

  • PowerShell(Microsoft Graph PowerShell)から PIM ロールの有効化を行う際に、MfaRule で RoleAssignmentRequestPolicyValidationFailed やサインイン エラー 500186 が発生する主な原因は、トークンに amr=mfa が含まれていないことです。
  • 条件付きアクセスや PIM ポリシーで MFA が必須のとき、サインイン時に MFA を強制するクレームを要求することで問題を回避できます。
  • Connect-MgGraph -ExtraQueryParameters @{claims='{"access_token":{"amr":{"values":["mfa"]}}}'} を利用することで、MFA 実施済みトークンを確実に取得できます。
  • -ContextScope Process を活用し、新しい PowerShell ウィンドウで実行することで、古いトークンの再利用によるトラブルを防止できます。
  • 必要に応じて MSAL を直接利用する方法や、認証強度ポリシーとの整合も確認し、ポータルと同等レベルのセキュリティを保ちながら自動化・スクリプト化を進めましょう。

「ポータルでは動くのにスクリプトだけ失敗する」という現象は、仕組みを理解してしまえば再現性高くコントロールできます。
今回紹介した方法で、PowerShell からの PIM ロール有効化を安全かつ安定した形で運用してみてください。

この記事を書いた人

実務の現場で詰まりがちなポイントを地図にするITブログ「IT trip」を運営。Windows/Office(Teams・Excel)からSQL、サーバ運用、ガジェットまで、再現性のある手順と“なぜそうなるか”を丁寧に解説します。読んだらすぐ試せること、そして迷った人の次の一歩が見えることを大切にしています。

コメント

コメントする

目次