Deploy functions from ARM, before create event subscription - azure

Using ARM I created a function APP and an event grid topic.
Now, from the same ARM, I want to create a subscription to the topic, but to do it, I need to deploy functions into the function App before.
Is it possible to deploy my functions from the same ARM? Or Do I must to have two different ARMs, one to create all stuff (storage and topics) except functions related and another one the create all resources that need the functions deployed (event subscriptions)? In the second case, I will need to deploy functions in the middle.
I'm looking for one ARM to deploy the full infrastructure from zero (including functions in the function app). Is this possible? How?

According to my test, we can create these resources in one template. For example
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json",
"contentVersion": "1.0.0.0",
"parameters": {
"eventGridTopicName": {
"type": "string",
"defaultValue": "EventGridTopic",
"metadata": {
"description": "The name of the Event Grid custom topic."
}
},
"eventGridSubscriptionName": {
"type": "string",
"defaultValue": "EventGridSub",
"metadata": {
"description": "The name of the Event Grid custom topic's subscription."
}
},
"location": {
"type": "string",
"defaultValue": "[resourceGroup().location]",
"metadata": {
"description": "The location in which the Event Grid resources should be deployed."
}
},
"appName": {
"type": "string",
"defaultValue": "Func",
"metadata": {
"description": "The name of the function app that you wish to create."
}
},
"functionName": {
"type": "string",
"defaultValue": "EventGridFunction",
"metadata": {
"description": "Function App Name"
}
},
"storageAccountType": {
"type": "string",
"defaultValue": "Standard_LRS",
"allowedValues": [
"Standard_LRS",
"Standard_GRS",
"Standard_RAGRS"
],
"metadata": {
"description": "Storage Account type"
}
},
"runtime": {
"type": "string",
"defaultValue": "dotnet",
"allowedValues": [
"node",
"dotnet",
"java"
],
"metadata": {
"description": "The language worker runtime to load in the function app."
}
}
},
"variables": {
"eventGridTopic": "[concat(uniquestring(resourceGroup().id),parameters('EventGridTopicName'))]",
"eventGridSub": "[concat(uniquestring(resourceGroup().id),parameters('eventGridSubscriptionName'))]",
"functionUrl": "[concat('https://', variables('FunctionAppName'),'.azurewebsites.net/runtime/webhooks/eventgrid?functionName=', parameters('FunctionName'),'&code=')]",
"functionAppName": "[concat(uniquestring(resourceGroup().id),parameters('appName'))]",
"hostingPlanName": "[parameters('appName')]",
"applicationInsightsName": "[parameters('appName')]",
"storageAccountName": "[concat(uniquestring(resourceGroup().id), 'azfunction')]",
"functionWorkerRuntime": "[parameters('runtime')]"
},
"resources": [
// create event topic
{
"name": "[variables('eventGridTopic')]",
"type": "Microsoft.EventGrid/topics",
"location": "[parameters('location')]",
"apiVersion": "2020-04-01-preview",
},
// create event topic subscrition
{
"name": "[concat(variables('eventGridTopic'), '/Microsoft.EventGrid/', variables('eventGridSub'))]",
"type": "Microsoft.EventGrid/topics/providers/eventSubscriptions",
"location": "[parameters('location')]",
"apiVersion": "2020-04-01-preview",
"dependsOn": [
"[variables('eventGridTopic')]",
"[resourceId('Microsoft.Web/sites/functions/', variables('functionAppName'), parameters('functionName'))]"
],
"properties": {
"destination": {
"endpointType": "AzureFunction",
"properties": {
"resourceId": "[resourceId('Microsoft.Web/sites/functions/', variables('functionAppName'), parameters('functionName'))]"
}
},
"filter": {
}
}
},
// create storage account
{
"type": "Microsoft.Storage/storageAccounts",
"name": "[variables('storageAccountName')]",
"apiVersion": "2016-12-01",
"location": "[parameters('location')]",
"kind": "Storage",
"sku": {
"name": "[parameters('storageAccountType')]"
}
},
// create host plan
{
"type": "Microsoft.Web/serverfarms",
"apiVersion": "2018-02-01",
"name": "[variables('hostingPlanName')]",
"location": "[parameters('location')]",
"sku": {
"name": "Y1",
"tier": "Dynamic"
},
"properties": {
"name": "[variables('hostingPlanName')]",
"computeMode": "Dynamic"
}
},
// create function app
{
"apiVersion": "2015-08-01",
"type": "Microsoft.Web/sites",
"name": "[variables('functionAppName')]",
"location": "[parameters('location')]",
"kind": "functionapp",
"dependsOn": [
"[resourceId('Microsoft.Web/serverfarms', variables('hostingPlanName'))]",
"[resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName'))]",
"[concat('microsoft.insights/components/', variables('applicationInsightsName'))]"
],
"properties": {
"serverFarmId": "[resourceId('Microsoft.Web/serverfarms', variables('hostingPlanName'))]",
"siteConfig": {
"appSettings": [
{
"name": "AzureWebJobsStorage",
"value": "[concat('DefaultEndpointsProtocol=https;AccountName=', variables('storageAccountName'), ';AccountKey=', listKeys(resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName')),'2015-05-01-preview').key1)]"
},
{
"name": "WEBSITE_CONTENTAZUREFILECONNECTIONSTRING",
"value": "[concat('DefaultEndpointsProtocol=https;AccountName=', variables('storageAccountName'), ';AccountKey=', listKeys(resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName')),'2015-05-01-preview').key1)]"
},
{
"name": "WEBSITE_CONTENTSHARE",
"value": "[toLower(variables('functionAppName'))]"
},
{
"name": "FUNCTIONS_EXTENSION_VERSION",
"value": "~3"
},
{
"name": "APPINSIGHTS_INSTRUMENTATIONKEY",
"value": "[reference(resourceId('microsoft.insights/components/', variables('applicationInsightsName')), '2015-05-01').InstrumentationKey]"
},
{
"name": "FUNCTIONS_WORKER_RUNTIME",
"value": "[variables('functionWorkerRuntime')]"
}
]
}
}
},
// create event gride trigger function
{
"apiVersion": "2019-08-01",
"name": "[concat(variables('functionAppName'),'/', parameters('functionName'))]",
"type": "Microsoft.Web/sites/functions",
"dependsOn":[ "[variables('functionAppName')]"],
"properties": {
"config": {
"bindings": [
{
"name": "eventGridEvent",
"direction": "in",
"type": "eventGridTrigger"
}
]
},
"files":{
// the code
"run.csx":"#r \"Microsoft.Azure.EventGrid\"\r\nusing Microsoft.Azure.EventGrid.Models;\r\n\r\npublic static void Run(EventGridEvent eventGridEvent, ILogger log)\r\n{\r\n log.LogInformation(eventGridEvent.Data.ToString());\r\n}"
}
}
},
// create application insight
{
"apiVersion": "2018-05-01-preview",
"name": "[variables('applicationInsightsName')]",
"type": "microsoft.insights/components",
"location": "East US",
"tags": {
"[concat('hidden-link:', resourceGroup().id, '/providers/Microsoft.Web/sites/', variables('applicationInsightsName'))]": "Resource"
},
"properties": {
"ApplicationId": "[variables('applicationInsightsName')]",
"Request_Source": "IbizaWebAppExtensionCreate"
}
}
],
"outputs": {
}
}
For more details, please refer to the blog.

