ARM template error Bad JSON content found in the request - azure

I am trying to deploy an ARM template using the Azure DevOps release pipeline. Azure KeyVault is one of the resources in the template. the deployment is successful when I use the Powershell script. however, when Azure DevOps Release pipeline is used, deployment fails with error "Bad JSON content found in the request"
The key vault resource definition is as below.
{
"type": "Microsoft.KeyVault/vaults",
"apiVersion": "2018-02-14",
"name": "[parameters('keyVaultName')]",
"location": "[parameters('location')]",
"tags": {
"displayName": "KeyVault"
},
"properties": {
"enabledForDeployment": "[parameters('enabledForDeployment')]",
"enabledForTemplateDeployment": "[parameters('enabledForTemplateDeployment')]",
"enabledForDiskEncryption": "[parameters('enabledForDiskEncryption')]",
"tenantId": "[parameters('tenantId')]",
"accessPolicies": [],
"sku": {
"name": "[parameters('skuName')]",
"family": "A"
}
}
}
Update: I suspected that it could be because of tenant id and hardcoded the tenant id to test. But still no luck.

According to the log, you are specifying the override parameters in the task. That's why you are using the ARM template I provided, but still facing the Bad request error. Because in the task logic, the script which in ARM files is the request body of the API. And we use this API to create a resource you specified in azure. For detailed task logic described, you can refer my previous answer.
The parameter definition in the ARM template is correct, but now, the error caused by the override parameters specified:
More specifically, the error is because of the subscription().tenantId in your parameter override definition.
You can try to use Write-Host subscription().tenantId to get its value and print out by using Azure powershell task. You will see that it could not get any thing. One word, this can only used in Json file instead of used in task.
So now, because of no value get from this expression, also you have override the previous value which defined in the JSON file. It will lack the key parameter value(tenantId) in the request body when the task is going to create a azure resource with API.
There has 2 solution can solve it.
1. Do not try to override the parameters which its value is using expression.
Here I just mean the parameter that relevant with Azure subscription. Most of the expression could not be compiled in the Azure ARM deploy task.
2. If you still want to override these special parameters with the special expression in the task.
If this, you must add one task firstly, to get the tenantId from that. Then pass it into the ARM deploy task.
You can add Azure Powershell task by using the following sample script:
Write-Output "Getting tenantId using Get-AzureRmSubscription..."
$subscription = (Get-AzureRmSubscription -SubscriptionId $azureSubscriptionId)
Write-Output "Requested subscription: $azureSubscriptionId"
$subscriptionId = $subscription.Id
$subscriptionName = $subscription.Name
$tenantId = $subscription.tenantId
Write-Output "Subscription Id: $subscriptionId"
Write-Output "Subscription Name: $subscriptionName"
Write-Output "Tenant Id: $tenantId"
Write-Host "##vso[task.setvariable variable=TenantID;]$$tenantId"
Then in the next task, you can use $(TenantID) to get its value.
Here you can refer to this two excellent blog: Blog1 and Blog2
I still recommend you to use the first solution since the volume of the pipeline will increase and complicate if choosing the second solution.

Related

Azure logic app - How can I share integration account across multiple resource groups

