Provision Access Policy with DependsOn - json

I'm trying to do the following:
Create a keyvault (works)
Create an AZ function (works)
Use the keyvault's vaultURI as an App Setting to the AZ function (works)
Give the AZ function managed identity (works)
Create an Access Policy whereby the AZ function has access to the keyvault (whoopsie!)
Originally I was creating the Access Policy within the Keyvault, but I had to declare the AZ function as depending on the Key Vault (such that I could fetch its URI). Obviously, I was then unable to set Key Vault to depend on the AZ Function (since this would create a cyclic dependency). I then tried creating the AccessPolicy as another step, and marking it as depends on the KeyVault, and the AZ Function (thinking it would be provisioned last).
But for some reason, when looking at the deployment logs, it always seems like he's trying to deploy it first! Any help would be appreciated.
ARM Template truncated for brevity:
"resources": [
{
"type": "Microsoft.KeyVault/vaults",
"apiVersion": "2016-10-01",
"name": "[variables('keyVaultName')]",
"location": "[ResourceGroup().location]",
"properties": {
"sku": {
"family": "A",
"name": "Standard"
},
"tenantId": "[subscription().tenantId]",
"accessPolicies": [
{
"tenantId": "[subscription().tenantId]",
"objectId": "[parameters('userId')]",
"permissions": {
"keys": [
"Get",
"List",
"Update",
"Create",
"Import",
"Delete",
"Recover",
"Backup",
"Restore"
],
"secrets": [
"Get",
"List",
"Set",
"Delete",
"Recover",
"Backup",
"Restore"
],
"certificates": [
"Get",
"List",
"Update",
"Create",
"Import",
"Delete",
"Recover",
"Backup",
"Restore",
"ManageContacts",
"ManageIssuers",
"GetIssuers",
"ListIssuers",
"SetIssuers",
"DeleteIssuers"
]
}
}
],
"enabledForDeployment": false,
"enabledForDiskEncryption": false,
"enabledForTemplateDeployment": false
}
},
{
"type": "Microsoft.KeyVault/vaults/accessPolicies",
"name": "[concat(variables('keyVaultName'),'/add')]",
"apiVersion": "2018-02-14",
"dependsOn": [
"[resourceId('Microsoft.Web/sites', variables('functionName'))]",
"[resourceId('Microsoft.KeyVault/vaults', variables('keyVaultName'))]"
],
//tried both the above and the below
"dependsOn": [
"[variables('keyVaultName')]",
"[variables('functionName')]"
],
"properties": {
"accessPolicies": [
{
"tenantId": "[subscription().tenantId]",
"objectId": "[reference(concat(resourceId('Microsoft.Web/sites', variables('functionName')), '/providers/Microsoft.ManagedIdentity/Identities/default'), '2015-08-31-PREVIEW').principalId]",
"permissions": {
"keys": [
],
"secrets": [
"Get",
"Set",
"Delete"
],
"certificates": [
]
}
}
]
}
},
.
.
.
.
.
.
.
.
{
"type": "Microsoft.Web/sites",
"apiVersion": "2016-08-01",
"name": "[variables('functionName')]",
"location": "[ResourceGroup().location]",
"dependsOn": [
"[variables('planName')]",
"[variables('appInsightsName')]",
"[variables('storageAccName')]",
"[variables('keyVaultName')]",
"[variables('databaseName')]"
],
"kind": "functionapp",
"identity": {
"type": "SystemAssigned"
},
"properties": {
"serverFarmId": "[variables('planName')]",
"enabled": true,
"reserved": false
},
"resources": [
{
"apiVersion": "2015-08-01",
"name": "connectionstrings",
"type": "config",
"dependsOn": [
"[variables('functionName')]",
"[variables('databaseName')]"
],
"properties": {
}
},
{
"apiVersion": "2015-08-01",
"name": "appsettings",
"type": "config",
"dependsOn": [
"[variables('functionName')]",
"[variables('appInsightsName')]",
"[variables('storageAccName')]",
"[variables('keyVaultName')]"
],
"properties": "[union(variables('completeAppSettings'),json(concat('{ AzureWebJobsStorage:\"', concat('DefaultEndpointsProtocol=https;AccountName=', variables('storageAccName'), ';AccountKey=', listKeys(resourceId('Microsoft.Storage/storageAccounts', variables('storageAccName')), '2019-04-01').keys[0].value), '\", WEBSITE_CONTENTAZUREFILECONNECTIONSTRING:\"',\tconcat('DefaultEndpointsProtocol=https;AccountName=', variables('storageAccName'), ';AccountKey=', listKeys(resourceId('Microsoft.Storage/storageAccounts', variables('storageAccName')), '2019-04-01').keys[0].value), '\", WEBSITE_CONTENTSHARE:\"', variables('functionName'), '\", APPINSIGHTS_INSTRUMENTATIONKEY:\"', reference(concat('microsoft.insights/components/', variables('appInsightsName'))).InstrumentationKey, '\", KeyVaultUri:\"', reference(concat('Microsoft.KeyVault/vaults/', variables('keyVaultName'))).vaultUri, '\"}')))]"
},
{
"type": "slots",
"apiVersion": "2016-08-01",
"name": "[variables('functionStagingName')]",
"location": "[ResourceGroup().location]",
"dependsOn": [
"[variables('functionName')]",
"[variables('keyVaultName')]"
],
"kind": "functionapp",
"properties": {
"enabled": false,
"serverFarmId": "[variables('planName')]"
}
}
]
}
]
P.s. I know the way I'm creating my app settings is a work of art (sarcasm). Please don't judge me, just know that it works.
P.p.s Complete ARM Template: https://pastebin.com/mma4PyRu