Related

azure ARm Template - Fails to associate AD app registration with function app

Background
I am trying to create an AD app registration for my function app to use for authentication.
I would like it to be for just our tenant, using Azure AD. The app is function app made up of a few endpoints
When I deploy the ARM template below, I don't get any errors, but in poking around and comparing it with what happens when I create authentication manually for my app, i see the following problems:
the application registration is created but there's no Application ID URI specified. When I create this manually via the portal I believe it's auto filled with a value "api://[applicationClientId]"
there are no scopes defined. again, when i create an authentication policy for my app manually via the portal, it does create a user_impersonation scope for me.
When i open up the function app in the portal, under "authentication" this new app registration hasn't been associated with it / or added.
Code
Here's what the ARM template looks like:
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"functionAppName": {
"type": "string",
"defaultValue": "[concat('widgets-', uniqueString(resourceGroup().id),'-app')]",
"minLength": 2,
"metadata": {
"description": "my function app"
}
},
"storageAccountName": {
"type": "string",
"defaultValue": "[concat('widgets', uniqueString(resourceGroup().id))]",
"minLength": 2,
"metadata": {
"description": "StorageAccount"
}
},
"location": {
"type": "string",
"defaultValue": "[resourceGroup().location]",
"metadata": {
"description": "Location for all resources."
}
},
"serviceBusNamespaceName": {
"type": "string",
"defaultValue": "[concat('widgets-', uniqueString(resourceGroup().id),'-bus')]",
"metadata": {
"description": "Name of the Service Bus namespace"
}
},
"serviceBusQueueName": {
"type": "string",
"defaultValue": "workspaces",
"metadata": {
"description": "Name of the Queue"
}
},
"queueAuthorizationRuleName": {
"type": "string",
"defaultValue": "myRule",
"metadata": {
"description": "Name of the Queue AuthorizationRule"
}
},
"aadAppClientId": {
"type": "string"
},
"tenant": {
"type": "string"
}
},
"variables": {
"appServicePlanPortalName": "[concat(parameters('functionAppName'),'servicePlan')]",
"appInsightsName": "[concat(parameters('functionAppName'),'-insights')]",
"identityName": "[concat(parameters('functionAppName'),'-userId')]",
"clientSecret": ""
},
"resources": [
{
"name": "[variables('identityName')]",
"type": "Microsoft.ManagedIdentity/userAssignedIdentities",
"apiVersion": "2018-11-30",
"location": "[parameters('location')]"
},
{
"type": "Microsoft.Storage/storageAccounts",
"name": "[parameters('storageAccountName')]",
"apiVersion": "2019-06-01",
"location": "[parameters('location')]",
"kind": "StorageV2",
"sku": {
"name": "Standard_LRS",
"tier": "Standard"
}
},
{
"type": "Microsoft.Storage/storageAccounts/queueServices",
"apiVersion": "2020-08-01-preview",
"name": "[concat(parameters('storageAccountName'), '/default')]",
"dependsOn": [
"[resourceId('Microsoft.Storage/storageAccounts', parameters('storageAccountName'))]"
],
"properties": {
"cors": {
"corsRules": []
}
}
},
{
"type": "Microsoft.Storage/storageAccounts/queueServices/queues",
"apiVersion": "2020-08-01-preview",
"name": "[concat(parameters('storageAccountName'), '/default/workspaces')]",
"dependsOn": [
"[resourceId('Microsoft.Storage/storageAccounts/queueServices', parameters('storageAccountName'), 'default')]",
"[resourceId('Microsoft.Storage/storageAccounts', parameters('storageAccountName'))]"
],
"properties": {
"metadata": {}
}
},
{
"type": "Microsoft.Storage/storageAccounts/tableServices/tables",
"apiVersion": "2021-06-01",
"name": "[concat(parameters('storageAccountName'), '/default/provisionedWorkspaces')]",
"dependsOn": [
"[resourceId('Microsoft.Storage/storageAccounts', parameters('storageAccountName'))]"
],
"properties": {
"partitionName": "workspaces"
}
},
{
"type": "Microsoft.ServiceBus/namespaces",
"apiVersion": "2017-04-01",
"name": "[parameters('serviceBusNamespaceName')]",
"location": "[parameters('location')]",
"sku": {
"name": "Standard"
},
"properties": {}
},
{
"type": "Microsoft.ServiceBus/namespaces/queues",
"apiVersion": "2017-04-01",
"name": "[format('{0}/{1}', parameters('serviceBusNamespaceName'), parameters('serviceBusQueueName'))]",
"properties": {
"lockDuration": "PT5M",
"maxSizeInMegabytes": 1024,
"requiresDuplicateDetection": false,
"requiresSession": false,
"defaultMessageTimeToLive": "P10675199DT2H48M5.4775807S",
"deadLetteringOnMessageExpiration": false,
"duplicateDetectionHistoryTimeWindow": "PT10M",
"maxDeliveryCount": 10,
"autoDeleteOnIdle": "P10675199DT2H48M5.4775807S",
"enablePartitioning": false,
"enableExpress": false
},
"resources": [
{
"apiVersion": "2017-04-01",
"name": "[parameters('queueAuthorizationRuleName')]",
"type": "AuthorizationRules",
"dependsOn": ["[parameters('serviceBusQueueName')]"],
"properties": {
"rights": ["Listen", "Send", "Manage"]
}
}
],
"dependsOn": [
"[resourceId('Microsoft.ServiceBus/namespaces', parameters('serviceBusNamespaceName'))]"
]
},
{
"apiVersion": "2015-05-01",
"name": "[variables('appInsightsName')]",
"type": "Microsoft.Insights/components",
"kind": "web",
"location": "[parameters('location')]",
"tags": {
"[concat('hidden-link:', resourceGroup().id, '/providers/Microsoft.Web/sites/', parameters('functionAppName'))]": "Resource"
},
"properties": {
"Application_Type": "web",
"ApplicationId": "[variables('appInsightsName')]"
}
},
{
"type": "Microsoft.Web/serverfarms",
"apiVersion": "2020-06-01",
"name": "[variables('appServicePlanPortalName')]",
"location": "[parameters('location')]",
"sku": {
"tier": "Standard",
"name": "S1"
},
"kind": "functionapp,linux",
"properties": {
"name": "[variables('appServicePlanPortalName')]",
"reserved": true
}
},
{
"type": "Microsoft.Web/sites",
"apiVersion": "2020-06-01",
"name": "[parameters('functionAppName')]",
"location": "[parameters('location')]",
"kind": "functionapp,linux",
"identity": {
"type": "UserAssigned",
"userAssignedIdentities": {
"[resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', variables('identityName'))]": {}
}
},
"dependsOn": [
"[resourceId('Microsoft.Web/serverfarms', variables('appServicePlanPortalName'))]",
"[resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', variables('identityName'))]"
],
"properties": {
"reserved": true,
"serverFarmId": "[resourceId('Microsoft.Web/serverfarms', variables('appServicePlanPortalName'))]",
"siteConfig": {
"linuxFxVersion": "DOTNETCORE|6.0",
"appSettings": [
{
"name": "APPINSIGHTS_INSTRUMENTATIONKEY",
"value": "[reference(resourceId('Microsoft.Insights/components', variables('appInsightsName')), '2015-05-01').InstrumentationKey]"
},
{
"name": "AzureWebJobsStorage",
"value": "[concat('DefaultEndpointsProtocol=https;AccountName=', parameters('storageAccountName'), ';EndpointSuffix=', environment().suffixes.storage, ';AccountKey=',listKeys(resourceId('Microsoft.Storage/storageAccounts', parameters('storageAccountName')), '2019-06-01').keys[0].value)]"
},
{
"name": "FUNCTIONS_EXTENSION_VERSION",
"value": "~4"
},
{
"name": "FUNCTIONS_WORKER_RUNTIME",
"value": "dotnet"
}
],
"resources": [
{
"type": "config",
"apiVersion": "2020-12-01",
"name": "authsettingsV2",
"location": "[resourceGroup().location]",
"dependsOn": [
"[concat('Microsoft.Web/sites/', parameters('functionAppName'))]"
],
"properties": {
"platform": {
"enabled": true,
"runtimeVersion": "~1"
},
"identityProviders": {
"azureActiveDirectory": {
"isAutoProvisioned": false,
"registration": {
"clientId": "[parameters('aadAppClientId')]",
"clientSecret": "[variables('clientSecret')]",
"openIdIssuer": "[concat('https://sts.windows.net/', parameters('tenant'), '/v2.0')]"
},
"validation": {
"allowedAudiences": [
"https://management.core.windows.net/"
]
}
}
}
},
"login": {
"routes": {},
"tokenStore": {
"enabled": true,
"tokenRefreshExtensionHours": 72,
"fileSystem": {},
"azureBlobStorage": {}
},
"preserveUrlFragmentsForLogins": false,
"allowedExternalRedirectUrls": [],
"cookieExpiration": {
"convention": "FixedTime",
"timeToExpiration": "08:00:00"
},
"nonce": {
"validateNonce": true,
"nonceExpirationInterval": "00:05:00"
}
},
"globalValidation": {
"redirectToProvider": "azureactivedirectory",
"unauthenticatedClientAction": "RedirectToLoginPage"
},
"httpSettings": {
"requireHttps": true,
"routes": {
"apiPrefix": "/.auth"
},
"forwardProxy": {
"convention": "NoProxy"
}
}
}
]
}
}
}
]
}
Two comments in case they help / are relevant:
client secret - As you can see I have a variable defined, but its blank. I'm not supplying a client secret value because I was assuming it would auto create for me. But maybe I shouldn't include that parameter at all?
Also, I'm using a linux container for the web app.
Any tips on how to fix these issues would be appreciated.
EDIT 1
I manually created and added an authencation policy and then I've been using resources.azure.com to see what's been created for me. I have two relevant sections under config.
One is called authsettings and looks like this:
And the other is under authsettingsV2 and looks like this:
I'm trying to use the authsettingsV2 for now... but it's not clear where I should paste it into in the ARM template.
Any suggestions?
EDIT 2
Added all the authsettingsv2 stuff under the site resource. No errors. but still the same results.
Found out that I can use the Az Powershell commandlets:
New-AzADApplication
New-AzADAppCredential

