Azure Policyのカスタムポリシーとイニシアチブ|組み込みで足りない時の一歩上【自動修復まで】

Azure

Azure Policyを触りはじめて最初にやるのは、たいてい組み込み(ビルトイン)ポリシーの割り当てです。「タグを必須にする」「特定リージョン以外を禁止する」あたりは、Microsoftが用意してくれた定義をそのまま割り当てるだけで動きます。ところが実務を進めると、必ずこう思う瞬間が来ます——「あれ、うちがやりたいこと、組み込みに無いぞ?」。

私も同じでした。組み込みで7割はカバーできるのですが、残りの3割、たとえば「この命名規則に従っていないリソースを弾きたい」といった自社ルールになると、途端に用意された定義が見つからなくなる。そこで登場するのがカスタムポリシーイニシアチブ(ポリシーセット)です。

「JSONで自分でポリシーを書くって聞くとハードル高そう…if/thenって何を書けばいいの?」

この記事では、組み込みで足りなくなったときの「一歩上」として、カスタムポリシー定義の作り方パラメーターで1つの定義を使い回す方法イニシアチブで複数をまとめて割り当てる方法、そしてDeployIfNotExists / Modifyによる自動修復(Remediation)までを、公式Learnの内容を初心者向けに噛み砕いて解説します。読み終わるころには、policyRuleのJSON構造を怖がらずに読めるようになっているはずです。

なお、そもそもAzure Policyが何者で、RBACと何が違うのか——という全体像があやふやな方は、先に Azure Policyとは?RBACとの違い・効果・運用の全体像を図解 に目を通しておくと、この記事の位置づけがはっきりします。本記事はその中の「カスタムポリシー・イニシアチブ」を深掘りする子記事です。組み込みポリシーの割り当て手順そのものは、姉妹記事の組み込みポリシーの割り当てに譲ります。

カスタムポリシー定義を作る:policyRuleのif/thenを読み解く

カスタムポリシーと聞くと身構えますが、正体は1つのJSONファイルです。そしてそのJSONの心臓部が policyRule、中でも ifthen の2つだけ。ここさえ分かれば、あとは応用です。

考え方は「もし(if)こういう条件のリソースなら、そのとき(then)こうする」という一文にすぎません。日常語に置き換えるとこうです。

  • if:どんなリソースを狙い撃ちするか(=評価する条件)
  • then:条件に当てはまったら何をするか(=効果 / effect)

たとえば「ストレージアカウントで、env というタグが付いていないものは作成を禁止する」というルールをJSONで書くと、こうなります。

"policyRule": {
  "if": {
    "allOf": [
      {
        "field": "type",
        "equals": "Microsoft.Storage/storageAccounts"
      },
      {
        "field": "tags['env']",
        "exists": "false"
      }
    ]
  },
  "then": {
    "effect": "deny"
  }
}

読み下すとこうです。if の中の allOf は「すべての条件を満たしたら」という AND の意味(どれか1つでよければ anyOf)。1つ目の条件で「リソースの種類がストレージアカウント」に絞り込み、2つ目で「env タグが存在しない(exists が false)」ものを狙う。両方に当てはまったら theneffect が発動して deny(作成を拒否)します。

ここで初心者がつまずくポイントを2つ潰しておきます。1つ目、field に書ける値。typelocation のような共通プロパティのほか、tags['env'] のようにタグを名指しでき、さらに各リソース固有のプロパティを指すエイリアス(alias)も指定できます。「このプロパティを条件にしたいけど、なんて書くの?」となったら、ポータルの定義エディターやAzure CLIで使えるエイリアス一覧を調べるのが近道です。

2つ目、effect の種類。よく使うのは audit(違反しても止めないがログに残す=まず様子見に最適)、deny(違反する作成・変更を拒否)、そして後半で扱う deployIfNotExistsmodify(自動修復系)です。いきなり deny にすると本番デプロイが止まって事故になるので、私は必ず audit で一度流して、非準拠がどれだけ出るか見てから deny に切り替えています。

定義を「作る」と「割り当てる」は別ステップ

ここも最初に混乱しやすい所です。カスタムポリシーは「定義を作る」→「割り当てる」の2段構え。定義を作っただけでは何も起きません。定義は「ルールの台本」を登録しただけで、実際に効かせるには対象スコープ(管理グループ/サブスクリプション/リソースグループ)へ割り当てて初めて評価が走ります。

