Entra ID 自動化 #4 条件付きアクセス — ポリシーをコードで管理する
アカウントとグループが「誰が何に属するか」だとすれば、条件付きアクセス(Conditional Access)はそのログインを今この状況で許可するのかを決める層です。P1 ライセンスの機能で、実質的に組織のゼロトラストポリシーが実装される場所です。今回は概念の整理とともに、ポリシーをポータルのクリックではなくコードで管理する方法を扱います。
構造 — ポリシーは if-then 文です #
条件付きアクセスポリシーひとつは 2 つの部分でできています。
- 割り当て(if): 誰が(ユーザー・グループ)、何に(アプリ)、どんな条件で(場所、デバイスの状態、プラットフォーム、サインインリスク)
- 制御(then): ブロックするか、条件付きで許可するか(MFA 要求、準拠デバイス要求、セッション制限)
ログインのたびに該当するすべてのポリシーが評価され、適用対象のポリシーの要件をすべて満たして初めてアクセスが許可されます。ポリシー A が MFA を、ポリシー B が準拠デバイスを要求するなら、両方を満たす必要があります。この「すべて AND」の特性のため、ポリシーが増えるほど相互作用が複雑になり、だからこそ後述のテスト手順が重要になります。
典型的な基本ポリシーセットはこうです。全ユーザーに MFA 要求(レガシー認証のブロックを含む)、管理者にフィッシング耐性のある認証を要求、未登録デバイスからのダウンロード制限。なお、Microsoft がテナントにマネージドポリシー(Microsoft-managed policies)をレポート専用状態で自動配布し、一定期間(最低 45 日)後に有効化する仕組みも動いているので、自分のテナントにどのマネージドポリシーが来ているかの把握も管理業務の一部です。
Graph API でポリシーを扱う #
ポリシーは Graph の /identity/conditionalAccess/policies リソースです。照会、作成、更新、削除のすべてが API でできます。
GET https://graph.microsoft.com/v1.0/identity/conditionalAccess/policies
POST https://graph.microsoft.com/v1.0/identity/conditionalAccess/policies
Content-Type: application/json
{
"displayName": "CA002: 全ユーザーに MFA を要求",
"state": "enabledForReportingButNotEnforced",
"conditions": {
"users": {
"includeUsers": ["All"],
"excludeUsers": ["<緊急アカウントの objectId>"]
},
"applications": { "includeApplications": ["All"] }
},
"grantControls": {
"operator": "OR",
"builtInControls": ["mfa"]
}
}state の値が 3 つあることが核心です。enabled、disabled、そして enabledForReportingButNotEnforced(レポート専用)。ポリシー運用の安全装置は、この 3 つ目の状態に入っています。
policy-as-code — クリックの代わりにレビューとデプロイ #
ポリシーを API で扱えるということは、コードで管理できるということです。実務の構成はこうなります。
- ポリシー定義を JSON ファイルとしてリポジトリに置きます。 ポリシー 1 つがファイル 1 つ、命名規則(番号 + 目的)をファイル名と displayName の両方に適用します。
- 変更は PR で行きます。「ゲストの MFA 例外を追加」のような変更が diff として見え、セキュリティ担当者のレビューを通ります。ポータルのクリックにはない監査可能性です。
- CI がデプロイします。 マージされるとパイプラインが Graph API で実際のテナントに反映します。Terraform の Entra プロバイダーで同じ流れを作ることもできます。
- ドリフトを監視します。 誰かがポータルで直接直したポリシーとリポジトリの定義の差分を定期的に比較して通知します。コードが真実であり続けるには、ドリフト検知が必ず付いてこなければなりません。
この構成の価値は監査とロールバックです。「このポリシーはいつなぜ変わったのか」が git の履歴に残り、誤った変更は revert ひとつで戻せます。
レポート専用 — ポリシー事故を防ぐ唯一の手順 #
条件付きアクセスの事故は波及が大きいです。条件を誤れば全社員がログインできなくなります。だから新しいポリシーと大きな変更には固定の手順があります。
- レポート専用状態でデプロイします。 ポリシーは評価はされるものの強制されず、サインインログに「このポリシーが有効だったらどうなっていたか」が記録されます。
- 影響を確認します。 サインインログのレポート専用タブとインサイトのワークブックで、意図した対象に意図した結果が出ているか、意図しないブロックがないかを見ます。What If ツール(および評価 API)で特定のユーザー・シナリオの結果をシミュレーションすることもできます。
- 期間を置いて観察してから enabled に切り替えます。 トラフィックパターンの違う曜日まで含めて見るのが安全です。
policy-as-code と組み合わせれば、「新規ポリシーの PR は state がレポート専用でなければマージ不可、enabled への切り替えは別 PR」というルールをパイプラインで強制できます。
緊急アカウント — すべてのポリシーの例外 #
緊急アクセスアカウント(break-glass account)は、条件付きアクセスの事故時にロックアウトされずに入れる最後の管理者アカウントです。原則は明確です。
- クラウド専用アカウントを 2 つ以上、強力な資格情報(可能ならフィッシング耐性のある方式)で作り、物理的に安全に保管します。
- すべての条件付きアクセスポリシーの excludeUsers に入れます。 policy-as-code なら、この除外がすべてのポリシーファイルに入っているかを CI のテストで検査できます。コード管理のもうひとつの利点です。
- このアカウントのログインには即時アラートを掛けます。使われないのが正常なアカウントなので、ログインそのものが事件です。
もうひとつ、ミス防止の装置として削除の復元を知っておくとよいです。条件付きアクセスポリシーは削除後 30 日間復元可能なソフトデリートです。自動化スクリプトが誤ってポリシーを消しても、元に戻せる窓があります。
まとめ #
- 条件付きアクセスはログインのたびに評価される if-then ポリシーの集合で、適用されるポリシーの要件をすべて満たして初めてアクセスが許可されます。
- ポリシーは
/identity/conditionalAccess/policiesで完全に CRUD できるので、JSON + PR レビュー + CI デプロイ + ドリフト検知の policy-as-code で管理できます。 - 新しいポリシーは必ずレポート専用でデプロイし、ログで影響を確認してから有効化します。この手順はパイプラインのルールとして強制できます。
- 緊急アカウントはすべてのポリシーから除外し、その除外を CI で検査し、ログイン時に即時アラートを掛けます。
- ポリシーの削除は 30 日のソフトデリートで復元の窓があります。次回は最終回、常時管理者権限をなくす PIM と監査の自動化です。