How to reference an existing storage account created in Azure portal in an ARM template

`
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"InputstorageAccount": {
"defaultValue": "inputstgdev",
"type": "String"
},
"GitrepoBranch": {
"type": "string",
"defaultValue": "master",
"metadata": {
"description": "Name of the branch to use when deploying (Default = master)."
}
},
"GitrepoURL": {
"type": "string",
"defaultValue": "https://github.com/FBoucher/AzUnzipEverything.git",
"metadata": {
"description": "URL to repo (Default = master)."
}
},
"InputcontainerName": {
"type": "string",
"defaultValue": "inputcontainer",
"metadata": {
"description": "Specifies the name of the blob container."
}
},
"OutputstorageAccount": {
"defaultValue": "outputstgdev",
"type": "String"
},
"OutputcontainerName": {
"type": "string",
"defaultValue": "outputcontainer",
"metadata": {
"description": "Specifies the name of the blob container."
}
}
},
"variables": {},
"resources": [
{
"type": "Microsoft.Storage/storageAccounts/blobServices/containers",
"apiVersion": "2019-06-01",
"name": "[concat(parameters('InputstorageAccount'), '/default/', parameters('InputcontainerName'))]",
"properties": {
"publicAccess": "None"
}
},
{
"type": "Microsoft.Storage/storageAccounts/blobServices/containers",
"apiVersion": "2019-06-01",
"name": "[concat(parameters('OutputstorageAccount'), '/default/', parameters('OutputcontainerName'))]",
"properties": {
"publicAccess": "None"
}
},
{
"name": "serviceplan",
"type": "Microsoft.Web/serverfarms",
"apiVersion": "2018-02-01",
"location": "[resourceGroup().location]",
"sku": {
"name": "F1",
"capacity": 1
},
"tags": {
"displayName": "serviceplan"
},
"properties": {
"name": "serviceplan"
}
},
{
"name": "functionapp",
"type": "Microsoft.Web/sites",
"apiVersion": "2018-11-01",
"location": "[resourceGroup().location]",
"kind": "functionapp",
"dependsOn": [
"[resourceId('Microsoft.Web/serverfarms', 'serviceplan')]",
"[resourceId('Microsoft.Storage/storageAccounts', parameters('InputstorageAccount'))]"
],
"properties": {
"serverFarmId": "[resourceId('Microsoft.Web/serverfarms', 'serviceplan')]",
"siteConfig": {
"appSettings": [
{
"name": "AzureWebJobsDashboard",
"value": "[concat('DefaultEndpointsProtocol=https;AccountName=', parameters('InputstorageAccount'), ';AccountKey=', listKeys(parameters('InputcontainerName'),'2015-05-01-preview').key1)]"
},
{
"name": "AzureWebJobsStorage",
"value": "[concat('DefaultEndpointsProtocol=https;AccountName=', parameters('InputstorageAccount'), ';AccountKey=', listKeys(parameters('InputcontainerName'),'2015-05-01-preview').key1)]"
},
{
"name": "WEBSITE_CONTENTAZUREFILECONNECTIONSTRING",
"value": "[concat('DefaultEndpointsProtocol=https;AccountName=', parameters('InputstorageAccount'), ';AccountKey=', listKeys(parameters('InputcontainerName'),'2015-05-01-preview').key1)]"
},
{
"name": "WEBSITE_CONTENTSHARE",
"value": "[toLower('functionapp')]"
},
{
"name": "FUNCTIONS_EXTENSION_VERSION",
"value": "~2"
},
{
"name": "APPINSIGHTS_INSTRUMENTATIONKEY",
"value": "[reference(resourceId('microsoft.insights/components/', 'applicationInsightsName'), '2015-05-01').InstrumentationKey]"
},
{
"name": "FUNCTIONS_WORKER_RUNTIME",
"value": "dotnet"
}
]
}
},
"resources":[
{
"apiVersion": "2015-08-01",
"name": "web",
"type": "sourcecontrols",
"dependsOn": [
"[resourceId('Microsoft.Web/sites/', parameters('InputstorageAccount'))]"
],
"properties": {
"RepoUrl": "[parameters('GitrepoURL')]",
"branch": "[parameters('GitrepoBranch')]",
"publishRunbook": true,
"IsManualIntegration": true
}
}
]
}
]
}
`I have a storage account called STGaccount which I created with the Azure portal and would like to use ARM template to create a container called inputcontainer in this STGaccount. Each time I try to do so I get an error message saying that the storage account STGaccount I am trying to create with the ARM template already exist in the resource group....So i guess I am writing my ARM template in a way that it still creates a new storage account with a name similar to the one I already have in the resource group. What I actually want to do is to reference the already existing storage account in my ARM template such that i do not have to create a new one.
Thanks in advance as I look forward to your response
Try this ARM template, this will help you to create a container in the existing Storage account.
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"storageAccountName": {
"defaultValue": "STGaccount",
"type": "String"
},
"containerName": {
"type": "string",
"defaultValue": "inputcontainer",
"metadata": {
"description": "Specifies the name of the blob container."
}
}
},
"variables": {},
"resources": [
{
"type": "Microsoft.Storage/storageAccounts/blobServices/containers",
"apiVersion": "2019-06-01",
"name": "[concat(parameters('storageAccountName'), '/default/', parameters('containerName'))]",
"properties": {
"publicAccess": "None"
}
}
]
}

