Multiple IP address variable in Azure ARM Template - json

If I am using an ARM Template to create an IP Group within Azure and want to add Multiple IP Addresses as a Parameter rather than putting them in the body of the resource is this possible?
The template is as follows
{
"type": "Microsoft.Network/ipGroups",
"apiVersion": "2021-05-01",
"name": "string",
"location": "string",
"tags": {
"tagName1": "tagValue1",
"tagName2": "tagValue2"
},
"properties": {
"ipAddresses": [ "10.10.10.10",
"10.10.10.11" ]
}
}
If I create a Parameter like the following
"ipgipaddress": {
"type": "string
"Value":
"10.10.10.10",
"10.10.10.11"
}
And update the code to
{
"type": "Microsoft.Network/ipGroups",
"apiVersion": "2021-05-01",
"name": "string",
"location": "string",
"tags": {
"tagName1": "tagValue1",
"tagName2": "tagValue2"
},
"properties": {
"ipAddresses": "[parameters('ipgroupsettings')]"
}
}

want to add Multiple IP Addresses as a Parameter rather than putting
them in the body of the resource is this possible?
Yes it is possible, you can add Multiple IP Addresses as a Parameter. As per the documentation, the property ipAddresses is of type string array.
To reproduce this ,In our ARM Template we have initialized those ipaddresses to a parameter of type array & further passed those values using "[paramerter(ipaddresses)]".
We have tested this, it is working fine.
Here is the ARM Template :
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"ipaddress":{
"type": "array",
"defaultValue": ["10.0.1.0/27","10.0.2.0/27"]
}
},
"functions": [],
"variables": {},
"resources": [{
"type": "Microsoft.Network/ipGroups",
"apiVersion": "2020-11-01",
"name": "testipgroups",
"location":"[resourceGroup().location]",
"properties":{
"ipAddresses": "[parameters('ipaddress')]"
}
}
],
"outputs": {}
}
Here is the sample Output for reference:

{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"ipaddress":{
"type": "string",
"defaultValue": "10.0.1.0/27,10.0.2.0/27"
}
},
"functions": [],
"variables": {
"iparray": "[split(parameters('ipaddress'),',')]"
},
"resources": [{
"type": "Microsoft.Network/ipGroups",
"apiVersion": "2020-11-01",
"name": "testipgroups",
"location":"[resourceGroup().location]",
"properties":{
"ipAddresses": "[variables('iparray')]"
}
}
],
"outputs": {}
}
If you want to save your time in providing input as String without much double quotes(" ") ,use split function with removing delimiter (comma in above example) which will create an array of IP's.

Related

Loop for nested template and dynamically get keyvault secret name

