The goal of this task is to create an ARM template that defines a virtual machine and all required resources. The template will be modified to produce multiple virtual machines. Modifications will include:

A second goal of this task is to modify the template to add a Bastion host and re-deploy the template.

Login to the Azure Portal

Click on the login URL and enter the given credentials to login to the Azure portal.

Note: Your credentials will be different from the one shown in the figure.

After logging in to portal using the credentials. You will see an empty resource group, where you can create some resources.

Create an ARM Template for a virtual machine

Go to the search box type "template deployment" and click on "Deploy a custom template".

Now click on "Create a Windows virtual machine".

After that click on the "Edit template"

Now here we will make some edits in our pre-defined template.

First, navigate to the virtual machine section and set "bootDiagnostics" as false. And also remove the "storageUri" (portion selected in the below image) from the bootDiagnostics.

Second, remove the storage account dependency from the virtual machine. Delete the selected protion from the template in the "dependsOn" as shown in the below image.

Now, go to the "Variables" section and remove the "nicName" variable.

Add another variable with name the "baseNames" and value equals ["primary", "secondary"]

"baseNames":["primary","secondary"]

Define multiple data disks for the virtual machine

NOTE: In this lab we are going to define just one data disk as defining multiple data disks will exceed the lab resources creation limit.

Go to the VM section and inside that search for the "dataDisks". Change the "diskSizeGB" to 10 as shown below.

Create multiple instances of Azure resources with an ARM template

Go to the "Parameters" section and remove the "dnsLabelPrefix" (selected part in the below image).

Now, go to the "Variables" section and add one variable with name "copies" and value equals 2.

"copies" : 2

Modify the public IP address element. Change the name to the one given below and also add the "copy" element. Also remove the "dnsSettings" from the properties (selected portion in the below image).

"name":"[concat(variables('baseNames')[copyIndex()],'-pip')]"
"copy":{
    "name": "pipCopy",
    "count": "[variables('copies')]"
}

Modify the network interface element. Change the name to the one given below and also add the "copy" element. Replace the dependsOn entry for the public ip address with "pipCopy".

"name":"[concat(variables('baseNames')[copyIndex()],'-nic')]"
"copy":{
    "name": "nicCopy",
    "count": "[variables('copies')]"
}
pipCopy

Replace the properties/ipConfigurations/properties/publicIpAddress/id element with:

"id": "[resourceId('Microsoft.Network/publicIPAddresses',concat(variables('baseNames')[copyIndex()],'-pip'))]"

Modify the virtual machine element. Change the name to the one given below and also add the "copy" element.

"name":"[concat(variables('baseNames')[copyIndex()],'-vm')]"
"copy":{
    "name": "vmCopy",
    "count": "[variables('copies')]"
}

Replace the dependsOn entry for the network interface with "nicCopy". Replace the properties/networkProfile/networkInterfaces/id element with:

"id": "[resourceId('Microsoft.Network/networkInterfaces',concat(variables('baseNames')[copyIndex()],'-nic'))]"

Remove the hostName element from the outputs element.

Now, your template should look something like this:

