👮‍♂️

Azure Policy について

2024/07/01に公開

はじめに

Azure Policy を利用することで Azure のリソースに対して一貫した管理とガバナンスを実現することが可能となります。本記事では Azure Policy について簡単に纏めたいと思います。詳細については以下の公式Docsをご参照ください

Azure Policy とは?

Azure Policyは、Azureリソースの構成とコンプライアンスを管理するためのサービスです。具体的には、組織のルールや基準に基づいてリソースの状態を評価し、ポリシーに従っていないリソースを特定・修正する手段を提供するというようなイメージです

ポリシーの例

  • タグ付けを強制する
  • 仮想マシンは特定のSKUしか使用できないようにする
  • リソースが特定のリージョンにのみデプロイされるようにする

ポリシーを利用することにより、リソースを一貫して適切な状態に保つことができるようになります

Azure RBAC との違いは?

どちらも Azure のガバナンスを実現するための機能となりますが目的が異なります

  • Azure Policy:リソースがどう使われるかを管理する
  • Azure RBAC:誰がリソースを使えるかを管理する

用語

Azure Portal にて「ポリシー」の画面を参照するといくつか用語が存在しますが、各用語について簡単に纏めておきます

  • ポリシー定義
    個々のAzureリソースに対して特定の条件やルールを適用するためもの

  • イニシアティブ定義
    複数のポリシー定義を纏めて1つのグループとして管理するためのもの。イニシアティブを使用することで、関連するポリシーを一括して割り当てたり、管理したりすることができる

  • ポリシーの割り当て
    作成したポリシー定義をスコープに適用する

  • イニシアティブの割り当て
    作成したイニシアティブ定義をスコープに適用する

  • 効果
    ポリシーがリソースに対してどのようなアクションを実行するかを定義するもの
    良く利用される効果の種類と説明は以下の通り
効果 説明
Deny(拒否) ポリシーに違反するリソースの作成や変更を拒否します
Audit(監査) ポリシーに違反するリソースを記録し、報告しますが、リソースの作成や変更は許可されます
Append(追加) リソースに対して特定の設定を自動的に追加します(タグに関してはmodifyの利用が推奨)
DeployIfNotExists(存在しない場合にデプロイ) リソースに特定の設定がない場合に、自動的にその設定をデプロイします
AuditIfNotExists(存在しない場合に監査) 特定のリソースが存在しない場合、その状態を監査し報告します

上記以外の効果については公式Docsをご参照ください

各用語の関連性

各用語の関連性を図に纏めると以下のようなイメージとなります

ポリシーとイニシアティブについて

ポリシーの適用(管理グループ)

ポリシーの適用(サブスクリプション)

ポリシーの適用(リソースグループ)

なお、ポリシー管理に関する推奨事項は公式Docsに記載があるのでご確認ください

効果が適用されるタイミングについて

Azure Policy は効果によって適用されるタイミングが異なります。
この辺りをとても分かりやすく説明されている記事がございましたので、紹介させていただきます

実際にPolicyを作成して適用してみよう

つらつらと Azure Policy についての説明を記載しましたが、実際にPolicyを作成して動作確認してみたほうがイメージが掴みやすいかと思います。Policy定義をイチから作るのはハードルが高いので、公開されているポリシー定義を利用して作成していきたいと思います

  1. サンプルのポリシー定義を探す
  2. ポリシー定義を作成する
  3. イニシアティブ定義を作成する
  4. イニシアティブの割り当て
  5. 動作確認

検証環境は以下のようなイメージとなります

1. サンプルのポリシー定義を探す

組み込みのポリシーや有志によって作成されたポリシーにて目的に近いポリシーが無いかを探す

本検証では「AzAdvertizer」を利用してサンプルポリシーの検索を実施。以下のポリシーをベースにポリシー定義の作成を行う

Deny-Subnet-Without-Nsg.json

2. ポリシー定義を作成する

2-1. ポリシー定義の作成

※本検証ではポリシー定義を管理グループに作成する


2-2. サンプルポリシーの修正(構文エラー)

サンプルポリシーをそのまま保存しようするとエラーとなるため修正を行う

エラーメッセージ
言語式 '[[parameters('excludedSubnets')]' の評価結果の型は 'String' ですが、必要な型は 'Array' です。

修正箇所は以下の通り(68, 85, 96行目)

修正前 修正後
"[[parameters('excludedSubnets')]" "[parameters('excludedSubnets')]"

修正後のコードは以下の通り
{
  "name": "Deny-Subnet-Without-Nsg",
  "type": "Microsoft.Authorization/policyDefinitions",
  "apiVersion": "2021-06-01",
  "scope": null,
  "properties": {
    "policyType": "Custom",
    "mode": "All",
    "displayName": "Subnets should have a Network Security Group",
    "description": "This policy denies the creation of a subnet without a Network Security Group. NSG help to protect traffic across subnet-level.",
    "metadata": {
      "version": "2.0.0",
      "category": "Network",
      "source": "https://github.com/Azure/Enterprise-Scale/",
      "alzCloudEnvironments": [
        "AzureCloud",
        "AzureChinaCloud",
        "AzureUSGovernment"
      ]
    },
    "parameters": {
      "effect": {
        "type": "String",
        "allowedValues": [
          "Audit",
          "Deny",
          "Disabled"
        ],
        "defaultValue": "Deny",
        "metadata": {
          "displayName": "Effect",
          "description": "Enable or disable the execution of the policy"
        }
      },
      "excludedSubnets": {
        "type": "Array",
        "metadata": {
          "displayName": "Excluded Subnets",
          "description": "Array of subnet names that are excluded from this policy"
        },
        "defaultValue": [
          "GatewaySubnet",
          "AzureFirewallSubnet",
          "AzureFirewallManagementSubnet"
        ]
      }
    },
    "policyRule": {
      "if": {
        "anyOf": [
          {
            "allOf": [
              {
                "equals": "Microsoft.Network/virtualNetworks",
                "field": "type"
              },
              {
                "count": {
                  "field": "Microsoft.Network/virtualNetworks/subnets[*]",
                  "where": {
                    "allOf": [
                      {
                        "exists": "false",
                        "field": "Microsoft.Network/virtualNetworks/subnets[*].networkSecurityGroup.id"
                      },
                      {
                        "field": "Microsoft.Network/virtualNetworks/subnets[*].name",
                        "notIn": "[parameters('excludedSubnets')]"
                      }
                    ]
                  }
                },
                "notEquals": 0
              }
            ]
          },
          {
            "allOf": [
              {
                "field": "type",
                "equals": "Microsoft.Network/virtualNetworks/subnets"
              },
              {
                "field": "name",
                "notIn": "[parameters('excludedSubnets')]"
              },
              {
                "field": "Microsoft.Network/virtualNetworks/subnets/networkSecurityGroup.id",
                "exists": "false"
              }
            ]
          }
        ]
      },
      "then": {
        "effect": "[parameters('effect')]"
      }
    }
  }
}

