Azure Functions: how to set CORS via automation?
Asked Answered
T

4

7

I have an azure function app that I would like to set up in repeatable (automated) manner so that I can duplicate it in different environments/resource groups. I'm able to create the function app via the azure cli, but I also need to configure the CORS options such that I can call it from a browser.

I've found where to do that in the azure portal web ui, in the 'Platform Features' tab(https://learn.microsoft.com/en-us/azure/azure-functions/functions-how-to-use-azure-function-app-settings#cors), but I can't find anything about modifying that setting via azure cli, or by the VSTS deployment task that I've set up to do releases when I change the functions in the app.

It seems you can even specify the CORS setting for local development via the local.settisg.json, but that only applies locally (https://learn.microsoft.com/en-us/azure/azure-functions/functions-run-local#local-settings). Were I deploying the app via the azure function tools cli I could supposedly specify the --publish-local-settings flag when I deploy, but I'm not deploying that way.

It seems like there must be a way to modify the CORS configuration without using the web UI, am I just not finding it?

Tetryl answered 25/10, 2017 at 0:9 Comment(0)
E
7

To set CORS settings programatically, you want to use ARM.

Here's an example you can follow: https://msftplayground.com/2016/08/setting-api-definition-url-cors-value-arm/

Evangelia answered 25/10, 2017 at 0:24 Comment(1)
Thank you, that worked. I'm posting the specific details in another answer in case it helps others get there more directly.Tetryl
T
10

Fabio's answer is correct, Azure Resource Manager templates work for this. Since the example he linked to was about logic apps and not azure functions, the getting the template right required a few changes and I wanted to add some detail that may help others get there faster.

To craft the template I ended up downloading the automation template from the function app that I created manually, and then deleting stuff until I got to what I think is the minimum. Here's what I'm using:

{
  "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {
    "function_app_name": {
      "defaultValue": "my-function-app",
      "type": "string"
    }
  },
  "variables": {},
  "resources": [
    {
      "comments": "CORS allow origins *.",
      "type": "Microsoft.Web/sites/config",
      "name": "[concat(parameters('function_app_name'), '/web')]",
      "apiVersion": "2016-08-01",
      "properties": {
        "cors": {
          "allowedOrigins": [
            "*"
          ]
        }
      },
      "dependsOn": []
    }
  ]
}

I also have a parameters file that goes with this that looks like this:

{
    "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#",
    "contentVersion": "1.0.0.0",
    "parameters": {
        "function_app_name": {
            "value": null
        }
    }
}

and then I have an Azure Resource Group Deployment step in my release definition that deploys this and substitutes the desired function app name depending on the environment I'm deploying to.

Tetryl answered 27/10, 2017 at 0:21 Comment(0)
E
7

To set CORS settings programatically, you want to use ARM.

Here's an example you can follow: https://msftplayground.com/2016/08/setting-api-definition-url-cors-value-arm/

Evangelia answered 25/10, 2017 at 0:24 Comment(1)
Thank you, that worked. I'm posting the specific details in another answer in case it helps others get there more directly.Tetryl
W
0

I tend to favour automating the fucntion CORS entries as part of the deployment (after function app resource has already been built with an ARM template earlier in the pipeline or another pipeline).

Since you can have multiple functions within a function app, I consider the CORS requirements specific to the function being deployed within a function app and I feel any CORS entries should be part of the actual function deployment process.

I use Azure CLI to automate the CORS setup. Please refer to How to set CORS via Automation for Azure Functions

az functionapp cors add --allowed-origins
                    [--ids]
                    [--name]
                    [--resource-group]
                    [--slot]
                    [--subscription]

You can also check/display existing entries like this:

az functionapp cors show --name MyFunctionApp --resource-group MyResourceGroup
Woolsack answered 8/8, 2019 at 9:45 Comment(1)
The problem is that you cannot set the cors supportCredentials to true this way. You will notice that the show property returns a 'supportCredentials' property that seems to be, as of time of writing, absent as a parameter in the cors add command.Bombsight
S
0

When you use Azure/bicep for deployment you can use the following snippet (note the cors option):

@description('The name of you Web Site.')
param siteName string = 'FuncApp-${uniqueString(resourceGroup().id)}'
param storageAccountName string = 'store${uniqueString(resourceGroup().id)}'

param location string = resourceGroup().location
var hostingPlanName = 'hpn-${resourceGroup().name}'

resource site 'Microsoft.Web/sites@2022-03-01' = {
 name: siteName
 kind: 'functionapp,linux'
 location: location
 properties: {
  siteConfig: {
    appSettings: [
      {
        name: 'FUNCTIONS_WORKER_RUNTIME'
        value: 'python'
      }
      {
        name: 'FUNCTIONS_EXTENSION_VERSION'
        value: '~4'
      }
      {
        name: 'AzureWebJobsStorage'
        value: 'DefaultEndpointsProtocol=https;AccountName=${storageAccountName};AccountKey=${storageAccount.listKeys().keys[0].value}'
      }
    ]
    cors: {
      allowedOrigins: [
        'https://portal.azure.com'
      ]
      supportCredentials: true
    }
  }
  serverFarmId: hostingPlan.id
  clientAffinityEnabled: false
 }
}

resource hostingPlan 'Microsoft.Web/serverfarms@2022-03-01' = {
 name: hostingPlanName
 location: location
 kind: 'linux'
 properties: {
   reserved: true
 }
 sku: {
   tier: 'Standard'
   name: 'S1'
 }
}

resource storageAccount 'Microsoft.Storage/storageAccounts@2022-09-01' = {
  name: storageAccountName
  location: location
  kind: 'StorageV2'
  sku: {
    name: 'Standard_LRS'
  }
}
Salad answered 25/4 at 8:44 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.