Internal Server Error while Listing the Function App Keys in Azure Government

I am trying to deploy a Http triggered Azure Function App in Azure Government through ARM template. Initially I got the name conflict error There was a conflict. The remote name could not be resolved: 'sftestgovstorage.file.core.windows.net'. I tried to solve this error by following the link. After which I tried listing the function app keys and tried creating a new key. I am getting the error message Internal Server Error.
I even tried adding the WEBSITE_CONTENTAZUREFILECONNECTIONSTRING setting into configuration with the storage account connection string with suffix ;EndpointSuffix=core.usgovcloudapi.net. But I am still not able to list or create new function app keys.
I am using the following code to create a new function key
HttpClient _client = new HttpClient();
_client.DefaultRequestHeaders.Add("Authorization", "Bearer " + jwtToken);
var response = await
_client.PostAsync($"https://functionAppName.azurewebsites.us/admin/host/keys/{keyName}", null);
The ARM template used is
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"coreFunctionApp_appServicePlanName": {
"type": "string",
"metadata": {
"description": "Name of the app service plan to host core function app."
},
"defaultValue": "SL360-Prod-BAM-Appsvc"
},
"coreFunctionApp_applicationInsightsName": {
"type": "string",
"metadata": {
"description": "Name of the application insights for the core function
app."
},
"defaultValue": "SL360-Prod-BAM-AppInsights"
},
"coreFunctionAppName": {
"type": "string",
"metadata": {
"description": "Name of the core function app"
},
"defaultValue": "SL360-Prod-BAM-FunApp"
},
"BAMConnectionString": {
"type": "string",
"metadata": {
"description": "BAM Connection String"
},
"defaultValue": "SL360-BAMConnectionString"
},
"storageAccountName": {
"type": "string",
"metadata": {
"description": "Name of the Storage account namespace"
},
"defaultValue": "SL360-Prod-BAM-Storage"
},
"storageContainerName": {
"type": "string",
"metadata": {
"description": "Name of the Storage account container"
},
"defaultValue": "SL360-Prod-BAM-Storage-container"
},
"storageAccountType": {
"type": "string",
"defaultValue": "Standard_LRS",
"allowedValues": [
"Standard_LRS",
"Standard_GRS",
"Standard_RAGRS"
],
"metadata": {
"description": "Storage Account type"
}
}
},
"variables": {
"storageAccountid": "
[concat(resourceGroup().id,'/providers/','Microsoft.Storage/storageAccounts/',
parameters('storageAccountName'))]",
"serverFarmApiVersion": "2018-02-01",
"storageApiVersion": "
[providers('Microsoft.Storage','storageAccounts').apiVersions[0]]",
"sitesApiVersion": "2018-11-01",
"insightsApiVersion": "2015-05-01"
},
"resources": [
{
"type": "Microsoft.Storage/storageAccounts",
"apiVersion": "[variables('storageApiVersion')]",
"kind": "Storage",
"location": "[resourceGroup().location]",
"name": "[parameters('storageAccountName')]",
"sku": {
"name": "[parameters('storageAccountType')]"
}
},
{
"apiVersion": "[variables('serverFarmApiVersion')]",
"dependsOn": [],
"location": "[resourceGroup().location]",
"name": "[parameters('coreFunctionApp_appServicePlanName')]",
"properties": {
"name": "[parameters('coreFunctionApp_appServicePlanName')]",
"computeMode": "Dynamic"
},
"sku": {
"name": "Y1",
"tier": "Dynamic"
},
"type": "Microsoft.Web/serverfarms"
},
{
"apiVersion": "[variables('insightsApiVersion')]",
"location": "[resourceGroup().location]",
"name": "[parameters('coreFunctionApp_applicationInsightsName')]",
"properties": {
"Application_Type": "web",
"ApplicationId": "
[parameters('coreFunctionApp_applicationInsightsName')]"
},
"tags": {
"[concat('hidden-link:', resourceGroup().id, '/providers/Microsoft.Web/sites/', parameters('coreFunctionAppName'))]": "Resource"
},
"type": "Microsoft.Insights/components"
}, {
"apiVersion": "[variables('sitesApiVersion')]",
"dependsOn": [
"[resourceId('Microsoft.Web/serverfarms',
parameters('coreFunctionApp_appServicePlanName'))]",
"[resourceId('Microsoft.Insights/components',
parameters('coreFunctionApp_applicationInsightsName'))]",
"[resourceId('Microsoft.Storage/storageAccounts',
parameters('storageAccountName'))]"
],
"kind": "functionapp",
"location": "[resourceGroup().location]",
"name": "[parameters('coreFunctionAppName')]",
"properties": {
"serverFarmId": "[resourceId('Microsoft.Web/serverfarms',
parameters('coreFunctionApp_appServicePlanName'))]",
"siteConfig": {
"appSettings": [
{
"name": "AzureWebJobsDashboard",
"value": "[concat('DefaultEndpointsProtocol=https;AccountName=',
parameters('storageAccountName'), ';AccountKey=', listKeys(variables('storageAccountid'),'2015-05-01-preview').key1)]"
},
{
"name": "AzureWebJobsStorage",
"value": "[concat('DefaultEndpointsProtocol=https;AccountName=',
parameters('storageAccountName'), ';AccountKey=', listKeys(variables('storageAccountid'),'2015-05-01-preview').key1)]"
},
{
"name": "FUNCTIONS_EXTENSION_VERSION",
"value": "~2"
},
{
"name": "WEBSITE_NODE_DEFAULT_VERSION",
"value": "6.5.0"
},
{
"name": "APPINSIGHTS_INSTRUMENTATIONKEY",
"value": "[reference(concat('microsoft.insights/components/',
parameters('coreFunctionApp_applicationInsightsName'))).InstrumentationKey]"
}
]
}
},
"type": "Microsoft.Web/sites"
},
],
"outputs":
"StorageAccessKey": {
"type": "string",
"value": "[listKeys(resourceId('Microsoft.Storage/storageAccounts',
parameters('storageAccountName')), providers('Microsoft.Storage', 'storageAccounts').apiVersions[0]).keys[0].value]"
}
}
}
Can anyone help me solve this issue?

