Checking whether multiple resources exists using existenceCondition in Azure policy - azure

I am trying to bring up an azure policy to create alert rules for a specific type of resource when there are desired alert rules already not defined for the particular resource. For that i used deployIfNotExists effect and existenceCondition with anyOf.
But it is not working as expected. Need some help on this if someone already handled similar scenario for your usecase.
"then": {
"effect": "deployIfNotExists",
"details": {
"type": "microsoft.insights/metricAlerts",
"resourceGroupName": "[resourceGroup().name]",
"existenceCondition": {
"anyOf": [
{
"field": "name",
"equals": "[concat('alert_appgw_failedrequests_',field('Name'))]"
},
{
"field": "name",
"equals": "[concat('alert_appgw_throughput_',field('Name'))]"
},
{
"field": "name",
"equals": "[concat('alert_appgw_unhealthyhost_',field('Name'))]"
}
]
},
"roleDefinitionIds": [
"/providers/Microsoft.Authorization/roleDefinitions/b24988ac-6180-42a0-ab88-20f7382dd24c"
],
"deployment": {
This is not working as expected, this is actually metricalert resource i try to create if not exists for appgateway, if i delete any one of the metricalert alone for an appgateway it is not creating an alertrule/metric alert.
I need to create a metricalert if even any one of the metric alert is deleted or not exists for a appgateway.
Someone help out with your ideas,
PS: Please correct me if this query is not clear enough.
Edit:
Posting the full definition, Actually, i am getting non-compliant resources as compliant too. #Niclas
{
"mode": "All",
"policyRule": {
"if": {
"allOf": [
{
"field": "type",
"equals": "Microsoft.Network/applicationGateways"
},
{
"field": "tags.nomonitor",
"exists": false
}
]
},
"then": {
"effect": "deployIfNotExists",
"details": {
"type": "microsoft.insights/metricAlerts",
"resourceGroupName": "[resourceGroup().name]",
"existenceCondition": {
"anyOf": [
{
"field": "name",
"equals": "[concat('alert_appgw_failedrequests_',field('Name'))]"
},
{
"field": "name",
"equals": "[concat('alert_appgw_throughput_',field('Name'))]"
},
{
"field": "name",
"equals": "[concat('alert_appgw_unhealthyhost_',field('Name'))]"
}
]
},
"roleDefinitionIds": [
"/providers/Microsoft.Authorization/roleDefinitions/b24988ac-6180-42a0-ab88-20f7382dd24c"
],
"deployment": {
"properties": {
"mode": "incremental",
"template": {
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"appgateway_name": {
"type": "String"
},
"location": {
"type": "String"
}
},
"resources": [
{
"type": "microsoft.insights/metricAlerts",
"apiVersion": "2018-03-01",
"name": "[concat('alert_appgw_failedrequests_',parameters('appgateway_name'))]",
"location": "global",
"properties": {
"description": "Platform alerts",
"severity": 2,
"enabled": true,
"scopes": [
"[concat('/subscriptions/', subscription().subscriptionId, '/resourceGroups/', resourceGroup().name, '/providers/Microsoft.Network/applicationGateways/',parameters('appgateway_name'))]"
],
"evaluationFrequency": "PT15M",
"windowSize": "PT15M",
"criteria": {
"allOf": [
{
"threshold": 10,
"name": "Metric1",
"metricNamespace": "Microsoft.Network/applicationGateways",
"metricName": "FailedRequests",
"operator": "GreaterThanOrEqual",
"timeAggregation": "Total",
"criterionType": "StaticThresholdCriterion"
}
],
"odata.type": "Microsoft.Azure.Monitor.SingleResourceMultipleMetricCriteria"
},
"autoMitigate": true,
"targetResourceType": "Microsoft.Network/applicationGateways",
"targetResourceRegion": "[parameters('location')]",
"actions": [
{
"actionGroupId": "/subscriptions/ec23feef-629f-481d-b69e-a5d7faa5cb26/resourceGroups/DefaultResourceGroup-WUS2/providers/microsoft.insights/actionGroups/ALERT-DL",
"webHookProperties": {}
}
]
}
},
{
"type": "microsoft.insights/metricAlerts",
"apiVersion": "2018-03-01",
"name": "[concat('alert_appgw_throughput_',parameters('appgateway_name'))]",
"location": "global",
"properties": {
"description": "Platform alerts",
"severity": 2,
"enabled": true,
"scopes": [
"[concat('/subscriptions/', subscription().subscriptionId, '/resourceGroups/', resourceGroup().name, '/providers/Microsoft.Network/applicationGateways/',parameters('appgateway_name'))]"
],
"evaluationFrequency": "PT15M",
"windowSize": "PT15M",
"criteria": {
"allOf": [
{
"threshold": 1000,
"name": "Metric1",
"metricNamespace": "Microsoft.Network/applicationGateways",
"metricName": "Throughput",
"operator": "GreaterThan",
"timeAggregation": "Average",
"criterionType": "StaticThresholdCriterion"
}
],
"odata.type": "Microsoft.Azure.Monitor.SingleResourceMultipleMetricCriteria"
},
"autoMitigate": true,
"targetResourceType": "Microsoft.Network/applicationGateways",
"targetResourceRegion": "[parameters('location')]",
"actions": [
{
"actionGroupId": "/subscriptions/ec23feef-629f-481d-b69e-a5d7faa5cb26/resourceGroups/DefaultResourceGroup-WUS2/providers/microsoft.insights/actionGroups/ALERT-DL",
"webHookProperties": {}
}
]
}
},
{
"type": "microsoft.insights/metricAlerts",
"apiVersion": "2018-03-01",
"name": "[concat('alert_appgw_unhealthyhost_',parameters('appgateway_name'))]",
"location": "global",
"properties": {
"description": "Platform alerts",
"severity": 2,
"enabled": true,
"scopes": [
"[concat('/subscriptions/', subscription().subscriptionId, '/resourceGroups/', resourceGroup().name, '/providers/Microsoft.Network/applicationGateways/',parameters('appgateway_name'))]"
],
"evaluationFrequency": "PT15M",
"windowSize": "PT15M",
"criteria": {
"allOf": [
{
"threshold": 1,
"name": "Metric1",
"metricNamespace": "Microsoft.Network/applicationGateways",
"metricName": "UnhealthyHostCount",
"operator": "GreaterThanOrEqual",
"timeAggregation": "Average",
"criterionType": "StaticThresholdCriterion"
}
],
"odata.type": "Microsoft.Azure.Monitor.SingleResourceMultipleMetricCriteria"
},
"autoMitigate": true,
"targetResourceType": "Microsoft.Network/applicationGateways",
"targetResourceRegion": "[parameters('location')]",
"actions": [
{
"actionGroupId": "/subscriptions/ec23feef-629f-481d-b69e-a5d7faa5cb26/resourceGroups/DefaultResourceGroup-WUS2/providers/microsoft.insights/actionGroups/ALERT-DL",
"webHookProperties": {}
}
]
}
}
]
},
"parameters": {
"appgateway_name": {
"value": "[field('Name')]"
},
"location": {
"value": "[field('Location')]"
}
}
}
}
}
}
},
"parameters": {}
}

Related

Azure policy which enforces frontdoor firewall to allow only certain IP's

I need to create a Azure policy which enforces frontdoor firewall to allow only certain IP's
Something like below,
https://github.com/Azure/azure-policy/blob/bbfc60104c2c5b7fa6dd5b784b5d4713ddd55218/samples/EventHub/allowed-event-hub-firewall-ip/azurepolicy.json
I have created the below policy but it is not adding the waf custom rule.
Can someone help to find what's wrong with below policy,
"properties": {
"displayName": "akapolicy",
"policyType": "Custom",
"mode": "All",
"metadata": {
},
"parameters": {},
"policyRule": {
"if": {
"allOf": [
{
"field": "type",
"equals": "Microsoft.Network/FrontDoorWebApplicationFirewallPolicies"
},
{
"anyOf": [
{
"field": "tags['application']",
"exists": true
}
]
}
]
},
"then": {
"details": {
"deployment": {
"properties": {
"mode": "incremental",
"template": {
"$schema": "http://schema.management.azure.com/schemas/2018-05-01/subscriptionDeploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"resources": [
{
"apiVersion": "2022-05-01",
"properties": {
"customRules": {
"rules": [
{
"action": "Allow",
"enabledState": "Enabled",
"matchConditions": [
{
"matchValue": [
"1.1.1.1"
],
"matchVariable": "RemoteAddr",
"operator": "Contains"
}
],
"name": "akamairule",
"priority": "1",
"rateLimitDurationInMinutes": "1",
"rateLimitThreshold": "50",
"ruleType": "MatchRule"
}
]
}
}
}
]
}
}
},
"roleDefinitionIds": [
"/providers/Microsoft.Authorization/roleDefinitions/4d97b98b-1d4f-4787-a291-c67834d212e7"
],
"type": "Microsoft.Network/frontdoorWebApplicationFirewallPolicies"
},
"effect": "deployIfNotExists"
}
}
},
}
}