{
    "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
    "contentVersion": "1.0.0.0",
    "parameters": {
        "adminUsername": {
            "type": "String",
            "metadata": {
                "description": "Username for the Virtual Machine."
            }
        },
        "adminPassword": {
            "minLength": 12,
            "type": "SecureString",
            "metadata": {
                "description": "Password for the Virtual Machine."
            }
        },
        "publicIpName": {
            "defaultValue": "myPublicIP",
            "type": "String",
            "metadata": {
                "description": "Name for the Public IP used to access the Virtual Machine."
            }
        },
        "publicIPAllocationMethod": {
            "defaultValue": "Dynamic",
            "allowedValues": [
                "Dynamic",
                "Static"
            ],
            "type": "String",
            "metadata": {
                "description": "Allocation method for the Public IP used to access the Virtual Machine."
            }
        },
        "publicIpSku": {
            "defaultValue": "Basic",
            "allowedValues": [
                "Basic",
                "Standard"
            ],
            "type": "String",
            "metadata": {
                "description": "SKU for the Public IP used to access the Virtual Machine."
            }
        },
        "OSVersion": {
            "defaultValue": "2022-datacenter-azure-edition-core",
            "allowedValues": [
                "2008-R2-SP1",
                "2008-R2-SP1-smalldisk",
                "2012-Datacenter",
                "2012-datacenter-gensecond",
                "2012-Datacenter-smalldisk",
                "2012-datacenter-smalldisk-g2",
                "2012-Datacenter-zhcn",
                "2012-datacenter-zhcn-g2",
                "2012-R2-Datacenter",
                "2012-r2-datacenter-gensecond",
                "2012-R2-Datacenter-smalldisk",
                "2012-r2-datacenter-smalldisk-g2",
                "2012-R2-Datacenter-zhcn",
                "2012-r2-datacenter-zhcn-g2",
                "2016-Datacenter",
                "2016-datacenter-gensecond",
                "2016-datacenter-gs",
                "2016-Datacenter-Server-Core",
                "2016-datacenter-server-core-g2",
                "2016-Datacenter-Server-Core-smalldisk",
                "2016-datacenter-server-core-smalldisk-g2",
                "2016-Datacenter-smalldisk",
                "2016-datacenter-smalldisk-g2",
                "2016-Datacenter-with-Containers",
                "2016-datacenter-with-containers-g2",
                "2016-datacenter-with-containers-gs",
                "2016-Datacenter-zhcn",
                "2016-datacenter-zhcn-g2",
                "2019-Datacenter",
                "2019-Datacenter-Core",
                "2019-datacenter-core-g2",
                "2019-Datacenter-Core-smalldisk",
                "2019-datacenter-core-smalldisk-g2",
                "2019-Datacenter-Core-with-Containers",
                "2019-datacenter-core-with-containers-g2",
                "2019-Datacenter-Core-with-Containers-smalldisk",
                "2019-datacenter-core-with-containers-smalldisk-g2",
                "2019-datacenter-gensecond",
                "2019-datacenter-gs",
                "2019-Datacenter-smalldisk",
                "2019-datacenter-smalldisk-g2",
                "2019-Datacenter-with-Containers",
                "2019-datacenter-with-containers-g2",
                "2019-datacenter-with-containers-gs",
                "2019-Datacenter-with-Containers-smalldisk",
                "2019-datacenter-with-containers-smalldisk-g2",
                "2019-Datacenter-zhcn",
                "2019-datacenter-zhcn-g2",
                "2022-datacenter",
                "2022-datacenter-azure-edition",
                "2022-datacenter-azure-edition-core",
                "2022-datacenter-azure-edition-core-smalldisk",
                "2022-datacenter-azure-edition-smalldisk",
                "2022-datacenter-core",
                "2022-datacenter-core-g2",
                "2022-datacenter-core-smalldisk",
                "2022-datacenter-core-smalldisk-g2",
                "2022-datacenter-g2",
                "2022-datacenter-smalldisk",
                "2022-datacenter-smalldisk-g2"
            ],
            "type": "String",
            "metadata": {
                "description": "The Windows version for the VM. This will pick a fully patched image of this given Windows version."
            }
        },
        "vmSize": {
            "defaultValue": "Standard_D2s_v5",
            "type": "String",
            "metadata": {
                "description": "Size of the virtual machine."
            }
        },
        "location": {
            "defaultValue": "[resourceGroup().location]",
            "type": "String",
            "metadata": {
                "description": "Location for all resources."
            }
        },
        "vmName": {
            "defaultValue": "simple-vm",
            "type": "String",
            "metadata": {
                "description": "Name of the virtual machine."
            }
        }
    },
    "variables": {
        "baseNames": [
            "primary",
            "secondary"
        ],
        "storageAccountName": "[format('bootdiags{0}', uniqueString(resourceGroup().id))]",
        "addressPrefix": "10.0.0.0/16",
        "subnetName": "Subnet",
        "subnetPrefix": "10.0.0.0/24",
        "virtualNetworkName": "MyVNET",
        "networkSecurityGroupName": "default-NSG",
        "copies": 2
    },
    "resources": [
        {
            "type": "Microsoft.Storage/storageAccounts",
            "apiVersion": "2021-04-01",
            "name": "[variables('storageAccountName')]",
            "location": "[parameters('location')]",
            "sku": {
                "name": "Standard_LRS"
            },
            "kind": "Storage"
        },
        {
            "type": "Microsoft.Network/publicIPAddresses",
            "apiVersion": "2021-02-01",
            "name": "[concat(variables('baseNames')[copyIndex()],'-pip')]",
            "location": "[parameters('location')]",
            "sku": {
                "name": "[parameters('publicIpSku')]"
            },
            "properties": {
                "publicIPAllocationMethod": "[parameters('publicIPAllocationMethod')]"
            },
            "copy": {
                "name": "pipCopy",
                "count": "[variables('copies')]"
            }
        },
        {
            "type": "Microsoft.Network/networkSecurityGroups",
            "apiVersion": "2021-02-01",
            "name": "[variables('networkSecurityGroupName')]",
            "location": "[parameters('location')]",
            "properties": {
                "securityRules": [
                    {
                        "name": "default-allow-3389",
                        "properties": {
                            "priority": 1000,
                            "access": "Allow",
                            "direction": "Inbound",
                            "destinationPortRange": "3389",
                            "protocol": "Tcp",
                            "sourcePortRange": "*",
                            "sourceAddressPrefix": "*",
                            "destinationAddressPrefix": "*"
                        }
                    }
                ]
            }
        },
        {
            "type": "Microsoft.Network/virtualNetworks",
            "apiVersion": "2021-02-01",
            "name": "[variables('virtualNetworkName')]",
            "location": "[parameters('location')]",
            "dependsOn": [
                "[resourceId('Microsoft.Network/networkSecurityGroups', variables('networkSecurityGroupName'))]"
            ],
            "properties": {
                "addressSpace": {
                    "addressPrefixes": [
                        "[variables('addressPrefix')]"
                    ]
                },
                "subnets": [
                    {
                        "name": "[variables('subnetName')]",
                        "properties": {
                            "addressPrefix": "[variables('subnetPrefix')]",
                            "networkSecurityGroup": {
                                "id": "[resourceId('Microsoft.Network/networkSecurityGroups', variables('networkSecurityGroupName'))]"
                            }
                        }
                    }
                ]
            }
        },
        {
            "type": "Microsoft.Network/networkInterfaces",
            "apiVersion": "2021-02-01",
            "name": "[concat(variables('baseNames')[copyIndex()],'-nic')]",
            "location": "[parameters('location')]",
            "dependsOn": [
                "pipCopy",
                "[resourceId('Microsoft.Network/virtualNetworks', variables('virtualNetworkName'))]"
            ],
            "properties": {
                "ipConfigurations": [
                    {
                        "name": "ipconfig1",
                        "properties": {
                            "privateIPAllocationMethod": "Dynamic",
                            "publicIPAddress": {
                                "id": "[resourceId('Microsoft.Network/publicIPAddresses',concat(variables('baseNames')[copyIndex()],'-pip'))]"
                            },
                            "subnet": {
                                "id": "[resourceId('Microsoft.Network/virtualNetworks/subnets', variables('virtualNetworkName'), variables('subnetName'))]"
                            }
                        }
                    }
                ]
            },
            "copy": {
                "name": "nicCopy",
                "count": "[variables('copies')]"
            }
        },
        {
            "type": "Microsoft.Compute/virtualMachines",
            "apiVersion": "2021-03-01",
            "name": "[concat(variables('baseNames')[copyIndex()],'-vm')]",
            "location": "[parameters('location')]",
            "dependsOn": [
                "nicCopy"
            ],
            "properties": {
                "hardwareProfile": {
                    "vmSize": "[parameters('vmSize')]"
                },
                "osProfile": {
                    "computerName": "[parameters('vmName')]",
                    "adminUsername": "[parameters('adminUsername')]",
                    "adminPassword": "[parameters('adminPassword')]"
                },
                "storageProfile": {
                    "imageReference": {
                        "publisher": "MicrosoftWindowsServer",
                        "offer": "WindowsServer",
                        "sku": "[parameters('OSVersion')]",
                        "version": "latest"
                    },
                    "osDisk": {
                        "createOption": "FromImage",
                        "managedDisk": {
                            "storageAccountType": "StandardSSD_LRS"
                        }
                    },
                    "dataDisks": [
                        {
                            "diskSizeGB": 10,
                            "lun": 0,
                            "createOption": "Empty"
                        }
                    ]
                },
                "networkProfile": {
                    "networkInterfaces": [
                        {
                            "id": "[resourceId('Microsoft.Network/networkInterfaces',concat(variables('baseNames')[copyIndex()],'-nic'))]"
                        }
                    ]
                },
                "diagnosticsProfile": {
                    "bootDiagnostics": {
                        "enabled": false
                    }
                }
            },
            "copy": {
                "name": "vmCopy",
                "count": "[variables('copies')]"
            }
        }
    ],
    "outputs": {}
}

