Assign NSG to VNet subnet using Bicep template - azure

I want to add an existing NSG to existing VNet subnet.
I tried doing it this way:
#description('Name of nsg')
param nsgName string
#description('Name of vnet')
param vnetName string
#description('Name of subnet')
param subnetName string
resource nsg 'Microsoft.Network/networkSecurityGroups#2022-01-01' existing = {
name: nsgName
}
resource subnet 'Microsoft.Network/virtualNetworks/subnets#2022-01-01' existing = {
name: '${vnetName}/${subnetName}'
}
resource nsgAttachment 'Microsoft.Network/virtualNetworks/subnets#2022-01-01' = {
name: '${vnetName}/${subnetName}'
properties: {
addressPrefix: subnet.properties.addressPrefix
networkSecurityGroup: {
id: nsg.id
}
}
}
Unfortunately, I can't pass the review/validation on Azure portal. It says that:
{"code":"InvalidTemplate","message":"Deployment template validation failed: 'Circular dependency detected on resource: '/subscriptions/xxxxxxxxx-02eaf5d20f25/resourceGroups/bicepRG/providers/Microsoft.Network/virtualNetworks/myVnetName/subnets/api'. Please see https://aka.ms/arm-template/#resources for usage details.'."}
How to assign a NSG to existing VNet subnet, or how to get rid of this Circular dependency error?

You will have to use a module to update the subnet:
// update-subnet.bicep
param vnetName string
param subnetName string
param properties object
resource subnet 'Microsoft.Network/virtualNetworks/subnets#2022-01-01' = {
name: '${vnetName}/${subnetName}'
properties: properties
}
From you main, you could invoke it like that:
// main.bicep
param nsgName string = 'thomastest-nsg2'
param vnetName string = 'thomastest-vnet'
param subnetName string = 'subnet1'
// Reference to nsg
resource nsg 'Microsoft.Network/networkSecurityGroups#2022-01-01' existing = {
name: nsgName
}
// Get existing subnet
resource subnet 'Microsoft.Network/virtualNetworks/subnets#2022-01-01' existing = {
name: '${vnetName}/${subnetName}'
}
// Update the subnet
module attachNsg 'update-subnet.bicep' = {
name: 'update-vnet-subnet-${vnetName}-${subnetName}'
params: {
vnetName: vnetName
subnetName: subnetName
// Update the nsg
properties: union(subnet.properties, {
networkSecurityGroup: {
id: nsg.id
}
})
}
}

Related

How to add existing route table to subnet

I am new to bicep and I am trying to attach an existing UDR named "udr-test" to 2 subnets, unfortunately with no luck.
This is my template that work fine but without UDR configuration:
var addressSpace = [
'10.0.0.0/16'
]
var subnets = [
{
name: 'Subnet1'
subnetPrefix: '10.0.2.0/24'
}
{
name: 'Subnet2'
subnetPrefix: '10.0.3.0/24'
}
]
resource VNET 'Microsoft.Network/virtualNetworks#2021-02-01' existing = {
name: 'vnet-test'
}
#batchSize(1)
resource Subnets 'Microsoft.Network/virtualNetworks/subnets#2020-11-01' = [for (sn, index) in subnets: {
name: sn.name
parent: VNET
properties: {
addressPrefix: sn.subnetPrefix
}
}]
Do you know how I can modify the template to add the UDR as well?
There is routeTable property on the subnet resource (see documentation):
// reference to existing route table
resource routeTable 'Microsoft.Network/routeTables#2022-01-01' existing = {
name: 'udr-test'
}
#batchSize(1)
resource Subnets 'Microsoft.Network/virtualNetworks/subnets#2020-11-01' = [for (sn, index) in subnets: {
name: sn.name
parent: VNET
properties: {
addressPrefix: sn.subnetPrefix
routeTable:{
id: routeTable.id // assign the route table
}
}
}]

