Azureの大規模運用では「リソースグループ(RG)に付けたタグを、配下の全リソースへ確実に反映する」ことがガバナンスの入口です。本記事では、組み込みのAzure Policyで新規/更新リソースにRGタグを継承させる基本から、既存資産の一括反映、RG側のタグ変更を自動で追随させる高度化(カスタムPolicy、Event Grid+Functions/Logic Apps)まで、実運用に耐える設計・手順・コード例をまとめて解説します。
なぜ「RGのタグ継承」を自動化するのか
タグはコスト配賦、責任分界、セキュリティ境界、運用自動化の鍵です。しかし人の手による付け忘れ・表記揺れ・値の齟齬は必ず起こります。そこでRGに正しいタグを付けるだけで、配下の全リソースへ統一反映される仕組みを用意すると、運用負荷とミスを劇的に減らせます。Azure PolicyのModify効果と修復タスク(Remediation)を使えば、Azureネイティブだけで実現できます。
結論(クイックアンサー)
| やりたいこと | 方法 | 補足 |
|---|---|---|
| 新規または更新されたリソースにRGのタグを自動付与 | 組み込みポリシー「Inherit a tag from the resource group」をEffect = Modifyで割り当て。 | 割り当て後に作成/更新されるリソースで、対象タグが存在しない場合のみRGからコピーされます。 |
| 既存リソースにもタグを一括反映 | ポリシーの修復タスク(Remediation)を実行。 | ポリシー割り当てに付与されたマネージドIDへTag Contributor以上の権限を付けること。 |
| RGタグを変更したらリソース側も自動更新 | カスタムAzure Policy:タグ値がRGと異なる場合に置換する条件+Modify。 Event Grid + Azure Functions/Logic Apps:RGタグ変更イベントで配下リソースのタグを更新。 | 組み込みは「タグが無い」場合のみ動くため、値の差分更新まで自動化するならカスタムやイベント駆動が必要。 |
前提と用語
- 対象スコープ:管理グループ / サブスクリプション / リソースグループにポリシーを割り当て可能。最小はRG、推奨はサブスクリプション以上。
- 権限:
- 人間(割り当て・修復開始):Policy Contributor またはSecurity Admin相当。
- ポリシー割り当てのマネージドID(実際にタグを書き込む):Tag Contributor(またはContributor)。
- 対象外:一部の子リソースや古いリソース種別はタグ非対応。非対応リソースは「NotApplicable」となり変更されません。
組み込みポリシーを使った実装(最短ルート)
Azure Portal での設定手順
- [ポリシー] → [定義] で Inherit a tag from the resource group を検索。
- [割り当て] をクリックし、適用範囲(RGまたはサブスクリプション)を指定。
- [パラメータ] で Tag Name に継承したいタグ名(例:
Environment)を入力。 - [効果(Effect)] は Modify を選択。
- マネージドID(システム割当)を有効化して割り当てを完了。
- 割り当て直後にロール割り当てで、このマネージドIDへ Tag Contributor を付与。
これで、割り当て後に作成・更新されるリソースに、対象タグが無ければRGの値がコピーされます。
既存リソースへ一括反映(修復タスク)
- 対象のポリシー割り当てを開き、[修復] を選択。
- 修復ジョブのスコープを選び、開始します(多数のリソースに及ぶ場合は時間がかかります)。
修復は評価結果(Non-compliant)のリソースを順次更新します。Activity Logが増えるため、本番ではウィンドウを設けて実行すると安全です。
CLI/PowerShellでの自動化
Azure CLI
# 1) 組み込みポリシー定義IDを取得
POLICY_DEF_ID=$(az policy definition list \
--query "[?displayName=='Inherit a tag from the resource group'] | [0].id" -o tsv)
# 2) ポリシーをRGへ割り当て(Effect=Modify, MI有効)
SUB_ID=
RG=
az policy assignment create
--name "inherit-tag-environment"
--scope "/subscriptions/$SUB_ID/resourceGroups/$RG"
--policy "$POLICY_DEF_ID"
--identity-type SystemAssigned
--params '{ "tagName": { "value": "Environment" } }'
# 3) 割り当てのマネージドIDへTag Contributorを付与
MI_PRINCIPAL_ID=$(az policy assignment show
--name "inherit-tag-environment"
--scope "/subscriptions/$SUB_ID/resourceGroups/$RG"
--query "identity.principalId" -o tsv)
az role assignment create
--assignee-object-id "$MI_PRINCIPAL_ID"
--assignee-principal-type ServicePrincipal
--role "Tag Contributor"
--scope "/subscriptions/$SUB_ID/resourceGroups/$RG"
# 4) 既存リソースへ修復タスク
az policy remediation create
--name "remediate-inherit-env"
--policy-assignment "inherit-tag-environment"
--resource-group "$RG"
PowerShell(Azモジュール)
$def = Get-AzPolicyDefinition | Where-Object {$_.Properties.DisplayName -eq 'Inherit a tag from the resource group'}
$scope = "/subscriptions/<subId>/resourceGroups/<rgName>"
$assignment = New-AzPolicyAssignment ` -Name "inherit-tag-environment"`
-PolicyDefinition $def ` -Scope $scope`
-Location "japaneast" ` -PolicyParameterObject @{ "tagName" = @{ "value" = "Environment" } }`
-IdentityType SystemAssigned
# MIへTag Contributorを付与
New-AzRoleAssignment ` -ObjectId $assignment.Identity.PrincipalId`
-RoleDefinitionName "Tag Contributor" `
-Scope $scope
# 修復
Start-AzPolicyRemediation -Name "remediate-inherit-env" -PolicyAssignmentId $assignment.Id -ResourceGroupName ""
Infrastructure as Code での再現
Bicep(組み込みポリシー割り当て)
param tagName string = 'Environment'
param assignmentName string = 'pa-inherit-tag-env'
param policyDefinitionId string = '/providers/Microsoft.Authorization/policyDefinitions/<GUID_of_built_in_policy>'
resource pa 'Microsoft.Authorization/policyAssignments@2022-06-01' = {
name: assignmentName
scope: resourceGroup()
identity: {
type: 'SystemAssigned'
}
properties: {
displayName: 'Inherit RG tag: ${tagName}'
policyDefinitionId: policyDefinitionId
enforcementMode: 'Default'
parameters: {
tagName: { value: tagName }
}
}
}
Terraform
data "azurerm_policy_definition" "inherit" {
display_name = "Inherit a tag from the resource group"
}
resource "azurerm_policy_assignment" "inherit_env" {
name = "inherit-tag-env"
scope = azurerm_resource_group.rg.id
policy_definition_id = data.azurerm_policy_definition.inherit.id
parameters = jsonencode({ tagName = { value = "Environment" } })
identity {
type = "SystemAssigned"
}
}
resource "azurerm_role_assignment" "mi_tag_contributor" {
scope = azurerm_resource_group.rg.id
role_definition_name = "Tag Contributor"
principal_id = azurerm_policy_assignment.inherit_env.identity[0].principal_id
}
「値の差分も自動更新」するカスタムPolicy(サンプル)
組み込みは「タグが無いときだけ追加」です。RGの値変更を既存リソースへ置換したい場合は、次のようなカスタムPolicyを作成します(単一タグ版)。
{
"properties": {
"displayName": "Inherit & Sync a tag from the RG",
"mode": "All",
"parameters": {
"tagName": {
"type": "String",
"metadata": { "displayName": "Tag Name" }
}
},
"policyRule": {
"if": {
"anyOf": [
{ "field": "[format('tags[''{0}'']', parameters('tagName'))]", "exists": false },
{
"not": {
"field": "[format('tags[''{0}'']', parameters('tagName'))]",
"equals": "[resourceGroup().tags[parameters('tagName')]]"
}
}
]
},
"then": {
"effect": "modify",
"details": {
"roleDefinitionIds": [
"/providers/Microsoft.Authorization/roleDefinitions/4d97b98b-1d4f-4787-a291-c67834d212e7" // Tag Contributor
],
"operations": [
{
"operation": "addOrReplace",
"field": "[format('tags[''{0}'']', parameters('tagName'))]",
"value": "[resourceGroup().tags[parameters('tagName')]]"
}
]
}
}
}
}
}
このポリシーを割り当てると、タグ未設定と値不一致の両方が修復対象になり、修復タスクや将来の更新時にRGの値へ自動整合されます。複数タグを扱うには、イニシアチブ(Policy Set)に同ポリシーをタグごとに組み込み、共通パラメータで一括割り当てするのが管理しやすいです。
RGタグ変更をトリガに「即時反映」するイベント駆動
「RGのタグ値を更新したら、数分以内に配下リソースも更新したい」場合は、Azure Policyだけでは待ち時間が読みにくいことがあります。そこでActivity Log(Event Grid)をトリガに自動更新します。
- Event Grid サブスクリプション:イベント種類は Microsoft.Resources.ResourceWriteSuccess、サブジェクトフィルターで
.../resourceGroups/<RG名>を対象にします。 - Azure Functions/Logic Apps:受信イベントの対象RG名を抽出し、RGのタグを取得 → RG配下リソースを列挙 → 各リソースへタグの
addOrUpdateを実行。 - 実行IDの権限:実行アプリのマネージドIDへRGスコープでTag Contributorを付与。
Functions(JavaScript)例(概念)
module.exports = async function (context, event) {
const sub = process.env['SUBSCRIPTION_ID'];
const rgName = event.subject.split('/resourceGroups/')[1].split('/')[0];
// 1) RGのタグを取得(Azure SDK: @azure/arm-resources)
// 2) RG配下のリソースを列挙(listByResourceGroup)
// 3) 各リソースのtagsにRGの対象タグを加筆/置換して更新
// ※ 実装ではリトライ/スロットリング/並列度制御を考慮
};
Event Gridは変更イベントに即応できるため、タグ整合のSLAを短くしたいユースケースに適します。
テスト手順(安全に動作確認)
- ステージングRGを作成し、RGに
Environment=Staging等のタグを付与。 - 組み込みポリシーを割り当て(Effect=Modify、MI+Tag Contributor)。
- RG内にテストVMやStorageを作成 → 生成直後にタグが継承されることを確認。
- 既存リソースのタグを意図的に削除し、修復タスクで復元されるか確認。
- RGのタグ値を
Staging→UATに変更。- 組み込みのみ:新規更新時にしか置換されないことを理解。
- カスタムPolicy or Event駆動:差分置換されることを確認。
よくあるつまずきと対処
| 症状 | 原因 | 対処 |
|---|---|---|
| 修復が失敗する/進まない | ポリシー割り当てのマネージドIDに書き込み権限が無い | RG/サブスクリプションスコープでTag Contributor(またはContributor)を付与 |
| 一部リソースにタグが付かない | リソース種別がタグ非対応、または子リソースでタグ不可 | 親リソースへ付与、別の属性で管理、または除外スコープに配置 |
| RGタグ変更が配下にすぐ反映されない | 組み込みポリシーは「タグ未設定のみ」、評価サイクル依存 | カスタムPolicy(差分置換)+修復、またはEvent Gridで即時反映 |
| 複数タグを一気に継承したい | 単一タグ前提の定義を多重管理している | 同一カスタムPolicyをタグ数分パラメータ違いでイニシアチブ化 |
| 監査だけ先にやりたい | いきなりModifyだと運用に影響が読めない | まずAuditで傾向把握 → 段階的にModifyへ切替 |
運用設計(スコープ・例外・監査)
- 割り当てスコープ:原則はサブスクリプション全体。特別なタグ方針があるRGは除外スコープ(Exclusions)へ。
- 命名規則:タグ名は
Environment/Owner/CostCenter等を英語に統一。値はコード体系化。 - 監査:最初はAuditで「欠落」「不一致」を可視化。レポートを合意してからModifyへ。
- 分離:本番・共通基盤は別イニシアチブにして適用/修復の時間帯を棲み分け。
- IaC組み込み:Bicep/Terraformでポリシー割り当て・ロール割り当て・修復(初回)まで自動化。
セキュリティと最小権限
- ポリシー割り当てのマネージドIDは最小権限で。タグ操作のみならTag Contributorで十分。
- 修復タスクの実行権限(人)は、Change管理に沿って限定。実行ログはActivity Logで監査。
- Event駆動の実行IDもRGスコープに限定し、不要なサブスクリプション全域付与は避ける。
パフォーマンスとコストの注意
- Modify/修復はリソース数に比例してAPI呼び出しが増えます。大規模修復は時間帯を分散。
- Azure Policy自体に課金はありませんが、修復に伴うActivity Logの増加やFunctions実行の費用は考慮。
チェックリスト(導入〜運用)
- RGに正しいタグ体系を定義・付与したか。
- 組み込みポリシー(Effect=Modify)を正しいスコープに割り当てたか。
- ポリシー割り当てのマネージドIDへTag Contributorを付与したか。
- ステージングで修復タスクを試し、影響範囲と所要を把握したか。
- 値の差分更新が必要ならカスタムPolicy/イベント駆動を設計したか。
- IaC化し、再現性を担保したか。
付録:よく使うコマンド&スクリプト断片
タグの状態確認(CLI)
az resource list -g <rgName> --query "[].{name:name,type:type,tags:tags}" -o table
カスタムPolicyの割り当て(CLI)
# 事前にポリシー定義(custom)を作成済みとして
az policy assignment create \
--name "sync-tag-environment" \
--scope "/subscriptions/<subId>/resourceGroups/<rgName>" \
--policy "/subscriptions/<subId>/providers/Microsoft.Authorization/policyDefinitions/<customPolicyName>" \
--identity-type SystemAssigned \
--params '{ "tagName": { "value": "Environment" } }'
まとめ
RGタグ継承は、組み込みポリシー(Modify)+修復タスクで最小コスト・最短時間に実現できます。さらに、カスタムPolicyで値の差分置換まで広げれば、RGを真の「タグの単一情報源(Single Source of Truth)」にできます。即時性が重要ならEvent Grid+Functions/Logic Appsで変更通知に追随。最後はIaCで配布し、権限と運用窓口を整備して完成です。これで「RGのタグを更新すると、同じタグがリソース側にも付く」仕組みをAzureネイティブだけで堅牢に運用できます。

コメント