2-3. ポリシー定義が作成されたことの確認

なお、作成する際に定義したカテゴリにてフィルターすることが可能

3. イニシアティブ定義を作成する

3-1. イニシアティブ定義の作成

※本検証ではイニシアティブ定義を管理グループに作成する


3-2. イニシアティブ定義が作成されたことの確認

なお、ポリシー定義と同様に作成する際に定義したカテゴリにてフィルターすることが可能

4. イニシアティブの割り当て

4-1. イニシアティブの割り当て

※本検証ではイニシアティブを管理グループに割り当てる


4-2. イニシアティブが割り当てされたことの確認

5. 動作確認

本検証で作成したポリシー定義は NSGを適用していない場合はサブネットを作成することができない という内容のため、実際にNSGを適用しない状態でサブネットを作成して動作確認を行う

5-1. 作業前提

  • リソースグループ(Policy-RG)と VNet(Policy-VNet)を作成済み
  • VNet(Policy-VNet)にはサブネットは1つも作成されていない


5-2. 動作確認

NSGを指定しない状態でサブネットの作成を実施する

以下のエラーメッセージが出力されてサブネットを追加することができないことを確認する

補足1:アクティビティログの転送について

Azure Policyに関するログ(例:管理グループにPolicyを作成した、管理グループにPolicyを適用した、Policyによってリソースの作成に失敗したなど)はアクティビティログにて確認することが可能です。本ログを Log Analytics Workspace などに転送する場合は 診断設定 にて設定を実施することになります

本検証のように管理グループ単位で Policy を適用する場合、アクティビティログを転送するには 管理グループの 診断設定 にて設定を行う必要があるのですが、本設定は Azure ポータル から実施することはできないため注意が必要です(管理グループの 診断設定 はAPIで有効化する必要がある)

Azure Resource Manager REST API を使用して、管理グループの診断設定を有効にして、関連する Azure アクティビティ ログ エントリを
Log Analytics ワークスペース、Azure Storage、または Azure Event Hub に送信できます

なお、サブスクリプション単位で出力されるログ(例:Policyによってリソースの作成に失敗したなど)については Azure ポータルから 診断設定 にて設定を行うことが可能です

補足2:Policyが有効化 or 無効化されたタイミングでメール通知させる

アクティビティログを診断設定にて Log Analytics Workspace へ転送している場合、アラートルールを構成することで Policy の有効化/無効化を実施したタイミングでメール通知させることが可能です。

Policy 有効/無効で EnforcementMode の値が異なるため条件として利用することができます

Policy の状態 EnforcementMode
Policy が有効状態 EnforcementModeが「Default」となる
Policy が無効状態 EnforcementModeが「DoNotEnforce」となる

検索クエリは以下の通り

Policyが「有効」の検索クエリ
AzureActivity
| where Properties contains "enforcementMode" and Properties contains "Default"
Policyが「無効」の検索クエリ
AzureActivity
| where Properties contains "enforcementMode" and Properties contains "DoNotEnforce"

Policyが有効になった場合に通知するアラートルール構成イメージ

なお、ポリシー有効化 or 無効化する方法としては以下の方法が考えられますが、本手順では 1 の方法を採用した場合の手順を記載しています

  1. ポリシー有効化/無効化
  2. ポリシーの適用を削除 ⇢ ポリシーの適用を再作成
  3. ポリシーにて「適用除外」を追加する
  4. ポリシー定義のeffectを "disabled" に変更(検知した場合でも拒否されないようeffectを変更する)

まとめ

今回は Azure Policy について用語の整理と簡単な動作確認を実施しました。Policyをイチから作成するのは大変なので、まずは参考になりそうなサンプルを見つけて流用することで手間を削減しましょうというのが本記事で一番伝えたいことになります。特に共有した AzAdvertizer には様々なサンプルが存在しているので Policy を作成する際には一度本サイトを確認いただいた方がよろしいと思います。

本記事が Azure Policy を検討する際に少しでもお役に立てば幸いです。

Appendix

公式Docs
https://learn.microsoft.com/ja-jp/azure/governance/policy/overview

https://learn.microsoft.com/ja-jp/azure/governance/policy/policy-glossary

サンプルポリシー
https://learn.microsoft.com/ja-jp/azure/governance/policy/samples/built-in-policies

https://www.azadvertizer.net/index.html

Zennの記事
https://zenn.dev/tomot/articles/f3b216b8f82ed1

https://zenn.dev/tomot/articles/e6b07bf9e76cce

Microsoft (有志)

Discussion