0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Bicepで動くコード/動かないコード(Vnet作成)

Posted at

はじめに

Bicepを勉強し始めたのですが、「こう書いてみたけどうまく動かないな…」というのがあったので備忘録的にまとめておきます。

作成するリソース

  • Vnetを作成して、サブネットは2つ定義する。
  • サブネットには、AllowSpecificSSHInboundというルール(IPアドレス:11.22.33.44からのSSH接続を許可)を持つNSGを紐づける。

⭕動くコード

それぞれ、コードの全量を載せてみます。
※もしかしたらパラメータファイルを使ったらもう少しスッキリするかと思います。

①VnetとNSGを定義する

param location string = 'eastus'
param MyName string = 'test-01'
param ipAddrPrefix string = '10.0.0.0/16'
param subnet1Prefix string = '10.0.0.0/24'
param subnet2Prefix string = '10.0.1.0/24'

var vnetName = '${MyName}-vnet'
var subnet1Name = '${MyName}-subnet1'
var subnet2Name = '${MyName}-subnet2'
var nsgName = '${MyName}-nsg'

resource virtualNetwork 'Microsoft.Network/virtualNetworks@2019-11-01' = {
  name: vnetName
  location: location
  properties: {
    addressSpace: {
      addressPrefixes: [
        ipAddrPrefix
      ]
    }
    subnets: [
      {
        name: subnet1Name
        properties: {
          addressPrefix: subnet1Prefix
          networkSecurityGroup: {
            id: nsg.id
          }
        }
      }
      {
        name: subnet2Name
        properties: {
          addressPrefix: subnet2Prefix
          networkSecurityGroup: {
            id: nsg.id
          }
        }
      }
    ]
  }
}

resource nsg 'Microsoft.Network/networkSecurityGroups@2022-09-01' = {
  name: nsgName
  location: location
  properties: {
    securityRules: [
      {
        name: 'AllowSpecificSSHInbound'
        properties: {
          access: 'Allow'
          direction: 'Inbound'
          protocol: 'Tcp'
          sourceAddressPrefix: '11.22.33.44'
          sourcePortRange: '*'
          destinationAddressPrefix: '*'
          destinationPortRange: '22'
          priority: 100
        }
      }
    ]

  }
}

Vnetの定義の中でサブネットも併せて定義して、別で定義したNSGを紐づけるイメージです。
これが一番しっくりくる書き方なんじゃないかと思います。

②NSG/サブネット/NSGをそれぞれ定義する

param location string = 'eastus'
param MyName string = 'test-02'
param ipAddrPrefix string = '10.0.0.0/16'
param subnet1Prefix string = '10.0.0.0/24'
param subnet2Prefix string = '10.0.1.0/24'

var vnetName = '${MyName}-vnet'
var subnet1Name = '${MyName}-subnet1'
var subnet2Name = '${MyName}-subnet2'
var nsgName = '${MyName}-nsg'

resource  vnet 'Microsoft.Network/virtualNetworks@2019-11-01' = {
  name: vnetName
  location: location
  properties: {
    addressSpace: {
      addressPrefixes: [
        ipAddrPrefix
      ]
    }
  }
}

resource subnet1 'Microsoft.Network/virtualNetworks/subnets@2022-09-01' ={
  parent: vnet
  name: subnet1Name
  properties: {
    addressPrefix: subnet1Prefix
    networkSecurityGroup: {
      id: nsg.id
    }
  }
}

resource subnet2 'Microsoft.Network/virtualNetworks/subnets@2022-09-01' ={
  parent: vnet
  name: subnet2Name
  properties: {
    addressPrefix: subnet2Prefix
    networkSecurityGroup: {
      id: nsg.id
    }
  }
}

resource nsg 'Microsoft.Network/networkSecurityGroups@2022-09-01' = {
  name: nsgName
  location: location
  properties: {
    securityRules: [
      {
        name: 'AllowSpecificSSHInbound'
        properties: {
          access: 'Allow'
          direction: 'Inbound'
          protocol: 'Tcp'
          sourceAddressPrefix: '11.22.33.44'
          sourcePortRange: '*'
          destinationAddressPrefix: '*'
          destinationPortRange: '22'
          priority: 100
        }
      }
    ]
  }
}

サブネットをVnetの外で定義します。その際、定義したサブネットはVnetの中に含まれるということをparentで明示しています。
同じ設定のサブネットを複数Vnetで使いまわす際にはこの書き方が良いのかもしれません。

