Azure PIM の永続アクティブ割り当てを Azure Policy で禁止してみた

Azure PIM の永続アクティブ割り当てを Azure Policy で禁止してみた

2026.03.31

こんにちは、クラウド事業本部コンサルティング部のいたくらです。

はじめに

Azure PIM(Privileged Identity Management)では、ロールの割り当てに有効期限を設定し、永続的なアクティブ割り当てを制限できます。
しかし、PIM のロール設定はロールごと・スコープごとに個別設定が必要で、かつ上位スコープの設定が継承されません。管理グループ・サブスクリプション・リソースグループとスコープが増えるほど、設定漏れのリスクが高まります。

本記事では、Azure Policyを使って「永続的なアクティブ割り当て」を一括で禁止する方法を紹介します。
Azure Policyは管理グループやサブスクリプションに割り当てると配下に継承されるため、PIMロール設定の継承問題を解消できます。実際にサブスクリプションスコープで検証した結果もあわせて紹介します。

三行まとめ

  • Azure Policy で roleAssignmentScheduleRequestsNoExpiration を拒否すれば、永続的なアクティブ割り当てを一括禁止できる
  • PIM ロール設定はスコープ間で継承されないが、Azure Policy は管理グループから配下に継承されるため設定漏れを防げる
  • ServicePrincipal は JIT アクティベーションができないため、principalType エイリアスで除外する

背景:MCSB PA-2 の推奨事項

Microsoft Cloud Security Benchmark(MCSB)の PA-2 では、常設特権(standing privileges)の作成を避け、JIT メカニズムを使用することを推奨しています。

Instead of creating standing privileges, use just-in-time (JIT) mechanism to assign privileged access to the different resource tiers.

引用:MCSB PA-2: Avoid standing access for user accounts and permissions

具体的には、Azure AD PIM(Privileged Identity Management)を使用して、Azure リソースへの JIT 特権アクセスを有効にすることが推奨されています。

制御手段の比較:PIMロール設定とAzure Policy

Azure リソースロールの永続的なアクティブ割り当てを禁止する手段は 2 つあります。

観点 PIM ロール設定 Azure Policy
永続アクティブ禁止 できる できる
期間の上限強制 できる できない
承認要件・MFA・通知 できる できない
適用範囲 ロールごと・スコープごとに個別設定 管理グループに割り当てれば配下に継承
運用負荷 ロール数 × スコープ数の設定が必要 1 つのポリシーで全ロールをカバー可能
スコープ間の継承 継承されない 継承される

PIM ロール設定は承認フローや MFA の設定など細かな制御ができますが、スコープごとに個別設定が必要です。一方、Azure Policy は管理グループに 1 つ割り当てるだけで配下すべてに適用されます。

推奨する使い分け

  • 永続アクティブ禁止(ガードレール) → Azure Policy で一括制御
  • 承認フロー・MFA 等が必要な高権限ロール → PIM ロール設定を個別に追加設定

Azure Policy の実装

ポリシー定義

scheduleInfo.expiration.type エイリアスを使用して、NoExpiration(無期限)のアクティブ割り当てリクエストを拒否するカスタムポリシーを作成します。

{
  "if": {
    "allOf": [
      {
        "field": "type",
        "equals": "Microsoft.Authorization/roleAssignmentScheduleRequests"
      },
      {
        "field": "Microsoft.Authorization/roleAssignmentScheduleRequests/requestType",
        "in": [
          "AdminAssign",
          "AdminExtend",
          "AdminRenew"
        ]
      },
      {
        "field": "Microsoft.Authorization/roleAssignmentScheduleRequests/scheduleInfo.expiration.type",
        "equals": "NoExpiration"
      },
      {
        "field": "Microsoft.Authorization/roleAssignmentScheduleRequests/principalType",
        "notEquals": "ServicePrincipal"
      }
    ]
  },
  "then": {
    "effect": "deny"
  }
}

各条件の意味は以下の通りです。

条件 説明
type = roleAssignmentScheduleRequests PIM 経由のロール割り当てリクエストを対象とする
requestType in AdminAssign, AdminExtend, AdminRenew 管理者による割り当て・延長・更新を対象とする
scheduleInfo.expiration.type = NoExpiration 無期限の割り当てリクエストを検出する
principalType != ServicePrincipal ServicePrincipal は JIT アクティベーションができないため除外する