How can I create a resource group and add a key vault to it using Bicep?

I'm trying to create a resource group and add a key vault to it.
However, I'm not able to set the new resource group as a target resource group for the key vault.
How can I have the key vault assigned to the newly created resource group without creating a second Bicep module for it?
var loc = 'westus'
// outputs the newly created resource group
module rgCreate 'test.rg.bicep' = {
scope: subscription()
name: 'rgCreate'
params: {
rgLocation: loc
}
}
resource keyVault 'Microsoft.KeyVault/vaults#2021-10-01' = {
name: 'Test'
location: loc
properties: {
enabledForTemplateDeployment: true
sku: {
family: 'A'
name: 'standard'
}
tenantId: tenant().tenantId
}
}
This is the workflow I'm aiming at:
First, if the resource group does not exist, you can't have targetScope = 'resourceGroup' in the main.bicep file. The command az deployment group create will fail:
{"code": "ResourceGroupNotFound", "message": "Resource group '' could not be found."}
You could always trigger the deployment form another resource that already exists (Not sure if it s a good idea tho).
An approach could be to have you main.bicep invoking two modules: one for resource group creation, one for resource creation:
// =========== rg.bicep ===========
// Setting target scope
targetScope = 'subscription'
param name string
param location string
// Creating resource group
resource rg 'Microsoft.Resources/resourceGroups#2021-01-01' = {
name: name
location: location
}
// =========== resources.bicep ===========
param location string = resourceGroup().location
param keyVaultName string
...
//Deploying key vault
resource keyVault 'Microsoft.KeyVault/vaults#2021-10-01' = {
name: keyVaultName
location: location
properties: {
enabledForTemplateDeployment: true
sku: {
family: 'A'
name: 'standard'
}
tenantId: tenant().tenantId
}
}
// Deploying other resources
...
// =========== main.bicep ===========
// Setting target scope
targetScope = 'subscription'
// Parameters
param rgName string = 'test-rg'
param rgLocation string = 'westus'
param keyVaultName string
...
// Creating resource group
module rgModule 'rg.bicep' = {
scope: subscription()
name: '${rgName}-create'
params:{
name: rgName
location: rgLocation
}
}
// Deploying resources in the newly created resource
module resources 'resources.bicep' = {
name: '${rgName}-resources-deployment'
scope: resourceGroup(rgName)
dependsOn: [ rgModule ]
params: {
location: rgLocation
keyVaultName: keyVaultName
...
}
}
To be honest, you could just run az group create command before deploying your template it will make things simpler.

How do I defined subnets in Bicep such that the parent Vnet has a reference and that I can dependOn the subnet deployment?

I have a situation where I need to define my subnets in the properties.subnets field of the parent virtual network otherwise I get the 'InUseSubnetCannotBeDeleted' problem
Option 1 - Defined inline
However if I define my subnets directly in the properties.subnet array (see below) then they are not created as children and I cannot seem to create a reference them as a resource for when I want to create a dependsOn reference for another resource.
resource virtualNetwork 'Microsoft.Network/virtualNetworks#2021-08-01' = {
// ... other fields
properties: {
subnets: [
// How can I get a reference to these that I can 'dependOn'?
{
name: 'subnet-1'
// ... other fields
}
{
name: 'subnet-2'
// ... other fields
}
]
}
}
Option 2 - Defined separately
resource virtualNetwork 'Microsoft.Network/virtualNetworks#2021-08-01' = {
// ... other fields
properties: {
subnets: [
subnet1 // Gives a circular reference error
]
}
}
resource subnet1 'Microsoft.Network/virtualNetworks/subnets#2021-08-01' = {
parent: virtualNetwork
name: 'subnet-1'
// ... other fields
}
I have tried defining the subnets as separate resources and then reference the resources in the properties.subnet array but, since subnets need a reference to the parent virtual network proeprty, Bicep complains about a circular reference.
It seems that ARM templates can use textual references using the name of the subnet in properties.subnets whcih could get around the circular reference, however Bicep does not allow this.
So how do I defined my subnets so that I can simulteneously satisfy the virtual network's required to have a reference to the subnets in properties.subnets as well as be able to have a resource reference that I can use in dependsOn clauses?
Maybe this will work. Bicep builds it without errors, but I have not tried to deploy it.
resource virtualNetwork 'Microsoft.Network/virtualNetworks#2021-08-01' = {
name: 'myvnet'
location: 'swedencentral'
properties: {
addressSpace: {
addressPrefixes: [
'10.0.0.0/20'
]
}
subnets: [
{
name: 'subnet-1'
properties: {
addressPrefix: '10.0.0.0/24'
}
}
]
}
}
resource subnet 'Microsoft.Network/virtualNetworks/subnets#2022-01-01' existing = {
name: 'myvnet/subnet-1'
scope: resourceGroup()
}
resource storage 'Microsoft.Storage/storageAccounts#2021-09-01' = {
name: 'mystorage'
location: 'swedencentral'
dependsOn: [
subnet
]
sku: {
name: 'Standard_LRS'
}
kind: 'StorageV2'
}