Arm template if condition

I am trying to implement if condition for the arm template. Idea is from the parameter to read if it suppose to deploy in prod or nonprod sub and have the subnets predefined. Then deploy storage and add some subnets to the storage account virtual network list.
The following line causing troubles:
"virtualNetworkRules": "[if(equals(parameters('Sub'), 'nonprod'),'variables('nonprodvirtualNetworkSubnets').virtualNetworkRulesCopy', 'variables('prodvirtualNetworkSubnets').virtualNetworkRulesCopy', )]",
All help is much appreciated.
"Parameters": {
"Sub": {
"type": "string",
"defaultValue": "nonprod",
"metadata": {
"description": "Prod or nonprod sub"
}
}
},
"variables": {
"subscriptionId": "[subscription().subscriptionId]",
"resourcegroupName": "[toUpper(concat(parameters('splitSubscriptionName')[0], '-', parameters('splitSubscriptionName')[1], '-', parameters('splitSubscriptionName')[2], '-02-NET-RSG'))]",
"virtualNetworkname": "[toLower(concat(parameters('splitSubscriptionName')[0], '-', parameters('splitSubscriptionName')[1], '-', parameters('splitSubscriptionName')[2], '-02-NET-', parameters('splitSubscriptionName')[3], '-00-net'))]",
"storageAccountType": "Standard_LRS", // "allowedValues": ["Standard_LRS", "Standard_GRS", "Standard_ZRS", "Premium_LRS"]
"blobServicesName": "default",
"VirtualNetworkExternalId": "[concat('/subscriptions/', variables('subscriptionId'), '/resourceGroups/', variables('resourcegroupName'), '/providers/Microsoft.Network/virtualNetworks/', variables('virtualNetworkname'), '/subnets/')]",
"nonprodAllowedSubnets": [
"mngm00-devtest-sub",
"mngm01-devtest-sub",
"mngm02-devtest-sub"
],
"prodAllowedSubnets": [
"mngm00-prod-sub",
"mngm01-prod-sub"
],
"nonprodvirtualNetworkSubnets": {
"copy": [
{
"name": "virtualNetworkRulesCopy",
"count": "[length(variables('nonprodAllowedSubnets'))]",
"input": {
"id": "[concat(variables('VirtualNetworkExternalId'), variables('nonprodAllowedSubnets')[copyIndex('virtualNetworkRulesCopy')])]",
"action": "Allow",
"state": "Succeeded"
}
}
]
},
"prodvirtualNetworkSubnets": {
"copy": [
{
"name": "virtualNetworkRulesCopy",
"count": "[length(variables('prodAllowedSubnets'))]",
"input": {
"id": "[concat(variables('VirtualNetworkExternalId'), variables('prodAllowedSubnets')[copyIndex('virtualNetworkRulesCopy')])]",
"action": "Allow",
"state": "Succeeded"
}
}
]
}
},
"resources": [
{
"type": "Microsoft.Storage/storageAccounts",
"apiVersion": "2019-04-01",
"name": "[parameters('storageAccountName')]",
"location": "[resourceGroup().location]",
"sku": {
"name": "[variables('storageAccountType')]"
},
"kind": "[parameters('storageAccountKind')]",
"properties": {
"accessTier": "[parameters('accessTier')]",
"supportsHttpsTrafficOnly": true,
"allowBlobPublicAccess": false,
"networkAcls": {
"bypass": "AzureServices",
"virtualNetworkRules": "[if(equals(parameters('Sub'), 'nonprod'),'variables('nonprodvirtualNetworkSubnets').virtualNetworkRulesCopy', 'variables('prodvirtualNetworkSubnets').virtualNetworkRulesCopy', )]",
"defaultAction": "Deny"
},
"encryption": {
"services": {
"file": {
"enabled": true
},
"blob": {
"enabled": true
}
},
"keySource": "Microsoft.Storage"
}
}
}
]
}
it should be like this:
[if(equals(parameters('Sub'), 'nonprod'), variables('nonprodvirtualNetworkSubnets').virtualNetworkRulesCopy, variables('prodvirtualNetworkSubnets').virtualNetworkRulesCopy]
so drop ' from your if

Azure DeployIfNotExist Policy evalutes but do not deploy template/show compliant

I am working on DeployIfNotExist Azure Policy which checks all vnets, checks if specific peering exists and if so checks UDR settings in place. If different than specified, it aims to deploy required UDR.
I am not able to get this to work and the current state is that initial check works fine (non-compliant vnets are reported) but no automatic remediation is done for new/updated vnets. Further, if I do manual remediation, the vnet is still marked as non-compliant.
Azure Policy Policy Rule below.
{
"if": {
"anyOf": [
{
"allOf": [
{
"field": "type",
"equals": "Microsoft.Network/virtualNetworks"
},
{
"field": "Microsoft.Network/virtualNetworks/VirtualNetworkPeerings[*].peeringState",
"equals": "Connected"
},
{
"field": "Microsoft.Network/virtualNetworks/VirtualNetworkPeerings[*].name",
"equals": "peerSpokeToHub"
}
]
},
{
"allOf": [
{
"field": "type",
"equals": "Microsoft.Network/virtualNetworks/VirtualNetworkPeerings"
},
{
"field": "Microsoft.Network/virtualNetworks/virtualNetworkPeerings/remoteVirtualNetwork.id",
"exists": "true"
}
]
}
]
},
"then": {
"effect": "deployIfNotExists",
"details": {
"type": "Microsoft.Network/virtualNetworks/subnets",
"existenceCondition": {
"allOf": [
{
"field": "Microsoft.Network/virtualNetworks/subnets/routeTable.id",
"exists": "true"
},
{
"field": "Microsoft.Network/virtualNetworks/subnets/routeTable.routes[*].name",
"equals": "toNVA"
},
{
"field": "Microsoft.Network/virtualNetworks/subnets/routeTable.routes[*].addressPrefix",
"equals": "0.0.0.0/0"
},
{
"field": "Microsoft.Network/virtualNetworks/subnets/routeTable.routes[*].nextHopType",
"equals": "VirtualAppliance"
},
{
"field": "Microsoft.Network/virtualNetworks/subnets/routeTable.routes[*].nextHopIpAddress",
"in": ["10.0.0.1", "10.0.0.2"]
},
{
"field": "Microsoft.Network/virtualNetworks/subnets/routeTable.routes[*].provisioningState",
"equals": "Succeeded"
}
]
},
"roleDefinitionIds": [
"/providers/Microsoft.Authorization/roleDefinitions/b24988ac-6180-42a0-ab88-20f7382dd24c"
],
"deployment": {
"properties": {
"mode": "incremental",
"template": {
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"vNetName": {
"type": "string",
"metadata": {
"description": "subnet to attach udr"
}
},
"RouteTableName": {
"type": "string",
"metadata": {
"description": "Name of a route table upon remediation"
}
},
"location": {
"type": "string",
"metadata": {
"description": "location of resource"
}
},
"NVAip": {
"type": "string",
"metadata": {
"description": "NVA IP"
}
}
},
"resources": [
{
"name": "[parameters('RouteTableName')]",
"type": "Microsoft.Network/routeTables",
"apiVersion": "2018-11-01",
"location": "[parameters('location')]",
"properties": {
"routes": [
{
"properties": {
"addressPrefix": "0.0.0.0/0",
"nextHopType": "VirtualAppliance",
"nextHopIpAddress": "[parameters('NVAip')]"
},
"name": "toNVA"
}
]
}
},
{
"apiVersion": "2017-08-01",
"name": "apply-routetable-to-subnet",
"type": "Microsoft.Resources/deployments",
"resourceGroup": "[resourceGroup().name]",
"dependsOn": [
"[concat('Microsoft.Network/routeTables/', 'RouteTable')]"
],
"properties": {
"mode": "Incremental",
"template": {
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"resources": [
{
"apiVersion": "2018-08-01",
"type": "Microsoft.Network/virtualNetworks/subnets",
"name": "[concat(parameters('vNetName'),'/default')]",
"location": "[resourceGroup().location]",
"properties": {
"addressPrefix": "[reference(resourceId(resourceGroup().name, 'Microsoft.Network/virtualNetworks/subnets', parameters('vNetName'), 'default'), '2018-03-01').addressPrefix]",
"routeTable": {
"id": "[resourceId('Microsoft.Network/routeTables', parameters('RouteTableName'))]"
},
"networkSecurityGroup": {
"id": "[reference(resourceId(resourceGroup().name, 'Microsoft.Network/virtualNetworks/subnets', parameters('vNetName'), 'default'), '2018-03-01').networkSecurityGroup.id]"
}
}
}
]
}
}
}
]
},
"parameters": {
"vNetName": {
"value": "[field('fullName')]"
},
"RouteTableName": {
"value": "[parameters('RouteTableName')]"
},
"NVAip": {
"value": "[parameters('fortigateIp')]"
},
"location": {
"value": "[field('location')]"
}
}
}
}
}
}
}
This seems like a problem with your ARM template. I would be sure to test it and check it. The ARM VSCode extension now has a what-if testing capability that lets you see what happens when you are to deploy that template.

