Hi I want to add Application Config Read Only Connection string in ARM Template
"appSettingsShared": {
"value": [
{
"name": "RedisCache:ConnectionString",
"value": "[concat(variables('RedisCacheName'),'.redis.cache.windows.net:6380,abortConnect=false,ssl=true,password=', listKeys(resourceId('Microsoft.Cache/Redis', variables('RedisCacheName')), '2015-08-01').primaryKey)]"
},
{
"name": "AppConfig:ConnectionString",
"value": "???"
}
]
I know how to do it using Azure CLI:
az appconfig credential list -g $resourceGroup -n $appConfigName --query "([?name=='Primary Read Only'].connectionString)[0]" --output tsv
Any help is really appreciated.
You can use the listkeys template function to retrieve your configStore keys and connection strings. The implementation is similar to the Configuration Stores - List Keys API, which returns a response similar to:
{
"value": [
{
"id": "439AD01B4BE67DB1",
"name": "Primary",
"value": "000000000000000000000000000000000000000000000000000000",
"connectionString": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"lastModified": "2018-04-24T16:30:54+00:00",
"readOnly": false
},
{
"id": "CB45E100456857B9",
"name": "Secondary",
"value": "000000000000000000000000000000000000000000000000000000",
"connectionString": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"lastModified": "2018-04-24T16:30:54+00:00",
"readOnly": false
},
{
"id": "B3AC55B7E71431A9",
"name": "Primary Read Only",
"value": "000000000000000000000000000000000000000000000000000000",
"connectionString": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"lastModified": "2018-04-24T16:30:54+00:00",
"readOnly": true
},
{
"id": "E2AF6A9A89DCC177",
"name": "Secondary Read Only",
"value": "000000000000000000000000000000000000000000000000000000",
"connectionString": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"lastModified": "2018-04-24T16:30:54+00:00",
"readOnly": true
}
]
}
Since you want to access the Read-Only connection strings, you can access it in your ARM template as follows:
"value": "[listKeys(resourceId('Microsoft.AppConfiguration/configurationStores', variables('configurationStore_name')), '2019-11-01-preview').value[2].connectionString]"
This would get you the Primary Read Only connection string. Similarly, value[3].connectionString would retrieve the Secondary Read Only connection string.
In your template file, you can have the following to get the Redis Cache ConnectionString that your provisioned:
"outputs": {
"RedisCacheConnectionString": {
"type": "string",
"value":"[concat(reference(parameters('redisCacheName')).hostName,':', reference(parameters('redisCacheName')).sslPort,',password=',listKeys(resourceId('Microsoft.Cache/redis', parameters('redisCacheName')), '2020-06-01').primaryKey,',ssl=True,abortConnect=False')]"
}
}
This answer is inspired based on #bhargavi-annadevara's answer.
Related
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]"
}
When using an ARM template to create a new Connection for a bot channels registration I use the following resource as part of Microsoft.BotService/botServices;
{
"type": "Microsoft.BotService/botServices/Connections",
"apiVersion": "2018-07-12",
"name": "[concat(parameters('botName'), '/ActiveDirectory')]",
"dependsOn": [
"[resourceId('Microsoft.BotService/botServices', parameters('botName'))]"
],
"location": "global",
"tags": "[parameters('resourceTags')]",
"properties": {
"clientId": "[parameters('appId')]",
"clientSecret": "[parameters('appSecret')]",
"scopes": "[parameters('scopes')]",
"serviceProviderId": "30dd229c-58e3-4a48-bdfd-91ec48eb906c",
"serviceProviderDisplayName": "Azure Active Directory v2",
"parameters": []
}
}
That gets me all the fields except Token Exchange Url & Tenant ID, which I do need to fill in;
I checked the documentation and could not find anything about this. I tried adding the following parameter to test;
"parameters": [
{
"key": "tenantID",
"value": "customValue"
}
]
That did not do anything, also just guessing here what the key should be..
How can I set these two fields using an Arm template?
The parameters were the way to go. However when using parameters, the clientID & clientSecret also need to be a parameter, as they are not picked up anymore as properties when a parameter is present. Below the resource Json the way it worked for me;
{
"type": "Microsoft.BotService/botServices/Connections",
"apiVersion": "2018-07-12",
"name": "[concat(parameters('botName'), '/ActiveDirectory')]",
"condition": "[equals(parameters('oauthEnabled'), 'True')]",
"dependsOn": [
"[resourceId('Microsoft.BotService/botServices', parameters('botName'))]"
],
"location": "global",
"tags": "[parameters('resourceTags')]",
"properties": {
"serviceProviderId": "30dd229c-58e3-4a48-bdfd-91ec48eb906c",
"serviceProviderDisplayName": "Azure Active Directory v2",
"parameters": [
{
"key": "clientId",
"value": "[parameters('appId')]"
},
{
"key": "clientSecret",
"value": "[parameters('appSecret')]"
},
{
"key": "scopes",
"value": "[parameters('scopes')]"
},
{
"key": "tenantID",
"value": "common"
},
{
"key": "tokenExchangeUrl",
"value": "[concat('api://botid-', parameters('appId'))]"
}
]
}
}
I have VS2019 and trying to create Logic Apps which includes SQL connection.
I deploy this LogicApps with Azure DevOps and getting error. I do not what is purpose of sql_1_privacySetting and what are possible values I could use. Specially I'm wondering how to set values in ARM.
ERROR:
##[error]Deployment template validation failed: 'The provided value 'Microsoft.WindowsAzure.ResourceStack.Frontdoor.Common.Entities.TemplateGenericProperty`1[Newtonsoft.Json.Linq.JToken]' for the template parameter 'sql_1_privacySetting' at line '1' and column '1605' is not valid. The parameter value is not part of the allowed value(s): 'None,Private,Organizational,Public'.'.
LogicApp.parameters.json
"sql_1_encryptConnection": {
"value": false
},
"sql_1_privacySetting": {
"value": ""
},
LogicApp.json
{
"type": "MICROSOFT.WEB/CONNECTIONS",
"apiVersion": "2018-07-01-preview",
"name": "[parameters('sql_1_Connection_Name')]",
"location": "[parameters('logicAppLocation')]",
"properties": {
"api": {
"id": "[concat(subscription().id, '/providers/Microsoft.Web/locations/', parameters('logicAppLocation'), '/managedApis/', 'sql')]"
},
"displayName": "[parameters('sql_1_Connection_DisplayName')]",
"parameterValues": {
"server": "[parameters('sql_1_server')]",
"database": "[parameters('sql_1_database')]",
"username": "[parameters('sql_1_username')]",
"password": "[parameters('sql_1_password')]",
"encryptConnection": "[parameters('sql_1_encryptConnection')]",
"privacySetting": "[parameters('sql_1_privacySetting')]",
"sqlConnectionString": "[parameters('sql_1_sqlConnectionString')]"
}
}
}
In my LogicApp.json it has these as the possible privacySetting allowed values:
"sql_1_privacySetting": {
"type": "string",
"metadata": {
"description": "Privacy Setting"
},
"allowedValues": [
"None",
"Private",
"Organizational",
"Public"
]
},
Set the
values as follows if you want it blank
"sql_1_privacySetting": {
"value": "None"
}
Options are
"None",
"Private",
"Organizational",
"Public"
I'm trying to provision a bot resource in Azure with two connection (an Azure Active Directory V2 and a sharepoint Online) using ARM template (see bellow).
I was able to make it work for AADv2 successfully, and everything works fine.
I was able to make it work when I provision the resource manually.
Sadly, you can't export the templates for a bot resource...And I can't succeed to make it work for Sharepoint online, and the only parameter I don't know what to set is the Service Provider Id, as I was able to test setting the other manually.
When i use the same as AADv2, the connection provisionned is AADv2 (30dd229c-58e3-4a48-bdfd-91ec48eb906c)...
My template to provision this resources is:
{
"name": "[concat(parameters('botId'),'/',parameters('SharepointConnectionName'))]",
"type": "Microsoft.BotService/botServices/Connections",
"apiVersion": "2017-12-01",
"location": "global",
"tags": {},
"sku": {
"name": "[parameters('sku')]"
},
"kind": "[parameters('kind')]",
"properties": {
"clientId": "[parameters('SharepointConnectionClientId')]",
"clientSecret": "[parameters('SharepointConnectionClientSecret')]",
"scopes": "[parameters('SharepointConnectionScopes')]",
"serviceProviderId": "[parameters('SharepointConnectionServiceProviderId')]",
"serviceProviderDisplayName": "[parameters('SharepointConnectionServiceProviderDisplayName')]",
"parameters": [
{
"key": "tenantId",
"value": "[parameters('SharepointConnectionTenantID')]"
},
{
"key": "clientId",
"value": "[parameters('SharepointConnectionClientId')]"
},
{
"key": "clientSecret",
"value": "[parameters('SharepointConnectionClientSecret')]"
},
{
"key": "GrantType",
"value": "[parameters('SharepointConnectionGrantType')]"
},
{
"key": "LoginURL",
"value": "[parameters('SharepointConnectionLoginURL')]"
},
{
"key": "DiscoveryURL",
"value": "[parameters('SharepointConnectionDiscoveryURL')]"
},
{
"key": "ResourceURL",
"value": "[parameters('SharepointConnectionResourceURL')]"
},
{
"key": "Capability",
"value": "[parameters('SharepointConnectionCapabilityURL')]"
}
]
},
"dependsOn": [
"[concat('Microsoft.BotService/botServices/', parameters('botId'))]"
]
}
Can you try using 307d995f-f1ce-4918-bd3f-037685e9d241?
I created two SharePoint Online connections using the browser/UI and after creating, I used Resource Explorer to show what I had created. Both use 307d995f-f1ce-4918-bd3f-037685e9d241 as the serviceProviderId when serviceProviderDisplayName is SharePoint Online.
We are working on an app that allows our Azure administrator to monitor Azure Resource requests by people in organization.
There is a requirement where I want to get list of all possible SKUs and SKU capacities through some API if available. I could have hard coded the values but considering the frequency of changes being brought by Microsoft to Azure subscription plans, I wanted to make it more generic and dog feed by Azure itself.
I could not find any API endpoint under Azure Rest API that provides us list of SKUs and Capacities for requested resource type.
Has anyone figured it out already? if not, what is the alternative and better approach?
Rahul.
The pattern for the Azure SKUs API in Azure Resource Manager is HTTP GET {resourceId}/skus?api-version=...
As others have indicated, there doesn't seem to be a good way to discover which ARM resource types have implemented the SKUs API. If you are looking for a generic option today, I would consider the following approach --
1) Gather a list of ARM resource ids in the subscription(s). You can use the ARM resources API to get this list.
2) For each resource id, call the following to retrieve the SKUs: GET {resourceId}/skus?api-version=...
3) Keep track of which ARM resource types return non-2xx status codes. These resource types do not implement the SKUs API and your code should ignore these resource types today.
Here are a few examples of the SKUs API for two common ARM resource types:
armclient get /subscriptions/{subscriptionId}/resourceGroups/{resourceGroup}/providers/Microsoft.Compute/virtualMachineScaleSets/{name}/skus?api-version=2017-03-30
armclient get /subscriptions/{subscriptionId}/resourceGroups/{resourceGroup}/providers/Microsoft.Web/serverFarms/{name}/skus?api-version=2014-04-01
As 4c74356b41 mentioned some might have that feature and some not. We can get the Azure REST API from the official document. And we can get some List SKU REST APIs, detail please refer to screenshot. You also can give your feedback to the Azure team.
Looks like Azure has made this REST API available now:
Resource Skus - List
Get all the resources in a subscription.
GET https://management.azure.com/subscriptions/{subscriptionId}/providers/Microsoft.Compute/skus?api-version=2021-07-01
Sample Response:
{
"value": [
{
"resourceType": "virtualMachines",
"locations": [
"westus"
],
"capabilities": [
{
"name": "MaxResourceVolumeMB",
"value": "20480"
},
{
"name": "OSVhdSizeMB",
"value": "1047552"
},
{
"name": "vCPUs",
"value": "1"
},
{
"name": "HyperVGenerations",
"value": "V1"
},
{
"name": "MemoryGB",
"value": "0.75"
},
{
"name": "MaxDataDiskCount",
"value": "1"
},
{
"name": "LowPriorityCapable",
"value": "False"
},
{
"name": "PremiumIO",
"value": "False"
},
{
"name": "vCPUsAvailable",
"value": "1"
},
{
"name": "ACUs",
"value": "50"
},
{
"name": "vCPUsPerCore",
"value": "1"
},
{
"name": "EphemeralOSDiskSupported",
"value": "False"
},
{
"name": "AcceleratedNetworkingEnabled",
"value": "False"
},
{
"name": "RdmaEnabled",
"value": "False"
},
{
"name": "MaxNetworkInterfaces",
"value": "2"
}
],
"locationInfo": [
{
"location": "westus",
"zones": [
"2",
"1"
],
"zoneDetails": [
{
"name": [
"2"
],
"capabilities": [
{
"name": "UltraSSDAvailable",
"value": "True"
}
]
}
]
}
],
"name": "Standard_A0",
"tier": "Standard",
"size": "A0",
"family": "standardA0_A7Family"
},
{
"resourceType": "virtualMachines",
"locations": [
"westus"
],
"capabilities": [
{
"name": "MaxResourceVolumeMB",
"value": "71680"
},
{
"name": "OSVhdSizeMB",
"value": "1047552"
},
{
"name": "vCPUs",
"value": "1"
},
{
"name": "HyperVGenerations",
"value": "V1"
},
{
"name": "MemoryGB",
"value": "1.75"
},
{
"name": "MaxDataDiskCount",
"value": "2"
},
{
"name": "LowPriorityCapable",
"value": "True"
},
{
"name": "PremiumIO",
"value": "False"
},
{
"name": "vCPUsAvailable",
"value": "1"
},
{
"name": "ACUs",
"value": "100"
},
{
"name": "vCPUsPerCore",
"value": "1"
},
{
"name": "EphemeralOSDiskSupported",
"value": "False"
},
{
"name": "AcceleratedNetworkingEnabled",
"value": "False"
},
{
"name": "RdmaEnabled",
"value": "False"
},
{
"name": "MaxNetworkInterfaces",
"value": "2"
}
],
"locationInfo": [
{
"location": "westus",
"zones": [
"1",
"2",
"3"
]
}
],
"name": "Standard_A1",
"tier": "Standard",
"size": "A1",
"family": "standardA0_A7Family"
}
],
"nextLink": null
}