【Azure】Bicepを用いてAzure policyを適用させる。

# 1. はじめに
### 1-1 ご挨拶
初めまして、井村と申します。
AzureのBicepを用いてAzure policyを適用させてみました。
Azure Policy の一般的なユースケースには、リソースの整合性、規制コンプライアンス、セキュリティ、コスト、管理のガバナンスになります。

### 1-2 対象読者
- Azureに興味がある
- Bicepに興味がある

### 1-3 適用させるポリシーについて
Azure policyはAzureで事前に用意されている組み込みポリシー(built-in policy)と自前で作成できるカスタムポリシー(custom policy)があります。今回は[組み込みポリシー](https://learn.microsoft.com/en-us/azure/governance/policy/samples/built-in-policies)を利用し、以下を制限するポリシーを適用させます。

- Azureリソースのデプロイ先を東日本リージョン、西日本リージョンのみに限定する。
- Azure VMのSKU(VMのサイズです)を指定したSKUのみ(B1s、B1ms)利用できるよう制限する。

# 2. 構築
### 2-1 main.bicep構成
利用するBicepテンプレートは以下になります。
[Github](https://github.com/hawk0722/Azure_Bicep_06_Azure-Policy)にあげてます。

<details><summary>main.bicep</summary>

```bicep:bicep
     1  targetScope = 'subscription'
     2
     3  @description('Parameter and variable for Allowed locations')
     4  param policyAssignmentNameAl string = 'Allowed locations - Japan'
     5  param policyDefinitionIDAl string = '/providers/Microsoft.Authorization/policyDefinitions/e56962a6-4747-49cd-b67b-bf8b01975c4c'
     6  param valueAL array = [ 'japaneast', 'japanwest' ]
     7
     8  @description('Parameter and variable for Allowed virtual machine size SKUs')
     9  param policyAssignmentNameVM string = 'Allowed virtual machine size SKUs - b1s,b1ms'  
    10  param policyDefinitionIDVM string = '/providers/Microsoft.Authorization/policyDefinitions/cccc23c7-8427-4f53-ad12-b6a63eb452b3'
    11  param valueVM array = [ 'Standard_b1ms', 'Standard_b1s' ]
    12
    13  param policyValues object = {
    14    AL: {
    15      name: policyAssignmentNameAl
    16      policyDefinitionId: policyDefinitionIDAl
    17      parameters: {
    18        listOfAllowedLocations: {
    19          value: valueAL
    20        }
    21      }
    22    }
    23    AVM: {
    24      name: policyAssignmentNameVM
    25      policyDefinitionId: policyDefinitionIDVM
    26      parameters: {
    27        listOfAllowedSKUs: {
    28          value: valueVM
    30      }
    31    }
    32  }
    33
    34  resource assignment 'Microsoft.Authorization/policyAssignments@2022-06-01' = [for policy in items(policyValues): {   
    35    name: policy.value.name
    36    properties: {
    37      policyDefinitionId: policy.value.policyDefinitionID
    38      parameters: policy.value.parameters
    39    }
    40  }]
    41

```
</details>

補足は以下の通りです。
- 4行目から6行目の「param」でロケーションを制限するパラメーターを定義します。
- 9行目から11行目の「param」でAzure VMのSKUを制限するパラメーターを定義します。
- 13行目から32行目の「param」で上記のパラメーターを辞書オブジェクトの要素に格納します。
- 34行目の「resource」でAzure policyを適用させます。

### 2-2 パラメーターの確認方法
ここからは私が作成したmain.bicepの流れを紹介します。
まずは[公式ドキュメント](https://learn.microsoft.com/ja-jp/azure/governance/policy/samples/built-in-policies)から組み込みポリシーを確認します。そこから自分が適用させたいポリシーを確認します。以下画像はロケーションを制限する組み込みポリシーになります。赤枠をクリックします。


|![Document.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1989465/27991fd5-27fe-ab1c-1b28-0f0496d35a42.png)|
|:-:|

クリック後、Azure上のAzure policyに飛んできます。下記画像の上部の赤枠が組み込みポリシーを利用するための"Definition ID"を取得できます。この値がmain.bicep内の5行目になります。
下部の赤枠が変数で利用するパラメーター名になります。この値がmain.bicep内の18行目になります。

|![Allowed-locations.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1989465/862f67ce-1786-1865-0228-75c76f0b91a0.png)|
|:-:|

|![source.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1989465/42fc8298-2535-961f-65ba-4edfea9b1809.png)|
|:-:|

# 3. 検証
### 3-1 リソースの構築
ロケーションを変更し下記コマンドを実行すると構築完了です。

```cmd:cmd (Azure CLI)
$ ls
main.bicep

$ az login

$ az deployment sub create --template-file main.bicep --location <Your location>
```

下記画像が構築前です。デフォルトのポリシー(イニシアティブ)のみあります。スコープは消していますが、サブスクリプションをスコープです。

|![before.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1989465/3c473de0-e6a7-06ff-130c-0806669fb380.png)|
|:-:|

下記画像が構築後です。ポリシーが２つ出来ています。

|![after.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1989465/3778110b-0ecc-0dcd-1f7f-c599a257fa72.png)|
|:-:|

### 3-2 ロケーションの検証
それでは検証を実施します。ストレージアカウントを作成します。
以下画像でロケーションをUSに設定し、レビューします。

|![CreateStorageAccount.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1989465/7cd55307-a1fc-a5c6-c51f-377185bee9e6.png)|
|:-:|

以下画面となりました。エラー詳細を確認するとAzure Policyによって制御されていることがわかります。

|![stAzurePolicy.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1989465/7833601b-e967-f23b-24fe-ab114f7053ae.png)|
|:-:|

以下画面では東日本リージョンを選択しエラーは発生しませんでした。このあと、ストレージアカウントが作成されることも確認済みです。

|![jaAzurePolicy.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1989465/0d6af4cd-04c1-00a8-8416-1aab8f442f6e.png)|
|:-:|

ロケーションの制限確認は以上です。

### 3-3 SKUの検証
それでは検証を実施します。Azure VMを作成します。
以下画像はSKUの設定になります。B1s、B1ms以外は「Blocked by Policy」にカテゴライズされています。
仮にDS1_v2を選択しても「Select」ボタンが非活性であり選択出来ない状態がわかります。

|![BlockSKU.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1989465/c226caa4-a1cd-14c5-7b93-379511f666ff.png)|
|:-:|

SKUの制限確認は以上です。

# 4. 終わりに
本記事を最後まで読んで頂きましてありがとうございます。
参考記事で各定義はjsonファイルに記述されmain.bicep飛ばす方法がとても綺麗なコードだなと思います。
是非取り入れたい技術ですね。

# 5. 参考記事
- [How to deploy Azure Policy with Bicep?](https://erudinsky.com/2022/09/20/azure-policy-as-code-with-bicep/)
- [Microsoft.Authorization policyAssignments](https://learn.microsoft.com/ja-jp/azure/templates/microsoft.authorization/policyassignments?pivots=deployment-language-bicep)
- [Azure Policy built-in policy definitions](https://learn.microsoft.com/en-us/azure/governance/policy/samples/built-in-policies)
- [How to deploy Azure Policy with Bicep](https://andrewmatveychuk.com/how-to-deploy-azure-policy-with-bicep/)
- [Bicep のデータ型](https://learn.microsoft.com/ja-jp/azure/azure-resource-manager/bicep/data-types)
- [Bicep の反復ループ](https://learn.microsoft.com/ja-jp/azure/azure-resource-manager/bicep/loops)