NoExpiration を拒否すると、AfterDuration(期間指定)または AfterDateTime(日時指定)のいずれかが必須になります。つまり、このポリシー 1 つで「期限付き必須」を暗黙的に強制できます。

ポリシー定義の作成

Azure CLI で作成する場合、上記の JSON を例えば policy-rule.json として保存し、以下のコマンドを実行します。

az policy definition create \
  --name "deny-permanent-active-assignment" \
  --display-name "Deny permanent active role assignments" \
  --description "Denies role assignment schedule requests with NoExpiration. Service Principals are excluded because they cannot use JIT activation." \
  --rules policy-rule.json \
  --mode All \
  --subscription "<サブスクリプションID>"

キャプチャ1:Policy定義の確認.png

ポリシーの割り当て

作成したポリシーをサブスクリプションまたは管理グループに割り当てます。
今回はサブスクリプションに割り当てます。

az policy assignment create \
  --name "deny-permanent-active-assignment" \
  --display-name "Deny permanent active role assignments" \
  --policy "/subscriptions/<サブスクリプションID>/providers/Microsoft.Authorization/policyDefinitions/deny-permanent-active-assignment" \
  --scope "/subscriptions/<サブスクリプションID>" \
  --enforcement-mode "Default"

実運用では管理グループスコープに割り当てることで、配下のすべてのサブスクリプション・リソースグループに一括適用できます。

キャプチャ2:Policy割り当ての確認.png

動作確認

テスト 1:永続アクティブ割り当て → 拒否されること

PIM 画面から、閲覧者(Reader)ロールを「アクティブ」かつ「永続的にアクティブ」で割り当てを試みます。

テスト7.png

テスト8.png

テスト9.png

Azure Policy によって拒否され、以下のエラーメッセージが表示されました。

'サブスクリプション' でロール '閲覧者' へのメンバー xxxx のロールの割り…
リソース 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx' はポリシーによって許可されませんでした。ポリシー識別子: '[{"policyAssignment":{"name":"Deny permanent active role assignments", ...}]'

Azure CLI で直接 PIM API を呼び出した場合も同様に拒否されます。

az rest --method PUT \
  --url "https://management.azure.com/subscriptions/<サブスクリプションID>/providers/Microsoft.Authorization/roleAssignmentScheduleRequests/<リクエストID>?api-version=2020-10-01" \
  --body '{
    "properties": {
      "principalId": "<ユーザーオブジェクトID>",
      "roleDefinitionId": "/subscriptions/<サブスクリプションID>/providers/Microsoft.Authorization/roleDefinitions/acdd72a7-3385-48ef-bd42-f606fba81ae7",
      "requestType": "AdminAssign",
      "scheduleInfo": {
        "startDateTime": "2026-03-30T14:00:00Z",
        "expiration": {
          "type": "NoExpiration"
        }
      }
    }
  }'
ERROR: Forbidden({"error":{"code":"RequestDisallowedByPolicy", ...}})

エラーレスポンスの evaluatedExpressions を見ると、ポリシー定義の allOf で指定した 4 条件すべてが True と評価されたため、Deny が発動していることがわかります。

エラーレスポンスの詳細(クリックで展開)
{
  "error": {
    "code": "RequestDisallowedByPolicy",
    "target": "<リクエストID>",
    "message": "Resource '<リクエストID>' was disallowed by policy.",
    "additionalInfo": [
      {
        "type": "PolicyViolation",
        "info": {
          "evaluationDetails": {
            "evaluatedExpressions": [
              {
                "result": "True",
                "expression": "type",
                "expressionValue": "Microsoft.Authorization/roleAssignmentScheduleRequests",
                "targetValue": "Microsoft.Authorization/roleAssignmentScheduleRequests",
                "operator": "Equals"
              },
              {
                "result": "True",
                "expression": "Microsoft.Authorization/roleAssignmentScheduleRequests/requestType",
                "expressionValue": "AdminAssign",
                "targetValue": ["AdminAssign", "AdminExtend", "AdminRenew"],
                "operator": "In"
              },
              {
                "result": "True",
                "expression": "Microsoft.Authorization/roleAssignmentScheduleRequests/scheduleInfo.expiration.type",
                "expressionValue": "NoExpiration",
                "targetValue": "NoExpiration",
                "operator": "Equals"
              },
              {
                "result": "True",
                "expression": "Microsoft.Authorization/roleAssignmentScheduleRequests/principalType",
                "targetValue": "ServicePrincipal",
                "operator": "NotEquals"
              }
            ]
          },
          "policyDefinitionId": "/subscriptions/<サブスクリプションID>/providers/Microsoft.Authorization/policyDefinitions/deny-permanent-active-assignment",
          "policyDefinitionName": "deny-permanent-active-assignment",
          "policyDefinitionDisplayName": "Deny permanent active role assignments",
          "policyDefinitionEffect": "deny"
        }
      }
    ]
  }
}