Deploy the ARM template

Before deploying the template, save a copy of the template to your local machine. Save the template definition and use the following settings to deploy the resources:

NOTE: Do not try to create a new resource group, use the default (pre-defined) resource group for this lab.

Now, click on "Create" button.

Wait to some time to finish it deploying the resources. After that you will get "Your deployment is complete" message.

Now, click on "Go to resource group" to view the resources.

We can see two virtual machines got created ("primary-vm", "secondary-vm").

Update and re-deploy an ARM template

Click on "Deployments" to view the deployment and select the newly created deployment (click on the deployment name).

Now, click on "Template" and click "Download" to download the old template before modifying it.

Now, select "Overview" and click on "Redeploy" to redeploy the template.

Click on "Edit template".

Go to the variables section and add the following variables.

"bastionSubnetName": "AzureBastionSubnet",
"bastionPrefix": "10.0.1.0/24",
"bastionName":  "tempadv-bastion",
"bastionPipName": "tempadv-bastion-pip",
"bastionSubnetId":  "[resourceId('Microsoft.Network/virtualNetworks/subnets',variables('virtualNetworkName'),variables('bastionSubnetName'))]",
"bastionPipId": "[resourceId('Microsoft.Network/publicIPAddresses',variables('bastionPipName'))]"

Add the following json definition at the bottom of the resources element to provision a new public IP address:

