VS codeからBicep を利用してAzFW policy をデプロイする実践とエラー対応例

以下のBicepを利用して、AzFW Policyをdeployしてみました。
エラーが出たので、エラーを解消する方法をも説明します。以下は検証用のBicep です。
(検証用のBicepにはrule自体は少ないのでエラー再現できないかも、適当にruleをいっぱいつけてくださいね。)

===========================================
```
param test_policy01_name string = 'test-policy01'

resource test_policy01_name_resource 'Microsoft.Network/firewallPolicies@2024-05-01' = {
  name: test_policy01_name
  location: 'japaneast'
  properties: {
    sku: {
      tier: 'Standard'
    }
    threatIntelMode: 'Off'
    threatIntelWhitelist: {
      fqdns: []
      ipAddresses: []
    }
    dnsSettings: {
      servers: []
      enableProxy: true
    }
  }
}

resource test_policy01_name_DefaultApplicationRuleCollectionGroup 'Microsoft.Network/firewallPolicies/ruleCollectionGroups@2024-05-01' = {
  parent: test_policy01_name_resource
  name: 'DefaultApplicationRuleCollectionGroup'
  properties: {
    priority: 300
    ruleCollections: [
      {
        ruleCollectionType: 'FirewallPolicyFilterRuleCollection'
        action: {
          type: 'Allow'
        }
        rules: [
          {
            ruleType: 'ApplicationRule'
            name: 'test-policy01-RC01-RULE01'
            protocols: [
              {
                protocolType: 'Http'
                port: 80
              }
              {
                protocolType: 'Https'
                port: 443
              }
            ]
            fqdnTags: []
            webCategories: []
            targetFqdns: [
              '*.microsoftonline.com'
            ]
            targetUrls: []
            terminateTLS: false
            sourceAddresses: [
              '192.168.10.8'
            ]
            destinationAddresses: []
            sourceIpGroups: []
            httpHeadersToInsert: []
          }
        ]
        name: 'test-policy01-RC01'
        priority: 100
      }
      {
        ruleCollectionType: 'FirewallPolicyFilterRuleCollection'
        action: {
          type: 'Allow'
        }
        rules: [
          {
            ruleType: 'ApplicationRule'
            name: 'test-policy01-RC04-RULE01'
            protocols: [
              {
                protocolType: 'Http'
                port: 80
              }
              {
                protocolType: 'Https'
                port: 443
              }
            ]
            fqdnTags: []
            webCategories: [
              'business'
            ]
            targetFqdns: []
            targetUrls: []
            terminateTLS: false
            sourceAddresses: [
              '172.10.2.0/24'
            ]
            destinationAddresses: []
            sourceIpGroups: []
            httpHeadersToInsert: []
          }
          {
            ruleType: 'ApplicationRule'
            name: 'test-policy01-RC04-RULE02'
            protocols: [
              {
                protocolType: 'Http'
                port: 80
              }
              {
                protocolType: 'Https'
                port: 443
              }
            ]
            fqdnTags: []
            webCategories: []
            targetFqdns: [
              'mirror-jp.firstyear.id.au'
              '*.ubuntu.com'
            ]
            targetUrls: []
            terminateTLS: false
            sourceAddresses: [
              '172.11.2.0/24'
            ]
            destinationAddresses: []
            sourceIpGroups: []
            httpHeadersToInsert: []
          }
        ]
        name: 'test-policy01-RC04'
        priority: 200
      }
    ]
  }
}

resource test_policy01_name_DefaultDnatRuleCollectionGroup 'Microsoft.Network/firewallPolicies/ruleCollectionGroups@2024-05-01' = {
  parent: test_policy01_name_resource
  name: 'DefaultDnatRuleCollectionGroup'
  properties: {
    priority: 100
    ruleCollections: [
      {
        ruleCollectionType: 'FirewallPolicyNatRuleCollection'
        action: {
          type: 'Dnat'
        }
        rules: [
          {
            ruleType: 'NatRule'
            name: 'test-policy01-RC03-RULE01'
            translatedAddress: '192.168.9.4'
            translatedPort: '10003'
            ipProtocols: [
              'TCP'
            ]
            sourceAddresses: [
              '54.100.219.100'
            ]
            sourceIpGroups: []
            destinationAddresses: [
              '52.140.213.76'
            ]
            destinationPorts: [
              '10001'
            ]
          }
          {
            ruleType: 'NatRule'
            name: 'test-policy01-RC03-RULE06'
            translatedAddress: '192.168.1.7'
            translatedPort: '443'
            ipProtocols: [
              'TCP'
            ]
            sourceAddresses: [
              '13.26.238.0/23'
              '14.61.192.0/23'
            ]
            sourceIpGroups: []
            destinationAddresses: [
              '10.100.120.100'
            ]
            destinationPorts: [
              '443'
            ]
          }
        ]
        name: 'test-policy01-RC03'
        priority: 100
      }
    ]
  }
}

resource test_policy01_name_DefaultNetworkRuleCollectionGroup 'Microsoft.Network/firewallPolicies/ruleCollectionGroups@2024-05-01' = {
  parent: test_policy01_name_resource
  name: 'DefaultNetworkRuleCollectionGroup'
  properties: {
    priority: 200
    ruleCollections: [
      {
        ruleCollectionType: 'FirewallPolicyFilterRuleCollection'
        action: {
          type: 'Allow'
        }
        rules: [
          {
            ruleType: 'NetworkRule'
            name: 'test-policy01-RC02-RULE04'
            ipProtocols: [
              'UDP'
            ]
            sourceAddresses: [
              '192.100.0.0/20'
            ]
            sourceIpGroups: []
            destinationAddresses: []
            destinationIpGroups: []
            destinationFqdns: [
              'test.com'
            ]
            destinationPorts: [
              '53'
            ]
          }
        ]
        name: 'test-policy01-RC02'
        priority: 100
      }
    ]
  }
}
```
===========================================

