Azure ARM template resourceId problem with nested deployments on subscription level - azure

I'm working on an ARM template to
A. deploy a resource group
B. deploy an ASE env.
To do both, as I understand I need to run a deployment on scope subscription level
New-AzDeployment -Name TestingASE -TemplateFile $HOME/azuredeploy.json -TemplateParameterFile $HOME/parameters.json -Location 'West Europe'
My template is pretty long already - so here are the most important parts (I think).
{
"$schema": "https://schema.management.azure.com/schemas/2018-05-01/subscriptionDeploymentTemplate.json#",
"contentVersion": "1.0.0.1",
"parameters": {
....
"resources": [
// Resource Group
{
"type": "Microsoft.Resources/resourceGroups",
"apiVersion": "2018-05-01",
"location": "[parameters('Location')]",
"name": "[parameters('rgName')]",
"properties": {}
},
{
"type": "Microsoft.Resources/deployments",
"apiVersion": "2019-05-01",
"name": "storageDeployment",
"resourceGroup": "[parameters('rgName')]",
"dependsOn": [
"[resourceId('Microsoft.Resources/resourceGroups/', parameters('rgName'))]"
],
"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": "2019-04-01",
"name": "[parameters('asevnetname')]",
"type": "Microsoft.Network/virtualNetworks",
"location": "[parameters('Location')]",
"properties": {
"addressSpace": {
"addressPrefixes": [
"[parameters('addressPrefix')]"
]
},
"subnets": [
{
"name": "[parameters('subnetName')]",
...
{
"apiVersion": "2019-02-01",
"type": "Microsoft.Web/hostingEnvironments",
"name": "[parameters('aseName')]",
"kind": "ASEV2",
"location": "[parameters('Location')]",
"properties": {
"name": "[parameters('aseName')]",
"location": "[parameters('Location')]",
"InternalLoadBalancingMode": "[parameters('ilbMode')]",
"virtualNetwork": {
"Id": "[resourceId(subscription().id, resourceGroup().Id, 'Microsoft.Network/virtualNetworks/subnets',parameters('asevnetname'),parameters('subnetName'))]"
}
....
This give me an output "The template function 'RESOURCEGROUP' is not expected at thislocation"
As far as I understand I'm following the guidelines
https://learn.microsoft.com/en-gb/azure/azure-resource-manager/templates/template-functions-resource#resourcegroup
The resourceGroup() function can't be used in a template that is deployed at the subscription level. It can only be used in templates that are deployed to a resource group. You can use the resourceGroup() function in a linked or nested template (with inner scope) that targets a resource group, even when the parent template is deployed to the subscription. In that scenario, the linked or nested template is deployed at the resource group level.
Thanks for helping with this.

The error happened at the resourceId format, it should be
resourceId([subscriptionId], [resourceGroupName], resourceType, resourceName1, [resourceName2], ...)
To get the resource ID for a resource in the same subscription but a
different resource group, provide the resource group name.
"[resourceId('otherResourceGroup', 'Microsoft.Storage/storageAccounts', 'examplestorage')]"
So, in this case, the virtualNetwork ID in the properties of Microsoft.Web/hostingEnvironments should be
"virtualNetwork": {
"Id": "[resourceId(parameters('rgName'), 'Microsoft.Network/virtualNetworks/subnets',parameters('asevnetname'),parameters('subnetName'))]"
}
or
"Id": "[resourceId(resourceGroup().name, 'Microsoft.Network/virtualNetworks/subnets',parameters('asevnetname'),parameters('subnetName'))]"
For more information, you could get more references to deploy an ASE within a subnet from this template.

Your deployment schema is subscriptionDeploymentTemplate and the New-AzDeployment cmdlet creates a deployment at the subscription scope. As per the docs you can't use that function when deploying at the subscription scope. You'll also encounter problems with the resourceId() function that wraps around it. The subscriptionResourceId() function should solve your problem.
"virtualNetwork": {
"Id": "[subscriptionResourceId('Microsoft.Network/virtualNetworks/subnets',parameters('asevnetname'),parameters('subnetName'))]"
}
The resource id will be returned in the subscription format as described here, if that isn't an acceptable format for the virtualNetwork.Id property of the Microsoft.Web/hostingEnvironments resource you're trying to deploy you might need to construct the resource id using the concat() function instead.

Related

Azure Resource Manager ResourceGroups deployment

Is it supported to have a single ARM file that is deployed on a resource-group level and still deploy another resource group, and resource to it?
And if yes, how does one have to address the resourceId for the dependsOn parameter?
I'm deploying like the following (I need to deploy on a resource group level - don't ask).
New-AzResourceGroupDeployment -Templatefile deploy.json -Location 'xx' -ResourceGroupName 'firstResourceGroup'
And have, in this ARM file, a resource group deployment
{
"type": "Microsoft.Resources/resourceGroups",
"apiVersion": "2020-06-01",
"location": "[parameters('location')]",
"name": "[parameters('SecondResourceGroup')]",
"properties": {}
}
and specify a further deployment (Microsoft.Resources/deployments) to this resource group.
{
"type": "Microsoft.Resources/deployments",
"name":"deployment-to-secondResourceGroup",
"apiVersion": "2020-06-01",
"resourceGroup": "[parameters('secondResourceGroup')]",
"properties": {
"mode": "Incremental",
"templateLink": {
"uri": "https://xyz"
}
}
}
This works fine if the resource group is already deployed, that is. But in reality, the resource group won't be ready to deploy to. So I need to set a dependsOn.
But when I try to use the dependsOn parameters I can't address the resource-group deployment.
"dependsOn": []
Here is how I define the dependsOn when deploying resources groups and then resources within the same template file.
{
"type": "Microsoft.Resources/deployments",
"name":"deployment-to-secondResourceGroup",
"apiVersion": "2020-06-01",
"resourceGroup": "[parameters('secondResourceGroup')]",
"dependsOn": [
"[resourceId('Microsoft.Resources/resourceGroups/', variables('secondResourceGroup'))]"
],
"properties": {
"mode": "Incremental",
"templateLink": {
"uri": "https://xyz"
}
}
}

How to add Access Policy to a Keyvault in different Resource Group through ARM Templates

I have 3 apps sharing 1 keyvault. So i decided to create 4 RGs. 3 RGs for 3 apps and 1 RG for keyvault and other common resources.
This is all working fine. I can create 3 apps through their own ARM Templates and Keyvault through it's own ARM Template.
So when app resources gets provisioned then i want to add accesspolicy for that app in keyvault through ARM Templates.
{
"apiVersion": "2018-05-01",
"name": "accesspolicies_deployment",
"resourceGroup": "Common-RG",
"type": "Microsoft.Resources/deployments",
"dependsOn": [],
"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.KeyVault/vaults/accessPolicies",
"name": "[concat('kvdevwus', '/add')]",
"apiVersion": "2018-02-14",
"properties": {
"accessPolicies": [
{
"tenantId": "[reference(variables('website'),'2018-02-01','Full').identity.tenantId]",
"objectId": "[reference(variables('website'),'2018-02-01','Full').identity.principalId]",
"permissions": {
"keys": [
"all"
],
"secrets": [
"all"
],
"certificates": [
"all"
],
"storage": [
"all"
]
}
}
]
}
}
],
"outputs": {
"principalId": {
"type": "string",
"value": "[reference(variables('website'),'2018-02-01','Full').identity.principalId]"
}
}
}
}
}
I'm using above template in the apps template. But getting Resource Not Found error.
Is the design itself is wrong or am i missing anything?
Would have to see more of the code to know for sure, but I suspect you're not going to be able to do what you want with an inline deployment, you have to use a linked template. We're working on fixing that, but it's not available yet.
I think you are missing the "dependsOn": [] in your accesspolicies_deployment resource. I have the same set-up as you were I have key vault in a common resource group and my web apps in different resource.
In my ARM template that creates website, I also added accesspolicies_deployment but added "dependsOn": [webapp01] to ensure that website it created first and the identity created before creating the keyvalut access policy
Using a nested template allows you to specify the resource group the nested template should be deployed to, which can be different than the resource group used for the template that contains the nested template.

Error when calling Azure Powershell New-AzResource: request content invalid

I am stuck on this Azure PowerShell error when calling New-AzResource:
new-azresource : InvalidRequestContent : The request content was invalid and could not be deserialized: 'Could not find member 'dependsOn' on object of type 'ResourceProxyDefinition'. Path 'dependsOn'.'.
The object I pass into the -property argument of New-AzResource is indeed an object with a dependsOn property. So the message is a decoy. And, of course, it works just fine in the CLI.
Interestingly, you cannot even find that message, or the substring ResourceProxyDefinition in any of the code for the Az PS module (https://github.com/Azure/azure-powershell). I have researched this to the extent I can think of, like looking at the underlyzing Azure API and source code. Try a Google search for ResourceProxyDefinition (no spaces) and you will mostly land on a GitHub issue I hijacked.
For the property object, I start from a json template (given below, partially). That JSON works directly in the CLI. However, for the azure powershell module, I use ConvertFrom-Json on the file contents and pass the resulting object as the argument.
{
"type": "Microsoft.VirtualMachineImages/imageTemplates",
"apiVersion": "2019-05-01-preview",
"location": "eastus2",
"dependsOn": [],
"tags": {
"imagebuilderTemplate": "My.WindowsServer.2019-Datacenter-1910020354.tpl"
},
"properties": {
"buildTimeoutInMinutes": 100,
"source": {
"type": "PlatformImage",
"publisher": "MicrosoftWindowsServer",
"offer": "WindowsServer",
"sku": "2019-Datacenter",
"version": "2019.0.20190603"
},
With some changes to your template to be like this:
{
"$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"resources": [
{
"name": "My.WindowsServer.2019-Datacenter-1910030425.tpl",
"type": "Microsoft.VirtualMachineImages/imageTemplates",
"apiVersion": "2019-05-01-preview",
"location": "eastus2",
"dependsOn": [],
"tags": {
"imagebuilderTemplate": "My.WindowsServer.2019-Datacenter-1910030425.tpl"
},
"properties": {
"buildTimeoutInMinutes": 100,
"source": {
"type": "PlatformImage",
"publisher": "MicrosoftWindowsServer",
"offer": "WindowsServer",
"sku": "2019-Datacenter",
"version": "2019.0.20190603"
which includes adding an extra level (nesting the previous template under "resources" and adding a "$schema" and "contentVersion" you are set for deployment.
Now, use:
New-AzResourceGroupDeployment -ResourceGroupName $imageResourceGroup `
-TemplateFile $imageTemplateFile
which will read in the JSON file and it works! Don't use New-AzResource.

How to obtain Cross regional deployment using ARMTemplate

I want to do cross regional deployment using ARM Template.
Example 1:
I have two resource group's A & B. A resource group has one storage account. I want to access A's storage account in B's resource group services.
Example 2:
I have two resource group's A & B. A resource group has one application insight service. I want to access A's application insight in B's ApiApp service with Instrumentation key added in ApiApp "appsettings".
I have tried adding below code snippet in ARMTemplate:
{
"apiVersion": "2017-05-10",
"name": "nestedTemplate",
"type": "Microsoft.Resources/deployments",
"resourceGroup": "testresgrp01",
"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.Insights/components",
"name": "[parameters('appinsightname')]",
"apiVersion": "2015-06-15",
"location": "South Central US",
"properties": {
}
}
]
},
"parameters": {}
}
},
{
"type": "Microsoft.Insights/components",
"name": "[parameters('appinsightname')]",
"apiVersion": "2015-06-15",
"location": "South Central US",
"properties": {
}
}
But this section errors while deployment giving below error:
New-AzureRmResourceGroupDeployment : - Error: Code=InvalidTemplate; Message=Deployment template validation failed: 'The
template resource 'nestedTemplate' at line '224' and column '10' is invalid. The api-version '2016-07-01' used to deploy the
template does not support 'ResourceGroup' property. Please use api-version '2017-05-10' or later to deploy the template.
If I remove "resourceGroup": "testresgrp01", section, the resource deployment creates a new service in resourcegroup.
How to resolve this issue?
Thank you
I'm pretty sure your Azure Powershell modules are outdated, update them to the latest and try again.
I usually delete all modules and install from scratch to ensure no conflicts.

How to define specific Resource Group in Azure Resource Manager nested template

Does anyone know how to place Resources in an ARM template into specific, and different Resource Groups? This might be the storage in one RG and the network in another, both created in the same, or different, templates (nested, for example).
Full details are below.
Reading through the best practice guide ARM template best practice and the whitepaper World Class ARM Templates Considerations and Proven Practices there's a recommendation that different elements of a deployment should be situated in separate Resource Groups. For example, in an IaaS solution, your DCs might sit in an Admin RG, your back-end servers in another, and your client desktops in a third.
I'm currently trying to deploy such a solution via nested templates, and I've stumbled upon an issue whereby all items being created are automatically placed inside the Resource Group selected when kicking the process off (i.e. the parent template). I've looked through the various documentation online but can't obviously find a way to force resources being created in a template into a specific Resource Group. Has anyone done this?
For anyone else that finds this in google (like I did):
It is now possible to deploy resources to multiple resource groups in one ARM template. Microsoft has details available here: https://learn.microsoft.com/en-us/azure/azure-resource-manager/resource-manager-cross-resource-group-deployment for the details.
To do this you include a nested deployment template within the main one, and set the nested deployment to another resource group. here is an example from the MS Site:
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"storagePrefix": {
"type": "string",
"maxLength": 11
},
"secondResourceGroup": {
"type": "string"
},
"secondSubscriptionID": {
"type": "string",
"defaultValue": ""
},
"secondStorageLocation": {
"type": "string",
"defaultValue": "[resourceGroup().location]"
}
},
"variables": {
"firstStorageName": "[concat(parameters('storagePrefix'), uniqueString(resourceGroup().id))]",
"secondStorageName": "[concat(parameters('storagePrefix'), uniqueString(parameters('secondSubscriptionID'), parameters('secondResourceGroup')))]"
},
"resources": [
{
"apiVersion": "2017-05-10",
"name": "nestedTemplate",
"type": "Microsoft.Resources/deployments",
"resourceGroup": "[parameters('secondResourceGroup')]",
"subscriptionId": "[parameters('secondSubscriptionID')]",
"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.Storage/storageAccounts",
"name": "[variables('secondStorageName')]",
"apiVersion": "2017-06-01",
"location": "[parameters('secondStorageLocation')]",
"sku":{
"name": "Standard_LRS"
},
"kind": "Storage",
"properties": {
}
}
]
},
"parameters": {}
}
},
{
"type": "Microsoft.Storage/storageAccounts",
"name": "[variables('firstStorageName')]",
"apiVersion": "2017-06-01",
"location": "[resourceGroup().location]",
"sku":{
"name": "Standard_LRS"
},
"kind": "Storage",
"properties": {
}
}
]
}
It is not possible to deploy resources into multiple resource groups from a template. Simply by virtue of the fact that the Azure Resource Manager REST API Reference only has a single place to specify the resource group name.
The concept of ARM templates is that you create a resource group and deploy a template into it, and thus provide a single administrative unit from which to manage those resources. This improves over the Azure Service Management model where you had to manage each resource individually.
Nested resource groups would be quite a nice feature to fulfill your need, but I've never heard of such a thing being planned for Azure.

Resources