テスト 2:期限付きアクティブ割り当て → 成功すること

同じ PIM 画面で、「永続的にアクティブ」のチェックを外し、期限付き(例:1 年間)で割り当てを実行します。

テスト10.png

テスト11.png

期限付きの割り当ては Azure Policy に拒否されず、正常に作成されました。

注意点

IAM ブレードからの割り当てはブロックされない

Azure Portal の IAM ブレード(サブスクリプション → アクセス制御 (IAM) → ロールの割り当ての追加)から作成した割り当ては、Azure Policy でブロックされませんでした。

テスト1.png

操作経路 使用される API Azure Policy による制御
PIM 画面からの割り当て roleAssignmentScheduleRequests ブロックされる
IAM ブレードからの割り当て roleAssignments(クラシック) ブロックされない
Azure CLI で PIM API を呼び出し roleAssignmentScheduleRequests ブロックされる

IAM ブレードはクラシックな roleAssignments API を使用しており、今回の Azure Policy が対象とする roleAssignmentScheduleRequests とは異なるリソースタイプです。そのため、Azure Policy だけでは完全な制御にはなりません。

PIM ロール設定の「永続するアクティブな割り当てを許可する」のチェックを外す設定と併用することで、両方の経路をカバーできます。

制御対象 PIM ロール設定 Azure Policy
PIM 経由の割り当て(roleAssignmentScheduleRequests 制御可能 制御可能
クラシック API の割り当て(roleAssignments 制御可能 制御不可
スコープ間の継承 継承されない 継承される

つまり、Azure Policy をガードレールとして導入しつつ、PIM ロール設定も併用するのが最も堅牢な構成です。

ServicePrincipal の除外

ServicePrincipal は対話的なログインができないため、PIM の JIT アクティベーションを利用できません。そのため、ポリシー定義で principalType エイリアスを使って除外しています。

Azure Policy で使用できるエイリアスは az provider show コマンドで調べられます。例えば principalType が使えるかどうかは以下で確認できます。

az provider show --namespace Microsoft.Authorization \
  --resource-type roleAssignmentScheduleRequests \
  --query "resourceTypes[0].aliases[?contains(name, 'principalType')]"

緊急時のアクセス経路

Azure リソースロールには専用の緊急アクセスアカウントの概念はありません。緊急時のアクセスは Entra ID 側の仕組みで確保されます。

  1. Entra ID の Global Administrator(緊急アクセスアカウント、永続アクティブ)でサインイン
  2. Entra 管理センターで「Access management for Azure resources」を有効化
  3. ルートスコープ(/)で User Access Administrator に自動昇格

このため、Azure リソースロールについては全ロールで永続アクティブを禁止しても、緊急時のアクセス経路には影響しません。

ライセンス要件

PIM の利用には以下のいずれかのライセンスが必要です。

  • Microsoft Entra ID P2
  • Microsoft Entra ID Governance

まとめ

  • Azure Policy で roleAssignmentScheduleRequestsNoExpiration を拒否することで、PIM 経由の永続的なアクティブ割り当てを一括禁止できる
  • PIM ロール設定はスコープごとに個別設定が必要で継承されないが、Azure Policy は管理グループから配下に継承されるため設定漏れのリスクを低減できる
  • ただし、IAM ブレード(クラシック API)からの割り当てはブロックされないため、PIM ロール設定との併用が推奨される
  • ServicePrincipal は principalType エイリアスで除外する

Azure Policy だけでは IAM ブレードからのクラシック API 経由の割り当てをブロックできないことには少し驚きました。
Azure Policy と PIM ロール設定はそれぞれカバー範囲が異なるため、どちらか一方ではなく併用することが重要だと感じました。

この記事がどなたかのお役に立てれば幸いです。
以上、クラウド事業本部コンサルティング部のいたくら(@itkr2305)でした!

参考ドキュメント

この記事をシェアする

FacebookHatena blogX

関連記事