Whitelist group for Azure Function Apps - azure

We are building a number of Azure Function Apps, each function app by default has its own IP white list.
We have multiple third parties that will consume these function apps. Each third party will likely have multiple IP addresses. Some function apps may be consumed by all third parties, other by one but not another, etc.
We would like a central way of managing this. We have a Powershell that we've used in the past to maintain the IP address, but was wondering if there was a better solution - perhaps are some templates built into Azure itself?
This must be a fairly common problem, does anyone have any suggestions please?

You can use Microsoft.Web/sites/config ARM object. You can deploy config object on top of your existing functions or include it in ARM definition of a complete functionApp template. In that way you can centrally manage IP rules and version control them. With PowerShell, you can orchestrate ARM deployments of IP rules based on your criteria.
https://learn.microsoft.com/en-us/azure/templates/microsoft.web/2018-11-01/sites/config
{
"type": "Microsoft.Web/sites/config",
"apiVersion": "2018-11-01",
"name": "[concat(variables('functionName'), '/web')]",
"location": "East US",
"dependsOn": [
"[resourceId('Microsoft.Web/sites', variables('functionName'))]"
],
"properties": {
"ipSecurityRestrictions": [
{
"ipAddress": "00.00.00.00/00",
"action": "Allow",
"tag": "Default",
"priority": 1000,
"name": "Rule 1"
},
{
"ipAddress": "00.00.00.00/00",
"action": "Allow",
"tag": "Default",
"priority": 2000,
"name": "Rule 2"
},
{
"ipAddress": "Any",
"action": "Deny",
"priority": 2147483647,
"name": "Deny all",
"description": "Deny all access"
}
]
}
}

The main problem is that IP-addresses can change quite often. I prefer to control this by subscription keys per client or / per client and API.
To do that, you can add an API Management (API Gateway Pattern) in front of your API's. You can also keep controlling per IP address using API Management, but I would say the api key is a good practice.
more info:
https://learn.microsoft.com/en-us/azure/api-management/api-management-access-restriction-policies#RestrictCallerIPs
https://microservices.io/patterns/apigateway.html

Related

Is it possible to check whether an azure app service is running using the Azure Management API?