How to select and add multiple subnets of a VNet in networking section of an azure eventHub using bicep

How to select and add multiple subnets of a VNet in the networking section of an azure eventHub resource using azure bicep.
// Create an event hub namespace
var eventHubNamespaceName = 'evhns-demo1436'
resource eventHubNamespace 'Microsoft.EventHub/namespaces#2021-01-01-preview' = {
name: eventHubNamespaceName
location: resourceGroup().location
sku: {
name: 'Standard'
tier: 'Standard'
capacity: 1
}
properties: {
zoneRedundant: true
}
}
// Create an event hub inside the namespace
var eventHubName = 'evh-demo1436'
resource eventHubNamespaceName_eventHubName 'Microsoft.EventHub/namespaces/eventhubs#2021-01-01-preview' = {
parent: eventHubNamespace
name: eventHubName
properties: {
messageRetentionInDays: 7
partitionCount: 1
}
}
// Grant Listen and Send on our event hub
resource eventHubNamespaceName_eventHubName_ListenSend 'Microsoft.EventHub/namespaces/eventhubs/authorizationRules#2021-01-01-preview' = {
parent: eventHubNamespaceName_eventHubName
name: 'ListenSend'
properties: {
rights: [
'Listen'
'Send'
]
}
dependsOn: [
eventHubNamespace
]
}
resource testVnet 'Microsoft.Network/virtualNetworks#2021-03-01' existing = {
name: 'testvnet'
}
resource testsubnet 'Microsoft.Network/virtualNetworks/subnets#2021-03-01' existing = {
parent: testVnet
name: 'testsubnet'
}
resource enHubVnetRule 'Microsoft.EventHub/namespaces/virtualnetworkrules#2018-01-01-preview' = {
name: 'vnetName'
parent: eventHubNamespace
properties: {
virtualNetworkSubnetId: testsubnet.id
}
}
With above code I can only add one particular subnet of a VNet to the VNet entry of azure EventHub resource in networking section using azure bicep.
How do I fetch all subnets of a VNet and add/select them all to the VNet entry of azure EventHub resource in networking section using azure bicep.
You have to use for loop for the subnet block and virtual-network rule block like below:
// Create an event hub namespace
param eventHubNamespaceName string = 'evhns-demo1436'
resource eventHubNamespace 'Microsoft.EventHub/namespaces#2021-01-01-preview' = {
name: eventHubNamespaceName
location: resourceGroup().location
sku: {
name: 'Standard'
tier: 'Standard'
capacity: 1
}
properties: {
zoneRedundant: true
}
}
// Create an event hub inside the namespace
param eventHubName string = 'evh-demo1436'
resource eventHubNamespaceName_eventHubName 'Microsoft.EventHub/namespaces/eventhubs#2021-01-01-preview' = {
parent: eventHubNamespace
name: eventHubName
properties: {
messageRetentionInDays: 7
partitionCount: 1
}
}
// Grant Listen and Send on our event hub
resource eventHubNamespaceName_eventHubName_ListenSend 'Microsoft.EventHub/namespaces/eventhubs/authorizationRules#2021-01-01-preview' = {
parent: eventHubNamespaceName_eventHubName
name: 'ListenSend'
properties: {
rights: [
'Listen'
'Send'
]
}
dependsOn: [
eventHubNamespace
]
}
param subnets array =[
'test'
'mysubnet'
]
param vnetname string = 'test-ansuman'
resource testVnet 'Microsoft.Network/virtualNetworks#2021-03-01' existing = {
name: vnetname
}
resource testsubnet 'Microsoft.Network/virtualNetworks/subnets#2021-03-01' existing =[for subnet in subnets : {
parent: testVnet
name: subnet
}]
resource enHubVnetRule 'Microsoft.EventHub/namespaces/virtualnetworkrules#2018-01-01-preview' = [for (subnet,i) in subnets :{
name: '${vnetname}-${subnet}'
parent: eventHubNamespace
properties: {
virtualNetworkSubnetId:testsubnet[i].id
}
}]
Output:

How can I create an array of subnets on an existing vnet using Bicep?

In my bicep file I obtain a reference to the existing vnet like this:
resource existingVNET 'Microsoft.Network/virtualNetworks#2021-02-01' existing = {
name: 'the-existing-vnet'
}
I have tried to include multiple (four to be exact) resource statements for each of the subnets like this:
resource subnetPbdResource 'Microsoft.Network/virtualNetworks/subnets#2020-11-01' = {
parent: existingVNET
name: 'first-snet'
...
}
resource subnetPbdResource 'Microsoft.Network/virtualNetworks/subnets#2020-11-01' = {
parent: existingVNET
name: 'second-snet'
...
}
...however, when I run this (using az deployment group create ...) I get an error: with code AnotherOperationInProgress. One random (it seems) subnet has been created under the vnet.
I've also tried to define an array of subnets like this:
var subnets = [
{
name: 'api'
subnetPrefix: '10.144.0.0/24'
}
{
name: 'worker'
subnetPrefix: '10.144.1.0/24'
}
]
...but I cannot find a way to assign the existing vnet with the subnets array. .properties.subnets is not accessible for the existing vnet resource it seems.
Any tip appreciated!
It seems that ARM gets tangled up when it tries to deploy more than one subnet resource at the same time.
You can use dependsOn to make sure the subnets get created one after another:
resource existingVNET 'Microsoft.Network/virtualNetworks#2021-02-01' existing = {
name: 'the-existing-vnet'
}
resource subnetPbdResource 'Microsoft.Network/virtualNetworks/subnets#2021-02-01' = {
name: 'first-snet'
parent: existingVNET
properties: {
addressPrefix: '10.0.1.0/24'
}
}
resource subnetPbdResource2 'Microsoft.Network/virtualNetworks/subnets#2021-02-01' = {
name: 'second-snet'
parent: existingVNET
properties: {
addressPrefix: '10.0.2.0/24'
}
dependsOn: [
subnetPbdResource
]
}
resource subnetPbdResource3 'Microsoft.Network/virtualNetworks/subnets#2021-02-01' = {
name: 'third-snet'
parent: existingVNET
properties: {
addressPrefix: '10.0.3.0/24'
}
dependsOn: [
subnetPbdResource2
]
}
I also got a great answer on Bicep github discussion
Basically it boils down to building an array of subnets, use #batchSize(1) to ensure serial creation of subnets (I guess this achieves the same as using dependsOn in answer from #Manuel Batsching) and pass the subnet array as parameter to Resource "create subnet statement".
Obvious advantage: no duplicate code to create subnet

Resources