ポータルなら「ポリシー」→「定義」→「+ポリシー定義」で、上のJSONの policyRule を含む定義を貼り付けて保存。CLI派なら az policy definition create にJSONファイルを渡す形です。作った定義はカスタム定義の一覧に並び、そこから「割り当て」ボタンで対象スコープに適用します。詳しい手順は公式の カスタムポリシー定義の作成チュートリアル が一次情報として正確です。この記事はその「読み方」を補う位置づけと思ってください。

パラメーターで1つの定義を使い回す

さて、さっきの定義を作ったあと、こう思いませんか。「必須にしたいタグ名が env じゃなくて costCenter のときは、また別の定義を作るの?」と。毎回コピペで定義を量産するのは、あとで手に負えなくなります。ここで効いてくるのがパラメーターです。

パラメーターは、定義の中で「ここは割り当てるときに差し替える穴」を作っておく仕組みです。関数の引数と同じ発想ですね。定義本体は1つのまま、割り当てのたびにタグ名や許可リージョンといった値だけを外から渡すことで、同じ定義を何通りにも使い回せます。

定義に parameters を持たせ、policyRule側では [parameters('tagName')] のように参照します。イメージはこうです。

"parameters": {
  "tagName": {
    "type": "String",
    "metadata": {
      "displayName": "必須にするタグ名",
      "description": "このタグが無いリソースを拒否します"
    }
  }
},
"policyRule": {
  "if": {
    "field": "[concat('tags[', parameters('tagName'), ']')]",
    "exists": "false"
  },
  "then": { "effect": "deny" }
}

こうしておくと、割り当てA では tagName = env、割り当てB では tagName = costCenter と、同じ定義から中身の違う運用ルールを2本生やせるわけです。定義を1つに保てるので、ロジックを直したいときも1箇所直せば全割り当てに効きます。メンテナンスのラクさが段違いです。

「定義=設計図、パラメーター=差し込み口、割り当て=実際に設置」。この3語の関係を覚えるとグッと楽になります。

パラメーターには型(String / Array / Boolean など)や、選べる値を制限する allowedValues、既定値の defaultValue も指定できます。たとえば「許可するリージョン」を Array 型パラメーターにしておけば、割り当て時に ["japaneast","japanwest"] のようにリストで渡せる。組み込みの「許可された場所」ポリシーがまさにこの作りで、中身を覗くと自分のカスタム定義の良いお手本になります。パラメーター構造の細かい仕様は 公式のパラメーター定義構造のドキュメント にまとまっています。

イニシアチブ(ポリシーセット)で複数をまとめて割り当てる

ポリシーが増えてくると、次の悩みが出ます。「タグ必須」「リージョン制限」「暗号化必須」…と1本ずつ割り当てていくと、割り当てが10個も20個も並んで管理しきれない。しかも新しいサブスクリプションを作るたびに、その10個を1つずつ付け直すのは苦行です。

ここで使うのがイニシアチブ(ポリシーセット)です。ひとことで言えば、複数のポリシー定義を1つの箱にまとめたもの。CDのアルバムを思い浮かべると分かりやすいです。ポリシー定義が1曲1曲だとすれば、イニシアチブは「関連する曲を束ねたアルバム」。アルバムを1枚渡せば、収録曲がまとめて付いてくる感覚です。

たとえば「自社標準ガバナンス」というイニシアチブに、タグ必須・リージョン制限・診断ログ有効化などをまとめて入れておけば、新しいサブスクリプションにはこのイニシアチブ1つを割り当てるだけで標準ルール一式が効きます。1本ずつ付ける手間も、付け忘れの事故も消えます。実際、Microsoftが用意する「Azure Security Benchmark」や各種コンプライアンス標準(ISO 27001 など)も、この大量の組み込みポリシーを束ねた巨大なイニシアチブとして提供されています。

イニシアチブを作るときのポイントは、収録する各ポリシーのパラメーターを、イニシアチブ側のパラメーターにひも付けられることです。たとえば「許可リージョン」というパラメーターをイニシアチブに1つ用意し、中の複数の定義がそれを共有して参照する、という設計ができる。割り当てる人はイニシアチブのパラメーターを1回埋めるだけで済み、収録ポリシー全体に反映されます。この構造の正確な仕様は イニシアチブ定義構造の公式ドキュメント を参照してください。