Azure Resource Template Dependencies / Application Insights

I have a chicken and egg problem deploying Application Insights with my web application to Azure. In the ARM template, the Application Insights module is dependent upon the web site for the application id (see dependencies in the ARM templates below). On the other hand, in order to fully instrument the web application, I need the instrumentation key from the Application Insights Module. How does one get around this?
Application Insights View From the Portal
ARM Template for Web App
ARM Template for Application Insights
The solution is to have the connection strings and app settings created as nested child resources of the web site. By using the child resource strategy, one can then make the appsettings dependent upon both the web site and application insights. This allows provisioning to occur in the following order:
Web Site
Application Insights
Web Site config / appsettings
The following two answers were helpful. The first one illustrates how to pull the instrumentation key. The second one illustrates how to nest app settings and connection strings as child resources of the web site.
How to pull the instrumentation key
How to nest app settings as child resources
Here is my final template:
{
"$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"webSiteName": {
"type": "string"
},
"aadTenant": {
"type": "string"
},
"aadAudience": {
"type": "string"
},
"endpoints": {
"type": "string",
"defaultValue": "n/a"
},
"apiEndpoint": {
"type": "string",
"defaultValue": "n/a"
},
"sqlConnStrName": {
"type": "string"
},
"sqlConnStrValue": {
"type": "string"
},
"skuName": {
"type": "string",
"defaultValue": "F1",
"allowedValues": [
"F1",
"D1",
"B1",
"B2",
"B3",
"S1",
"S2",
"S3",
"P1",
"P2",
"P3",
"P4"
],
"metadata": {
"description": "Describes plan's pricing tier and instance size. Check details at https://azure.microsoft.com/en-us/pricing/details/app-service/"
}
},
"skuCapacity": {
"type": "int",
"defaultValue": 1,
"minValue": 1,
"metadata": {
"description": "Describes plan's instance count"
}
}
},
"variables": {
"hostingPlanName": "[concat(parameters('webSiteName'), '-hostingplan')]"
},
"resources": [
{
"apiVersion": "2015-08-01",
"name": "[variables('hostingPlanName')]",
"type": "Microsoft.Web/serverfarms",
"location": "[resourceGroup().location]",
"tags": {
"displayName": "HostingPlan"
},
"sku": {
"name": "[parameters('skuName')]",
"capacity": "[parameters('skuCapacity')]"
},
"properties": {
"name": "[variables('hostingPlanName')]"
}
},
{
"apiVersion": "2015-08-01",
"name": "[parameters('webSiteName')]",
"type": "Microsoft.Web/sites",
"location": "[resourceGroup().location]",
"dependsOn": [
"[variables('hostingPlanName')]"
],
"tags": {
"[concat('hidden-related:', resourceId('Microsoft.Web/serverfarms', variables('hostingPlanName')))]": "empty",
"displayName": "Website"
},
"properties": {
"name": "[parameters('webSiteName')]",
"serverFarmId": "[resourceId('Microsoft.Web/serverfarms', variables('hostingPlanName'))]"
},
"resources": [
{
"apiVersion": "2015-08-01",
"name": "appsettings",
"type": "config",
"dependsOn": [
"[parameters('webSiteName')]",
"[concat('AppInsights', parameters('webSiteName'))]"
],
"properties": {
"ida:Tenant": "[parameters('aadTenant')]",
"ida:Audience": "[parameters('aadAudience')]",
"endpoints": "[parameters('endpoints')]",
"apiEndpoint": "[parameters('apiEndpoint')]",
"applicationInsightsInstrumentationKey": "[reference(resourceId('Microsoft.Insights/components', concat('AppInsights', parameters('webSiteName'))), '2014-04-01').InstrumentationKey]"
}
},
{
"apiVersion": "2015-08-01",
"type": "config",
"name": "connectionstrings",
"dependsOn": [
"[parameters('webSiteName')]"
],
"properties": {
"[parameters('sqlConnStrName')]": {
"value": "[parameters('sqlConnStrValue')]",
"type": "SQLServer"
}
}
},
{
"apiVersion": "2015-08-01",
"name": "logs",
"type": "config",
"dependsOn": [
"[parameters('webSiteName')]"
],
"properties": {
"applicationLogs": {
"fileSystem": {
"level": "Off"
},
"azureTableStorage": {
"level": "Off",
"sasUrl": null
},
"azureBlobStorage": {
"level": "Information",
"sasUrl": "TO DO: pass in a SAS Url",
"retentionInDays": null
}
},
"httpLogs": {
"fileSystem": {
"retentionInMb": 40,
"enabled": true
}
},
"failedRequestsTracing": {
"enabled": true
},
"detailedErrorMessages": {
"enabled": true
}
}
}
]
},
{
"apiVersion": "2014-04-01",
"name": "[concat(variables('hostingPlanName'), '-', resourceGroup().name)]",
"type": "Microsoft.Insights/autoscalesettings",
"location": "[resourceGroup().location]",
"tags": {
"[concat('hidden-link:', resourceId('Microsoft.Web/serverfarms', variables('hostingPlanName')))]": "Resource",
"displayName": "AutoScaleSettings"
},
"dependsOn": [
"[variables('hostingPlanName')]"
],
"properties": {
"profiles": [
{
"name": "Default",
"capacity": {
"minimum": 1,
"maximum": 2,
"default": 1
},
"rules": [
{
"metricTrigger": {
"metricName": "CpuPercentage",
"metricResourceUri": "[resourceId('Microsoft.Web/serverfarms', variables('hostingPlanName'))]",
"timeGrain": "PT1M",
"statistic": "Average",
"timeWindow": "PT10M",
"timeAggregation": "Average",
"operator": "GreaterThan",
"threshold": 80.0
},
"scaleAction": {
"direction": "Increase",
"type": "ChangeCount",
"value": 1,
"cooldown": "PT10M"
}
},
{
"metricTrigger": {
"metricName": "CpuPercentage",
"metricResourceUri": "[resourceId('Microsoft.Web/serverfarms', variables('hostingPlanName'))]",
"timeGrain": "PT1M",
"statistic": "Average",
"timeWindow": "PT1H",
"timeAggregation": "Average",
"operator": "LessThan",
"threshold": 60.0
},
"scaleAction": {
"direction": "Decrease",
"type": "ChangeCount",
"value": 1,
"cooldown": "PT1H"
}
}
]
}
],
"enabled": false,
"name": "[concat(variables('hostingPlanName'), '-', resourceGroup().name)]",
"targetResourceUri": "[resourceId('Microsoft.Web/serverfarms', variables('hostingPlanName'))]"
}
},
{
"apiVersion": "2014-04-01",
"name": "[concat('ServerErrors ', parameters('webSiteName'))]",
"type": "Microsoft.Insights/alertrules",
"location": "[resourceGroup().location]",
"dependsOn": [
"[parameters('webSiteName')]"
],
"tags": {
"[concat('hidden-link:', resourceId('Microsoft.Web/sites', parameters('webSiteName')))]": "Resource",
"displayName": "ServerErrorsAlertRule"
},
"properties": {
"name": "[concat('ServerErrors ', parameters('webSiteName'))]",
"description": "[concat(parameters('webSiteName'), ' has some server errors, status code 5xx.')]",
"isEnabled": true,
"condition": {
"odata.type": "Microsoft.Azure.Management.Insights.Models.ThresholdRuleCondition",
"dataSource": {
"odata.type": "Microsoft.Azure.Management.Insights.Models.RuleMetricDataSource",
"resourceUri": "[resourceId('Microsoft.Web/sites', parameters('webSiteName'))]",
"metricName": "Http5xx"
},
"operator": "GreaterThan",
"threshold": 5.0,
"windowSize": "PT5M"
},
"action": {
"odata.type": "Microsoft.Azure.Management.Insights.Models.RuleEmailAction",
"sendToServiceOwners": true,
"customEmails": ["you#example.com"]
}
}
},
{
"apiVersion": "2014-04-01",
"name": "[concat('ForbiddenRequests ', parameters('webSiteName'))]",
"type": "Microsoft.Insights/alertrules",
"location": "[resourceGroup().location]",
"dependsOn": [
"[parameters('webSiteName')]"
],
"tags": {
"[concat('hidden-link:', resourceId('Microsoft.Web/sites', parameters('webSiteName')))]": "Resource",
"displayName": "ForbiddenRequestsAlertRule"
},
"properties": {
"name": "[concat('ForbiddenRequests ', parameters('webSiteName'))]",
"description": "[concat(parameters('webSiteName'), ' has some requests that are forbidden, status code 403.')]",
"isEnabled": true,
"condition": {
"odata.type": "Microsoft.Azure.Management.Insights.Models.ThresholdRuleCondition",
"dataSource": {
"odata.type": "Microsoft.Azure.Management.Insights.Models.RuleMetricDataSource",
"resourceUri": "[resourceId('Microsoft.Web/sites', parameters('webSiteName'))]",
"metricName": "Http403"
},
"operator": "GreaterThan",
"threshold": 5,
"windowSize": "PT5M"
},
"action": {
"odata.type": "Microsoft.Azure.Management.Insights.Models.RuleEmailAction",
"sendToServiceOwners": true,
"customEmails": [ ]
}
}
},
{
"apiVersion": "2014-04-01",
"name": "[concat('CPUHigh ', variables('hostingPlanName'))]",
"type": "Microsoft.Insights/alertrules",
"location": "[resourceGroup().location]",
"dependsOn": [
"[variables('hostingPlanName')]"
],
"tags": {
"[concat('hidden-link:', resourceId('Microsoft.Web/serverfarms', variables('hostingPlanName')))]": "Resource",
"displayName": "CPUHighAlertRule"
},
"properties": {
"name": "[concat('CPUHigh ', variables('hostingPlanName'))]",
"description": "[concat('The average CPU is high across all the instances of ', variables('hostingPlanName'))]",
"isEnabled": false,
"condition": {
"odata.type": "Microsoft.Azure.Management.Insights.Models.ThresholdRuleCondition",
"dataSource": {
"odata.type": "Microsoft.Azure.Management.Insights.Models.RuleMetricDataSource",
"resourceUri": "[resourceId('Microsoft.Web/serverfarms', variables('hostingPlanName'))]",
"metricName": "CpuPercentage"
},
"operator": "GreaterThan",
"threshold": 90,
"windowSize": "PT15M"
},
"action": {
"odata.type": "Microsoft.Azure.Management.Insights.Models.RuleEmailAction",
"sendToServiceOwners": true,
"customEmails": [ ]
}
}
},
{
"apiVersion": "2014-04-01",
"name": "[concat('LongHttpQueue ', variables('hostingPlanName'))]",
"type": "Microsoft.Insights/alertrules",
"location": "[resourceGroup().location]",
"dependsOn": [
"[variables('hostingPlanName')]"
],
"tags": {
"[concat('hidden-link:', resourceId('Microsoft.Web/serverfarms', variables('hostingPlanName')))]": "Resource",
"displayName": "AutoScaleSettings"
},
"properties": {
"name": "[concat('LongHttpQueue ', variables('hostingPlanName'))]",
"description": "[concat('The HTTP queue for the instances of ', variables('hostingPlanName'), ' has a large number of pending requests.')]",
"isEnabled": false,
"condition": {
"odata.type": "Microsoft.Azure.Management.Insights.Models.ThresholdRuleCondition",
"dataSource": {
"odata.type": "Microsoft.Azure.Management.Insights.Models.RuleMetricDataSource",
"resourceUri": "[concat(resourceGroup().id, '/providers/Microsoft.Web/serverfarms/', variables('hostingPlanName'))]",
"metricName": "HttpQueueLength"
},
"operator": "GreaterThan",
"threshold": 100.0,
"windowSize": "PT5M"
},
"action": {
"odata.type": "Microsoft.Azure.Management.Insights.Models.RuleEmailAction",
"sendToServiceOwners": true,
"customEmails": [ ]
}
}
},
{
"apiVersion": "2014-04-01",
"name": "[concat('AppInsights', parameters('webSiteName'))]",
"type": "Microsoft.Insights/components",
"location": "Central US",
"dependsOn": [
"[parameters('webSiteName')]"
],
"tags": {
"[concat('hidden-link:', resourceId('Microsoft.Web/sites', parameters('webSiteName')))]": "Resource",
"displayName": "AppInsightsComponent"
},
"properties": {
"ApplicationId": "[parameters('webSiteName')]"
}
}
],
"outputs": {
"siteUri": {
"type": "string",
"value": "[reference(concat('Microsoft.Web/sites/', parameters('webSiteName')), '2015-08-01').hostnames[0]]"
}
}
}
Alternative and updated answer (2020/03): do what the Azure Portal UX does (can be viewed via "Download template" at a last step of webapp creation).
For application insights resource, you don't necessarily need to wait for website resource to be created. According to applicationInsights ARM the website.Name is used to applicaitonInsights.properties.ApplicationId.
Since you are creating both at the same time, you can pass the name value both to ApplicationInsights and website resources from input:
{
"$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"subscriptionId": {
"type": "string"
},
"name": {
"type": "string"
},
"location": {
"type": "string"
},
"hostingEnvironment": {
"type": "string"
},
"hostingPlanName": {
"type": "string"
},
"serverFarmResourceGroup": {
"type": "string"
},
"alwaysOn": {
"type": "bool"
},
"sku": {
"type": "string"
},
"skuCode": {
"type": "string"
},
"workerSize": {
"type": "string"
},
"workerSizeId": {
"type": "string"
},
"numberOfWorkers": {
"type": "string"
},
"currentStack": {
"type": "string"
},
"netFrameworkVersion": {
"type": "string"
}
},
"resources": [
{
"apiVersion": "2018-11-01",
"name": "[parameters('name')]",
"type": "Microsoft.Web/sites",
"location": "[parameters('location')]",
"tags": {},
"dependsOn": [
"microsoft.insights/components/testapp01",
"[concat('Microsoft.Web/serverfarms/', parameters('hostingPlanName'))]"
],
"properties": {
"name": "[parameters('name')]",
"siteConfig": {
"appSettings": [
{
"name": "APPINSIGHTS_INSTRUMENTATIONKEY",
"value": "[reference('microsoft.insights/components/testapp01', '2015-05-01').InstrumentationKey]"
},
{
"name": "APPLICATIONINSIGHTS_CONNECTION_STRING",
"value": "[reference('microsoft.insights/components/testapp01', '2015-05-01').ConnectionString]"
},
{
"name": "ApplicationInsightsAgent_EXTENSION_VERSION",
"value": "~2"
}
],
"metadata": [
{
"name": "CURRENT_STACK",
"value": "[parameters('currentStack')]"
}
],
"netFrameworkVersion": "[parameters('netFrameworkVersion')]",
"alwaysOn": "[parameters('alwaysOn')]"
},
"serverFarmId": "[concat('/subscriptions/', parameters('subscriptionId'),'/resourcegroups/', parameters('serverFarmResourceGroup'), '/providers/Microsoft.Web/serverfarms/', parameters('hostingPlanName'))]",
"hostingEnvironment": "[parameters('hostingEnvironment')]",
"clientAffinityEnabled": true
}
},
{
"apiVersion": "2018-11-01",
"name": "[parameters('hostingPlanName')]",
"type": "Microsoft.Web/serverfarms",
"location": "[parameters('location')]",
"kind": "",
"tags": {},
"dependsOn": [],
"properties": {
"name": "[parameters('hostingPlanName')]",
"workerSize": "[parameters('workerSize')]",
"workerSizeId": "[parameters('workerSizeId')]",
"numberOfWorkers": "[parameters('numberOfWorkers')]",
"hostingEnvironment": "[parameters('hostingEnvironment')]"
},
"sku": {
"Tier": "[parameters('sku')]",
"Name": "[parameters('skuCode')]"
}
},
{
"apiVersion": "2015-05-01",
"name": "testapp01",
"type": "microsoft.insights/components",
"location": "centralus",
"tags": {},
"properties": {
"ApplicationId": "[parameters('name')]",
"Request_Source": "IbizaWebAppExtensionCreate"
}
}
]
}
The order of creation will be following:
Application Insights resource
App Service webapp
To elaborate on Mikl X answer, you can have the website depend on the application insights resource and set the instrumentation key on the app settings of the website.
Skipping irrelevant parts:
"resources": [
{
"type": "Microsoft.Insights/components",
"name": "[variables('appInsightsName')]"
... more config
},
{
"type": "Microsoft.Web/sites",
"name": "[variables('apiName')]",
"dependsOn": [
"[resourceId('Microsoft.Insights/components', variables('appInsightsName'))]" <-- ensure app insights is created first
],
"properties": {
"siteConfig": {
"appSettings": [
{
"name": "APPINSIGHTS_INSTRUMENTATIONKEY",
"value": "[reference(variables('appInsightsName')).InstrumentationKey]" <-- use key of previously created resource
}
]
}
}
}
... more config
]