❌動かないコード

③Vnetの定義内にサブネットおよびNSGの定義内容もすべて含める

param location string = 'eastus'
param MyName string = 'test-03'
param ipAddrPrefix string = '10.0.0.0/16'
param subnet1Prefix string = '10.0.0.0/24'
param subnet2Prefix string = '10.0.1.0/24'

var vnetName = '${MyName}-vnet'
var subnet1Name = '${MyName}-subnet1'
var subnet2Name = '${MyName}-subnet2'
// var nsgName = '${MyName}-nsg'

resource vm 'Microsoft.Network/virtualNetworks@2019-11-01' = {
  name: vnetName
  location: location
  properties: {
    addressSpace: {
      addressPrefixes: [
        ipAddrPrefix
      ]
    }
    subnets: [
      {
        name: subnet1Name
        properties: {
          addressPrefix: subnet1Prefix
          networkSecurityGroup: {
            properties: {
              securityRules: [
                {
                  name: 'AllowSpecificSSHInbound'
                  properties: {
                    access: 'Allow'
                    direction: 'Inbound'
                    protocol: 'Tcp'
                    sourceAddressPrefix: '11.22.33.44'
                    sourcePortRange: '*'
                    destinationAddressPrefix: '*'
                    destinationPortRange: '22'
                    priority: 100
                  }
                }
              ]
            }
          }
        }
      }
      {
        name: subnet2Name
        properties: {
          addressPrefix: subnet2Prefix
          networkSecurityGroup: {
            properties: {
              securityRules: [
                {
                  name: 'AllowSpecificSSHInbound'
                  properties: {
                    access: 'Allow'
                    direction: 'Inbound'
                    protocol: 'Tcp'
                    sourceAddressPrefix: '11.22.33.44'
                    sourcePortRange: '*'
                    destinationAddressPrefix: '*'
                    destinationPortRange: '22'
                    priority: 100
                  }
                }
              ]
            }
          }
        }
      }
    ]
  }
}

Vnetの定義ブロックの中に、すべての設定を詰め込んだ形です。
上記を実行すると以下のようなエラーメッセージが出力されました。

{
    "status": "Failed",
    "error": {
        "code": "DeploymentFailed",
        "target": "/subscriptions/<サブスクリプションID>/resourceGroups/<リソースグループ名>/providers/Microsoft.Resources/deployments/03.vnet",
        "message": "At least one resource deployment operation failed. Please list deployment operations for details. Please see https://aka.ms/arm-deployment-operations for usage details.",
        "details": [
            {
                "code": "InvalidRequestFormat",
                "message": "Cannot parse the request.",
                "details": [
                    {
                        "code": "MissingJsonReferenceId",
                        "message": "Value for reference id is missing. Path properties.subnets[0].properties.networkSecurityGroup."
                    },
                    {
                        "code": "MissingJsonReferenceId",
                        "message": "Value for reference id is missing. Path properties.subnets[1].properties.networkSecurityGroup."
                    }
                ]
            }
        ]
    }
}

メッセージ的にproperties.subnets[*].properties.networkSecurityGroupの中にidを指定していないためエラーになっているように思われたので、空っぽのNSG定義を追加してみました。

④Vnetの定義内にサブネットおよびNSGの定義内容もすべて含める(NSGはガラだけ定義)

param location string = 'eastus'
param MyName string = 'test-04'
param ipAddrPrefix string = '10.0.0.0/16'
param subnet1Prefix string = '10.0.0.0/24'
param subnet2Prefix string = '10.0.1.0/24'

var vnetName = '${MyName}-vnet'
var subnet1Name = '${MyName}-subnet1'
var subnet2Name = '${MyName}-subnet2'
var nsgName = '${MyName}-nsg'