How to use a DocumentDB(MongoDB) connection string as an Environment variable in an Azure Resource Management Template

I want to use a DocumentDB(MongoDB) connection string as an environment variable in an Azure Resource Management Template. Forexample i have a resource group which has a wep app and a DocumentDB(MongoDB) database.
"siteConfig": {
"appSettings": [
{
"name": "db",
"value": "connection string"
}
]
}
How can i assign an environment variable to a connection string in template?
ARM template supports listKeys and list{Value} function, more details we can refer to ARM template function.
We can find DocumentDB list connection strings API, so we can use listconnectionstrings function to get documentdb connection string in the ARM template.
"appSettings": [
{
"name": "db",
"value": " [listConnectionStrings(resourceId('Microsoft.DocumentDb/databaseAccounts', parameters('documentdb')), '2015-04-08').connectionStrings[0].connectionString]"
}
It works correct on my side. If we want to add appsetting for WebApp, we also can do with following code
"resources": [
{
"name": "appsettings",
"type": "config",
"apiVersion": "2015-08-01",
"dependsOn": [
"[resourceId('Microsoft.Web/sites', variables('webSiteName'))]"
],
"tags": {
"displayName": "appsetting"
},
"properties": {
"db": "[listConnectionStrings(resourceId('Microsoft.DocumentDb/databaseAccounts', parameters('documentdb')), '2015-04-08').connectionStrings[0].connectionString]"
}
}
]
Check the result from the Azure portal.
Update:
ARM template demo code
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"hostingPlanName": {
"type": "string",
"minLength": 1
},
"documentdb": {
"type": "string",
"minLength": 1
},
"skuName": {
"type": "string",
"defaultValue": "S1",
"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": {
"webSiteName": "[concat('webSite', uniqueString(resourceGroup().id))]",
"docDbName": "tomdocumentdb",
"storageAccountId": "[concat(resourceGroup().id,'/providers/Microsoft.Storage/storageAccounts/', parameters('storageAccountName'))]"
},
"resources": [
{
"apiVersion": "2015-08-01",
"name": "[parameters('hostingPlanName')]",
"type": "Microsoft.Web/serverfarms",
"location": "[resourceGroup().location]",
"tags": {
"displayName": "HostingPlan"
},
"sku": {
"name": "[parameters('skuName')]",
"capacity": "[parameters('skuCapacity')]"
},
"properties": {
"name": "[parameters('hostingPlanName')]"
}
},
{
"apiVersion": "2015-08-01",
"name": "[variables('webSiteName')]",
"type": "Microsoft.Web/sites",
"location": "[resourceGroup().location]",
"tags": {
"[concat('hidden-related:', resourceGroup().id, '/providers/Microsoft.Web/serverfarms/', parameters('hostingPlanName'))]": "Resource",
"displayName": "Website"
},
"dependsOn": [
"[concat('Microsoft.Web/serverfarms/', parameters('hostingPlanName'))]"
],
"properties": {
"name": "[variables('webSiteName')]",
"serverFarmId": "[resourceId('Microsoft.Web/serverfarms', parameters('hostingPlanName'))]"
},
"resources": [
{
"name": "appsettings",
"type": "config",
"apiVersion": "2015-08-01",
"dependsOn": [
"[resourceId('Microsoft.Web/sites', variables('webSiteName'))]"
],
"tags": {
"displayName": "appsetting"
},
"properties": {
"db": "[listConnectionStrings(resourceId('Microsoft.DocumentDb/databaseAccounts', parameters('documentdb')), '2015-04-08').connectionStrings[0].connectionString]"
}
}
]
}
]
}
Paramter file
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"hostingPlanName": {
"value": "tomtest" //your hostingplan name
},
"skuName": {
"value": "B1"
},
"documentdb": {
"value": "tomdocument" // your documentdb name
}
}
}
After a bit of a struggle:
"appSettings": [{
"Name": "DOCUMENTDB_ENDPOINT",
"Value": "[reference(concat('Microsoft.DocumentDb/databaseAccounts/', parameters('databaseAccountName'))).documentEndpoint]"
}, {
"Name": "DOCUMENTDB_PRIMARY_KEY",
"Value": "[listKeys(resourceId('Microsoft.DocumentDb/databaseAccounts', parameters('databaseAccountName')), '2015-04-08').primaryMasterKey]"
}]

