Functionapp With Custom Runtime Image, Use ACR Admin Credentials in ARM Template - azure

I'm in the process of migrating our functionapps to custom runtime containers. I'm doing this through ARM templates.
I've got to the point where I can do this, however, in order to get it to work, I have to manually open the Deployment Center and hit save after provisioning, otherwise the functionapp cannot pull down from the ACR (and the logs say there's an auth error).
2022-10-10T22:25:29.055Z INFO - Recycling container because of AppSettingsChange and isMainSite = True
2022-10-10T22:25:32.116Z ERROR - DockerApiException: Docker API responded with status code=InternalServerError, response={"message":"Get https://redacted.azurecr.io/v2/redacted/manifests/preview: unauthorized: authentication required, visit https://aka.ms/acr/authorization for more information."}
As soon as I click save (I don't even change anything) it pulls down and deploys correctly.
Whilst I don't need to reprovision often, this manual step is a pain and I want to fix it, what do I need to add to my ARM template to facilitate this?
The relevent section of the ARM template is:
{
"type": "Microsoft.Web/sites",
"apiVersion": "2022-03-01",
"name": "[parameters('functionAppName')]",
"location": "[parameters('location')]",
"kind": "functionapp,linux,container",
"identity": {
"type": "SystemAssigned"
},
"dependsOn": [
"[variables('appServicePlanResourceId')]",
"[variables('deploymentStorageAccountId')]",
"[variables('networkResourceId')]",
"[resourceId('microsoft.insights/components', parameters('functionAppName'))]"
],
"tags": {
"Product": "[variables('productTag')]",
"Environment": "[parameters('environmentTag')]"
},
"properties": {
"ftpsState": "FtpsOnly",
"httpsOnly": true,
"reserved": true,
"serverFarmId": "[variables('appServicePlanResourceId')]",
"siteConfig": {
"appSettings": [
{
"name": "AzureWebJobsStorage",
"value": "[concat('DefaultEndpointsProtocol=https;AccountName=', parameters('deploymentStorageAccountName'), ';EndpointSuffix=', environment().suffixes.storage, ';AccountKey=',listKeys(variables('deploymentStorageAccountId'), '2019-06-01').keys[0].value)]"
},
{
"name": "WEBSITE_CONTENTAZUREFILECONNECTIONSTRING",
"value": "[concat('DefaultEndpointsProtocol=https;AccountName=', parameters('deploymentStorageAccountName'), ';EndpointSuffix=', environment().suffixes.storage, ';AccountKey=',listKeys(variables('deploymentStorageAccountId'), '2019-06-01').keys[0].value)]"
},
{
"name": "WEBSITE_CONTENTSHARE",
"value": "[toLower(parameters('functionAppName'))]"
},
{
"name": "FUNCTIONS_EXTENSION_VERSION",
"value": "~3"
},
{
"name": "APPLICATIONINSIGHTS_CONNECTION_STRING",
"value": "[concat('InstrumentationKey=', reference(resourceId('Microsoft.Insights/components', parameters('functionAppName')), '2020-02-02-preview').instrumentationKey)]"
},
{
"name": "FUNCTIONS_WORKER_RUNTIME",
"value": "dotnet"
},
{
"name": "EventGridTopicEndpoint",
"value": "[reference(variables('eventGridTopicId')).endpoint]"
},
{
"name": "EventGridTopicAccessKey",
"value": "[listKeys(variables('eventGridTopicId'), '2020-06-01').key1]"
},
{
"name": "WEBSITE_DNS_SERVER",
"value": "redacted"
},
{
"name": "WEBSITE_VNET_ROUTE_ALL",
"value": 1
},
{
"name": "WEBSITES_ENABLE_APP_SERVICE_STORAGE",
"value": "false"
}
],
"linuxFxVersion": "[parameters('linuxFxVersion')]",
"acrUseManagedIdentityCreds": false
}
},
"resources": [
{
"type": "networkConfig",
"apiVersion": "2019-08-01",
"name": "virtualNetwork",
"dependsOn": [ "[variables('functionAppResourceId')]" ],
"properties": {
"subnetResourceId": "[variables('subnetResourceId')]",
"isSwift": true
}
}
]
}
[parameters('linuxFxVersion')] evaluates to DOCKER|redacted.azurecr.io/redacted:preview
Every answer that I've found so far requires either adding config options with docker usernames and passwords, or using a managed identity, neither of which is what we want.

You need to add an RBAC assignment to your ACR instance granting the system-assigned identity of your function app the AcrPull role.
The alternative is using admin credentials.
When you hit "Save" in the deployment center, it's using one of those two methods -- it's retrieving the admin credentials from the ACR and applying them to the app service. It's not doing anything special, it's doing exactly what you can do yourself.
I recommend using managed identities instead. You can even create a single user-assigned identity and share it across multiple function apps, if you really want to.

Reference a secret in a key vault:
"adminPassword": {
"reference": {
"keyVault": {
"id": "/subscriptions/<SubscriptionID>/resourceGroups/mykeyvaultdeploymentrg/providers/Microsoft.KeyVault/vaults/<KeyVaultName>"
},
"secretName": "vmAdminPassword"
}
}

So with hints taken from the other two answers and from here, I've devised two solutions.
Using Service Principal Role
Add "acrUseManagedIdentityCreds": true to the siteConfig in my ARM template
Assign the AcrPull role to the service principal of the functionapp (I've not tested this snippet because perms weren't set-up quite right and it's too late for me to ask someone to change them)
"resources": [
{
"type": "Microsoft.Authorization/roleAssignments",
"apiVersion": "2018-09-01-preview",
"name": "[guid(resourceGroup().id)]",
"dependsOn": [
"[parameters('functionAppName')]"
],
"properties": {
"roleDefinitionId": "[concat('/subscriptions/', subscription().subscriptionId, '/providers/Microsoft.Authorization/roleDefinitions/', '7f951dda-4ed3-4680-a7ca-43fe172d538d')]",
"principalId": "[reference(resourceId('Microsoft.Web/sites', parameters('functionAppName')), '2022-03-01').identity.principalId]"
}
}
]
Getting Admin Creds with Reference
Add these variables to my template:
"registryName": "containerRegName",
"registrySubscriptionId": "container-reg-sub-id",
"registryResourceGroup": "container-reg-rg",
"registryResourceId": "[resourceId(variables('registrySubscriptionId'), variables('registryResourceGroup'), 'Microsoft.ContainerRegistry/registries', variables('registryName'))]"
},
Then add these configuration options to my appsettings:
{
"name": "DOCKER_REGISTRY_SERVER_URL",
"value": "[reference(variables('registryResourceId'), '2019-05-01').loginServer]"
},
{
"name": "DOCKER_REGISTRY_SERVER_USERNAME",
"value": "[listCredentials(variables('registryResourceId'), '2019-05-01').username]"
},
{
"name": "DOCKER_REGISTRY_SERVER_PASSWORD",
"value": "[listCredentials(variables('registryResourceId'), '2019-05-01').passwords[0].value]"
}

Related

Azure Web App staging slot App Settings missing on ARM template deployment

I am working on ARM templates for some web application deployments. These templates set up a web application along with a staging slot for this application. The way I wish to handle this is to only deploy the app settings to the staging slot. By doing this I can handle rollbacks nicely as the app settings will swap with the slot and have any old values tied to the app they were deployed with. However upon deploying these ARM templates successfully I can see there are no app settings deployed to my staging slots other than website_node_default_version.
Below is a snippet of the ARM templates showing one pair of web app + staging slot:
{
"type": "Microsoft.Web/sites",
"apiVersion": "2016-08-01",
"name": "[variables('egressAppName')]",
"location": "[parameters('location')]",
"kind": "app",
"properties": {
"enabled": true,
"serverFarmId": "[resourceId('Microsoft.Web/serverfarms', variables('appServicePlanName'))]",
"clientAffinityEnabled": true
}
},
{
"type": "Microsoft.Web/sites/slots",
"apiVersion": "2016-08-01",
"name": "[concat(variables('egressAppName'),'/','staging')]",
"location": "[parameters('location')]",
"dependsOn": [
"[resourceId('Microsoft.Web/sites', variables('egressAppName'))]"
],
"kind": "app",
"properties": {
"enabled": true,
"serverFarmId": "[resourceId('Microsoft.Web/serverfarms', variables('appServicePlanName'))]",
"clientAffinityEnabled": true,
"appSettings": [
{
"name": "APP_INSIGHTS_INSTRUMENTATION_KEY",
"value": "[reference(resourceId(variables('rsg') ,'microsoft.insights/components/', variables('ainName')), '2015-05-01').InstrumentationKey]"
},
{
"name": "ASPNETCORE_ENVIRONMENT",
"value": "[parameters('netCoreEnvironment')]"
},
{
"name": "MONITOR_API_ACCOUNT_RATE_LIMIT",
"value": "[parameters('accountRateLimit')]"
},
{
"name": "MONITOR_API_ACCOUNT_RATE_LIMIT_WINDOW_SECONDS",
"value": "[parameters('accountLimitWindow')]"
},
{
"name": "MONITOR_API_IP_RATE_LIMIT",
"value": "[parameters('ipLimit')]"
},
{
"name": "MONITOR_API_IP_RATE_LIMIT_WINDOW_SECONDS",
"value": "[parameters('ipLimitWindow')]"
},
{
"name": "MONITOR_DATA_EXPLORER_INSTANCE_NAME",
"value": "[variables('dataExplorerName')]"
},
{
"name": "MONITOR_DATA_EXPLORER_REGION",
"value": "[parameters('location')]"
},
{
"name": "MONITOR_DIAG_ACCOUNT_APP_ID",
"value": "[parameters('diagAccountAppID')]"
},
{
"name": "MONITOR_DIAG_ACCOUNT_APP_SECRET_LOCATION",
"value": "[parameters('diagAccountAppSecret')]"
},
{
"name": "MONITOR_EGRESS_APP_TENANT",
"value": "[parameters('egressTenantID')]"
},
{
"name": "MONITOR_KEY_VAULT_APP_ID",
"value": "[parameters('keyVaultAppID')]"
},
{
"name": "MONITOR_KEY_VAULT_APP_SECRET",
"value": "[parameters('keyVaultAppSecret')]"
},
{
"name": "MONITOR_KEY_VAULT_NAME",
"value": "[variables('keyVaultName')]"
},
{
"name": "MONITOR_PGSQL_CONNECTION_STRING",
"value": "[parameters('postgresConnectionString')]"
},
{
"name": "MONITOR_TOKEN_VALIDATION_CLOCK_SKEW_SECONDS",
"value": "[parameters('validationClockSkew')]"
},
{
"name": "WEBSITE_RUN_FROM_PACKAGE",
"value": "1"
}
]
}
}
I have tried deleting just the staging slots and redeploying as well as deleting all the web apps and redeploying with no luck. At this point I'm just hoping to get more eyes over this to see if I've missed anything obvious. I'm deploying these ARM templates through Azure DevOps release pipelines using the Azure Resource Group Deployment task.
The appSettings should be defined in the SiteConfig object instead of Microsoft.Web/sites/slots properties as your template. To create a Microsoft.Web/sites/slots/config resource for app settings, you could add the JSON to the resources section of your template.
Also, you can see the Monitoring and diagnostic settings could be swapped here.

Enabling auditing settings on Azure SQL database via ARM Template

I have been working on a template to deploy SQL/XSS injection detection. All is well except for enabling the auditing settings. In the docs I see the following:
{
"name": "default",
"type": "Microsoft.Sql/servers/databases/auditingSettings",
"apiVersion": "2017-03-01-preview",
"properties": {
"state": "string",
"storageEndpoint": "string",
"storageAccountAccessKey": "string",
"retentionDays": "integer",
"auditActionsAndGroups": [
"string"
],
"storageAccountSubscriptionId": "string",
"isStorageSecondaryKeyInUse": boolean
}
}
I believe I've followed this structure. See my full code here or the snippet here:
- apiVersion: 2017-03-01-preview
type: Microsoft.Sql/servers/auditingSettings
name: "[concat(parameters('sqlServerName'), '/auditing-default')]"
dependsOn:
- "[resourceId('Microsoft.Sql/servers', parameters('sqlServerName'))]"
properties:
state: Enabled
storageEndpoint: "[reference(resourceId('Microsoft.Storage/storageAccounts', parameters('storageAccountName')),
'2018-03-01-preview').PrimaryEndpoints.Blob]"
storageAccountAccessKey: "[listKeys(resourceId('Microsoft.Storage/storageAccounts',
parameters('storageAccountName')), '2018-03-01-preview').keys[0].value]"
retentionDays: 0
storageAccountSubscriptionId: "[subscription().subscriptionId]"
isStorageSecondaryKeyInUse: false'
I am seeing that there is a discrepancy between the servers/databases and just /servers for the type, but I actually borrowed this code from the Azure Quick Starts and the specific file here where the code is the following:
{
"apiVersion": "2017-03-01-preview",
"type": "Microsoft.Sql/servers/auditingSettings",
"name": "[concat(parameters('sqlServerName'), '/', 'default')]",
"properties": {
"state": "Enabled",
"storageEndpoint": "[reference(resourceId('Microsoft.Storage/storageAccounts', parameters('storageAccountName')), '2018-03-01-preview').PrimaryEndpoints.Blob]",
"storageAccountAccessKey": "[listKeys(resourceId('Microsoft.Storage/storageAccounts', parameters('storageAccountName')), '2018-03-01-preview').keys[0].value]",
"retentionDays": 0,
"auditActionsAndGroups": null,
"storageAccountSubscriptionId": "[subscription().subscriptionId]",
"isStorageSecondaryKeyInUse": false
}
}
The official docs don't seem to have info on adding the auditingSettings on a server level, but then here the type is directly under server, so I'm a bit lost. I haven't looked into the schema yet, but any help/guidance as to what might be going on here would be much appreciated!
We recently published a template that shows how to deploy an Azure SQL Server with server auditing enabled.
The full example is here: https://github.com/Azure/azure-quickstart-templates/tree/master/quickstarts/microsoft.sql/sql-auditing-server-policy-to-blob-storage
As the other answers are returning 404s here's a full list of instructions to get the basics working in ARM for auditing at the SQL Server level. This will therefore audit all databases within the SQL Server.
Firstly, create a parameter for the name of your SQL Server and storage account:
"sqlServerName": {
"type": "string"
},
"auditingStorageAccountName": {
"type": "string"
}
Then in your resources section create a storage account to store your audit records, this example will replicate the audit blobs to the paired region (RA-GRS). It was necessary to add network ACLs explicitly as shown so that Azure can write the audit logs. This example also uses storage account assigned keys but managed identities are also possible:
{
"type": "Microsoft.Storage/storageAccounts",
"apiVersion": "2019-06-01",
"name": "[parameters('auditingStorageAccountName')]",
"location": "[resourceGroup().location]",
"sku": {
"name": "Standard_RAGRS",
"tier": "Standard"
},
"kind": "StorageV2",
"properties": {
"networkAcls": {
"bypass": "AzureServices",
"virtualNetworkRules": [],
"ipRules": [],
"defaultAction": "Allow"
},
"supportsHttpsTrafficOnly": true,
"allowBlobPublicAccess": false,
"encryption": {
"services": {
"blob": {
"keyType": "Account",
"enabled": true
}
},
"keySource": "Microsoft.Storage"
},
"accessTier": "Hot"
}
},
...
Finally add the auditing settings themselves - this example is for a resource added at the root (i.e. directly within "resources": {}), to add it as sub-resource to the SQL Server itself the type needs to be just "auditingSettings". A retention days of zero means audit records will be kept indefinitely. It was necessary to add the subscription ID explicitly otherwise the settings do not appear correctly when viewed in the portal:
{
"type": "Microsoft.Sql/servers/auditingSettings",
"name": "default",
"apiVersion": "2020-11-01-preview",
"dependsOn": [
"[resourceId('Microsoft.Sql/servers/', parameters('sqlServerName'))]",
"[resourceId('Microsoft.Storage/storageAccounts', parameters('auditingStorageAccountName'))]"
],
"properties": {
"retentionDays": 0,
"state": "Enabled",
"storageEndpoint": "[reference(resourceId('Microsoft.Storage/storageAccounts', parameters('auditingStorageAccountName'))).primaryEndpoints.blob]",
"storageAccountAccessKey": "[listKeys(parameters('auditingStorageAccountName'), '2019-06-01').keys[0].value]",
"storageAccountSubscriptionId": "[subscription().subscriptionId]"
}
},
...
For those looking for guidance on enabling server level auditing to a Log Analytics workspace, I found this github link