Based on information from Microsoft site, it is possible get key vault secrets during the implementation. I would like to have similar solution but for 5 VMs and reuse templates in Loop to create 5 VMs with different password from key vault. The key vault already exists with the secrets name. The secrets name are like: Secrets0...Secrets4.
Does anyone has any idea of how to do this? Below my solution with Loop but doesn't works for me.
I appreciate for your support.
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"location": {
"type": "string",
"defaultValue": "[resourceGroup().location]",
"metadata": {
"description": "The location where the resources will be deployed."
}
},
"vaultName": {
"type": "string",
"metadata": {
"description": "The name of the keyvault that contains the secret."
}
},
"secretName": {
"type": "string",
"metadata": {
"description": "The name of the secret."
}
},
"vaultResourceGroupName": {
"type": "string",
"metadata": {
"description": "The name of the resource group that contains the keyvault."
}
},
"vaultSubscription": {
"type": "string",
"defaultValue": "[subscription().subscriptionId]",
"metadata": {
"description": "The name of the subscription that contains the keyvault."
}
}
},
"resources": [
{
"type": "Microsoft.Resources/deployments",
"apiVersion": "2020-10-01",
"name": "[concat('DynamicSecret,copyIndex('VMsLoop'))]"
"copy": {
"name": "VMsLoop",
"count": 5,
"mode": "Serial",
"batchSize": 1
},
"properties": {
"mode": "Incremental",
"expressionEvaluationOptions": {
"scope": "inner"
},
"template": {
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"adminLogin": {
"type": "string"
},
"adminPassword": {
"type": "securestring"
},
"location": {
"type": "string"
}
},
"variables": {
"sqlServerName": "[concat('sql-', uniqueString(resourceGroup().id, 'sql'))]"
},
"resources": [
{
"type": "Microsoft.Sql/servers",
"apiVersion": "2018-06-01-preview",
"name": "[variables('sqlServerName')]",
"location": "[parameters('location')]",
"properties": {
"administratorLogin": "[parameters('adminLogin')]",
"administratorLoginPassword": "[parameters('adminPassword')]"
}
}
],
"outputs": {
"sqlFQDN": {
"type": "string",
"value": "[reference(variables('sqlServerName')).fullyQualifiedDomainName]"
}
}
},
"parameters": {
"location": {
"value": "[parameters('location')]"
},
"adminLogin": {
"value": "ghuser"
},
"adminPassword": {
"reference": {
"keyVault": {
"id": "[resourceId(parameters('vaultSubscription'), parameters('vaultResourceGroupName'), 'Microsoft.KeyVault/vaults', parameters('vaultName'))]"
},
"secretName": "[concat(parameters('secretName'),copyIndex('VMsLoop'))]"
}
}
}
}
}
],
"outputs": {
}
}
The template you have provided actually works (except for one tiny typo - missing closing quote after DynamicSecret at "[concat('DynamicSecret,copyIndex('VMsLoop'))]" ).
However, since the uniquestring function that is used to generate the sql server name is deterministic (i.e. generated using the passed parameters of resoure group name and 'sql' string - uniqueString(resourceGroup().id, 'sql'). So the loop is hitting the same server instance just changing the password to the next secret in the list.
You can either promote the sqlServerName to parameter and suffix it with the loop index, or keep it as a variable and expand the uniqueString function with the deployment (i.e. uniqueString(resourceGroup().id, deployment().name, 'sql') ).

Azure ARM Template - Key Vault Username & Password ID Variables?

Is it possible to concatenate the id path of the Key Vault URL within a variable? At the moment I have adminUsername and adminPassword parameters in the parameters.json file and the id fully typed out. However, I can fill out the id based on known information so makes the deployment easier. Below is my parameters.json file as is (with the important info taken out):
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"adminUsername": {
"reference": {
"keyVault": {
"id": "/subscriptions/<SubID>/resourceGroups/<RG>/providers/Microsoft.KeyVault/vaults/<KV>"
},
"secretName": "LocalAdminUsername"
}
},
"adminPassword": {
"reference": {
"keyVault": {
"id": "/subscriptions/<SubID>/resourceGroups/<RG>/providers/Microsoft.KeyVault/vaults/<KV>"
},
"secretName": "LocalAdminPassword"
}
}
}
}
It is the id where I want to include variables - possible? Thanks.
You can only specify static values inside a parameter file. However, you can use a nested deployment to dynamically generate the KeyVault resource ID (example below).
In a nutshell;
Define parameters for parts of the resource identifier
Use template functions to assign defaults where possible
Use concat() to construct the identifier in a variable
Use a nested deployment to refer to the key vault using the variable.
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"kvSubscriptionId": {
"type": "string",
"defaultValue": "[subscription().id]"
},
"kvResourceGroupName": {
"type": "string",
"defaultValue": "[resourceGroup().name]"
},
"kvResourceName": {
"type": "string",
"defaultValue": "kv-resource-name"
}
},
"functions": [],
"variables": {
"kvResourceId": "[concat('/subscriptions/', parameters('kvSubscriptionId'), '/resourceGroups/', parameters('kvResourceGroupName'), '/providers/Microsoft.KeyVault/vaults/', parameters('kvResourceName'))]"
},
"resources": [
{
"type": "Microsoft.Resources/deployments",
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"apiVersion": "2018-05-01",
"name": "nested",
"properties": {
"mode": "Incremental",
"template": {
"parameters": {
"adminUsername": {
"type": "string"
}
},
"resources": [...]
}
},
"parameters": {
"adminUsername": {
"reference": {
"keyVault": {
"id": "[variables('kvResourceId')]"
},
"secretName": "LocalAdminUserName"
}
}
}
}
]
}
This technique is documented here: Reference secrets with dynamic ID.

