🚔

ARM テンプレート と Azure Policy で Defender for Servers のリソース レベルの有効化を設定

2023/12/30に公開

はじめに

前の記事で Defender for Servers のリソース レベルの有効化を試しましたが、PowerShell スクリプトだと都度実行しないといけない、ということでまず ARM テンプレートを検証し、その後 Azure Policy で実現する方法を試してみます。
https://zenn.dev/microsoft/articles/7bfee6a78d1d64

ARM テンプレートで Plan 1 有効化

Defender for Servers の設定は通常のリソースの設定とは異なり、Microsoft.Compute/virtualMachines のタイプのリソースに対して、Microsoft.Security/pricings のタイプのパラメータを設定します。これを拡張リソースと呼ぶようです (リソース ロックなども同様) 。
通常 ARM テンプレートはスコープを管理グループ、サブスクリプション、リソース グループのいずれかを選択するのですが、拡張リソースの場合はスコープに対象のリソース ID (今回の場合は VM のリソース ID) に設定する必要があります。
https://learn.microsoft.com/ja-jp/azure/azure-resource-manager/templates/scope-extension-resources?tabs=azure-cli

なお、このスコープを指定しない場合、デフォルトでリソース グループがスコープとなり、リソース グループは Microsoft.Security/pricings のタイプを持たないためデプロイエラーになります。

P1 を有効化する ARM テンプレートは以下のようになります。パラメータの scope には対象の VM のリソース ID を設定します。

{
    "$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
    "contentVersion": "1.0.0.0",
    "parameters": {
      "scope": {
        "type": "String",
	  "metadata": {
            "displayName": "Target VM Resource Id"
          }
       }
    },
    "resources": [
        {
            "type": "Microsoft.Security/pricings",
            "apiVersion": "2024-01-01",
            "name": "virtualMachines",
            "properties": {
                "pricingTier": "Standard",
                "subPlan": "P1"
            },
            "scope": "[parameters('scope')]"
        }
    ]
}

動作確認:ARM テンプレートで Plan 1 有効化

カスタム テンプレートからデプロイします。


デプロイ後、対象 VM で Defender for Servers が有効化されました。

Azure Policy で Plan 1 有効化

特定のタグ名と値を持つ VM に対して、Plan 1 を有効化するポリシーを作成します。

{
  "mode": "All",
  "policyRule": {
    "if": {
      "allOf": [
        {
          "field": "type",
          "equals": "Microsoft.Compute/virtualMachines"
        },
        {
          "field": "[concat('tags[', parameters('tagName'), ']')]",
          "equals": "[parameters('tagValue')]"
        }
      ]
    },
    "then": {
      "effect": "deployIfNotExists",
      "details": {
        "type": "Microsoft.Security/pricings",
        "existenceCondition": {
          "field": "Microsoft.Security/pricings/pricingTier",
          "equals": "Standard"
        },
        "roleDefinitionIds": [
          "/providers/Microsoft.Authorization/roleDefinitions/b24988ac-6180-42a0-ab88-20f7382dd24c"
        ],
        "deployment": {
          "properties": {
            "mode": "incremental",
            "template": {
              "$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
              "contentVersion": "1.0.0.0",
              "parameters": {
                "scope": {
                  "type": "string"
                }
              },
              "resources": [
                {
                  "type": "Microsoft.Security/pricings",
                  "apiVersion": "2024-01-01",
                  "name": "virtualMachines",
                  "scope": "[parameters('scope')]",
                  "properties": {
                    "pricingTier": "Standard",
                    "subPlan": "P1"
                  }
                }
              ]
            },
            "parameters": {
              "scope": {
                "value": "[field('id')]"
              }
            }
          }
        }
      }
    }
  },
  "parameters": {
    "tagName": {
      "type": "String",
      "metadata": {
        "displayName": "Tag Name",
        "description": "Name of the tag to look for on the virtual machine."
      }
    },
    "tagValue": {
      "type": "String",
      "metadata": {
        "displayName": "Tag Value",
        "description": "Value of the tag to look for on the virtual machine."
      }
    }
  }
}

ポリシー定義解説

PolicyRule

if セクション
リソースタイプが Microsoft.Compute/virtualMachines であることをチェックしています。
指定されたタグ名 (tagName) と値 (tagValue) の組み合わせが VM に付与されているかをチェックします。

then セクション
effect: "deployIfNotExists" は指定された条件が満たされていない場合に、自動的に修正アクションがトリガーされることを意味しています。

details
対象となるリソースタイプに Microsoft.Security/pricings を指定しています。
existenceCondition で pricingTier が "Standard" であることを確認します。Standard である場合、準拠していると判断され、Standard ではない場合、deployment の内容がデプロイされます。
roleDefinitionIds は、ポリシーが修復アクションを行うために必要となる特定のアクセス権を定義します。

deployment
非準拠となったリソースに対する自動修正アクションを定義します。

template
ARM テンプレートの内容を記載しており、Microsoft.Security/pricings の VirtualMachines の項目に対して properties の pricingTier を Standard、subPlan を P1 に設定します。

parameters
2 箇所ありますが、前者の "template": に含まれる parameters は ARM テンプレートとして受け取るパラメータ、後者の parameters は ARM テンプレートに引き渡すためのパラメータ設定で、field('id') を使用して "if": の条件に合致した VM のリソース ID を設定します。なお、field() は直接 ARM テンプレートの箇所では使用できず、デプロイエラーになります。
https://learn.microsoft.com/ja-jp/azure/governance/policy/concepts/definition-structure#fields
https://learn.microsoft.com/ja-jp/azure/governance/policy/samples/pattern-deploy-resources#sample-policy-definition

Parameters

tagName と tagValue:
ポリシーを適用する特定のタグ名とタグ値を指定し、対象とする VM を特定します。

動作確認:Azure Policy で Plan 1 有効化

対象の VM に inclDfS:true のタグを付与します。


ポリシーをサブスクリプションに割り当て、修復タスクを作成します。



修復タスクが完了し、意図した ARM テンプレートが実行されています。


まとめ

本記事では Defender for Servers のリソース レベルの有効化を自動化するために ARM テンプレート と Azure Policy を利用しました。こちらを活用することで、新規 VM を作成するたびに都度実行するよりも運用負荷はかなり下げられると思います。

Microsoft (有志)

Discussion