I am trying to deploy my logic app to multiple environments using CI/CD pipeline. I am getting an error -The client 'guid' with object id ''guid' ' has permission to perform action 'Microsoft.Logic/workflows/write' on scope 'Test Resource group'; however, it does not have permission to perform action 'Microsoft.Logic/integrationAccounts/join/action' on the linked scope(s) 'Development Resource group integration account' or the linked scope(s) are invalid.
Creating another integration account for test resource group doesnt come under free tier. Is there a way to share integration account across multiple resource groups
Not sure what the permissions issue is but you might need to give more information around this.
But try the below first in your pipeline. Works for us with 3 different resource groups and two integration accounts
"parameters": {
"IntegrationAccountName": {
"type": "string",
"minLength": 1,
"defaultValue": "inter-account-name"
},
"Environment": {
"type": "string",
"minLength": 1,
"defaultValue": "dev"
}
},
"variables": {
"resourceGroupName": "[if(equals(parameters('Environment'), 'prd'),'rg-resources-production','rg-resources-staging')]",
"LogicAppIntegrationAccount": "[concat('/subscriptions/3fxxx4de-xxxx-xxxx-xxxx-88ccxxxfbab4/resourceGroups/',variables('resourceGroupName'),'/providers/Microsoft.Logic/integrationAccounts/',parameters('IntegrationAccount'))]",
},
In the above sample, we had two different integration accounts one for testing and one for production. This is why I have set the integration account name as a parameter as it changes between environments.
I have created a variable "resourceGroupName" this is important because this url is setting up a direct link to the integration account which is stored in a known resource group. In this sample I have included an if statement using the value set at the "environment" parameter. This helps select which resource group is going to be used.
I then create another variable which stores the new URL. Replace the subscription guid with your own: 3fxxx4de-xxxx-xxxx-xxxx-88ccxxxfbab4.
Once that is created you need to change the ARM template to use the variable you just created. To set it,place in the properties object.
"properties": {
"state": "Enabled",
"integrationAccount": {
"id": "[variables('LogicAppIntegrationAccount')]"
},
So for you pipeline it should just be a normal arm template but with these two parameters above being set.
Let me know if you have more questions around this.

How to test within Azure - Azure Resource Manager (ARM Templates)

Assume we have a Checkpoint Firewall Template created on Azure Portal. Is there a way to test the Template within Azure? Also if the Template is modified, is there a way to Test that new modified Template within Azure?
You can test an ARM Template by using it in a deployment. You can also use the what-if setting to produce hypothetical output without actually deploying anything.
Microsoft Azure Docs for What-If
To create a What-If deployment you can proceed a number of ways; Azure CLI, PowerShell, REST, etc. Here is an example using REST (Postman).
Use the endpoint
POST https://management.azure.com/subscriptions/{subscriptionId}/resourcegroups/{resourceGroupName}/providers/Microsoft.Resources/deployments/{deploymentName}/whatIf?api-version=2020-06-01
Provide a body payload:
{
"location": "westus2",
"properties": {
"mode": "Incremental",
"parameters": {},
"template": {}
}
}
Add your template and parameters. Supply a bearer token for authentication and deploy.
You can check the Azure What-If REST API docs here.

Azure Function ARM Deployment with listkeys results in BadRequest Error

I have a simple ARM template that deploys two Azure Functions, an App Service Plan and a Storage Account:
The only "special" thing is, that the function function-key-issue-two adds the default host key from the function function-key-issue-one as an app setting:
"FunctionOneKey": "[listkeys(concat(variables('functionTwoAppId'), '/host/default/'),'2016-08-01').functionKeys.default]",
If I deploy this template to a new resource group, it works the first time. Every subsequent deployment fails with a Bad Request Error on the Resource function-key-issue-one/default:
This is how the operation details looks like:
{
"Code": "BadRequest",
"Message": "Encountered an error (ServiceUnavailable) from host runtime.",
"Target": null,
"Details": [
{
"Message": "Encountered an error (ServiceUnavailable) from host runtime."
},
{
"Code": "BadRequest"
},
{
"ErrorEntity": {
"Code": "BadRequest",
"Message": "Encountered an error (ServiceUnavailable) from host runtime."
}
}
],
"Innererror": null
}
If I remove the FunctionOneKey App Setting, the deployment works. Also If I don't specify the App Setting WEBSITE_RUN_FROM_PACKAGE, the deployment also works.
The function code is deployed later using the AzureFunctionApp#1 Azure DevOps Task as a Zip package (that is why I set WEBSITE_RUN_FROM_PACKAGE to 1).
How to reproduce:
The ARM template I am using is available here.
You can deploy it using. e. g. the New-AzResourceGroupDeployment cmdlet:
New-AzResourceGroupDeployment -ResourceGroupName 'function-key-issue-rg' -TemplateFile "D:\sources\issues\functionDeployment\azuredeploy.json" -name "azuredeploy-$(New-Guid)"
Update 1:
The reason for the ServiceUnavailable error is probably because Kudu adds a web.config with a rewrite rule (because I use WEBSITE_RUN_FROM_PACKAGE but don't have deployed the function):
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.webServer>
<rewrite>
<rules>
<rule name = "Site Unavailable" stopProcessing = "true">
<match url = ".*" />
<action type = "CustomResponse" statusCode = "503" subStatusCode = "0" statusReason = "Site Unavailable" statusDescription = "Could not download zip" />
</rule>
</rules>
</rewrite>
</system.webServer>
</configuration>
My next attempt was to prevent Kudu from doing this by setting
SCM_TOUCH_WEBCONFIG_AFTER_DEPLOYMENT to 0 (See: Don't touch web.config at the end of the deployment). And now it looks like, subsequent deployments sometimes succeed:
But still not a reliable solution :-/.
Update 2:
Same issue with the Azure Function Runtime ~2.
Switching the Azure Function to Linux also doesn't solve the issue.
Update 3:
I opend a GitHub issue regarding this topic.
Any idea what is wrong here? Any workarounds?
I too have had this problem deploying Function Apps and app settings with ARM templates.
After a back-and-forth with Azure support, we realised that the persistence of the app settings causes a restart of the Function App during deployment, which results in a 503 Service Unavailable while it spins back up. This happens while the deployment is still in progress, which then causes intermittent failures of the Microsoft.Web/sites/host. This is also despite the ARM deployment mode being set to incremental, which seems to be ignored completely for function app settings.
The Diagnostics Settings of the Function App will list the hard restarts for you and might give some insight into the app setting that caused it.
A suggestion was made from Azure support to separate the app settings into their own Microsoft.Web/sites/config section in the ARM template, which dependsOn the Function App having finished deployment. I've not tried this yet, and this also goes against what's in the Function App ARM examples, where they are a child config resource of a Microsoft.Web/sites.
I think you can change the way you are establishing communication between your functions, and you will also fix your issue. I would recommend you to use Azure Managed Identity to configure the communication between your functions, instead of using the function keys. Please have a look at this article to get more details of what I am saying.
first of all, i would suggest to use Azure KeyVault as a default storage for your keys, like described here.
But it seems, that this is related also some issues regarding Appservice and Package Deployments.
Take a look here: https://github.com/microsoft/azure-pipelines-tasks/issues/10961 and here: https://github.com/microsoft/azure-pipelines-tasks/issues/11444.
The documentation also says something like this:
https://learn.microsoft.com/de-de/azure/azure-functions/run-functions-from-deployment-package
Hope this is helpfull.
I had, sort of, the same problem in a template, that deployed EventGrid Topic subscribers to a Topic. Precense of the the listkey() function in the json template resulted in the same, very non-descriptive error message.
I've made it work, by updating the ARM template schema to the newest schema supported on Azure: 2019-08-01
Like this:
Top line in the file:
"$schema": "https://schema.management.azure.com/schemas/2019-08-01/deploymentParameters.json#",
and inline, in the listkeys function:
listkeys(concat(resourceId('Microsoft.Web/sites', parameters('functionAppName')), '/host/default'), '2019-08-01').functionKeys.default)
Now, several, subsequent deployments work again, at least for me.
I have had this problem recently and contacted the Azure Functions team, and what I understood from them is this: (I am using ARM Template should be same logic to all with different approaches)
1- using WEBSITE_RUN_FROM_PACKAGE = 1 must be set before deploying the Zip File, meaning adding dependency between the ZipDeploy with deploying AppSettings.
why?
if this flag is not set at first, the function would take the ZipFile and extract it to wwroot folder, leading to empty SitePackage folder and breaking the deployment and function. this flag makes the function upload a zip file to a folder in the function shared file system under data/SitePackage, with also a package.txt that has the name of the related Zip.
this flag aren't supposed to be changed back and forth, because it would break the deployment due to confusing whether it should upload the zip to SitePackages or Extract it to wwroot.
an answer i was given if turning your flag for the first time, it could happen that the first deployment fail, and you need to try again.
2- when using WEBSITE_RUN_FROM_PACAKAGE the function go through a sort of restart, that is written on the docs here you see that after deployment a restart is done.
so the step of "listKeys" could fall on a restart and leading to failure, what you need to do is Add a "wait" step for 1-2 minutes after the function deployed to be sure that everything is done.
Good Luck
I have faced pretty much the same issue. I need to feed the Azure Function which its own host key. After several different test scenarios my conclusion is that there is some delay between the Azure Function App deployment finish and the moment the Host keys are available.
My current workaround is to create previously a key in the KeyVault a use this key in two different places:
To create a new host key in the Azure Function
To feed the Azure Function appsettings
Some sample codes:
Generating Key in the KeyVault from PS
$secureSecret = ConvertTo-SecureString New-Guid.ToString() -AsPlainText -Force
Set-AzureKeyVaultSecret -VaultName $keyVaultName -Name "azure-function-key" -SecretValue $secureSecret
Create the host key and passing it to the function
Note that parameters('internalKey') would be fed from the KeyVault reference
"apiVersion": "2019-08-01",
"type": "Microsoft.Web/sites",
"kind": "functionapp",
"name": "[variables('functionAppName')]",
"location": "[variables('location')]",
"resources": [{
"dependsOn": ["[resourceId(resourceGroup().name, 'Microsoft.Web/sites', variables('functionAppName'))]"],
"type": "Microsoft.Web/sites/host/functionKeys",
"apiVersion": "2018-11-01",
"name": "[concat(variables('functionAppName'), '/default/internalkey')]",
"properties": {
"name": "internalkey",
"value": "[parameters('internalKey')]"
}
},
{
"apiVersion": "2019-08-01",
"name": "appsettings",
"type": "config",
"dependsOn": [
"[resourceId(resourceGroup().name, 'Microsoft.Web/sites', variables('functionAppName'))]"
],
"properties": {
"FUNCTIONS_EXTENSION_VERSION": "~3",
"HostFunctionKey": "[parameters('internalKey')]"
}
}]
Even in you try the listKeys approach with your new host key it won't get the value. First time it will fail and successive times it will get the previous value if it has changed.

Why won't my app service clone properly on Azure

I'm attempting to clone my web app using azure's clone feature. It's found under app services -> Developer tools -> clone app. Every time I run the function it results in a "Deployment Failed" due to conflict.
I've tried changing the clone options: target App name, using new and existing resource groups, new and existing app service plans and with or without application insights.
This is the error message I get every time I try to run this:
{
"id": "/subscriptions/<My subscription>",
"operationId": "<opID>",
"properties": {
"provisioningOperation": "Create",
"provisioningState": "Failed",
"timestamp": "2019-07-22T13:59:57.4502596Z",
"duration": "PT3M32.7637096S",
"trackingId": "<trackID>",
"statusCode": "Conflict",
"statusMessage": {
"status": "Failed",
"error": {
"code": "ResourceDeploymentFailure",
"message": "The resource operation completed with terminal provisioning state 'Failed'.",
"details": [
{
"message": "Provisioning failed with errors: System.FormatException: Input string was not in a correct format.\r\n at System.Text.StringBuilder.FormatError()\r\n at System.Text.StringBuilder.AppendFormatHelper(IFormatProvider provider, String format, ParamsArray args)\r\n at System.String.FormatHelper(IFormatProvider provider, String format, ParamsArray args)\r\n at System.String.Format(String format, Object[] args)\r\n at Microsoft.Web.Hosting.Administration.GeoScale.Sql.WebSiteCloneManager.LogCloneProgress(Operation cloneOperation, SiteClone cloneRequest, CloneStatus cloneStatus, String messageFormat, Object[] args)\r\n at Microsoft.Web.Hosting.Administration.GeoScale.Sql.WebSiteCloneManager.AssociateClonedSiteWithSourceControl(SiteClone cloneRequest, Operation cloneOperation, GeoWebClient destinationStampClient, Site clonedSite)\r\n at Microsoft.Web.Hosting.Administration.GeoScale.Sql.WebSiteCloneManager.RefreshRestoreProgressForClone(IRepositoryContext context, SiteClone clone, Operation cloneOperation)\r\n at Microsoft.Web.Hosting.Administration.GeoScale.Sql.WebSiteCloneManager.<>c__DisplayClass47_0.<ProcessClonesWithProvisioningInProgress>b__0(SiteClone clone)"
}
]
}
},
"targetResource": {
"id": "/subscriptions/<myresource>",
"resourceType": "Microsoft.Web/sites",
"resourceName": "<ResourceName>"
}
}
}
Update: The App was created but the deployment settings weren't transferred over. I'm using Kudu to deploy so that may have been what causes the issue.
From your "update" on the question, if I understand correctly - 'The app was created but the settings weren't transferred over.'
Here are the known restrictions of app cloning currently (As mentioned in the Azure doc below):
Auto scale settings are not cloned
Backup schedule settings are not cloned
VNET settings are not cloned
App Insights are not automatically set up on the destination app
Easy Auth settings are not cloned
Kudu Extension are not cloned
TiP rules are not cloned
Database content is not cloned
Outbound IP Addresses changes if cloning to a different scale unit
Not available for Linux Apps
Reference Azure Doc: https://learn.microsoft.com/azure/app-service/app-service-web-app-cloning#current-restrictions
To clone an existing app including all associated deployment slots, you need to use the IncludeSourceWebAppSlots parameter. The following PowerShell command demonstrates the use of that parameter with the New-AzWebApp command:
$srcappslot = Get-AzWebAppSlot -ResourceGroupName SourceAzureResourceGroup -Name source-app -Slot source-appslot
The following command demonstrates creating a clone of the source app to a new app:
$destapp = New-AzWebApp -ResourceGroupName DestinationAzureResourceGroup -Name dest-app -Location "North Central US" -AppServicePlan DestinationAppServicePlan -SourceWebApp $srcappslot
Additionally on Slots:
When you clone configuration from another deployment slot, the cloned configuration is editable. Some configuration elements follow the content across a swap (not slot specific), whereas other configuration elements stay in the same slot after a swap (slot specific). The following lists show the settings that change when you swap slots.

Serviceprincipal template for Azure Datalake analytics in datafactory

on this page:
https://learn.microsoft.com/en-us/azure/data-factory/v1/data-factory-usql-activity
there is a template for using Azure Datalake analytics in azure datafactory with service principal (instead of authorizing manually for each use).
the template looks like this:
{
"name": "AzureDataLakeAnalyticsLinkedService",
"properties": {
"type": "AzureDataLakeAnalytics",
"typeProperties": {
"accountName": "adftestaccount",
"dataLakeAnalyticsUri": "azuredatalakeanalytics.net",
"servicePrincipalId": "<service principal id>",
"servicePrincipalKey": "<service principal key>",
"tenant": "<tenant info, e.g. microsoft.onmicrosoft.com>",
"subscriptionId": "<optional, subscription id of ADLA>",
"resourceGroupName": "<optional, resource group name of ADLA>"
}
}
}
This template does not work in azure data factory, it insists that for the type
"AzureDataLakeAnalytics", it is not possible to have "serviceprincipalid" and it still requires "authorization" as a property.
my question is:
what is the correct json template for configuring a AzureDataLakeAnalyticsLinkedService with a serviceprincipal ?
Ok, sorry for asking a question that i figured out myself in the end.
While it is true that the azure portal complains about the template it does allow you deploy it. I had of course tried this, but since the azure portal does not show the error message, only an error flag, i did not realize the error was from the service principals lack of permission and not from the template it complained about.
So by adding more permissions to the service principal and deploying the json, disregarding the compiler complaints. It did work. Sorry for bothering.

Resources