運用のコツを1つ。割り当ては、できるだけ個別ポリシーではなくイニシアチブ単位でやるのがおすすめです。あとから「ルールをもう1つ足したい」となったとき、イニシアチブに定義を1個追加すれば、そのイニシアチブを割り当てている全スコープに自動で行き渡ります。バラバラに割り当てていると、この一括更新の恩恵が受けられません。RBACで「権限は個人でなくグループに付ける」のと同じ発想ですね。

DeployIfNotExists / Modifyで自動修復(Remediation)する

ここまでの auditdeny は、あくまで「見張る・止める」効果でした。でも運用していると、こう思いませんか。「すでに作られてしまった非準拠リソースを、いちいち手で直すのが面倒」。100個のリソースにタグが抜けていたら、100回ポチポチ…考えたくないですよね。

これを解決するのが自動修復(Remediation)で、担当する効果が deployIfNotExists(略してDINE)と modify の2つです。

  • modify:リソースのプロパティやタグを追加・変更・削除する。「タグが無ければ規定値を付ける」といった軽い修復向き。
  • deployIfNotExists(DINE):条件を満たす関連リソースが無ければ、ARMテンプレートで自動デプロイする。「診断設定が無ければLog Analyticsへの診断を自動で作る」といった重めの修復向き。

ここで一番大事な注意点を、太字で強調しておきます。DeployIfNotExists と Modify を使うには、割り当てにマネージドID(システム割り当てID)が必要です。理由は単純で、これらの効果は「Azure Policyがあなたの代わりにリソースを作ったり書き換えたりする」から。そのためにPolicy自身が動くための身分証(=マネージドID)と、そのIDへの適切なロール(たとえばModifyなら対象を書き換えられる貢献者相当のロール)が要ります。

幸い、ポータルからこれらの効果を持つ定義/イニシアチブを割り当てると、マネージドIDの作成と必要ロールの付与を、割り当てウィザードがほぼ自動でやってくれます。ここでロールが足りないと修復が「失敗」で止まるので、自動修復がうまく動かないときは、まず割り当てのマネージドIDに正しいロールが付いているかを真っ先に疑ってください。私が最初にハマったのもこれで、原因はIDへのロール付与漏れでした。

「既存リソース」は修復タスクで明示的に直す

もう1つ勘違いしやすい点。deployIfNotExists / modify を割り当てても、それだけでは「既に存在する」非準拠リソースは自動では直りません。これらの効果が自然に発動するのは、原則これから作成・更新されるリソースに対してです。すでにある非準拠リソースをまとめて直すには、「修復タスク(Remediation task)」を手動またはスクリプトで起動する必要があります。

ポータルなら「ポリシー」→「修復」から、対象の割り当てを選んで修復タスクを作成。CLIなら az policy remediation create です。これを走らせると、PolicyのマネージドIDが既存の非準拠リソースを洗い出し、順番に修復をかけていきます。「割り当てたのに古いリソースが直らない」と焦ったら、たいていこの修復タスクの起動を忘れているだけです。手順の詳細は リソースの修復に関する公式ドキュメント が正確です。

まとめ

この記事では、組み込みで足りなくなったときの「一歩上」として、カスタムポリシーとイニシアチブ、そして自動修復を、実務でつまずく順に見てきました。要点を振り返っておきます。

  • カスタムポリシー:正体は1つのJSON。心臓部は policyRuleif(狙う条件)と then(効果)。まず audit で流し、確認できたら deny に切り替えると安全。
  • パラメーター:定義に「差し込み口」を作り、割り当て時にタグ名やリージョンを差し替える。1つの定義を値違いで使い回せる。
  • イニシアチブ:複数の定義を1つの箱にまとめて一括割り当て。割り当てはイニシアチブ単位にすると更新がラク。
  • 自動修復(DINE / Modify):割り当てにマネージドIDと適切なロールが必須。既存の非準拠リソースは修復タスクを起動して初めて直る。

ここまで来れば、「組み込みに無いから諦める」ということはもう無くなります。自社のルールをコードで表現し、まとめて配り、ズレたら自動で戻す——ガバナンスを”仕組み”で回す入口に立てたはずです。あとは実際の運用設計(どのスコープに何を割り当てるか、除外はどう扱うか)ですが、そちらは運用と設計の記事で扱います。

あわせて読みたい:

タイトルとURLをコピーしました