How to make AzureRM not to drop previously configured properties of `Microsoft.Web/sites/config` at next deployment?

This is current configuration, https://management.azure.com/subscriptions/<subid>/resourceGroups/<groupid>/providers/Microsoft.Web/sites/<sitename>/config/logs?api-version=2018-02-01 :
{
"id": "/subscriptions/<subid>/resourceGroups/<group>/providers/Microsoft.Web/sites/<sitename>/config/logs",
"name": "logs",
"type": "Microsoft.Web/sites/config",
"location": "West Europe",
"tags": {
"displayName": "Website",
},
"properties": {
"applicationLogs": {
"fileSystem": {
"level": "Off"
},
"azureTableStorage": {
"level": "Off",
"sasUrl": null
},
"azureBlobStorage": {
"level": "Verbose",
"sasUrl": "<here is fully specified sasUrl>",
"retentionInDays": 0
}
},
// ...
This is done in order to configure that SasUrl there which is done only after we have SA, and using Powershell. When New-AzureRmResourceGroupDeployment run with this template, those properties are lost (sasUrl and other).
{
"apiVersion": "2016-08-01",
"name": "[variables('prodWebAppName')]",
"type": "Microsoft.Web/sites",
"location": "[parameters('location')]",
"dependsOn": [
"[variables('appServicePlanName')]"
],
"tags": {
"displayName": "Website"
},
"properties": {
"serverFarmId": "[resourceId('Microsoft.Web/serverfarms', variables('appServicePlanName'))]",
"hostNames": [
// ...
],
"enabledHostNames": [
// ..
],
"defaultHostName": "[concat(variables('prodWebAppName'), '.azurewebsites.net')]",
"siteConfig": {
"netFrameworkVersion": "v4.6",
"phpVersion": "Off",
"alwaysOn": true,
"webSocketsEnabled": true,
"appSettings": [
// ...
],
"connectionStrings": [
// ...
]
}
},
// .. and then slots configuration
That seems to happen because those netFrameworkVersion and like settings are under Microsoft.Web/sites/<sitename>/config also. Probably it should be put in a separate json template to run for this site or slot specifically. The template is used to provision all environments (AAT, QA, Prod) at once which makes things more complex.
Also, do you think it is right to make QA and AAT in App Service slots like MS advertise at https://learn.microsoft.com/en-us/azure/app-service/web-sites-staged-publishing? To my mind this does not suit well for script/template based continuous deployment/delivery for not simple systems.
ARM is meant to apply final state to your resources so it will apply the values in your ARM template (blanks/nulls) to the settings in your resources.
Instead of using PS after the fact to create the storage resource and update the setting, have you considered deploying the storage account in the ARM template and using a reference to it's key using listKeys instead?

Azure - Set WebSocket On from ARM json template

I'm trying to turn WebSockets On for an Azure WebApp from an Azure ARM json template that deploys my whole infrastructure.
Here is an extract with regards to the Azure Web App. It doesn't work, i.e the WebSockets are still Off. I unsuccessfully tried different spelling: webSocketsEnabled or WebSockets.
"resources":[
{
"name": "[variables('MyApp')]",
"type": "Microsoft.Web/sites",
"location": "Brazil South",
"apiVersion": "2016-08-01",
"dependsOn": [
"[resourceId('Microsoft.Web/serverfarms', variables('MyAppPlanBrazil'))]"
],
"tags": {
"[concat('hidden-related:', resourceId('Microsoft.Web/serverfarms', variables('MyAppPlanBrazil')))]": "Resource",
"displayName": "MyAppAppBrazil"
},
"properties": {
"name": "[variables('MyAppPlanBrazil')]",
"serverFarmId": "[resourceId('Microsoft.Web/serverfarms', variables('MyAppPlanBrazil'))]",
"siteConfig": {
"AlwaysOn": true,
"webSocketsEnabled": true,
"connectionStrings": [
{
...
},
{
...
},
]
}
}
]
UPDATE
As suggested in answer below I updated the apiVersion to "2016-08-01" but this still doesn't work.
Also note that while my schema is the one described here, apiVersion is squiggled in VS and it says the authorized value is "2015-08-01" only.
UPDATE2
I tried the solutions below. They work for their authors but not for me. I guess the problem is elsewhere. My infrastructure is already deployed and I try to update it with webSocketsEnabled. Whereas in the solution below I imagine the authors directly create the web app with webSocketsEnabled.
Also, I coupled webSocketsEnabled with alwaysOn whereas the pricing tier of my webapp doesn't allow "AlwaysOn" (as it says in the portal I need to upgrade to use that feature) so I'll try without alwaysOn.
UPDATE3
At the end, the above template worked when I removed AlwaysOn.
Thank you to those who tried to help me.
Set your api version to this: "2016-08-01"
Use
"webSocketsEnabled": true
This is from the Microsoft.Web/sites template reference:
https://learn.microsoft.com/en-us/azure/templates/microsoft.web/sites
The api version you are using (2015-08-01) from:
https://github.com/Azure/azure-resource-manager-schemas/blob/master/schemas/2015-08-01/Microsoft.Web.json
Doesn't have web sockets in it, but the later one:
https://github.com/Azure/azure-resource-manager-schemas/blob/master/schemas/2016-08-01/Microsoft.Web.json
Does have webSocketsEnabled.
Please have a try to use the following code. It works correctly on my side.
Updated: add whole test arm template and you could have a try to use the following code with your service plan name and resource group name
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"serverFarmName": {
"type": "string",
"defaultValue": "YourPlan"
},
"serverFarmResourceGroup": {
"type": "string",
"defaultValue": "ResourceGroupName"
}},
"variables": {
"ARMtemplateTestName": "[concat('ARMtemplateTest', uniqueString(resourceGroup().id))]"},
"resources": [
{
"name": "[variables('ARMtemplateTestName')]",
"type": "Microsoft.Web/sites",
"location": "southcentralus",
"apiVersion": "2015-08-01",
"dependsOn": [ ],
"tags": {
"[concat('hidden-related:', resourceId(parameters('serverFarmResourceGroup'), 'Microsoft.Web/serverFarms', parameters('serverFarmName')))]": "Resource",
"displayName": "ARMtemplateTest"
},
"properties": {
"name": "[variables('ARMtemplateTestName')]",
"serverFarmId": "[resourceId(parameters('serverFarmResourceGroup'), 'Microsoft.Web/serverFarms', parameters('serverFarmName'))]"
},
"resources": [
{
"name": "web",
"type": "config",
"apiVersion": "2015-08-01",
"dependsOn": [
"[resourceId('Microsoft.Web/sites', variables('ARMtemplateTestName'))]"
],
"tags": {
"displayName": "enableWebSocket"
},
"properties": {
"webSocketsEnabled": true,
"alwaysOn": true
}
},
{
"apiVersion": "2015-08-01",
"name": "connectionstrings",
"type": "config",
"dependsOn": [
"[resourceId('Microsoft.Web/Sites', variables('ARMtemplateTestName'))]"
],
"properties": {
"ConnString1": {
"value": "My custom connection string",
"type": "custom"
},
"ConnString2": {
"value": "My SQL connection string",
"type": "SQLAzure"
}
}
},
{
"name": "appsettings",
"type": "config",
"apiVersion": "2015-08-01",
"dependsOn": [
"[resourceId('Microsoft.Web/sites', variables('ARMtemplateTestName'))]"
],
"tags": {
"displayName": "Appsetting"
},
"properties": {
"key1": "value1",
"key2": "value2"
}
}
]
}],
"outputs": {}
}
Test Result:
All the above solution should work.
My initial snippet worked as well ... as soon as I removed alwaysOn.
Indeed, I was using a free tiers App Service Plan for which alwaysOn is not available. While there was no errors or anything else indicating something wrong, I could not set webSocketEnabled and alwaysOn at the same time in that case.

Generate or Specify Azure Service Bus Namespace SAS Token with ARM Template

I'm using Azure ARM templates in order to make sure that I can repeatedly deploy uniform infrastructure and services. My ARM template consists of an App Service, Web App, Service Bus Queue, and Azure SQL database. On top of this, I'm setting up continuous deployment through VSTS.
Everything is working well EXCEPT I am not sure how to set a Service Bus SAS token at the Namespace level. I don't see a way in the Service Bus ARM template to specify one, so I cannot pre-generate a token and place it in my web.config file. I also don't see a way to have one generated on my behalf, then pull the values back to my web.config file. Any suggestions would be greatly appreciated.
I believe you have two options:
1) Get generated key from the output:
"outputs": {
"eh:Endpoint": {
"value": "[listKeys(resourceId('Microsoft.EventHub/namespaces/authorizationRules', variables('eventHubNamespaceName'), 'SendOnlyKey'),'2015-08-01').primaryKey]",
"type": "string"
},
}
And incorporate it in your build/release process.
2) Try to push a key with a template:
{
"apiVersion": "[parameters('eventHubVersion')]",
"name": "[variables('eventHubNamespaceName')]",
"type": "Microsoft.EventHub/namespaces",
"location": "[resourceGroup().location]",
"resources": [
{
"apiVersion": "2014-09-01",
"name": "[variables('eventHubName')]",
"type": "eventHubs",
"dependsOn": [
"[concat('Microsoft.EventHub/namespaces/', variables('eventHubNamespaceName'))]"
],
"properties": {
"path": "[variables('eventHubName')]",
"MessageRetentionInDays": "[parameters('messageRetentionInDays')]",
"PartitionCount": "[parameters('partitionCount')]"
},
"resources": [
{
"apiVersion": "[parameters('eventHubVersion')]",
"name": "StorageRetention",
"type": "consumergroups",
"dependsOn": [
"[variables('eventHubName')]",
"[concat('Microsoft.EventHub/namespaces/', variables('eventHubNamespaceName'))]"
],
"tags": {
"displayName": "eh"
}
}
]
},
{
"apiVersion": "[parameters('eventHubVersion')]",
"name": "[concat(variables('eventHubNamespaceName'),'/SendOnlyKey')]",
"type": "Microsoft.EventHub/namespaces/authorizationRules",
"dependsOn": [
"[concat('Microsoft.EventHub/namespaces/', variables('eventHubNamespaceName'))]"
],
"location": "[resourceGroup().location]",
"properties": {
"KeyName": "SendOnlyKey",
"ClaimType": "SendSharedAccessKey",
"ClaimValue": "None",
"PrimaryKey": "[parameters('eventHubSendPrimaryKey')]",
"SecondaryKey": "your_key",
"Rights": [ "Send" ],
"Revision": -1
}
},
{
"apiVersion": "[parameters('eventHubVersion')]",
"name": "[concat(variables('eventHubNamespaceName'),'/ListenOnlyKey')]",
"type": "Microsoft.EventHub/namespaces/authorizationRules",
"dependsOn": [
"[concat('Microsoft.EventHub/namespaces/', variables('eventHubNamespaceName'))]"
],
"location": "[resourceGroup().location]",
"properties": {
"KeyName": "ListenOnlyKey",
"ClaimType": "ReceiveSharedAccessKey",
"ClaimValue": "None",
"PrimaryKey": "your_key",
"SecondaryKey": "your_key",
"Rights": [ "Listen" ],
"Revision": -1
}
}
]
}
However note that the second solutions works only for an older version of API and sooner or later will be deprecated. Additionally I tested it only for pushing keys for a hub, not a namespace.
This might help others arriving at this answer
In EastUS using API_VERSION = 2017-04-01
The following will work to obtain references to primarykey and related fields
- connectionString: "[concat('',listKeys(resourceId('Microsoft.EventHub/namespaces/eventhubs/authorizationRules','{{ eh_namespace }}', '{{ eventhub_name }}','fw'), '2017-04-01').primaryConnectionString,'')]"

Resources