🧙‍♂️

[Azure]RBACのDescription記載を必須にするAzure Policyの作成

2023/03/27に公開

↓のくだりでRBACの付与理由をDescriptionで管理するようにしましたが、絶対に書き忘れて経緯が追えないRBACが出てくると確信したのでバリデーション処理としてAzure PolicyでDescription記載を必須にするカスタムポリシーを作成しました!

https://zenn.dev/koosun/articles/9e1df047a6eaac

カスタムポリシー

allofで以下のand条件を取ることで制御に成功しました。

  • デプロイタイプが'Microsoft.Authorization/roleAssignments'である
  • 'Microsoft.Authorization/roleAssignments/description'フィールドが存在しない
{
  "mode": "All",
    "policyRule": {
      "if": {
        "allOf": [
          {
            "field": "type",
            "equals": "Microsoft.Authorization/roleAssignments"
          },
          {
            "field": "Microsoft.Authorization/roleAssignments/description",
            "exists": "false"
          }
        ]
      },
      "then": {
        "effect": "deny"
      }
    }
}

書き方についての補足

今回のポリシーの場合、2つの条件いずれもfield式でプロパティの内容を判別し
その組み合わせでDescriptionの記載がないロールアサインのデプロイを判別しています。
field式は受けられる値が決まっており、前者と後者はそれぞれ以下の値に該当します。

https://learn.microsoft.com/ja-jp/azure/governance/policy/concepts/definition-structure#fields

  • type…リソースタイプを特定。今回の場合、RBAC付与時に呼びされるリソースプロバイダー(Microsoft.Authorization)が持つリソースタイプ(roleAssignments)を指定。
"field": "type",
"equals": "Microsoft.Authorization/roleAssignments"
  • エイリアス…リソースごとに保有する個別のプロパティのエイリアス(別名)を指定。
"field": "Microsoft.Authorization/roleAssignments/description",
"exists": "false"

当初、エイリアスの方がいまいち理解できずにDescriptionの参照方法がよくわかりませんでした。
色々調べた結果として、上記で貼った記事で説明があるようにリソース毎のAPIが持つプロパティをAzure Policyで参照できるようにバインドされた名前(別名)をエイリアスと呼んでいるようです。

APIのプロパティ Azure Policy用にバインドされた名前
properties.description Microsoft.Authorization/roleAssignments/description

type/エイリアスの調べ方
typeの方は普段Azureを触っていれば何となく想像がつくと思いますが、制御したい操作(今回であればRBAC付与)のアクティビティログからリソースタイプを確認するのがいいかもしれません。
一覧で確認したい場合はPortalのリソース エクスプローラーなどから見ると早いと思います。

typeを調べた上で、そのリソースタイプから参照できるエイリアスの一覧はGet-AzPolicyAliasaz provider showから確認します。下記はAzure CLIで確認する場合。

PS /home/dev> az provider show --namespace 'Microsoft.Authorization' --expand 'resourceTypes/aliases' --query 'resourceTypes[].aliases[].name' --output table | Select-String '/roleAssignments/'

Microsoft.Authorization/roleAssignments/roleDefinitionId
Microsoft.Authorization/roleAssignments/principalId
Microsoft.Authorization/roleAssignments/principalType
Microsoft.Authorization/roleAssignments/canDelegate
Microsoft.Authorization/roleAssignments/description
Microsoft.Authorization/roleAssignments/condition
Microsoft.Authorization/roleAssignments/conditionVersion
Microsoft.Authorization/roleAssignments/scope
Microsoft.Authorization/roleAssignments/createdOn
Microsoft.Authorization/roleAssignments/updatedOn
Microsoft.Authorization/roleAssignments/createdBy
Microsoft.Authorization/roleAssignments/updatedBy
Microsoft.Authorization/roleAssignments/delegatedManagedIdentityResourceId

実装

上記のルールでカスタムポリシー定義を作成し、任意のスコープにポリシーを割り当てることで
想定通り制御されることを確認しました。
エラー時の警告文はポリシー割り当ての作成時に指定したものです。

descriptionあり

PS /home/dev> az role assignment create --assignee sp_name --role Reader --scope /subscriptions/*** --assignee '***' --description 'descriptionあり' --output none --only-show-errors

PS /home/dev> 

descriptionなし

PS /home/dev> az role assignment create --assignee sp_name --role Reader --scope /subscriptions/*** --assignee '***' --output none --only-show-errors

(RequestDisallowedByPolicy) Resource '***' was disallowed by policy. Reasons: 'Descriptionが記載されていません!!!'. See error details for policy resource IDs.
Code: RequestDisallowedByPolicy
Message: Resource '***' was disallowed by policy. Reasons: 'Descriptionが記載されていません!!!'. See error details for policy resource IDs.
Target: ***
Additional Information:Type: PolicyViolation
Info: {
    "evaluationDetails": {
        "evaluatedExpressions": [
            {
                "result": "True",
                "expressionKind": "Field",
                "expression": "type",
                "path": "type",
                "expressionValue": "Microsoft.Authorization/roleAssignments",
                "targetValue": "Microsoft.Authorization/roleAssignments",
                "operator": "Equals"
            },
            {
                "result": "True",
                "expressionKind": "Field",
                "expression": "Microsoft.Authorization/roleAssignments/description",
                "path": "properties.description",
                "targetValue": "false",
                "operator": "Exists"
            }
        ],
        "reason": "Description\u304c\u8a18\u8f09\u3055\u308c\u3066\u3044\u307e\u305b\u3093\uff01\uff01\uff01"
    },
    "policyDefinitionId": "/subscriptions/***/providers/Microsoft.Authorization/policyDefinitions/***",
    "policyDefinitionName": "***",
    "policyDefinitionDisplayName": "require_description",
    "policyDefinitionEffect": "deny",
    "policyAssignmentId": "/subscriptions/***/providers/Microsoft.Authorization/policyAssignments/***",
    "policyAssignmentName": "***",
    "policyAssignmentDisplayName": "require_description_sub-test1",
    "policyAssignmentScope": "/subscriptions/***",
    "policyAssignmentParameters": {}
}
PS /home/dev> 

まとめ

denyにしているため想定外の不具合が心配ですが、今のところ問題は起きていません。
いったん経過観察をしようと思います。

Discussion