How to turn on Auditing & Threat Detection for Azure SQL Database in ARM Template?

Azure SQL Database Threat Detection feature has been in General Preview since November 2015.
https://azure.microsoft.com/en-us/blog/threat-detection-public-preview/
However, I could not find out how can one turn on this feature and its dependency (Azure SQL Database Auditing) in the ARM template, neither in the Azure Quickstart Templates nor Azure Resource Manager Schema GitHubs links.
azure-quickstart-templates
azure-resource-manager-schemas
Appreciate if anyone who knows can answer on this.
Thanks very much.
Here are 2 sample templates:
First one, enable Auditing and Threat Detection for the whole SQL server.
{
"$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"serverName": {
"type": "string",
"metadata": {
"description": "The name of the new database server to create."
}
},
"serverLocation": {
"type": "string",
"metadata": {
"description": "The location of the database server."
}
},
"administratorLogin": {
"type": "string",
"metadata": {
"description": "The account name to use for the database server administrator."
}
},
"administratorLoginPassword": {
"type": "securestring",
"metadata": {
"description": "The password to use for the database server administrator."
}
},
"databaseName": {
"type": "string",
"metadata": {
"description": "The name of the new database to create."
}
},
"collation": {
"type": "string",
"defaultValue": "SQL_Latin1_General_CP1_CI_AS",
"metadata": {
"description": "The database collation for governing the proper use of characters."
}
},
"edition": {
"type": "string",
"defaultValue": "Standard",
"metadata": {
"description": "The type of database to create. The available options are: Web, Business, Basic, Standard, and Premium."
}
},
"maxSizeBytes": {
"type": "string",
"defaultValue": "1073741824",
"metadata": {
"description": "The maximum size, in bytes, for the database"
}
},
"requestedServiceObjectiveName": {
"type": "string",
"defaultValue": "S0",
"metadata": {
"description": "The name corresponding to the performance level for edition. The available options are: Shared, Basic, S0, S1, S2, S3, P1, P2, and P3."
}
},
"eventTypesToAudit": {
"type": "string",
"defaultValue":"All",
"metadata": {
"description": "The event type to audit."
}
}
},
"resources": [
{
"name": "[parameters('serverName')]",
"type": "Microsoft.Sql/servers",
"location": "[parameters('serverLocation')]",
"apiVersion": "2014-04-01-preview",
"properties": {
"administratorLogin": "[parameters('administratorLogin')]",
"administratorLoginPassword": "[parameters('administratorLoginPassword')]",
"version": "12.0"
},
"resources": [
{
"name": "[parameters('databaseName')]",
"type": "databases",
"location": "[parameters('serverLocation')]",
"apiVersion": "2014-04-01-preview",
"dependsOn": [
"[concat('Microsoft.Sql/servers/', parameters('serverName'))]"
],
"properties": {
"edition": "[parameters('edition')]",
"collation": "[parameters('collation')]",
"maxSizeBytes": "[parameters('maxSizeBytes')]",
"requestedServiceObjectiveName": "[parameters('requestedServiceObjectiveName')]"
}
},
{
"apiVersion": "2014-04-01-preview",
"dependsOn": [
"[concat('Microsoft.Sql/servers/', parameters('serverName'))]"
],
"location": "[parameters('serverLocation')]",
"name": "AllowAllWindowsAzureIps",
"properties": {
"endIpAddress": "0.0.0.0",
"startIpAddress": "0.0.0.0"
},
"type": "firewallrules"
},
{
"apiVersion": "2014-04-01-preview",
"type": "auditingPolicies",
"name": "Default",
"dependsOn": [
"[concat('Microsoft.Sql/servers/', parameters('serverName'))]",
"[concat('Microsoft.Sql/servers/', parameters('serverName'), '/databases/',parameters('databaseName'))]"
],
"properties": {
"auditingState": "Enabled",
"storageAccountName": "<your-storage-account-name>",
"storageAccountKey": "<your-storage-account-key>",
"storageAccountResourceGroupName": "<your-storage-account-resource-group-name>",
"storageAccountSubscriptionId": "<your-storage-account-subscriptionid>",
"eventTypesToAudit": "parameters('eventTypesToAudit')"
}
},
{
"apiVersion": "2015-05-01-preview",
"type": "securityAlertPolicies",
"name": "Default",
"dependsOn": [
"[concat('Microsoft.Sql/servers/', parameters('serverName'))]",
"[concat('Microsoft.Sql/servers/', parameters('serverName'), '/databases/',parameters('databaseName'))]",
"[concat('Microsoft.Sql/servers/', parameters('serverName'), '/auditingPolicies/Default')]"
],
"properties": {
"state": "Enabled",
"disabledAlerts": "",
"emailAddresses": "abcd#efgh.com",
"emailAccountAdmins": "true"
}
}
]
}
]
}
Second one, enable Auditing and Threat Detection only for a specific database.
{
"$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"serverName": {
"type": "string",
"metadata": {
"description": "The name of the new database server to create."
}
},
"serverLocation": {
"type": "string",
"metadata": {
"description": "The location of the database server."
}
},
"administratorLogin": {
"type": "string",
"metadata": {
"description": "The account name to use for the database server administrator."
}
},
"administratorLoginPassword": {
"type": "securestring",
"metadata": {
"description": "The password to use for the database server administrator."
}
},
"databaseName": {
"type": "string",
"metadata": {
"description": "The name of the new database to create."
}
},
"collation": {
"type": "string",
"defaultValue": "SQL_Latin1_General_CP1_CI_AS",
"metadata": {
"description": "The database collation for governing the proper use of characters."
}
},
"edition": {
"type": "string",
"defaultValue": "Standard",
"metadata": {
"description": "The type of database to create. The available options are: Web, Business, Basic, Standard, and Premium."
}
},
"maxSizeBytes": {
"type": "string",
"defaultValue": "1073741824",
"metadata": {
"description": "The maximum size, in bytes, for the database"
}
},
"requestedServiceObjectiveName": {
"type": "string",
"defaultValue": "S0",
"metadata": {
"description": "The name corresponding to the performance level for edition. The available options are: Shared, Basic, S0, S1, S2, S3, P1, P2, and P3."
}
},
"eventTypesToAudit": {
"type": "string",
"defaultValue":"All",
"metadata": {
"description": "The event type to audit."
}
}
},
"resources": [
{
"name": "[parameters('serverName')]",
"type": "Microsoft.Sql/servers",
"location": "[parameters('serverLocation')]",
"apiVersion": "2014-04-01-preview",
"properties": {
"administratorLogin": "[parameters('administratorLogin')]",
"administratorLoginPassword": "[parameters('administratorLoginPassword')]",
"version": "12.0"
},
"resources": [
{
"name": "[parameters('databaseName')]",
"type": "databases",
"location": "[parameters('serverLocation')]",
"apiVersion": "2014-04-01-preview",
"dependsOn": [
"[concat('Microsoft.Sql/servers/', parameters('serverName'))]"
],
"properties": {
"edition": "[parameters('edition')]",
"collation": "[parameters('collation')]",
"maxSizeBytes": "[parameters('maxSizeBytes')]",
"requestedServiceObjectiveName": "[parameters('requestedServiceObjectiveName')]"
},
"resources":[
{
"apiVersion": "2014-04-01-preview",
"type": "auditingPolicies",
"name": "Default",
"dependsOn": [
"[concat('Microsoft.Sql/servers/', parameters('serverName'), '/databases/',parameters('databaseName'))]"
],
"properties": {
"auditingState": "Enabled",
"storageAccountName": "<your-storage-account-name>",
"storageAccountKey": "<your-storage-account-key>",
"storageAccountResourceGroupName": "<your-storage-account-resource-group-name>",
"storageAccountSubscriptionId": "<your-storage-account-subscriptionid>",
"eventTypesToAudit": "parameters('eventTypesToAudit')"
}
},
{
"apiVersion": "2015-05-01-preview",
"type": "securityAlertPolicies",
"name": "Default",
"dependsOn": [
"[concat('Microsoft.Sql/servers/', parameters('serverName'), '/databases/',parameters('databaseName'))]",
"[concat('Microsoft.Sql/servers/', parameters('serverName'), '/databases/',parameters('databaseName'), '/auditingPolicies/Default')]"
],
"properties": {
"state": "Enabled",
"disabledAlerts": "",
"emailAddresses": "abcd#efgh.com",
"emailAccountAdmins": "true"
}
}
]
},
{
"apiVersion": "2014-04-01-preview",
"dependsOn": [
"[concat('Microsoft.Sql/servers/', parameters('serverName'))]"
],
"location": "[parameters('serverLocation')]",
"name": "AllowAllWindowsAzureIps",
"properties": {
"endIpAddress": "0.0.0.0",
"startIpAddress": "0.0.0.0"
},
"type": "firewallrules"
}
]
}
]
}
Note: Please don't forget to replace the information for the storage account.
Actually, Yoav Rubin has already answered your question in comment of the blog. And, I have tested the answer, and have done some refinement.
There was a change in the last week which requires 2 more parameters to the securityAlertPolicies section:
"storageEndpoint": "https://<storage account name>.blob.core.windows.net/",
"storageAccountAccessKey": "<storage account key>"
This is so the service can write the alerts generated to your storage account as well.
The answer from Jack Zeng was close, but (at this point in time) you need auditingSettings to point to blob storage, since security alerting doesn't work with table storage. So add the following auditingSettings and securityAlertPolicies as child resources of the Microsoft.Sql/servers resource.
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {},
"variables": {},
"resources": [
{
"name": "[parameters('sqlserverName')]",
"type": "Microsoft.Sql/servers",
"location": "[resourceGroup().location]",
"apiVersion": "2014-04-01-preview",
"properties": {},
"resources": [
{
"apiVersion": "2015-05-01-preview",
"type": "auditingSettings",
"name": "Default",
"dependsOn": [
"[parameters('sqlserverName')]",
"[concat('Microsoft.Storage/storageAccounts/', parameters('storageAccountName'))]"
],
"properties": {
"State": "Enabled",
"storageEndpoint": "[concat('https://', parameters('storageAccountName'), '.blob.core.windows.net/')]",
"storageAccountAccessKey": "[listKeys(resourceId('Microsoft.Storage/storageAccounts', parameters('storageAccountName')), providers('Microsoft.Storage', 'storageAccounts').apiVersions[0]).keys[0].value]",
"storageAccountSubscriptionId": "[subscription().subscriptionId]",
"eventTypesToAudit": "All"
}
},
{
"apiVersion": "2015-05-01-preview",
"type": "securityAlertPolicies",
"name": "DefaultSecurityAlert",
"dependsOn": [
"[parameters('sqlserverName')]",
"[concat('Microsoft.Storage/storageAccounts/', parameters('storageAccountName'))]",
"[concat('Microsoft.Sql/servers/', parameters('sqlserverName'), '/auditingSettings/Default')]"
],
"properties": {
"state": "Enabled",
"disabledAlerts": "",
"emailAddresses": "[parameters('securityAlertPolicyEmails')]",
"emailAccountAdmins": "Enabled",
"retentionDays": "10",
"storageEndpoint": "[concat('https://', parameters('storageAccountName'), '.blob.core.windows.net/')]",
"storageAccountAccessKey": "[listKeys(resourceId('Microsoft.Storage/storageAccounts', parameters('storageAccountName')), providers('Microsoft.Storage', 'storageAccounts').apiVersions[0]).keys[0].value]"
}
}
]
}
]
}
Sources:
The blob storage auditing config is from here: https://blogs.msdn.microsoft.com/azuresqldbsupport/2017/01/11/arm-template-turning-on-blob-auditing/
The threat detection resource config is from here (note that the storage auditing config from this example didn't work for me): https://blogs.msdn.microsoft.com/azuresqldbsupport/2017/01/11/arm-template-to-deploy-server-with-auditing-and-threat-detection-turned-on/

Resources