your template is absolutely fine, so if this doesnt work it looks like a bug. having said that, you can always work around this by moving your accessPolicy assignment into a nested template:
{
"type": "Microsoft.Resources/deployments",
"apiVersion": "2018-05-01",
"name": "linkedTemplate",
"dependsOn": [
"[variables('keyVaultName')]",
"[variables('functionName')]"
],
"properties": {
"mode": "Incremental",
"templateLink": {
"uri":"https://mystorageaccount.blob.core.windows.net/AzureTemplates/newStorageAccount.json",
"contentVersion":"1.0.0.0"
},
"parameters": {
"managedIdentityId":{"value": "[reference(concat(resourceId('Microsoft.Web/sites', variables('functionName')), '/providers/Microsoft.ManagedIdentity/Identities/default'), '2015-08-31-PREVIEW').principalId]"}
}
}
You'd need to upload the template somewhere (which should consist of just your accessPolicy assignment
Reading: https://learn.microsoft.com/en-us/azure/azure-resource-manager/resource-group-linked-templates#external-template

Try removing the apiVersion from the reference() function, that should delay the call until after the resource is provisioned. e.g.
[reference(concat(resourceId('Microsoft.Web/sites', variables('functionName')), '/providers/Microsoft.ManagedIdentity/Identities/default')).principalId]"

Related

ARM database error: Can not perform requested operation on nested resource. Parent resource not found

"resources": [
{
"type": "Microsoft.Sql/servers",
"location": "[parameters('location')]",
"apiVersion": "2019-06-01-preview",
"name": "[parameters('serverName')]",
"identity": { "type": "SystemAssigned" },
"condition": "[and(parameters('enableVA'), parameters('useVAManagedIdentity'))]",
"properties": {
"administratorLogin": "[parameters('administratorLogin')]",
"administratorLoginPassword": "[parameters('administratorPassword')]"
},
"resources": [
{
"type": "Microsoft.Sql/servers/databases",
"apiVersion": "2021-02-01-preview",
"name": "[concat(parameters('serverName'), '/', parameters('databaseName'))]",
"location": "[parameters('serverLocation')]",
"dependsOn": [ "[concat('Microsoft.Sql/servers/', parameters('serverName'))]" ],
"sku": {
"name": "GP_S_Gen5_1",
"tier": "GeneralPurpose"
},
"properties": {
"collation": "SQL_Latin1_General_CP1_CI_AS",
"maxSizeBytes": "1073741824"
}
}
]
}
I've tried to use the nested resource for my DB, and I get the error that is described below. Deployment performed in powershell.
Don’t concat the server name in the database name property, just use the db name. The server name is implied by the nested definition.
This is a very common template, one which MS has extensive examples of. Here is a copy from the most basic docs example:
"resources": [
{
"type": "Microsoft.Sql/servers",
"apiVersion": "2020-02-02-preview",
"name": "[parameters('serverName')]",
"location": "[parameters('location')]",
"properties": {
"administratorLogin": "[parameters('administratorLogin')]",
"administratorLoginPassword": "[parameters('administratorLoginPassword')]"
},
"resources": [
{
"type": "databases",
"apiVersion": "2020-08-01-preview",
"name": "[parameters('sqlDBName')]",
"location": "[parameters('location')]",
"sku": {
"name": "Standard",
"tier": "Standard"
},
"dependsOn": [
"[resourceId('Microsoft.Sql/servers', concat(parameters('serverName')))]"
]
}
]

How do we pass the server ID to a server endpoint to a Storage sync aka file sync service through an ARM template

*"type": "microsoft.storagesync/storageSyncServices/syncGroups/serverEndpoints"
{
"type": "microsoft.storagesync/storageSyncServices/registeredServers",
"apiVersion": "2020-03-01",
"name": "[concat(parameters('FilesyncName'), '/rs')]",
"dependsOn": [
"[resourceId('microsoft.storagesync/storageSyncServices', parameters('FilesyncName'))]"
],
"properties": {
"agentVersion": "XXXX",
"serverOSVersion": "XXXX",
"lastHeartBeat": "XXXXX",
"serverRole": "Standalone",
"clusterId": "XX",
"serverId": "XXXXX",
"friendlyName": "XXXXXXXX"
}
},
{
"type": "microsoft.storagesync/storageSyncServices/syncGroups/serverEndpoints",
"apiVersion": "2020-03-01",
"name": "[concat(parameters('FilesyncName'),'/',parameters('syncgroupname'),'/','-se')]",
"dependsOn": [
"[resourceId('microsoft.storagesync/storageSyncServices/syncGroups', parameters('FilesyncName'), parameters('syncgroupname'))]",
"[resourceId('microsoft.storagesync/storageSyncServices', parameters('FilesyncName'))]",
"[resourceId('microsoft.storagesync/storageSyncServices/registeredServers', parameters('FilesyncName'), 'rs')]"
],
"properties": {
"serverLocalPath": "F:\\",
"cloudTiering": "On",
"volumeFreeSpacePercent": 20,
"tierFilesOlderThanDays": 7,
"friendlyName": "XXXX",
"serverResourceId": "[resourceId('microsoft.storagesync/storageSyncServices/registeredServers', parameters('FilesyncName'), 'rs')]",
"offlineDataTransfer": "On",
"offlineDataTransferShareName": "fsnew",
"initialDownloadPolicy": "NamespaceOnly",
"localCacheMode": "UpdateLocallyCachedFiles"
}
}*
The above resource type and the ARM TEMPLATE for adding the server end points.
This template doesn't trigger the provisioning the server end-point. Would like to see an example of the same.TIA
The following is a working ARM template that deploys a Storage Sync Service, a Sync Group and a Server Endpoint.
You can get the serverResourceId property when you register the server with your Storage sync server as described here, but in the ResourceId format:
/subscriptions/***/resourceGroups/***/providers/microsoft.storagesync/storageSyncServices/mystoragesyncservice/registeredServers/85fa92da-2b2e-447c-d3rg-f8bf43c4064f
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"storagesyncservicename": {
"type": "string",
"defaultValue": "mystoragesyncservice"
}
},
"variables": {},
"resources": [
{
"type": "microsoft.storagesync/storageSyncServices",
"apiVersion": "2020-03-01",
"name": "[parameters('storagesyncservicename')]",
"location": "westus2",
"properties": {
"incomingTrafficPolicy": "AllowAllTraffic"
}
},
{
"type": "microsoft.storagesync/storageSyncServices/syncGroups",
"apiVersion": "2020-03-01",
"name": "[concat(parameters('storagesyncservicename'), '/mystoragesyncgroup')]",
"dependsOn": [
"[resourceId('microsoft.storagesync/storageSyncServices', parameters('storagesyncservicename'))]"
],
"properties": {}
},
{
"type": "microsoft.storagesync/storageSyncServices/syncGroups/serverEndpoints",
"apiVersion": "2020-03-01",
"name": "[concat(parameters('storagesyncservicename'), '/mystoragesyncgroup/5770750b-a1e6-4910-9781-1482fdee757a')]",
"dependsOn": [
"[resourceId('microsoft.storagesync/storageSyncServices/syncGroups', parameters('storagesyncservicename'), 'mystoragesyncgroup')]",
"[resourceId('microsoft.storagesync/storageSyncServices', parameters('storagesyncservicename'))]"
],
"properties": {
"serverLocalPath": "D:\\Data",
"cloudTiering": "Off",
"volumeFreeSpacePercent": 20,
"friendlyName": "mytestafs",
"serverResourceId": "/subscriptions/***/resourceGroups/***/providers/microsoft.storagesync/storageSyncServices/mystoragesyncservice/registeredServers/85fa92da-2b2e-447c-d3rg-f8bf43c4064f",
"offlineDataTransfer": "Off",
"initialDownloadPolicy": "NamespaceThenModifiedFiles",
"localCacheMode": "UpdateLocallyCachedFiles"
}
}
]
}
I dont see any reason why not. its just a regular provider in Azure ARM api.

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)

Provisioning resource group and azure function at deployment level

I've written up the script below to do the following:
Provision a resource group
In a separate deployment:
Provision a storage account
Provision a server farm
Provision a function app
The problem lies in the setting of the app settings in the function app, when I'm setting up the AzureWebJobsStorage. The resourceId function fails to resolve the storage account. When looking at the documention for the resourceId function, it states:
When used with a subscription-level deployment, the resourceId() function can only retrieve the ID of resources deployed at that level. [docs]
But now I don't know how to resolve this!
Template:
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"resourceGroupName": {
"type": "string"
},
"functionName": {
"type": "string"
},
"storageAccName": {
"type": "string"
},
"namingPrefix": {
"type": "string"
}
},
"variables": {
"resourceGroupLocation": "North Europe",
"planName": "[replace(concat(variables('resourceGroupLocation'), 'Plan'),' ','')]",
"resourceGroupName": "[concat(parameters('namingPrefix'), '-', parameters('resourceGroupName'))]",
"functionName": "[concat(parameters('namingPrefix'), '-', parameters('functionName'))]",
"storageAccName": "[toLower(concat(parameters('namingPrefix'), parameters('storageAccName')))]"
},
"resources": [
{
"type": "Microsoft.Resources/resourceGroups",
"apiVersion": "2018-05-01",
"location": "[variables('resourceGroupLocation')]",
"name": "[variables('resourceGroupName')]",
"properties": {}
},
{
"type": "Microsoft.Resources/deployments",
"apiVersion": "2019-05-01",
"name": "NestedTemplate",
"resourceGroup": "[variables('resourceGroupName')]",
"dependsOn": [
"[variables('resourceGroupName')]"
],
"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",
"apiVersion": "2019-04-01",
"name": "[variables('storageAccName')]",
"location": "[variables('resourceGroupLocation')]",
"sku": {
"name": "Standard_LRS",
"tier": "Standard"
},
"kind": "Storage",
"properties": {
"networkAcls": {
"bypass": "AzureServices",
"virtualNetworkRules": [],
"ipRules": [],
"defaultAction": "Allow"
},
"supportsHttpsTrafficOnly": true,
"encryption": {
"services": {
"file": {
"enabled": true
},
"blob": {
"enabled": true
}
},
"keySource": "Microsoft.Storage"
}
}
},
{
"type": "Microsoft.Web/serverfarms",
"apiVersion": "2016-09-01",
"name": "[variables('planName')]",
"location": "[variables('resourceGroupLocation')]",
"sku": {
"name": "Y1",
"tier": "Dynamic",
"size": "Y1",
"family": "Y",
"capacity": 0
},
"kind": "functionapp",
"properties": {
"name": "[variables('planName')]",
"computeMode": "Dynamic",
"perSiteScaling": false,
"reserved": false,
"targetWorkerCount": 0,
"targetWorkerSizeId": 0
}
},
{
"type": "Microsoft.Web/sites",
"apiVersion": "2016-08-01",
"name": "[variables('functionName')]",
"location": "[variables('resourceGroupLocation')]",
"dependsOn": [
"[variables('planName')]",
"[variables('appInsightsName')]",
"[variables('storageAccName')]"
],
"kind": "functionapp",
"identity": {
"type": "SystemAssigned"
},
"properties": {
"enabled": true,
"hostNameSslStates": [
{
"name": "[concat(variables('functionName'), '.azurewebsites.net')]",
"sslState": "Disabled",
"hostType": "Standard"
},
{
"name": "[concat(variables('functionName'), '.scm.azurewebsites.net')]",
"sslState": "Disabled",
"hostType": "Repository"
}
],
"siteConfig": {
"appSettings": [
{
"name": "AzureWebJobsStorage",
"value": "[concat('DefaultEndpointsProtocol=https;AccountName=', variables('storageAccName'), ';AccountKey=', listKeys(resourceId('Microsoft.Storage/storageAccounts', variables('storageAccName')), providers('Microsoft.Storage', 'storageAccounts').apiVersions[0]).key1)]"
},
{
"name": "WEBSITE_CONTENTAZUREFILECONNECTIONSTRING",
"value": "[concat('DefaultEndpointsProtocol=https;AccountName=', variables('storageAccName'), ';AccountKey=', listKeys(resourceId('Microsoft.Storage/storageAccounts', variables('storageAccName')), providers('Microsoft.Storage', 'storageAccounts').apiVersions[0]).key1)]"
},
{
"name": "WEBSITE_CONTENTSHARE",
"value": "[variables('functionName')]"
},
{
"name": "FUNCTIONS_WORKER_RUNTIME",
"value": "node"
},
{
"name": "WEBSITE_NODE_DEFAULT_VERSION",
"value": "10.14.1"
},
{
"name": "FUNCTIONS_EXTENSION_VERSION",
"value": "~2"
}
]
},
"serverFarmId": "[variables('planName')]",
"reserved": false
}
}
]
}
}
}
]
}
Executed using following line:
New-AzDeployment -Location "North Europe" -TemplateFile $TemplateFilePath -TemplateParameterFile $ParametersFilePath -namingPrefix $namingPrefix;
Output
Resource Microsoft.Storage/storageAccounts 'testStorageAccount' failed with message '{
"error": {
"code": "ResourceNotFound",
"message": "The Resource 'Microsoft.Storage/storageAccounts/testStorageAccount' under resource group '<null>'
was not found."
}
}'
You've run into a few "limitations" in the template language that make this hard at the moment (we're working on improving both).
1) Inline nested deployments have the scope of the top-level deployment when evaluating template language expressions (anything in []) which is sometimes convenient (you can share variables for example) but more often than not causes some problem (like the resourceId function). ARM has always behaved this way but with the advent of subscription level deployments it's a bit more problematic (you run into it more). To get around this you can use linked templates - I know that's not always ideal but they will behave as expected.
2) the second thing you're running into is that list*() functions are evaluated immediately if ARM thinks the resource you're accessing is not within the same deployment. Due to #1, that's what ARM thinks in this case and why trying to concat() the resourceID still doesn't work.
Aside from that, stay away from the providers() function for apiVersions, it's not deterministic and the results of that function can change without you knowing it. The code you had in your original post for listKeys did work a while back and you might see it in samples floating around, but changes in the platform can break that function's behavior. Literal apiVersions are always better in ARM templates.
The docs are confusing and don't describe how resourceId() works at that level. It should really say:
When used in a subscription level deployment resourceId() can only get the resource IDs of resource groups (Microsoft.Resources/resourceGroups), policies (Microsoft.Authorization/policyAssignments), and role definitions (Microsoft.Authorization/roleDefinitions), as these are subscription level specific resources.
Since that's how it actually works. More docs here.
In terms of how to proceed from here, you'll simply need to deploy the resource groups in one template at the subscription level, and the resources in another template at the resource group level.
I hit this issue and found that they more recently support nested templates better by defining inner and outer scopes on the deployment resources and function scopes.
https://learn.microsoft.com/bs-latn-ba/azure/azure-resource-manager/templates/cross-scope-deployment?tabs=azure-cli#how-functions-resolve-in-scopes
https://www.youtube.com/watch?v=96XxVyxrhZI
For anyone who runs into this issue at a later date (probably myself) I was forced to create the resource group in my powershell script, and then use new-AzResourceGroupDeployment instead.
To accommodate this, the changes to the deployment template were minimal (I remove the resource group and brought the nested template one level up). However, I was also accessing the storage account key incorrectly. This has been updated in the code below.
$resourceGroup = Get-AzResourceGroup -Name $resourceGroupName -ErrorAction SilentlyContinue
if(!$resourceGroup)
{
Write-Host "Creating resource group '$resourceGroupName' in location '$resourceGroupLocation'";
New-AzResourceGroup -Name $resourceGroupName -Location $resourceGroupLocation
}
else{
Write-Host "Using existing resource group '$resourceGroupName'";
}
# Start the deployment
Write-Host "Starting deployment...";
if(Test-Path $parametersFilePath) {
New-AzResourceGroupDeployment -ResourceGroupName $resourceGroupName -TemplateFile $TemplateFilePath -TemplateParameterFile $parametersFilePath;
}
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"resourceGroupName": {
"type": "string"
},
"functionName": {
"type": "string"
},
"storageAccName": {
"type": "string"
},
"namingPrefix": {
"type": "string"
}
},
"variables": {
"resourceGroupLocation": "North Europe",
"planName": "[replace(concat(variables('resourceGroupLocation'), 'Plan'),' ','')]",
"resourceGroupName": "[concat(parameters('namingPrefix'), '-', parameters('resourceGroupName'))]",
"functionName": "[concat(parameters('namingPrefix'), '-', parameters('functionName'))]",
"storageAccName": "[toLower(concat(parameters('namingPrefix'), parameters('storageAccName')))]"
},
"resources": [
{
"type": "Microsoft.Storage/storageAccounts",
"apiVersion": "2019-04-01",
"name": "[variables('storageAccName')]",
"location": "[variables('resourceGroupLocation')]",
"sku": {
"name": "Standard_LRS",
"tier": "Standard"
},
"kind": "Storage",
"properties": {
"networkAcls": {
"bypass": "AzureServices",
"virtualNetworkRules": [],
"ipRules": [],
"defaultAction": "Allow"
},
"supportsHttpsTrafficOnly": true,
"encryption": {
"services": {
"file": {
"enabled": true
},
"blob": {
"enabled": true
}
},
"keySource": "Microsoft.Storage"
}
}
},
{
"type": "Microsoft.Web/serverfarms",
"apiVersion": "2016-09-01",
"name": "[variables('planName')]",
"location": "[variables('resourceGroupLocation')]",
"sku": {
"name": "Y1",
"tier": "Dynamic",
"size": "Y1",
"family": "Y",
"capacity": 0
},
"kind": "functionapp",
"properties": {
"name": "[variables('planName')]",
"computeMode": "Dynamic",
"perSiteScaling": false,
"reserved": false,
"targetWorkerCount": 0,
"targetWorkerSizeId": 0
}
},
{
"type": "Microsoft.Web/sites",
"apiVersion": "2016-08-01",
"name": "[variables('functionName')]",
"location": "[variables('resourceGroupLocation')]",
"dependsOn": [
"[variables('planName')]",
"[variables('appInsightsName')]",
"[variables('storageAccName')]"
],
"kind": "functionapp",
"identity": {
"type": "SystemAssigned"
},
"properties": {
"enabled": true,
"hostNameSslStates": [
{
"name": "[concat(variables('functionName'), '.azurewebsites.net')]",
"sslState": "Disabled",
"hostType": "Standard"
},
{
"name": "[concat(variables('functionName'), '.scm.azurewebsites.net')]",
"sslState": "Disabled",
"hostType": "Repository"
}
],
"siteConfig": {
"appSettings": [
{
"name": "AzureWebJobsStorage",
"value": "[concat('DefaultEndpointsProtocol=https;AccountName=', variables('storageAccName'), ';AccountKey=', listKeys(resourceId('Microsoft.Storage/storageAccounts', variables('storageAccName')), providers('Microsoft.Storage', 'storageAccounts').apiVersions[0]).keys[0].value)]"
},
{
"name": "WEBSITE_CONTENTAZUREFILECONNECTIONSTRING",
"value": "[concat('DefaultEndpointsProtocol=https;AccountName=', variables('storageAccName'), ';AccountKey=', listKeys(resourceId('Microsoft.Storage/storageAccounts', variables('storageAccName')), providers('Microsoft.Storage', 'storageAccounts').apiVersions[0]).keys[0].value)]"
},
{
"name": "WEBSITE_CONTENTSHARE",
"value": "[variables('functionName')]"
},
{
"name": "FUNCTIONS_WORKER_RUNTIME",
"value": "node"
},
{
"name": "WEBSITE_NODE_DEFAULT_VERSION",
"value": "10.14.1"
},
{
"name": "FUNCTIONS_EXTENSION_VERSION",
"value": "~2"
}
]
},
"serverFarmId": "[variables('planName')]",
"reserved": false
}
}
]
}
Edited -
Sorry I jumped the gun earlier, the issue is with New-AzDeployment which is specifically for deploying subscription level resources.
https://learn.microsoft.com/en-us/powershell/module/az.resources/new-azdeployment?view=azps-2.7.0
Excerpts from the link above -
The New-AzDeployment cmdlet adds a deployment at the current
subscription scope. This includes the resources that the deployment
requires.
An Azure resource is a user-managed Azure entity. A resource can live
in a resource group, like database server, database, website, virtual
machine, or Storage account. Or, it can be a subscription level
resource, like role definition, policy definition, etc.
To add resources to a resource group, use the
New-AzResourceGroupDeployment which creates a deployment at a resource
group. The New-AzDeployment cmdlet creates a deployment at the current
subscription scope, which deploys subscription level resources.