ARM template webtest alertrule fails with ResourceNotFound

I have a Azure Resource Manager Template that is part of a set of nested templates. It creates a App Insights component, an alert rule against the website for forbidden requests, a multistep web test, and an alert rule against the web test. All the resources except the alert rule against the web test deploy successfully. I can go into the portal and create the alert against the test without issue after the deployment fails.
{
"$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"company": {
"type": "string"
},
"region": {
"type": "string"
},
"retailerAPIKey": {
"type": "string"
},
"deviceID": {
"type": "string"
},
"lumicastVersion": {
"type": "string"
}
},
"variables": {
"frameworkWebSite": "[concat(parameters('company'),'-BLS-FRAMEWORK-',parameters('region'))]"
},
"resources": [
{
"name": "[concat('ForbiddenRequests ', variables('frameworkWebSite'))]",
"type": "Microsoft.Insights/alertrules",
"location": "[parameters('region')]",
"apiVersion": "2014-04-01",
"tags": {
"displayName": "ForbiddenRequests frameworkWebSite"
},
"properties": {
"name": "[concat('ForbiddenRequests ', variables('frameworkWebSite'))]",
"description": "[concat(variables('frameworkWebSite'), ' has some requests that are forbidden, status code 403.')]",
"isEnabled": false,
"condition": {
"odata.type": "Microsoft.Azure.Management.Insights.Models.ThresholdRuleCondition",
"dataSource": {
"odata.type": "Microsoft.Azure.Management.Insights.Models.RuleMetricDataSource",
"resourceUri": "[concat(resourceGroup().id, '/providers/Microsoft.Web/sites/', variables('frameworkWebSite'))]",
"metricName": "Http403"
},
"operator": "GreaterThan",
"threshold": 0,
"windowSize": "PT5M"
},
"action": {
"odata.type": "Microsoft.Azure.Management.Insights.Models.RuleEmailAction",
"sendToServiceOwners": true,
"customEmails": [ ]
}
}
},
{
"name": "[variables('frameworkWebSite')]",
"type": "Microsoft.Insights/components",
"location": "Central US",
"apiVersion": "2014-04-01",
"tags": {
"displayName": "Component frameworkWebSite",
"[concat('hidden-link:',resourceGroup().id,'/providers/Microsoft.Web/sites/',variables('frameworkWebSite'))]": "Resource"
},
"properties": {
"applicationId": "[variables('frameworkWebSite')]"
}
},
{
"name": "[concat('siteinit-', variables('frameworkWebSite'))]",
"apiVersion": "2015-05-01",
"type": "Microsoft.Insights/webtests",
"location": "Central US",
"tags": {
"displayName": "WebtestL ABL BSL Init frameworkWebSite",
"[concat('hidden-link:', resourceId('microsoft.insights/components/', variables('frameworkWebSite')))]": "Resource"
},
"dependsOn": [
"[concat('microsoft.insights/components/', variables('frameworkWebSite'))]"
],
"properties": {
"Name": "[concat('GETBytelightInit-',parameters('region'))]",
"Description": "[concat('GETBytelightInit-',parameters('region'),'.webtest')]",
"Enabled": true,
"Frequency": 600,
"Timeout": 120,
"Kind": "multistep",
"Locations": [
{ "Id": "us-il-ch1-azr" },
{ "Id": "us-ca-sjc-azr" },
{ "Id": "us-tx-sn1-azr" }
],
"Configuration": {
"WebTest": "[concat('<workingwebtest goes here>','<ends here>')]"
},
"SyntheticMonitorId": "[concat('siteinit-', variables('frameworkWebSite'))]"
}
},
{
"name": "[concat('siteinit-', variables('frameworkWebSite'), '-alert')]",
"type": "Microsoft.Insights/alertrules",
"apiVersion": "2015-04-01",
"location": "[parameters('region')]",
"tags": {
"displayName": "Alert webtest site Init frameworkWebSite",
"[concat('hidden-link:', resourceId('microsoft.insights/components/', variables('frameworkWebSite')))]": "Resource",
"[concat('hidden-link:', resourceId('microsoft.insights/webtests/', concat('siteinit-', variables('frameworkWebSite'))))]": "Resource"
},
"dependsOn": [
"[concat('microsoft.insights/components/', variables('frameworkWebSite'))]",
"[concat('microsoft.insights/webtests/siteinit-', variables('frameworkWebSite'))]"
],
"properties": {
"name": "[concat('siteinit-', variables('frameworkWebSite'), '-alert')]",
"description": "Alert for site Initialize",
"isEnabled": true,
"condition": {
"$type": "Microsoft.WindowsAzure.Management.Monitoring.Alerts.Models.LocationThresholdRuleCondition, Microsoft.WindowsAzure.Management.Mon.Client",
"odata.type": "Microsoft.Azure.Management.Insights.Models.LocationThresholdRuleCondition",
"dataSource": {
"$type": "Microsoft.WindowsAzure.Management.Monitoring.Alerts.Models.RuleMetricDataSource, Microsoft.WindowsAzure.Management.Mon.Client",
"odata.type": "Microsoft.Azure.Management.Insights.Models.RuleMetricDataSource",
"resourceUri": "[resourceId('microsoft.insights/webtests/', concat('siteinit-', variables('frameworkWebSite')))]",
"metricName": "GSMT_AvRaW"
},
"windowSize": "PT15M",
"failedLocationCount": 2
},
"action": {
"$type": "Microsoft.WindowsAzure.Management.Monitoring.Alerts.Models.RuleEmailAction, Microsoft.WindowsAzure.Management.Mon.Client",
"odata.type": "Microsoft.Azure.Management.Insights.Models.RuleEmailAction",
"sendToServiceOwners": true,
"customEmails": [ ]
}
}
}
],
"outputs": {
"TestLink": {
"type": "string",
"value": "[resourceId('microsoft.insights/webtests/', concat('siteinit-', variables('frameworkWebSite')))]"
}
}
}
The deployment fails with:
"statusMessage": {
"Code": "ResourceNotFound",
"Message": "Exception of type 'Microsoft.WindowsAzure.Management.Monitoring.MonitoringServiceException' was thrown."
},
This is just the first of many test that will go in this template and each deployment has 2 copies of the site. So manual alert rule creation isn't an option.
I think there is a problem with your resourceUri:
"resourceUri": "[concat(resourceGroup().id, '/providers/Microsoft.Web/sites/', variables('frameworkWebSite'))]",
Give it a try with the resourceId() function:
"resourceUri": "[resourceId(resourceGroup().name, 'Microsoft.Web/sites', variables('frameworkWebSite'))]",
See resourceId() reference here.
Hope this helps.

Resources