Related
Is it only possible to create one on-demand SFPT Server with one Resource group in Azure?
This is a link regards to SFPT on Azure. https://learn.microsoft.com/en-us/samples/azure-samples/sftp-creation-template/sftp-on-azure/
I tried to create a second SFPT in the same Resource group, but previous SFPT got replaced with the new one.
I tried Goolging on this one, but I was not able to find the answer, so I am posting this question here.
Yes we can deploy multiple SFTP server to our Azure resource group.
But the template you are using already they have declare default variables ,Instead of that we need to declare parameters as shown in below template, So that you can use the same template multiple times.
TEMPLATE:-
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"metadata": {
"_generator": {
"name": "bicep",
"version": "0.4.63.48766",
"templateHash": "17013458610905703770"
}
},
"parameters": {
"storageAccountType": {
"type": "string",
"defaultValue": "Standard_LRS",
"metadata": {
"description": "Storage account type"
},
"allowedValues": [
"Standard_LRS",
"Standard_ZRS",
"Standard_GRS"
]
},
"storageAccountPrefix": {
"type": "string",
"defaultValue": "sftpstg",
"metadata": {
"description": "Prefix for new storage account"
}
},
"fileShareName": {
"type": "string",
"defaultValue": "sftpfileshare",
"metadata": {
"description": "Name of file share to be created"
}
},
"sftpUser": {
"type": "string",
"defaultValue": "sftp",
"metadata": {
"description": "Username to use for SFTP access"
}
},
"sftpPassword": {
"type": "securestring",
"metadata": {
"description": "Password to use for SFTP access"
}
},
"location": {
"type": "string",
"defaultValue": "[resourceGroup().location]",
"metadata": {
"description": "Primary location for resources"
}
},
"containerGroupDNSLabel": {
"type": "string",
"defaultValue": "[uniqueString(resourceGroup().id, deployment().name)]",
"metadata": {
"description": "DNS label for container group"
}
},
"sftpContainerGroupName": {
"type": "string",
"metadata": {
"description": "cngroup for container group"
}
},
"sftpContainerName": {
"type": "string",
"metadata": {
"description": "container name"
}
}
},
"functions": [],
"variables": {
"sftpContainerImage": "atmoz/sftp:debian",
"sftpEnvVariable": "[format('{0}:{1}:1001', parameters('sftpUser'), parameters('sftpPassword'))]",
"storageAccountName": "[take(toLower(format('{0}{1}', parameters('storageAccountPrefix'), uniqueString(resourceGroup().id))), 24)]"
},
"resources": [
{
"type": "Microsoft.Storage/storageAccounts",
"apiVersion": "2019-06-01",
"name": "[variables('storageAccountName')]",
"location": "[parameters('location')]",
"kind": "StorageV2",
"sku": {
"name": "[parameters('storageAccountType')]"
}
},
{
"type": "Microsoft.Storage/storageAccounts/fileServices/shares",
"apiVersion": "2019-06-01",
"name": "[toLower(format('{0}/default/{1}', variables('storageAccountName'), parameters('fileShareName')))]",
"dependsOn": [
"[resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName'))]"
]
},
{
"type": "Microsoft.ContainerInstance/containerGroups",
"apiVersion": "2019-12-01",
"name": "[parameters('sftpContainerGroupName')]",
"location": "[parameters('location')]",
"properties": {
"containers": [
{
"name": "[parameters('sftpContainerName')]",
"properties": {
"image": "[variables('sftpContainerImage')]",
"environmentVariables": [
{
"name": "SFTP_USERS",
"secureValue": "[variables('sftpEnvVariable')]"
}
],
"resources": {
"requests": {
"cpu": 1,
"memoryInGB": 1
}
},
"ports": [
{
"port": 22,
"protocol": "TCP"
}
],
"volumeMounts": [
{
"mountPath": "[format('/home/{0}/upload', parameters('sftpUser'))]",
"name": "sftpvolume",
"readOnly": false
}
]
}
}
],
"osType": "Linux",
"ipAddress": {
"type": "Public",
"ports": [
{
"port": 22,
"protocol": "TCP"
}
],
"dnsNameLabel": "[parameters('containerGroupDNSLabel')]"
},
"restartPolicy": "OnFailure",
"volumes": [
{
"name": "sftpvolume",
"azureFile": {
"readOnly": false,
"shareName": "[parameters('fileShareName')]",
"storageAccountName": "[variables('storageAccountName')]",
"storageAccountKey": "[listKeys(resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName')), '2019-06-01').keys[0].value]"
}
}
]
},
"dependsOn": [
"[resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName'))]"
]
}
],
"outputs": {
"containerDNSLabel": {
"type": "string",
"value": "[format('{0}.{1}.azurecontainer.io', reference(resourceId('Microsoft.ContainerInstance/containerGroups', parameters('sftpContainerGroupName'))).ipAddress.dnsNameLabel, reference(resourceId('Microsoft.ContainerInstance/containerGroups', parameters('sftpContainerGroupName')), '2019-12-01', 'full').location)]"
}
}
}
Deployment details:-
I'm currently facing an issue with nested template.
When I'm applying my template (detail below), I get this answer from Azure:
Azure Error: InvalidTemplate
Message: Deployment template validation failed: 'The template reference 'sandbox.test.portal' is not valid: could not find template resource or resource copy with this name. Please see https://aka.ms/arm-template-expressions/#reference for usage details.'.
However, I don't really understand why I get this issue, because for the content inside the nested template, I used what they provide in the documentation here: https://github.com/Azure/azure-quickstart-templates/blob/master/101-azure-dns-new-zone/azuredeploy.json
My ARM template:
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"location": {
"type": "string",
"defaultValue": "[resourceGroup().location]",
"metadata": {
"description": "Location for all resources."
}
},
"newZoneName": {
"type": "string",
"defaultValue": "sandbox.test.portal",
"metadata": {
"description": "The name of the DNS zone to be created. Must have at least 2 segements, e.g. hostname.org"
}
},
"newRecordName": {
"type": "string",
"defaultValue": "www",
"metadata": {
"description": "The name of the DNS record to be created. The name is relative to the zone, not the FQDN."
}
}
},
"variables": {
"publicIPAddressName": "[concat(resourceGroup().name, '-pip')]",
},
"resources": [
{
"apiVersion": "2015-06-15",
"type": "Microsoft.Network/publicIPAddresses",
"name": "[variables('publicIPAddressName')]",
"location": "[parameters('location')]",
"properties": {
"publicIPAllocationMethod": "Dynamic",
"dnsSettings": {
"domainNameLabel": "[parameters('dnsLabelPrefix')]"
}
}
},
{
"apiVersion": "2017-05-10",
"name": "nestedTemplate",
"type": "Microsoft.Resources/deployments",
"resourceGroup": "my-rg",
"subscriptionId": "[subscription().subscriptionId]",
"properties": {
"mode": "Incremental",
"template": {
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
},
"variables": {
},
"resources": [
{
"type": "Microsoft.Network/dnszones",
"name": "[parameters('newZoneName')]",
"apiVersion": "2016-04-01",
"location": "global",
"properties": {
}
},
{
"type": "Microsoft.Network/dnszones/a",
"name": "[concat(parameters('newZoneName'), '/', parameters('newRecordName'))]",
"apiVersion": "2016-04-01",
"location": "global",
"dependsOn": [
"[parameters('newZoneName')]"
],
"properties": {
"TTL": 3600,
"ARecords": [
{
"ipv4Address": "1.2.3.4"
},
{
"ipv4Address": "1.2.3.5"
}
]
}
}
],
"outputs": {
"nameServers": {
"type": "array",
"value": "[reference(parameters('newZoneName')).nameServers]"
}
}
}
}
}
]
}
basically, you need to remove the outputs from the nested inline template, so remove this bit:
"outputs": {
"nameServers": {
"type": "array",
"value": "[reference(parameters('newZoneName')).nameServers]"
}
}
long story short, nested inline deployments are bad. dont use them.
alternatively move those to the parent template and do a real lookup:
reference(resourceId('Microsoft.Network/dnszones', parameters('newZoneName')))
You have several minor mistakes in your template:
Comma in variables '-pip')]",
Undefined parameter dnsLabelPrefix
The general mistake in nested outputs. When you use nested templates azure don't find it in your main template. Therefore you must use a reference function with identifier and API: "[reference(resourceId('Microsoft.Network/dnszones', parameters('newZoneName')), '2016-04-01').nameServers]".
I modified your template and validate in my subscription.
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"newZoneName": {
"type": "string",
"defaultValue": "sandbox.test.portal",
"metadata": {
"description": "The name of the DNS zone to be created. Must have at least 2 segements, e.g. hostname.org"
}
},
"newRecordName": {
"type": "string",
"defaultValue": "www",
"metadata": {
"description": "The name of the DNS record to be created. The name is relative to the zone, not the FQDN."
}
},
"dnsLabelPrefix": {
"type": "string",
"defaultValue": "[concat('dns',uniqueString(resourceGroup().name))]"
},
"nestedResourceGroup": {
"type": "string",
"defaultValue": "my-rg",
"metadata": {
"description": "my-rg"
}
}
},
"variables": {
"publicIPAddressName": "[concat(resourceGroup().name, '-pip')]"
},
"resources": [
{
"apiVersion": "2015-06-15",
"type": "Microsoft.Network/publicIPAddresses",
"name": "[variables('publicIPAddressName')]",
"location": "[resourceGroup().location]",
"properties": {
"publicIPAllocationMethod": "Dynamic",
"dnsSettings": {
"domainNameLabel": "[parameters('dnsLabelPrefix')]"
}
}
},
{
"apiVersion": "2017-05-10",
"name": "nestedTemplate",
"type": "Microsoft.Resources/deployments",
"resourceGroup": "[parameters('nestedResourceGroup')]",
"subscriptionId": "[subscription().subscriptionId]",
"properties": {
"mode": "Incremental",
"template": {
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
},
"variables": {
},
"resources": [
{
"type": "Microsoft.Network/dnszones",
"name": "[parameters('newZoneName')]",
"apiVersion": "2016-04-01",
"location": "global",
"properties": {
}
},
{
"type": "Microsoft.Network/dnszones/a",
"name": "[concat(parameters('newZoneName'), '/', parameters('newRecordName'))]",
"apiVersion": "2016-04-01",
"location": "global",
"dependsOn": [
"[resourceId('Microsoft.Network/dnszones', parameters('newZoneName'))]"
],
"properties": {
"TTL": 3600,
"ARecords": [
{
"ipv4Address": "1.2.3.4"
},
{
"ipv4Address": "1.2.3.5"
}
]
}
}
],
"outputs": {
"nameServers": {
"type": "array",
"value": "[reference(resourceId('Microsoft.Network/dnszones', parameters('newZoneName')), '2016-04-01').nameServers]"
}
}
}
}
}
]
}
Have a nice day!
With the following ARM template, I deploy an Azure Databricks with a custom managed Resource Group Name and add the workers to a custom VNET. In the portal this works fine. But When I try to do this inside an ARM template the managed resource groups keep deploying a workers vnet for the workers. I am thinking that I am on the right track but missing one setting. But can't figure it out. Is there anyone who can see what I am missing ?
Source ARM: https://github.com/Azure/azure-quickstart-templates/tree/master/101-databricks-workspace-with-vnet-injection
{
"$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json",
"contentVersion": "1.0.0.0",
"parameters": {
"databricksName": {
"type": "string",
"metadata": {
"description": "The name of the databricks workspace"
}
},
"pricingTier": {
"type": "string",
"allowedValues": [
"trial",
"standard",
"premium"
],
"metadata": {
"description": "The pricing tier of workspace."
}
},
"managedResourceGroupName": {
"type": "string",
"metadata": {
"description": "The name of the managed resource group that databricks will create"
}
},
"Location": {
"type": "string",
"defaultValue": "[resourceGroup().location]",
"metadata": {
"description": "The Location of the deployment"
}
},
"vnetName": {
"type": "string",
"metadata": {
"description": "The Name of the virtual network where the Workers would be connected to"
}
},
"privateSubnetName": {
"defaultValue": "public-subnet",
"type": "string",
"metadata": {
"description": "The name of the private subnet to create."
}
},
"publicSubnetName": {
"defaultValue": "private-subnet",
"type": "string",
"metadata": {
"description": "The name of the public subnet to create."
}
}
},
"variables": {
"ManagedResourceGroupId": "[concat(subscription().id, '/resourceGroups/', parameters('managedResourceGroupName'))]",
"vnetId": "[resourceId('Microsoft.Network/virtualNetworks', parameters('vnetName'))]"
},
"resources": [
{
"name": "[parameters('databricksName')]",
"type": "Microsoft.Databricks/workspaces",
"apiVersion": "2018-04-01",
"tags": {
"description": "MIG6 databricks workspace",
"costCenter": "WPIPM12SG552"
},
"location": "[parameters('Location')]",
"properties": {
"managedResourceGroupId": "[variables('managedResourceGroupId')]",
"parameters": {
"customVirtualNetworkId": {
"value": "[variables('vnetId')]"
},
"customPublicSubnetName": {
"value": "[parameters('publicSubnetName')]"
},
"customPrivateSubnetName": {
"value": "[parameters('privateSubnetName')]"
}
}
},
"sku": {
"name": "[parameters('pricingTier')]"
}
}
]
}
You need to nest the vnet in the template, this works for me:
{
"$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"vnetName": {
"type": "string"
},
"vnetRG": {
"type": "string"
},
"publicSubnetName": {
"type": "string"
},
"publicSubnetCIDR": {
"type": "string"
},
"privateSubnetName": {
"type": "string"
},
"privateSubnetCIDR": {
"type": "string"
},
"workspaceName": {
"type": "string"
},
"tier": {
"type": "string"
},
"location": {
"type": "string"
},
"nsgName": {
"defaultValue": "databricks-nsg",
"type": "string"
},
"environment": {
"type": "string"
}
},
"resources": [
{
"apiVersion": "2017-05-10",
"name": "nestedTemplate",
"type": "Microsoft.Resources/deployments",
"resourceGroup": "[parameters('vnetRG')]",
"properties": {
"mode": "Incremental",
"template": {
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {},
"variables": {},
"resources": [
{
"apiVersion": "2018-04-01",
"type": "Microsoft.Network/virtualNetworks/subnets",
"name": "[concat(parameters('vnetName'), '/', parameters('publicSubnetName'))]",
"location": "[parameters('location')]",
"properties": {
"addressPrefix": "[parameters('publicSubnetCIDR')]",
"networkSecurityGroup": {
"id": "[variables('nsgId')]"
}
}
},
{
"apiVersion": "2018-04-01",
"type": "Microsoft.Network/virtualNetworks/subnets",
"name": "[concat(parameters('vnetName'), '/', parameters('privateSubnetName'))]",
"location": "[parameters('location')]",
"dependsOn": [
"[concat('Microsoft.Network/virtualNetworks/', parameters('vnetName'), '/subnets/', parameters('publicSubnetName'))]"
],
"properties": {
"addressPrefix": "[parameters('privateSubnetCIDR')]",
"networkSecurityGroup": {
"id": "[variables('nsgId')]"
}
}
}
]
},
"parameters": {}
}
},
{
"apiVersion": "2018-04-01",
"type": "Microsoft.Databricks/workspaces",
"location": "[parameters('location')]",
"name": "[parameters('workspaceName')]",
"dependsOn": [
"['Microsoft.Resources/deployments/nestedTemplate']"
],
"sku": {
"name": "[parameters('tier')]"
},
"comments": "Please do not use an existing resource group for ManagedResourceGroupId.",
"properties": {
"ManagedResourceGroupId": "[variables('managedResourceGroupId')]",
"parameters": {
"customVirtualNetworkId": {
"value": "[variables('vnetId')]"
},
"customPublicSubnetName": {
"value": "[parameters('publicSubnetName')]"
},
"customPrivateSubnetName": {
"value": "[parameters('privateSubnetName')]"
}
}
}
}
],
"variables": {
"managedResourceGroupId": "[concat(subscription().id, '/resourceGroups/', variables('managedResourceGroupName'))]",
"managedResourceGroupName": "[concat(resourceGroup().name,'-DATABRICKS-MANAGED')]",
"vnetId": "[concat('/subscriptions/', subscription().subscriptionId, '/resourceGroups/', parameters('vnetRG'), '/providers/Microsoft.Network/virtualNetworks/', parameters('vnetName'))]",
"nsgId": "[concat('/subscriptions/', subscription().subscriptionId, '/resourceGroups/', parameters('vnetRG'), '/providers/Microsoft.Network/networkSecurityGroups/', parameters('nsgName'))]"
},
"outputs": {}
}
I am trying to send array of email values as parameters and trying to deploy 'Action group' using 'Copy' in the resource template .My Action group template is getting deployed without errors but email fields are empty. I was passing two email values as parameters. I'm stuck with this for a day. It would be great if someone throw some lights on where i am going wrong.
Template.json:
{
"$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"actionGroupName": {
"type": "string",
"defaultValue": "newActionGroup",
"metadata": {
"description": "Unique name (within the Resource Group) for the Action group."
}
},
"actionGroupShortName": {
"type": "string",
"defaultValue": "newActionGroup",
"metadata": {
"description": "Short name (maximum 12 characters) for the Action group."
}
},
"emailReceiverName": {
"type": "array",
"metadata": {
"description": "email receiver service Name."
}
},
"emailReceiverAddress": {
"type": "array",
"metadata": {
"description": "email receiver address."
}
}
},
"variables": {
"customemailReceiverName": "[array(parameters('emailReceiverName'))]",
"customemailReceiverAddress": "[parameters('emailReceiverAddress')]"
},
"resources": [
{
"type": "Microsoft.Insights/actionGroups",
"name": "[parameters('actionGroupName')]",
"apiVersion": "2018-03-01",
"location": "Global",
"properties": {
"groupShortName": "[parameters('actionGroupShortName')]",
"copy": [
{
"name": "counts",
"count": "[length(parameters('emailReceiverName'))]",
"input": {
"emailReceivers": [
{
"name": "[parameters('emailReceiverName')[copyIndex('counts')]",
"emailAddress": "[parameters('emailReceiverAddress')[copyIndex('counts')]]"
}
]
}
}
]
}
}
] }
Parameter.json:
{
"$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"actionGroupName": {
"value": "actiongroupslb"
},
"actionGroupShortName": {
"value": "agSLB"
},
"emailReceiverName": {
"value": ["siva","siva1"]
},
"emailReceiverAddress": {
"value": ["siva#gmail.com","svaji#gmail.com"]
}
}
}
Action group created with missing email values
Here's whats working for me:
{
"type": "Microsoft.Insights/actionGroups",
"apiVersion": "2018-03-01",
"name": "[variables('actionGroups')[copyIndex()].Name]",
"copy": {
"name": "ActionGroupCopy",
"count": "[length(parameters('emailReceiverName'))]"
},
"location": "Global",
"properties": {
"groupShortName": "[variables('actionGroups')[copyIndex()].Name]",
"enabled": true,
"emailReceivers": [
{
"name": "[variables('actionGroups')[copyIndex()].EmailName]",
"emailAddress": "[variables('actionGroups')[copyIndex()].EmailAddress]"
}
]
}
},
Here's the variable:
"actionGroups": [
{
"Name": "teamname",
"EmailAddress": "email#domain.com",
"EmailName": "emailname"
},
{
"Name": "teamname1",
"EmailAddress": "email1#domain.com",
"EmailName": "emailname1"
}
],
If you need multiple receivers, use the resource property copy function, not resource:
{
"type": "Microsoft.Insights/actionGroups",
"apiVersion": "2018-03-01",
"name": "name",
"location": "Global",
"properties": {
"groupShortName": "name",
"enabled": true,
"copy": [
{
"name": "emailReceivers",
"count": "[length(parameters('emailReceiverName'))]",
"input": {
"name": "[parameters('emailReceiverName')[copyIndex('emailReceivers')]]",
"emailAddress": "[parameters('emailReceiverAddress')[copyIndex('emailReceivers')]]"
}
}
]
}
},
this is assuming they map 1-to-1
I am trying to deploy the below Palo Alto deployment to an Azure environment. We are using it as an internal firewall for the various features it provides that NSGs don't, so we don't want a public IP. We're using a virtual gateway and sticking the firewall behind it in an active-active pair (the load balancer, NSGs, etc. are being done in a separate template).
I've been trying to get this template to work for a while now, but I'm stuck on deploying the two VMs with multiple NICs. I keep getting this error:
ERROR: Azure Error: InvalidTemplate
Message: Deployment template validation failed: 'The template variable 'nicName' is not valid: The template function 'copyIndex' is not expected at this location. The function can only be used in a resource with copy specified. Please see https://aka.ms/arm-copy for usage details.. Please see https://aka.ms/arm-template-expressions for usage details.'.
I've tried a bunch of fixes - changing the variable syntax, changing the syntax of the resource, but none of them are working. I've checked the Azure documentation on using the copyIndex feature, but I can't see where I'm going wrong. I was hoping someone with a bit more experience could point out where my syntax is wrong and provide suggestions on how to correct it?
Many thanks, template is below:
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"LoadBalancerSku": {
"type": "string",
"allowedValues": [
"Standard",
"Basic"
],
"metadata": {
"description": "Std LB load balances across all the ports where as Basic LB load balances on a port-to-port basis"
},
"defaultValue": "Standard"
},
"storageName": {
"type": "string",
"metadata": {
"description": "Name of the storage account created to store the VM's disks. Storage account name must be globally unique."
},
"defaultValue": "Enter a globally unique name"
},
"mgmtPublicIPDns": {
"type": "string",
"metadata": {
"description": "DNS Name prefix of public IP resource for Management interface of VM-Series firewall. Name must be globally unique."
},
"defaultValue": "Enter a globally unique name"
},
"networkSecurityGroupName": {
"type": "string",
"defaultValue": "nsg",
"metadata": {
"description": "Network Security Group Name"
}
},
"networkSecurityGroupInboundIP": {
"type": "string",
"metadata": {
"description": "Your source public IP address. Added to the inbound NSG on eth0 (MGMT), to restrict access to the deployment."
},
"defaultValue": "1.1.1.1/32"
},
"avSetName": {
"type": "string",
"metadata": {
"description": "Name of the availability set for outbound firewall"
},
"defaultValue": "outbound-avset"
},
"storageType": {
"type": "string",
"allowedValues": [
"Standard_LRS",
"Standard_GRS",
"Premium_LRS",
"Standard_RAGRS"
],
"metadata": {
"description": "Type of the storage account created"
},
"defaultValue": "Standard_LRS"
},
"virtualNetworkName": {
"type": "string",
"defaultValue": "firewall-test",
"metadata": {
"description": "Virtual Network Name"
}
},
"virtualNetworkAddressPrefix": {
"type": "string",
"defaultValue": "10.0.0.0/16",
"metadata": {
"description": "CIDR for Virtual Network"
}
},
"mgmtSubnetName": {
"type": "string",
"defaultValue": "Mgmt",
"metadata": {
"description": "Subnet for Management Network"
}
},
"mgmtSubnetPrefix": {
"type": "string",
"defaultValue": "10.0.0.0/24",
"metadata": {
"description": "CIDR for Management Network"
}
},
"untrustSubnetName": {
"type": "string",
"defaultValue": "Untrust",
"metadata": {
"description": "Subnet for Untrusted Network"
}
},
"untrustSubnetPrefix": {
"type": "string",
"defaultValue": "10.0.1.0/24",
"metadata": {
"description": "CIDR for Untrusted Network"
}
},
"trustSubnetName": {
"type": "string",
"defaultValue": "Trust",
"metadata": {
"description": "Subnet for Trusted Network"
}
},
"trustSubnetPrefix": {
"type": "string",
"defaultValue": "10.0.2.0/24",
"metadata": {
"description": "CIDR for Trusted Network"
}
},
"mgmtPublicIPName": {
"type": "string",
"metadata": {
"description": "Name prefix of public IP resource for Management interface of VM-Series firewall."
},
"defaultValue": "mgmt-pip"
},
"loadBalancerName": {
"type": "string",
"metadata": {
"description": "Name for the outbound load balancer resource."
},
"defaultValue": "outbound-lb"
},
"loadBalancerIP": {
"type": "string",
"metadata": {
"description": "IP Address for the outbound load balancer resource in the Trust network."
},
"defaultValue": "10.0.2.4"
},
"imageSku": {
"type": "string",
"defaultValue": "bundle1",
"allowedValues": [
"byol",
"bundle1",
"bundle2"
],
"metadata": {
"description": "byol = Bring Your Own License; bundle1 = Bundle 1 PAYG (Hourly); bundle2 = Bundle 2 PAYG (Hourly)"
}
},
"virtualMachineName": {
"type": "string",
"metadata": {
"description": "Name prefix of VM-Series VM in the Azure portal"
},
"defaultValue": "outbound-vm-series"
},
"vmSize": {
"type": "string",
"allowedValues": [
"Standard_D3",
"Standard_D4",
"Standard_D3_v2",
"Standard_D4_v2",
"Standard_D5_v2",
"Standard_D14_v2",
"Standard_A4"
],
"metadata": {
"description": "Azure VM size for VM-Series"
},
"defaultValue": "Standard_D3_v2"
},
"authenticationType": {
"type": "string",
"metadata": {
"description": "Type of administrator user authentication "
},
"allowedValues": [
"sshPublicKey",
"password"
],
"defaultValue": "password"
},
"adminUsername": {
"type": "string",
"defaultValue": "pandemo",
"metadata": {
"description": "Username of the administrator account of VM instances"
}
},
"adminPassword": {
"type": "securestring",
"defaultValue": "Dem0pa$$w0rd",
"metadata": {
"description": "Password for the administrator account of all VM instances. This must be specified if Authentication Type is 'password'."
}
},
"sshKey": {
"type": "string",
"defaultValue": "",
"metadata": {
"description": "SSH RSA public key file as a string. Must be specified if Authentication Type is 'sshPublicKey'."
}
},
"vmCount": {
"type": "int",
"defaultValue": 2,
"metadata": {
"description": "Number of VM-Series firewall"
}
}
},
"variables": {
"baseUrl": "http://git.lr.net/Azure/management/firewall/tree/master/azure-pan-hub",
"deployStorageURL": "[concat(variables('baseUrl'),'/deployStorage.json')]",
"deployVnetURL": "[concat(variables('baseUrl'),'/deployVnet.json')]",
"deployFirewallURL": "[concat(variables('baseUrl'),'/deployFirewall.json')]",
"location": "[resourceGroup().location]",
"rgname": "[resourceGroup().name]",
"nicName": "[concat(parameters('virtualMachineName'), copyindex())]",
"imagePublisher": "paloaltonetworks",
"imageOffer": "vmseries1",
"version": "latest",
"vnetname": "[parameters('virtualNetworkName')]",
"vnetID": "[resourceId('Microsoft.Network/virtualNetworks',variables('vnetname'))]",
"mgmtSubnetRef": "[concat(variables('vnetID'),'/subnets/',parameters('mgmtSubnetName'))]",
"untrustSubnetRef": "[concat(variables('vnetID'),'/subnets/',parameters('untrustSubnetName'))]",
"trustSubnetRef": "[concat(variables('vnetID'),'/subnets/',parameters('trustSubnetName'))]",
"subnets": [
{
"name": "[parameters('mgmtSubnetName')]",
"properties": {
"addressPrefix": "[parameters('mgmtSubnetPrefix')]"
}
},
{
"name": "[parameters('untrustSubnetName')]",
"properties": {
"addressPrefix": "[parameters('untrustSubnetPrefix')]"
}
},
{
"name": "[parameters('trustSubnetName')]",
"properties": {
"addressPrefix": "[parameters('trustSubnetPrefix')]"
}
}
]
},
"resources": [
{
"name": "deployStorage",
"type": "Microsoft.Resources/deployments",
"apiVersion": "2015-01-01",
"properties": {
"mode": "Incremental",
"template": {
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"resources": [
{
"type": "Microsoft.Storage/storageAccounts",
"name": "[parameters('storageName')]",
"apiVersion": "2015-06-15",
"location": "[variables('location')]",
"properties": {
"accountType": "[parameters('storageType')]"
}
}
]
}
}
},
{
"name": "deployVnet",
"type": "Microsoft.Resources/deployments",
"apiVersion": "2017-05-10",
"properties": {
"mode": "Incremental",
"template": {
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"resources": [
{
"type": "Microsoft.Network/virtualNetworks",
"apiVersion": "2015-06-15",
"location": "[variables('location')]",
"name": "[variables('vnetname')]",
"properties": {
"addressSpace": {
"addressPrefixes": [
"[parameters('virtualNetworkAddressPrefix')]"
]
},
"subnets": "[variables('subnets')]"
}
}
]
}
}
},
{
"name": "deployAvailabilitySet",
"type": "Microsoft.Resources/deployments",
"apiVersion": "2015-01-01",
"dependsOn": [
"Microsoft.Resources/deployments/deployStorage",
"Microsoft.Resources/deployments/deployVNet"
],
"properties": {
"mode": "Incremental",
"template": {
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"resources": [
{
"apiVersion": "2015-05-01-preview",
"type": "Microsoft.Compute/availabilitySets",
"name": "[parameters('avSetName')]",
"location": "[variables('location')]"
}
]
}
}
},
{
"name": "deployMgmtNetworkInterface",
"type": "Microsoft.Resources/deployments",
"apiVersion": "2018-08-01",
"dependsOn": [
"Microsoft.Resources/deployments/deployStorage",
"Microsoft.Resources/deployments/deployVNet"
],
"properties": {
"mode": "Incremental",
"template": {
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"resources": [
{
"name": "[concat(parameters('virtualMachineName'), copyindex(), '-nic0')]",
"type": "Microsoft.Network/networkInterfaces",
"location": "[variables('location')]",
"apiVersion": "2015-06-15",
"dependsOn": [
"[concat('Microsoft.Network/publicIPAddresses/', parameters('mgmtPublicIPName'), copyindex())]"
],
"copy": {
"name": "nicLoop",
"count": "[parameters('vmCount')]"
},
"properties": {
"ipConfigurations": [
{
"name": "ipconfig-mgmt",
"properties": {
"privateIPAllocationMethod": "Dynamic",
"subnet": {
"id": "[concat(variables('vnetId'),'/subnets/', parameters ('mgmtSubnetName'))]"
}
}
}
]
}
}
]
}
}
},
{
"name": "deployUntrustNetworkInterface",
"type": "Microsoft.Resources/deployments",
"apiVersion": "2018-08-01",
"dependsOn": [
"Microsoft.Resources/deployments/deployStorage",
"Microsoft.Resources/deployments/deployVNet"
],
"properties": {
"mode": "Incremental",
"template": {
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"resources": [
{
"name": "[concat(parameters('virtualMachineName'), copyindex(), '-nic1-std')]",
"type": "Microsoft.Network/networkInterfaces",
"location": "[variables('location')]",
"apiVersion": "2015-06-15",
"copy": {
"name": "nicLoop",
"count": "[parameters('vmCount')]"
},
"properties": {
"enableIPForwarding": true,
"ipConfigurations": [
{
"name": "ipconfig-untrust",
"properties": {
"privateIPAllocationMethod": "Dynamic",
"subnet": {
"id": "[concat(variables('vnetId'),'/subnets/', parameters ('untrustSubnetName'))]"
}
}
}
]
}
}
]
}
}
},
{
"name": "deploytrustNetworkInterface",
"type": "Microsoft.Resources/deployments",
"apiVersion": "2018-08-01",
"dependsOn": [
"Microsoft.Resources/deployments/deployStorage",
"Microsoft.Resources/deployments/deployVNet"
],
"properties": {
"mode": "Incremental",
"template": {
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"resources": [
{
"name": "[concat(parameters('virtualMachineName'), copyindex(), '-nic2')]",
"type": "Microsoft.Network/networkInterfaces",
"location": "[variables('location')]",
"apiVersion": "2015-06-15",
"copy": {
"name": "nicLoop",
"count": "[parameters('vmCount')]"
},
"properties": {
"enableIPForwarding": true,
"ipConfigurations": [
{
"name": "ipconfig-trust",
"properties": {
"privateIPAllocationMethod": "Dynamic",
"subnet": {
"id": "[concat(variables('vnetId'),'/subnets/', parameters ('trustSubnetName'))]"
}
}
}
]
}
}
]
}
}
},
{
"name": "[concat(parameters('virtualMachineName'), '-std-', copyindex())]",
"type": "Microsoft.Resources/deployments",
"apiVersion": "2018-08-01",
"dependsOn": [
"[concat('Microsoft.Network/networkInterfaces/', parameters('virtualMachineName'), copyindex(), '-nic0')]",
"[concat('Microsoft.Network/networkInterfaces/', parameters('virtualMachineName'), copyindex(), '-nic1-std')]",
"[concat('Microsoft.Network/networkInterfaces/', parameters('virtualMachineName'), copyindex(), '-nic2')]"
],
"copy": {
"name": "vmLoop",
"count": "[parameters('vmCount')]"
},
"properties": {
"mode": "Incremental",
"template": {
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"resources": [
{
"type": "Microsoft.Compute/virtualMachines",
"name": "[concat(parameters('virtualMachineName'), '-std')]",
"location": "[variables('location')]",
"apiVersion": "2015-05-01-preview",
"plan": {
"name": "[parameters('imageSku')]",
"product": "[variables('imageOffer')]",
"publisher": "[variables('imagePublisher')]"
},
"properties": {
"hardwareProfile": {
"vmSize": "[parameters('vmSize')]"
},
"osProfile": {
"computerName": "[parameters('virtualMachineName')]",
"adminUsername": "[parameters('adminUsername')]",
"adminPassword": "[parameters('adminPassword')]"
},
"storageProfile": {
"imageReference": {
"publisher": "[variables('imagePublisher')]",
"offer": "[variables('imageOffer')]",
"sku": "[parameters('imageSku')]",
"version": "latest"
},
"osDisk": {
"name": "osdisk",
"vhd": {
"uri": "[concat('http://', parameters('storageName'), '.blob.core.windows.net/vhds/', parameters('virtualMachineName'), '-', variables('imageOffer'), '-', parameters('imageSku'), '.vhd')]"
},
"caching": "ReadWrite",
"createOption": "FromImage"
}
},
"networkProfile": {
"networkInterfaces": [
{
"id": "[resourceId('Microsoft.Network/networkInterfaces', concat(variables('nicName'),'-nic0'))]",
"properties": {
"primary": true
}
},
{
"id": "[resourceId('Microsoft.Network/networkInterfaces', concat(variables('nicName'),'-nic1-std'))]",
"properties": {
"primary": false
}
},
{
"id": "[resourceId('Microsoft.Network/networkInterfaces', concat(variables('nicName'),'-nic2'))]",
"properties": {
"primary": false
}
}
]
}
}
}
]
}
}
}
]
}
so in general with loops, you can only use copyIndex() function inside loops (and you are trying to use it outside of loop). with variables you can use this (same method applies to property loops):
"variables": {
"copy": [
{
"name": "real_var_name_goes_here",
"count": "how_many_items_with_var",
"input": {
"key": "value" << have to use copyIndex('real_var_name_goes_here')
}
}
]
}
and you'd use normal way for regular loops
Reading:
https://learn.microsoft.com/en-us/azure/azure-resource-manager/resource-group-create-multiple