resource vm 'Microsoft.Network/virtualNetworks@2019-11-01' = {
  name: vnetName
  location: location
  properties: {
    addressSpace: {
      addressPrefixes: [
        ipAddrPrefix
      ]
    }
    subnets: [
      {
        name: subnet1Name
        properties: {
          addressPrefix: subnet1Prefix
          networkSecurityGroup: {
            id: nsg.id
            properties: {
              securityRules: [
                {
                  name: 'AllowSpecificSSHInbound'
                  properties: {
                    access: 'Allow'
                    direction: 'Inbound'
                    protocol: 'Tcp'
                    sourceAddressPrefix: '11.22.33.44'
                    sourcePortRange: '*'
                    destinationAddressPrefix: '*'
                    destinationPortRange: '22'
                    priority: 100
                  }
                }
              ]
            }
          }
        }
      }
      {
        name: subnet2Name
        properties: {
          addressPrefix: subnet2Prefix
          networkSecurityGroup: {
            id: nsg.id
            properties: {
              securityRules: [
                {
                  name: 'AllowSpecificSSHInbound'
                  properties: {
                    access: 'Allow'
                    direction: 'Inbound'
                    protocol: 'Tcp'
                    sourceAddressPrefix: '11.22.33.44'
                    sourcePortRange: '*'
                    destinationAddressPrefix: '*'
                    destinationPortRange: '22'
                    priority: 100
                  }
                }
              ]
            }
          }
        }
      }
    ]
  }
}

resource nsg 'Microsoft.Network/networkSecurityGroups@2022-09-01' = {
  name: nsgName
  location: location
}

idがないというエラーに対処するためだけに、NSGのガラだけ定義しています。実はこのコードはエラーにならず登録はできます。ただNSGの設定を見てみると追加されているはずのAllowSpecificSSHInboundルールが追加されていませんでした。
スクリーンショット 2023-04-16 205834.png

⑤Vnet/サブネット/NSGをそれぞれ定義する(Vnetとサブネットの紐づけにparentを使わない)

param location string = 'eastus'
param MyName string = 'test-05'
param ipAddrPrefix string = '10.0.0.0/16'
param subnet1Prefix string = '10.0.0.0/24'
param subnet2Prefix string = '10.0.1.0/24'

var vnetName = '${MyName}-vnet'
var subnet1Name = '${MyName}-subnet1'
var subnet2Name = '${MyName}-subnet2'
var nsgName = '${MyName}-nsg'

resource  vnet 'Microsoft.Network/virtualNetworks@2022-09-01' = {
  name: vnetName
  location: location
  properties: {
    addressSpace: {
      addressPrefixes: [
        ipAddrPrefix
      ]
    }
    subnets: [
      {
        id: subnet1.id
      }
      {
        id: subnet2.id
      }
    ]
  }
}

resource subnet1 'Microsoft.Network/virtualNetworks/subnets@2022-09-01' ={
  name: subnet1Name
  properties: {
    addressPrefix: subnet1Prefix
    networkSecurityGroup: {
      id: nsg.id
    }
  }
}

resource subnet2 'Microsoft.Network/virtualNetworks/subnets@2022-09-01' ={
  name: subnet2Name
  properties: {
    addressPrefix: subnet2Prefix
    networkSecurityGroup: {
      id: nsg.id
    }
  }
}

resource nsg 'Microsoft.Network/networkSecurityGroups@2022-09-01' = {
  name: nsgName
  location: location
  properties: {
    securityRules: [
      {
        name: 'AllowSpecificSSHInbound'
        properties: {
          access: 'Allow'
          direction: 'Inbound'
          protocol: 'Tcp'
          sourceAddressPrefix: '11.22.33.44'
          sourcePortRange: '*'
          destinationAddressPrefix: '*'
          destinationPortRange: '22'
          priority: 100
        }
      }
    ]
  }
}

Vnetとサブネットの紐づけにparentを使わず、properties.subnets[*]の中にサブネットそれぞれのidを指定してみました。
実行したところ、以下のようなエラーメッセージが出力されました。

InvalidTemplate - Deployment template validation failed: 'The template resource 'test-05-vnet' at line '1' and column '716' is not valid: The language expression property array index '1' is out of bounds.. Please see https://aka.ms/arm-functions for usage details.'.

なぜ動かないのか(自分なりの解釈)

なぜ動かないのか(定義として許されないのか)について調べてみましたが、公式ドキュメントなどからは見つけられなかったので、自分なりにNGとなる理由を考えてみました。もしドキュメントなどをご存じの方がいれば教えてください。

③はVnetのテンプレートドキュメントを見る限り、NSGのセキュリティルールも細かく定義できるように読み取れます。しかし、NSGのnameに該当する設定項目が無いため、Vnetの定義ブロック内ではNSGを新規作成できないのではと推測しています。

⑤については、仮にVnetの定義を全てコメントアウトした場合でも構文上はエラーにはなりませんが、Azure的には実現できない状態になる(サブネットだけ定義することはできない)ため、エラーになるのかなと考えています(②はVnetの定義をコメントアウトすると構文エラーになります)。

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?