Azure Policyでリソースをちゃんと管理したい人の為のテンプレート

Azureを社内で検証用基盤として活用し、複数人で利用している場合
- このリソース、いつ作ったやつだ…？
- 作成者と用途がわからん…

といったケース、結構あると思います。
今回はそれらの対応が出来るポリシーテンプレートを作成したのでご紹介します。

# テンプレートセット
## CreatedAt
CreatedAtは、各種リソース及びリソースグループにCreatedAtタグが存在しない場合、UTCで現在の日付と時刻を追加します。
既に存在している場合は何もしません。
結果的にリソース作成時にタグが追加され、いつ作られたのかを記録できます。
```json:CreatedAt
{
  "mode": "All",
  "policyRule": {
    "if": {
      "allOf": [
        {
          "field": "tags['CreatedAt']",
          "exists": false
        }
      ]
    },
    "then": {
      "effect": "modify",
      "details": {
        "operations": [
          {
            "operation": "addOrReplace",
            "field": "tags['CreatedAt']",
            "value": "[concat(substring(utcNow(), 0, 4), '/', substring(utcNow(), 5, 2), '/', substring(utcNow(), 8, 2), ' ', substring(utcNow(), 11, 8), '(UTC)')]"
          }
        ],
        "roleDefinitionIds": [
          "/providers/Microsoft.Authorization/roleDefinitions/8e3af657-a8ff-443c-a75c-2fe8c4bcb635"
        ]
      }
    }
  },
  "parameters": {}
}
```


## UpdatedAt
UpdatedAtは、各種リソース及びリソースグループにUTCで現在の日付と時刻を追加します。
結果的にリソース作成時と更新時にタグが追加され、いつ変更されたのかを記録できます。
```json:UpdatedAt
{
  "mode": "All",
  "policyRule": {
    "if": {
      "anyOf": [
        {
          "field": "tags['UpdatedAt']",
          "exists": false
        },
        {
          "field": "tags['UpdatedAt']",
          "exists": true
        }
      ]
    },
    "then": {
      "effect": "modify",
      "details": {
        "operations": [
          {
            "operation": "addOrReplace",
            "field": "tags['UpdatedAt']",
            "value": "[concat(substring(utcNow(), 0, 4), '/', substring(utcNow(), 5, 2), '/', substring(utcNow(), 8, 2), ' ', substring(utcNow(), 11, 8), '(UTC)')]"
          }
        ],
        "roleDefinitionIds": [
          "/providers/Microsoft.Authorization/roleDefinitions/8e3af657-a8ff-443c-a75c-2fe8c4bcb635"
        ]
      }
    }
  },
  "parameters": {}
}
```

## Author強制
Author強制は、リソースグループにAuthorタグが存在し、特定のドメインに一致するメールアドレスが登録されているかを検証します。
検証に失敗した場合、リソースグループの作成を拒否します。
```json:Author強制
{
  "mode": "All",
  "policyRule": {
    "if": {
      "allOf": [
        {
          "field": "type",
          "equals": "Microsoft.Resources/subscriptions/resourceGroups"
        },
        {
          "field": "[concat('tags[',parameters('tagEmail'), ']')]",
          "notLike": "[concat('*@',parameters('tagValueEmailDomain'))]"
        }
      ]
    },
    "then": {
      "effect": "[parameters('effect')]"
    }
  },
  "parameters": {
    "tagEmail": {
      "type": "String",
      "metadata": {
        "displayName": "tagEmail",
        "description": "Name of the tag containing the email address, e.g. 'SubOwner-Email'"
      }
    },
    "tagValueEmailDomain": {
      "type": "String",
      "metadata": {
        "displayName": "emailDomain",
        "description": "Enter the domain name of the email address, e.g. Accenture.com"
      }
    },
    "effect": {
      "type": "String",
      "metadata": {
        "displayName": "Effect",
        "description": "Deny, Audit or Disabled the execution of the Policy"
      },
      "allowedValues": [
        "Deny",
        "Audit",
        "Disabled"
      ],
      "defaultValue": "Deny"
    }
  }
}
```

## Projectタグ必須
`リソース グループでタグを必須にする`ポリシー定義でProjectタグを必須にし、案件名または個人検証利用の場合`Individual`とする運用にしています。
タグが存在しない場合、リソースの作成や更新は拒否されます。