1.VScodeでBicep fileを開き、右クリックして[Deploy bicep file]をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/620054/7feeaca6-9b24-43f2-a98d-3c3c239a2867.png)

2.[Select subscription]のpop upがでますので適切に選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/620054/30d7a9b1-c889-4055-8031-424c42c29ede.png)

3.[Select resource group]のpop upが出ますので適切に選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/620054/b80ab0dd-6cff-4f54-9407-bd79176fe227.png)

4.OUTPUTのところに以下のようなdeploy linkがあるので、そこでclickして、Azure portalのdeploy画面に行きます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/620054/acf76101-db67-4220-b5de-652e51def82a.png)


5.Azure Portalのdeploy画面にいくと、以下のエラーが表示しています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/620054/0fcc79e9-82c4-49b8-97b6-cd98cd944e4d.png)

{"code":"FirewallPolicyRuleCollectionGroupUpdateNotAllowedWhenUpdatingOrDeleting","message":"Firewall Policy Rule Collection Group DefaultNetworkRuleCollectionGroup can not be updated because it is in Updating state from previous operation ID : c5f92718-31c9-4876-8c1b-bfc5de0cc343."}

{"code":"FirewallPolicyRuleCollectionGroupUpdateNotAllowedWhenUpdatingOrDeleting","message":"Firewall Policy Rule Collection Group DefaultDnatRuleCollectionGroup can not be updated because it is in Updating state from previous operation ID : c7f34e7c-b97c-4755-

6.Azure policyが実際には作られました。でも中にはApplication Ruleだけがあって、NAT ruleとNetwork ruleがdeployされていません。

分析：
エラーと結果から見ると、Application Ruleが先にdepolyしているところでupdating状態になっていますが、平行でNAT ruleとNetwork ruleもdepolyしようとしている挙動で失敗しました。

解決方法：
Bicep fileにNAT ruleとNetwork Ruleの部分にdependonを追加します。
例：
~~~
resource test_policy01_name_DefaultDnatRuleCollectionGroup 'Microsoft.Network/firewallPolicies/ruleCollectionGroups@2024-05-01' = {
  parent: test_policy01_name_resource
  name: 'DefaultDnatRuleCollectionGroup'
  dependsOn:  [ test_policy01_name_DefaultApplicationRuleCollectionGroup   
  ]　→→ここの意味は 前のAppruleがdeploy完了してから、こちら実行しますよ。

resource test_policy01_name_DefaultNetworkRuleCollectionGroup 'Microsoft.Network/firewallPolicies/ruleCollectionGroups@2024-05-01' = {
  parent: test_policy01_name_resource
  name: 'DefaultNetworkRuleCollectionGroup'
  dependsOn:  [ test_policy01_name_DefaultDnatRuleCollectionGroup    
  ]　→→ここの意味は 前のNATruleがdeploy完了してから、こちら実行しますよ。
~~~

■結論：Bicep fileでAzFW policyをデプロイする際、Bicep fileの中にDependonのロジックを入れる必要があります。dependonはないと、Apprule,Dnatrule,Networkruleが同時にdeployしますので競合が発生して、失敗する可能性があります。もちろん、rule自体は少ない場合、瞬間に完了して競合は発生しなくてDepoly成功する場合もありますが、rule自体が多い場合、ほぼ失敗します。
つまり、基本、Dependonを入れてくださいね。