Display JSON Properties in Kusto Query - specific Subnets

Hello i have a little problem i couldn't find an answer i could understand anywhere.
i am about to make a dashboard in azure by using Azure Resource Graph Explorer and their Kusto query language, i would like to display how many Subnets there is i the subscription.
but when i try to seperate and show the subnets in it only show me either the amount of Vnets there is or it show one line of subnets and not how many.
i've tried to project the subnets with following code but dont know what to write to show a single line with two rows with the name "subnets" and how many of them.
Summary: is that; i want to write a Kusto query that i can pin to dashboard that shows how many subnets there is.
Code i tried to write:
resources
| project properties.subnets
output is:
properties_subnets
null
[{"type":"Microsoft.Network/virtualNetworks/subnets","properties":{"provisioningState":"Succeeded", etc. etc. etc.
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"virtualNetworks_Vnet_name": {
"defaultValue": "Vnet",
"type": "String"
}
},
"variables": {},
"resources": [
{
"type": "Microsoft.Network/virtualNetworks",
"apiVersion": "2020-05-01",
"name": "[parameters('virtualNetworks_Vnet_name')]",
"location": "westeurope",
"properties": {
"addressSpace": {
"addressPrefixes": [
"10.0.0.0/16"
]
},
"subnets": [
{
"name": "default",
"properties": {
"addressPrefix": "10.0.0.0/24",
"delegations": [],
"privateEndpointNetworkPolicies": "Enabled",
"privateLinkServiceNetworkPolicies": "Enabled"
}
},
{
"name": "default2",
"properties": {
"addressPrefix": "10.0.1.0/24",
"serviceEndpoints": [],
"delegations": [],
"privateEndpointNetworkPolicies": "Enabled",
"privateLinkServiceNetworkPolicies": "Enabled"
}
}
],
"virtualNetworkPeerings": [],
"enableDdosProtection": false,
"enableVmProtection": false
}
},
{
"type": "Microsoft.Network/virtualNetworks/subnets",
"apiVersion": "2020-05-01",
"name": "[concat(parameters('virtualNetworks_Vnet_name'), '/default')]",
"dependsOn": [
"[resourceId('Microsoft.Network/virtualNetworks', parameters('virtualNetworks_Vnet_name'))]"
],
"properties": {
"addressPrefix": "10.0.0.0/24",
"delegations": [],
"privateEndpointNetworkPolicies": "Enabled",
"privateLinkServiceNetworkPolicies": "Enabled"
}
},
{
"type": "Microsoft.Network/virtualNetworks/subnets",
"apiVersion": "2020-05-01",
"name": "[concat(parameters('virtualNetworks_Vnet_name'), '/default2')]",
"dependsOn": [
"[resourceId('Microsoft.Network/virtualNetworks', parameters('virtualNetworks_Vnet_name'))]"
],
"properties": {
"addressPrefix": "10.0.1.0/24",
"serviceEndpoints": [],
"delegations": [],
"privateEndpointNetworkPolicies": "Enabled",
"privateLinkServiceNetworkPolicies": "Enabled"
}
}
]
}
resources
| where type=~"Microsoft.Network/virtualNetworks"
| project array_length(properties.subnets)

Azure ARM copy Index not working in Json

I am trying to deploy multiple Azure VNETs using the code below,it
it gives error below
{
"error": {
"code": "InvalidTemplate",
"details": null,
"message": "Deployment template validation failed: 'The template resource '[concat(variables('namePrefix'), parameters('VNetSettings').vnets.name, [copyIndex(1)])]' at line '1' and column '923' is not valid: The language expression property 'name' has an invalid array index.. Please see https://aka.ms/arm-template-expressions for usage details.'.",
"target": null
},
"properties": null
}
This is my Code below. I want to use coyIndex to loop through multiple instances of azure virtual networks. Based on number of vnet names provided i want it get number of instances to be created.
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"VNetSettings": {
"type": "object"
},
"namingSettings": {
"type": "object"
}
},
"variables": {
"namePrefix": "[concat(parameters('namingSettings').name.org,'-',parameters('namingSettings').name.accountEnv,'-',parameters('namingSettings').name.sdlcEnv,'-',parameters('namingSettings').name.region,'-',parameters('namingSettings').name.appname,'-')]"
},
"resources": [
{
"apiVersion": "2018-04-01",
"type": "Microsoft.Network/virtualNetworks",
"name": "[concat(variables('namePrefix'), parameters('VNetSettings').vnets.name, [copyIndex(1)])]",
"location": "[resourceGroup().location]",
"copy": {
"name": "vnetcopy",
"count": "[length(parameters('VNetSettings').vnets.name)]"
},
"scale": null,
"properties": {
"addressSpace": {
"addressPrefixes": [
"[parameters('VNetSettings').vnets.cidr]"
]
}
}
}
]
}
Update
Parameter fileenter code here
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#",
"contentVersion": "1.0.0.0",
"parameters":{
"namingSettings": {
"value": {
"name": {
"org": "it",
"accountEnv": "nonprod",
"sdlcEnv": "it-test",
"region": "eastus2",
"tier": "",
"object": "",
"networkbuild": "network",
"auditbuild": "audit",
"automationbuild": "automation",
"dnsbuild": "dns",
"appname": "network"
}
}
},
"VNetSettings": {
"value": {
"vnets": [
{
"name": "vnet0",
"cidr": "10.10.10.0/24",
}
],
}
}
}
}
Your concat() input is wrong. copyIndex() should not be inside []. Try this:
"[concat(variables('namePrefix'), parameters('VNetSettings').vnets.name, copyIndex(1))]"
copyIndex() is just another function, you only wrap the string with [] once no matter how many functions are inside
you need to adjust your template to reflect the fact you are iterating over an array (right now you iterate over the name, and vnets.name is not a valid construct in the ARM Templates).
you need to do something like this:
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"VNetSettings": {
"type": "object"
},
"namingSettings": {
"type": "object"
}
},
"variables": {
"namePrefix": "[concat(parameters('namingSettings').name.org,'-',parameters('namingSettings').name.accountEnv,'-',parameters('namingSettings').name.sdlcEnv,'-',parameters('namingSettings').name.region,'-',parameters('namingSettings').name.appname,'-')]"
},
"resources": [
{
"apiVersion": "2018-04-01",
"type": "Microsoft.Network/virtualNetworks",
"name": "[concat(variables('namePrefix'), parameters('VNetSettings').vnets[copyIndex()].name)]",
"location": "[resourceGroup().location]",
"copy": {
"name": "vnetcopy",
"count": "[length(parameters('VNetSettings').vnets)]"
},
"scale": null,
"properties": {
"addressSpace": {
"addressPrefixes": [
"[parameters('VNetSettings').vnets[copyIndex()].cidr]"
]
}
}
}
]
}
notice you need to use copyIndex() to get to the current vnet in your array and you need to use the .vnet to determine length