We have a demo application that is a docker image deployed to a Linux App Service on the Free App Service Plan SKU. It is used infrequently and as such it aggressively spins down. On the next activation it takes about 3-5 minutes to spin up the image. I would like to use the azure management api to check to see if the service is running to know whether the response should be in 3s or 200s. GET web seems the most appropriate API to call but the response shows that it is running, likely reflecting the state of the underlying app service plan. A trimmed response is below and gives the same whether the app is hot or cold.
Example Response
"id": "/subscriptions/{subId}/resourceGroups/{rgName}/providers/Microsoft.Web/sites/{name}",
"name": "{name}",
"type": "Microsoft.Web/sites",
"kind": "app,linux,container",
"location": "East US",
"properties": {
"name": "{name}",
"state": "Running",
"webSpace": "ML-EastUSwebspace-Linux",
"usageState": "Normal",
It is not a Good practice to check from API Management if an Azure Service is running or not .
Only the following features are supported by Azure APIIM.
Best practice is to setup of alerts on critical application metrics.
Alerts are based on Action Groups that we configure to receive an Alert.
I overlooked Web Apps - List Instance Identifiers but this is results in what I am looking for. When the app is spun down the list of identifiers is the empty set and conversely when active it has an identifier.
Spun Down
{
"value": [],
"nextLink": null,
"id": null
}
Active
{
"value": [
{
"id": "/subscriptions/{subid}/resourceGroups/{rgname}/providers/Microsoft.Web/sites/{name}/instances/81c6b43bcb7aea592e620086200b3ab40b78857d08aa07e29c330415afa10cf8",
"name": "81c6b43bcb7aea592e620086200b3ab40b78857d08aa07e29c330415afa10cf8",
"type": "Microsoft.Web/sites/instances",
"location": "East US",
"properties": {
"state": "UNKNOWN",
"name": "81c6b43bcb7aea592e620086200b3ab40b78857d08aa07e29c330415afa10cf8",
"siteInstanceName": "81c6b43bcb7aea592e620086200b3ab40b78857d08aa07e29c330415afa10cf8",
"statusUrl": "{url}",
"detectorUrl": "{url}",
"consoleUrl": "{url}",
"healthCheckUrl": null,
"machineName": "lw0sdlwk0006ZZ",
"containers": null
}
}
],
"nextLink": null,
"id": null
}

Use Azure Container Instances via ARM to create an indeterminate number of containers

I am attempting to deploy an Azure Storage account along with an indeterminate number of tables via an ARM template.
Since MS are yet to provide a tables resource type for ARM, I'm instead using Azure Container Instances to spin up a container running azure-cli and then create the table that way.
As you can see in my example below, I'm using property iteration to create multiple containers - one for each table. This seemed to be working until the number of tables to create changed, and then I started getting errors.
The updates on container group 'your-aci-instance' are invalid. If you are going to update the os type, restart policy, network profile, CPU, memory or GPU resources for a container group, you must delete it first and then create a new one.
I understand what it's saying, but it does seem strange to me that you can create a container group yet not alter the group of containers within.
As ARM doesn't allow you do delete resources, I'd have to add a manual step to my deployment process to ensure that the ACI doesn't exist, which isn't really desirable.
Equally undesirable would be to use resource iteration to create multiple ACI's - there would be the possibility of many ACI's being strewn about the Resource Group that will never be used again.
Is there some ARM magic that I don't yet know about which can help me achieve the creation of tables that meets the following criteria?
Only a single ACI is created.
The number of tables to be created can change.
Notes
I have tried to use variable iteration to create a single 'command' array for a single container, but it seems that ACI considers all commands as a one liner, so this caused an error.
Further reading suggests that it is only possible to run one command on container startup.
How do I run multiple commands when deploying a container group?
Current attempt
Here is a snippet from my ARM template showing how I used property iteration to try and achieve my goal.
{
"condition": "[not(empty(variables('tables')))]",
"type": "Microsoft.ContainerInstance/containerGroups",
"name": "[parameters('containerInstanceName')]",
"apiVersion": "2018-10-01",
"location": "[resourceGroup().location]",
"properties": {
"copy": [
{
"name": "containers",
"count": "[max(length(variables('tables')), 1)]",
"input": {
"name": "[toLower(variables('tables')[copyIndex('containers')])]",
"properties": {
"image": "microsoft/azure-cli",
"command": [
"az",
"storage",
"table",
"create",
"--name",
"[variables('tables')[copyIndex('containers')]]"
],
"environmentVariables": [
{
"name": "AZURE_STORAGE_KEY",
"value": "[listkeys(parameters('storageAccount_Application_Name'), '2019-04-01').keys[0].value]"
},
{
"name": "AZURE_STORAGE_ACCOUNT",
"value": "[parameters('storageAccount_Application_Name')]"
},
{
"name": "DATETIME",
"value": "[parameters('dateTime')]"
}
],
"resources": {
"requests": {
"cpu": "1",
"memoryInGb": "1.5"
}
}
}
}
}
],
"restartPolicy": "OnFailure",
"osType": "Linux"
},
"dependsOn": [
"[resourceId('Microsoft.Storage/storageAccounts', parameters('storageAccount_Application_Name'))]"
],
"tags": {
"displayName": "Application Storage Account - Tables",
"Application": "[parameters('tagApplication')]",
"environment": "[parameters('tagEnvironment')]",
"version": "[parameters('tagVersion')]"
}
}
If it says the field is immutable - it is, there's nothing you can do about it really. You can always create a unique name for that container instance and use complete deployment mode and only deploy ACI to this particular resource group, that way it will always have only this ACI instance and others will get deleted and it will work around immutability.
you can call an azure function from inside the template (HTTP trigger) and pass in names of storage tables to create and it will do that, for example.
But either way its a hack.

Provision Azure Redis Cache using ARM and specify Access Keys

I try to provision an Azure Redis Cache using an ARM template. This is working as expected with the exception that I can't specify the access keys.
Usually I work with the generated keys which is probably the recommended way - but in this case I wan't to provide thos keys within my deployment (for some legacy reasons).
Q: Is it possible to provide the access keys within an ARM template? Or can I set them after the deployment using PowerShell?
Here is a snippet of my ARM template:
"resources": [
{
"type": "Microsoft.Cache/Redis",
"name": "[parameters('myRedis_name')]",
"apiVersion": "2016-04-01",
"location": "West Europe",
"tags": {},
"properties": {
"redisVersion": "3.2",
"sku": {
"name": "Standard",
"family": "C",
"capacity": 1
},
"enableNonSslPort": false,
"redisConfiguration": {
"maxclients": "1000",
"maxmemory-reserved": "50",
"maxmemory-delta": "50"
}
},
"resources": [],
"dependsOn": []
},
Just like Azure Storage keys (or DocumentDB keys, etc), you have no ability to specify the keys. You may either use what's provided or, at any time, regenerate the keys (either primary or secondary). This is how keys are managed, regardless whether using ARM or the portal. Here's a screengrab where you can see the regen options:
There's no way to enter a specific key of your own.

How to use a existing Microsoft.Web/serverfarms in a Azure Resource Manager Template?

I want to deploy a website (Microsoft.Web/sites) resource to a existing hosting plan (Microsoft.Web/serverfarms) without having to define the sku, workersize, etc. in the ARM template. It should just use the hosting plan as-is without changing it. But the sku seems to be required for the hosting plan definition and the hosting plan definition seems to be required for the website definition.
At the moment we read the sku of the hosting plan and set it as a parameter in the ARM template, but sometimes it still triggers a scaling operation in azure and restarts all websites on the hosting plan.
The only thing you need in the ARM Template to set the hosting plan is the resourceId of that serverFarm - that's the serverFarmId property below...
"name": "[variables('websiteName')]",
"type": "Microsoft.Web/sites",
"location": "centralus",
"apiVersion": "2015-08-01",
"dependsOn": [ ],
"tags": {
"displayName": "website"
},
"properties": {
"name": "[variables('websiteName')]",
"serverFarmId": "[resourceId(parameters('serverFarmResourceGroupName'), 'Microsoft.Web/serverFarms', parameters('AppSvcPlanName'))]"
}
That's barebones, but it will put a web app into the existing serverFarm.

Autoscaling IaaS VMs in ARM mode from a template

I've created an template-based deployment that over-provisions a number of Linux VMs. I'd like to autoscale them as per classic instances, where Azure will turn on/turn off instances according to CPU load.
Is this possible with ARM mode? And if not, is there a suggested alternative method? The only examples I can find are around using Application Insights and PaaS functionality. I've got a Python app running in Docker on Ubuntu hosts.
For IaaS, you must use virtual machine scale sets to use autoscale, else you need to stick with PaaS (web apps).
For this you would first need to create an availability group for the VMs. The resource decleration in the ARM template looks something like this:
{
"type": "Microsoft.Compute/availabilitySets",
"name": "[variables('availabilitySetName')]",
"apiVersion": "2015-05-01-preview",
"location": "[parameters('location')]",
"properties": {
"platformFaultDomainCount": "2"
}
}
Then for the virtual machine resource the decliration in the ARM Template would look something like this:
{
"apiVersion": "2015-05-01-preview",
"type": "Microsoft.Compute/virtualMachines",
"name": "[concat(variables('vmName'), '0')]",
"location": "[parameters('location')]",
"dependsOn": [
"[concat('Microsoft.Storage/storageAccounts/', parameters('newStorageAccountName'))]",
"[concat('Microsoft.Network/networkInterfaces/', variables('nicName'), '0')]",
"[concat('Microsoft.Compute/availabilitySets/', variables('availabilitySetName'))]"
],
"properties": {
"availabilitySet": {
"id": "[resourceId('Microsoft.Compute/availabilitySets', variables('availabilitySetName'))]"
},
...},
The quckstart templates are a good ref: https://raw.githubusercontent.com/azure/azure-quickstart-templates/master/201-2-vms-2-FDs-no-resource-loops/azuredeploy.json
Once you have two or more VMs of the same size in an availability set, you would configure autoscale using microsoft.insights/autoscalesettings, which I beleive you referenced in the question. This is done at the cloud service so it will work similar to PaaS... like so:
{
"apiVersion": "2014-04-01",
"name": "[concat(variables('vmName'), '-', resourceGroup().name)]",
"type": "microsoft.insights/autoscalesettings",
"location": "East US",
...},
A pretty good example is here: https://raw.githubusercontent.com/Azure/azure-quickstart-templates/6abc9f320e39d9d75dffb60846e88ab80d3ff33a/201-web-app-sql-database/azuredeploy.json
I also setup autoscale using the portal first and reviewed ARMExplorer to get a better idea of how things should look in my code. ARMExplorer is here: Azure Resource Explorer

Resources