{
  "name": "[variables('bastionPipName')]",
  "type": "Microsoft.Network/publicIPAddresses",
  "apiVersion": "2018-08-01",
  "location": "[resourceGroup().location]",
  "sku": {
      "name": "Standard"
  },
  "properties": {
      "publicIPAllocationMethod": "Static"
  }
},

Add the following json definition at the bottom of the resources element to provision a new subnet:

{
  "apiVersion": "2019-02-01",
  "type": "Microsoft.Network/virtualNetworks/subnets",
  "name": "[concat(variables('virtualNetworkName'), '/', variables('bastionSubnetName'))]",
  "location": "[resourceGroup().location]",
  "dependsOn": [
      "[resourceId('Microsoft.Network/virtualNetworks/', variables('virtualNetworkName'))]"
  ],
  "properties": {
      "addressPrefix": "[variables('bastionPrefix')]"
  }
},

Add the following json definition at the bottom of the resources element to provision a new Bastion host:

{
  "apiVersion": "2018-10-01",
  "type": "Microsoft.Network/bastionHosts",
  "name": "[variables('bastionName')]",
      "tags":{
      "displayName":"OP Bastion Host"
  },
  "location": "[resourceGroup().location]",
  "dependsOn": [
      "[variables('bastionPipId')]",
      "[variables('bastionSubnetId')]"
  ],
  "properties": {
      "ipConfigurations": [
          {
              "name": "IpConf",
              "properties": {
                  "subnet": {
                      "id": "[variables('bastionSubnetId')]"
                  },
                  "publicIPAddress": {
                      "id": "[variables('bastionPipId')]"
                  }
              }
          }
      ]
  }
}

Now click on "Save".

Your final template should look something like this:

{
    "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
    "contentVersion": "1.0.0.0",
    "parameters": {
        "adminUsername": {
            "type": "String",
            "metadata": {
                "description": "Username for the Virtual Machine."
            }
        },
        "adminPassword": {
            "minLength": 12,
            "type": "SecureString",
            "metadata": {
                "description": "Password for the Virtual Machine."
            }
        },
        "publicIpName": {
            "defaultValue": "myPublicIP",
            "type": "String",
            "metadata": {
                "description": "Name for the Public IP used to access the Virtual Machine."
            }
        },
        "publicIPAllocationMethod": {
            "defaultValue": "Dynamic",
            "allowedValues": [
                "Dynamic",
                "Static"
            ],
            "type": "String",
            "metadata": {
                "description": "Allocation method for the Public IP used to access the Virtual Machine."
            }
        },
        "publicIpSku": {
            "defaultValue": "Basic",
            "allowedValues": [
                "Basic",
                "Standard"
            ],
            "type": "String",
            "metadata": {
                "description": "SKU for the Public IP used to access the Virtual Machine."
            }
        },
        "OSVersion": {
            "defaultValue": "2022-datacenter-azure-edition-core",
            "allowedValues": [
                "2008-R2-SP1",
                "2008-R2-SP1-smalldisk",
                "2012-Datacenter",
                "2012-datacenter-gensecond",
                "2012-Datacenter-smalldisk",
                "2012-datacenter-smalldisk-g2",
                "2012-Datacenter-zhcn",
                "2012-datacenter-zhcn-g2",
                "2012-R2-Datacenter",
                "2012-r2-datacenter-gensecond",
                "2012-R2-Datacenter-smalldisk",
                "2012-r2-datacenter-smalldisk-g2",
                "2012-R2-Datacenter-zhcn",
                "2012-r2-datacenter-zhcn-g2",
                "2016-Datacenter",
                "2016-datacenter-gensecond",
                "2016-datacenter-gs",
                "2016-Datacenter-Server-Core",
                "2016-datacenter-server-core-g2",
                "2016-Datacenter-Server-Core-smalldisk",
                "2016-datacenter-server-core-smalldisk-g2",
                "2016-Datacenter-smalldisk",
                "2016-datacenter-smalldisk-g2",
                "2016-Datacenter-with-Containers",
                "2016-datacenter-with-containers-g2",
                "2016-datacenter-with-containers-gs",
                "2016-Datacenter-zhcn",
                "2016-datacenter-zhcn-g2",
                "2019-Datacenter",
                "2019-Datacenter-Core",
                "2019-datacenter-core-g2",
                "2019-Datacenter-Core-smalldisk",
                "2019-datacenter-core-smalldisk-g2",
                "2019-Datacenter-Core-with-Containers",
                "2019-datacenter-core-with-containers-g2",
                "2019-Datacenter-Core-with-Containers-smalldisk",
                "2019-datacenter-core-with-containers-smalldisk-g2",
                "2019-datacenter-gensecond",
                "2019-datacenter-gs",
                "2019-Datacenter-smalldisk",
                "2019-datacenter-smalldisk-g2",
                "2019-Datacenter-with-Containers",
                "2019-datacenter-with-containers-g2",
                "2019-datacenter-with-containers-gs",
                "2019-Datacenter-with-Containers-smalldisk",
                "2019-datacenter-with-containers-smalldisk-g2",
                "2019-Datacenter-zhcn",
                "2019-datacenter-zhcn-g2",
                "2022-datacenter",
                "2022-datacenter-azure-edition",
                "2022-datacenter-azure-edition-core",
                "2022-datacenter-azure-edition-core-smalldisk",
                "2022-datacenter-azure-edition-smalldisk",
                "2022-datacenter-core",
                "2022-datacenter-core-g2",
                "2022-datacenter-core-smalldisk",
                "2022-datacenter-core-smalldisk-g2",
                "2022-datacenter-g2",
                "2022-datacenter-smalldisk",
                "2022-datacenter-smalldisk-g2"
            ],
            "type": "String",
            "metadata": {
                "description": "The Windows version for the VM. This will pick a fully patched image of this given Windows version."
            }
        },
        "vmSize": {
            "defaultValue": "Standard_D2s_v5",
            "type": "String",
            "metadata": {
                "description": "Size of the virtual machine."
            }
        },
        "location": {
            "defaultValue": "[resourceGroup().location]",
            "type": "String",
            "metadata": {
                "description": "Location for all resources."
            }
        },
        "vmName": {
            "defaultValue": "simple-vm",
            "type": "String",
            "metadata": {
                "description": "Name of the virtual machine."
            }
        }
    },
    "variables": {
        "baseNames": [
            "primary",
            "secondary"
        ],
        "storageAccountName": "[format('bootdiags{0}', uniqueString(resourceGroup().id))]",
        "addressPrefix": "10.0.0.0/16",
        "subnetName": "Subnet",
        "subnetPrefix": "10.0.0.0/24",
        "virtualNetworkName": "MyVNET",
        "networkSecurityGroupName": "default-NSG",
        "copies": 2,
        "bastionSubnetName": "AzureBastionSubnet",
        "bastionPrefix": "10.0.1.0/24",
        "bastionName": "tempadv-bastion",
        "bastionPipName": "tempadv-bastion-pip",
        "bastionSubnetId": "[resourceId('Microsoft.Network/virtualNetworks/subnets',variables('virtualNetworkName'),variables('bastionSubnetName'))]",
        "bastionPipId": "[resourceId('Microsoft.Network/publicIPAddresses',variables('bastionPipName'))]"
    },
    "resources": [
        {
            "type": "Microsoft.Storage/storageAccounts",
            "apiVersion": "2021-04-01",
            "name": "[variables('storageAccountName')]",
            "location": "[parameters('location')]",
            "sku": {
                "name": "Standard_LRS"
            },
            "kind": "Storage"
        },
        {
            "type": "Microsoft.Network/publicIPAddresses",
            "apiVersion": "2021-02-01",
            "name": "[concat(variables('baseNames')[copyIndex()],'-pip')]",
            "location": "[parameters('location')]",
            "sku": {
                "name": "[parameters('publicIpSku')]"
            },
            "properties": {
                "publicIPAllocationMethod": "[parameters('publicIPAllocationMethod')]"
            },
            "copy": {
                "name": "pipCopy",
                "count": "[variables('copies')]"
            }
        },
        {
            "type": "Microsoft.Network/networkSecurityGroups",
            "apiVersion": "2021-02-01",
            "name": "[variables('networkSecurityGroupName')]",
            "location": "[parameters('location')]",
            "properties": {
                "securityRules": [
                    {
                        "name": "default-allow-3389",
                        "properties": {
                            "priority": 1000,
                            "access": "Allow",
                            "direction": "Inbound",
                            "destinationPortRange": "3389",
                            "protocol": "Tcp",
                            "sourcePortRange": "*",
                            "sourceAddressPrefix": "*",
                            "destinationAddressPrefix": "*"
                        }
                    }
                ]
            }
        },
        {
            "type": "Microsoft.Network/virtualNetworks",
            "apiVersion": "2021-02-01",
            "name": "[variables('virtualNetworkName')]",
            "location": "[parameters('location')]",
            "dependsOn": [
                "[resourceId('Microsoft.Network/networkSecurityGroups', variables('networkSecurityGroupName'))]"
            ],
            "properties": {
                "addressSpace": {
                    "addressPrefixes": [
                        "[variables('addressPrefix')]"
                    ]
                },
                "subnets": [
                    {
                        "name": "[variables('subnetName')]",
                        "properties": {
                            "addressPrefix": "[variables('subnetPrefix')]",
                            "networkSecurityGroup": {
                                "id": "[resourceId('Microsoft.Network/networkSecurityGroups', variables('networkSecurityGroupName'))]"
                            }
                        }
                    }
                ]
            }
        },
        {
            "type": "Microsoft.Network/networkInterfaces",
            "apiVersion": "2021-02-01",
            "name": "[concat(variables('baseNames')[copyIndex()],'-nic')]",
            "location": "[parameters('location')]",
            "dependsOn": [
                "pipCopy",
                "[resourceId('Microsoft.Network/virtualNetworks', variables('virtualNetworkName'))]"
            ],
            "properties": {
                "ipConfigurations": [
                    {
                        "name": "ipconfig1",
                        "properties": {
                            "privateIPAllocationMethod": "Dynamic",
                            "publicIPAddress": {
                                "id": "[resourceId('Microsoft.Network/publicIPAddresses',concat(variables('baseNames')[copyIndex()],'-pip'))]"
                            },
                            "subnet": {
                                "id": "[resourceId('Microsoft.Network/virtualNetworks/subnets', variables('virtualNetworkName'), variables('subnetName'))]"
                            }
                        }
                    }
                ]
            },
            "copy": {
                "name": "nicCopy",
                "count": "[variables('copies')]"
            }
        },
        {
            "type": "Microsoft.Compute/virtualMachines",
            "apiVersion": "2021-03-01",
            "name": "[concat(variables('baseNames')[copyIndex()],'-vm')]",
            "location": "[parameters('location')]",
            "dependsOn": [
                "nicCopy"
            ],
            "properties": {
                "hardwareProfile": {
                    "vmSize": "[parameters('vmSize')]"
                },
                "osProfile": {
                    "computerName": "[parameters('vmName')]",
                    "adminUsername": "[parameters('adminUsername')]",
                    "adminPassword": "[parameters('adminPassword')]"
                },
                "storageProfile": {
                    "imageReference": {
                        "publisher": "MicrosoftWindowsServer",
                        "offer": "WindowsServer",
                        "sku": "[parameters('OSVersion')]",
                        "version": "latest"
                    },
                    "osDisk": {
                        "createOption": "FromImage",
                        "managedDisk": {
                            "storageAccountType": "StandardSSD_LRS"
                        }
                    },
                    "dataDisks": [
                        {
                            "diskSizeGB": 10,
                            "lun": 0,
                            "createOption": "Empty"
                        }
                    ]
                },
                "networkProfile": {
                    "networkInterfaces": [
                        {
                            "id": "[resourceId('Microsoft.Network/networkInterfaces',concat(variables('baseNames')[copyIndex()],'-nic'))]"
                        }
                    ]
                },
                "diagnosticsProfile": {
                    "bootDiagnostics": {
                        "enabled": false
                    }
                }
            },
            "copy": {
                "name": "vmCopy",
                "count": "[variables('copies')]"
            }
        },
        {
            "type": "Microsoft.Network/publicIPAddresses",
            "apiVersion": "2018-08-01",
            "name": "[variables('bastionPipName')]",
            "location": "[resourceGroup().location]",
            "sku": {
                "name": "Standard"
            },
            "properties": {
                "publicIPAllocationMethod": "Static"
            }
        },
        {
            "type": "Microsoft.Network/virtualNetworks/subnets",
            "apiVersion": "2019-02-01",
            "name": "[concat(variables('virtualNetworkName'), '/', variables('bastionSubnetName'))]",
            "location": "[resourceGroup().location]",
            "dependsOn": [
                "[resourceId('Microsoft.Network/virtualNetworks/', variables('virtualNetworkName'))]"
            ],
            "properties": {
                "addressPrefix": "[variables('bastionPrefix')]"
            }
        },
        {
            "type": "Microsoft.Network/bastionHosts",
            "apiVersion": "2018-10-01",
            "name": "[variables('bastionName')]",
            "location": "[resourceGroup().location]",
            "dependsOn": [
                "[variables('bastionPipId')]",
                "[variables('bastionSubnetId')]"
            ],
            "tags": {
                "displayName": "OP Bastion Host"
            },
            "properties": {
                "ipConfigurations": [
                    {
                        "name": "IpConf",
                        "properties": {
                            "subnet": {
                                "id": "[variables('bastionSubnetId')]"
                            },
                            "publicIPAddress": {
                                "id": "[variables('bastionPipId')]"
                            }
                        }
                    }
                ]
            }
        }
    ],
    "outputs": {}
}

Re-deploy the template with the same parameter settings.

Click on "Review + create".

Click on "Create".

Wait for some time to finish it deploying.

Now, the deployment is finished, click on "Go to resource group" to view resources.

Select the "primary-vm".

Click on connect and select "Bastion"

Enter the "Username" and "Password" that you used while deploying the template.

Now, click on "Connect".

We successfully got connected to a VM via Bastion host.

This lab is Now completed.