How to create multiple Service Bus topics using ARM template?

I've looked at the https://github.com/Azure/azure-quickstart-templates/tree/master/101-servicebus-topic example. Now I'm trying to figure out how to create several topics when running the deploy script using nested resource looping (https://azure.microsoft.com/en-us/documentation/articles/resource-group-create-multiple/#looping-on-a-nested-resource).
It would be nice to just define an array in the value for serviceBusTopicName and then somehow creating topics by looping through it, instead of doing it manually.
I am getting the following error when trying to deploy.
Error: Code=InvalidTemplate; Message=Deployment template validation failed: 'The template resource '[parameters('serviceBusTopicName')[copyIndex()]]' at line '72' column '14' is not valid.
Copying nested resources is not supported. Please see https://aka.ms/arm-copy/#looping-on-a-nested-resource for usage details.'.
This is the template.json that I have tried to get to work.
"parameters": {
"serviceBusNamespaceName": {
"type": "string",
"metadata": {
"description": "Name of the Service Bus namespace"
}
},
"serviceBusTopicName": {
"type": "array",
"metadata": {
"description": "Name of the Topic"
}
},
"serviceBusApiVersion": {
"type": "string",
"defaultValue": "2015-08-01",
"metadata": {
"description": "Service Bus ApiVersion used by the template"
},
"resources": [
{
"apiVersion": "[variables('sbVersion')]",
"name": "[parameters('serviceBusNamespaceName')]",
"type": "Microsoft.ServiceBus/Namespaces",
"location": "[variables('location')]",
"kind": "Messaging",
"sku": {
"name": "StandardSku",
"tier": "Standard"
},
"resources": [
{
"apiVersion": "[variables('sbVersion')]",
"name": "[parameters('serviceBusTopicName')]",
"type": "Topics",
"dependsOn": [
"[concat('Microsoft.ServiceBus/namespaces/', parameters('serviceBusNamespaceName'))]"
],
"properties": {
"path": "[parameters('serviceBusTopicName')]"
},
"copy": {
"name": "datasetcopy",
"count": "[length(parameters('serviceBusTopicName'))]"
}
}
]
},
parameters.json
{"$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"serviceBusNamespaceName": {
"value": "ServiceBus"
},
"serviceBusTopicName": {
"value": [
"Person",
"Stadium",
"Team"
]
},
"serviceBusApiVersion": {
"value": "2015-08-01"
}
}
As #Lain said, copying nested resource isn't supported as of now Check Here. For deploying multiple resource you have to move it to root. I just finished my POC for deploying multiple topics (Just topics assuming Namespace already exists) here is the code. I am passing topic names as a comma separated string:
{
"$schema": "http://schema.management.azure.com/schemas/2014-04-01-preview/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"serviceBusNamespaceName": {
"type": "string",
"metadata": {
"description": "Name of the Service Bus namespace"
}
},
"serviceBusTopicName": {
"type": "string",
"metadata": {
"description": "Comma seperated Topic Names"
}
},
"serviceBusApiVersion": {
"type": "string",
"defaultValue": "2015-08-01",
"metadata": {
"description": "Service Bus ApiVersion used by the template"
}
}
},
"variables": {
"location": "[resourceGroup().location]",
"sbVersion": "[parameters('serviceBusApiVersion')]",
"TopicNames": "[split(parameters('serviceBusTopicName'), ',')]"
},
"resources": [{
"apiVersion": "[variables('sbVersion')]",
"name": "[concat(parameters('serviceBusNamespaceName'), '/', variables('TopicNames')[copyIndex()])]",
"type": "Microsoft.ServiceBus/Namespaces/Topics",
"copy": {
"name": "TopicNameCopy",
"count": "[length(variables('TopicNames'))]"
},
"properties": {
"path": "[variables('TopicNames')[copyIndex()]]"
}
}]
}
The link in the error message goes through this pretty well, but you can't have loops in nested resources, you need to push the resource up to the top level, and then link the resources together using names. This template will do what you seem to be trying to do:
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"serviceBusNamespaceName": {
"type": "string",
"metadata": {
"description": "Name of the Service Bus Namespace"
}
},
"serviceBusTopicNames": {
"type": "array",
"metadata": {
"description": "Name of the Service Bus Topic"
}
}
},
"variables": {
"sbVersion": "2015-08-01"
},
"resources": [
{
"apiVersion": "[variables('sbVersion')]",
"name": "[parameters('serviceBusNamespaceName')]",
"type": "Microsoft.ServiceBus/namespaces",
"location": "[resourceGroup().location]",
"properties": {
}
},
{
"apiVersion": "[variables('sbVersion')]",
"name": "[concat(parameters('serviceBusNamespaceName'), '/', parameters('serviceBusTopicNames')[copyIndex()])]",
"type": "Microsoft.ServiceBus/namespaces/Topics",
"dependsOn": [
"[concat('Microsoft.ServiceBus/namespaces/', parameters('serviceBusNamespaceName'))]"
],
"copy": {
"name": "datasetcopy",
"count": "[length(parameters('serviceBusTopicNames'))]"
},
"properties": {
"path": "[parameters('serviceBusTopicNames')[copyIndex()]]"
},
"resources": [
]
}
]
}