Deployment template validation failed while deploying machine in azure

Facing following issues while performing vagrant up with azure provider
"response": {
"body": "{\"error\":{\"code\":\"InvalidTemplate\",\"message\":\"Deployment template validation failed: 'The value fo
r the template parameter 'adminPassword' at line '1' and column '306' is not provided. Please see https://aka.ms/arm-dep
loy/#parameter-file for usage details.'.\"}}",
Template file:
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"vaults_VaultVagrant_name": {
"defaultValue": "VaultVagrant",
"type": "String"
},
"AdminPassword":{
"type":"securestring"
}
},
"variables": {},
"resources": [
{
"type": "Microsoft.KeyVault/vaults",
"name": "[parameters('vaults_VaultVagrant_name')]",
"apiVersion": "2015-06-01",
"location": "eastus",
"tags": {},
"properties": {
"sku": {
"family": "A",
"name": "standard"
},
"tenantId": "yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy",
"accessPolicies": [
{
"tenantId": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"objectId": "1efb1891-8ad4-4f69-9e0d-f5849e6f8c98",
"permissions": {
"keys": [
"get",
"create",
"delete",
"list",
"update",
"import",
"backup",
"restore"
],
"secrets": [
"all"
]
}
}
],
"enabledForDeployment": true
},
"resources": [],
"dependsOn": []
}
]
}
Parameter
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"AdminPassword": {
"reference": {
"keyVault": {
"id":"/subscriptions/xxxxxxxxxxxxxxxxxxxxxxxxx/resourceGroups/azurevag/providers/Microsoft.KeyVault/vaults/VaultVagrant"
},
"secretName": "vagrant"
}
}
}
}
I am deploying both files from local machine as like in below
azure group deployment create -f "c:\MyTemplates\example.json" -e
"c:\MyTemplates\example.params.json" -g examplegroup -n
exampledeployment
ISSUE:After deployment is successfully created checked the deployment script in azure portal where both the files look like below
TemplateFile
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"vaults_VaultVagrant_name": {
"defaultValue": "VaultVagrant",
"type": "String"
}
},
"variables": {},
"resources": [
{
"comments": "Generalized from resource: '/subscriptions/214d050d-5430-4fd8-bb08-8152128a07b9/resourceGroups/azurevag/providers/Microsoft.KeyVault/vaults/VaultVagrant'.",
"type": "Microsoft.KeyVault/vaults",
"name": "[parameters('vaults_VaultVagrant_name')]",
"apiVersion": "2015-06-01",
"location": "eastus",
"tags": {},
"properties": {
"sku": {
"family": "A",
"name": "standard"
},
"tenantId": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"accessPolicies": [
{
"tenantId": "yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy",
"objectId": "1efb1891-8ad4-4f69-9e0d-f5849e6f8c98",
"permissions": {
"keys": [
"get",
"create",
"delete",
"list",
"update",
"import",
"backup",
"restore"
],
"secrets": [
"all"
]
}
}
],
"enabledForDeployment": true
},
"resources": [],
"dependsOn": []
}
]
}
Note: Parameter adminpassword is missed after deployment
Parameter file:
parameter file is empty.
How the values(admin password) are missed after deployment?