Creating SAS token with ARM template: error InvalidValuesForRequestParameters - azure

I am trying to generate a SAS token from an ARM template, to allow my template to subsequently access resources in a blob storage (including linked templates). The SAS token is supposed to be stored in a vault I'm also creating in this template. The storage account exists independently (in another RG)
However, I get the following error:
{
"code": "InvalidValuesForRequestParameters",
"message": "Values for request parameters are invalid: signedPermission,signedExpiry,signedResourceTypes,signedServices."
}
My template had this variable and line to generate the SAS token:
"variables": {
"vaultName": "[concat('hpc',uniqueString(resourceGroup().id, parameters('keyVaultName')))]",
"accountSasProperties": {
"type": "object",
"defaultValue": {
"signedServices": "fb",
"signedPermission": "rwdlacup",
"signedExpiry": "2021-11-30T00:00:00Z",
"signedResourceTypes": "co"
}
}
},
(...)
{
"apiVersion": "2018-02-14",
"type": "Microsoft.KeyVault/vaults/secrets",
"dependsOn": [
"[concat('Microsoft.KeyVault/vaults/', variables('vaultName'))]"
],
"name": "[concat(variables('vaultName'), '/', 'StorageSaSToken')]",
"properties": {
"value": "[listAccountSas(resourceId(parameters('StorageAccountRg'),'Microsoft.Storage/storageAccounts', parameters('storageAccountName')), '2018-07-01', variables('accountSasProperties')).accountSasToken]"
}
}
I tried several variation of the parameters, but could not find what's wrong, and the error is not really helping
I tried (among other things):
removing the 'signed' in front of the parameters (services instead of signedServices)
various combination of services, resource types and permission
various times (shorter, longer...)

When we define variables, we do not need to specify a data type for the variable. For more details, please refer to here.
So please update your template as the following template
"variables": {
"vaultName": "[concat('hpc',uniqueString(resourceGroup().id, parameters('keyVaultName')))]",
"accountSasProperties": {
"signedServices": "fb",
"signedPermission": "rwdlacup",
"signedExpiry": "2021-11-30T00:00:00Z",
"signedResourceTypes": "co"
}
},
(...)
{
"apiVersion": "2018-02-14",
"type": "Microsoft.KeyVault/vaults/secrets",
"dependsOn": [
"[concat('Microsoft.KeyVault/vaults/', variables('vaultName'))]"
],
"name": "[concat(variables('vaultName'), '/', 'sas')]",
"properties": {
"value": "[listAccountSas(resourceId(parameters('StorageAccountRg'),'Microsoft.Storage/storageAccounts', parameters('storageAccountName')), '2018-07-01', variables('accountSasProperties')).accountSasToken]"
}
}

Found the issue with the help of #jim-xu answer, and it's the worst kind of solution: the stupid mistake
I switched "accountSasProperties" from parameters to variables, and in the process, I forgot to remove the "defaultValue", and put the value directly under "accountSasProperties"
the correct syntax for a variable in my case:
"accountSasProperties": {
"signedServices": "fb",
"signedPermission": "rwdlacup",
"signedExpiry": "2021-11-30T00:00:00Z",
"signedResourceTypes": "co"
}
I incidentally also remove object type, as pointed out by #jim-xu in his answer

Related

How to reference Keyvault Secret Tags from ARM template

I have an ARM template which syncs secret value from source Keyvault into Destination one.
I also want to sync secret tags, but ARM reference that I use for 'sourceKV.secret.tags' retrieval does not work
[reference(resourceId('subscriptionId', 'resourceGroup', 'Microsoft.KeyVault/vaults/secrets', 'SourceKV', 'Secret'), '2021-04-01-preview', 'Full').tags.tagName]
any ideas what can be the issue, or what is the correct form to retrieve tags during ARM template deployment?
These work for me:
"outputs": {
"tags": {
"type": "string",
"value": "[reference('/subscriptions/xxxx/resourceGroups/yyyy/providers/Microsoft.KeyVault/vaults/zzzz/secrets/mysecret', '2022-07-01', 'Full').tags]"
},
"tagValue": {
"type": "string",
"value": "[reference('/subscriptions/xxxx/resourceGroups/yyyy/providers/Microsoft.KeyVault/vaults/zzzz/secrets/mysecret', '2022-07-01', 'Full').tags.hello]"
},
"tagValue2": {
"type": "string",
"value": "[reference(resourceId(subscription().subscriptionId, resourceGroup().name, 'Microsoft.KeyVault/vaults/secrets', 'xxxx', 'mysecret'), '2021-04-01-preview', 'Full').tags.hello]"
}
}
Will result in:
"outputs": {
"tagValue": {
"type": "String",
"value": "world"
},
"tagValue2": {
"type": "String",
"value": "world"
},
"tags": {
"type": "Object",
"value": {
"hello": "world"
}
}
}
Also works with the API version you used. It is important that you use 'Full', otherwise you won't get the tags. Note that you can use this syntax anywhere in your template. I just used it in the outputs because it is good for testing.
As I found out it is not possible to use Reference function for setting tags property value for keyvault as valid usages state
reference func only works if it is used inside properties block or for outputs; but as tags are not part of properties instead of returning value reference fun returns just string "reference(resource...)"

How do I specify multiple rows in an Azure Vulnerability Assessment baseline definition in my ARM (JSON) template?

I'm trying to add some Azure Vulnerability Assessment baseline definitions to my ARM templates. I use JSON for my ARM templates. I cannot find any documentation on how to specify certain VA baseline definitions, though, namely ones that need to have multiple rows in the baselines.
Specifically, I'm trying to add a baseline defintiion for VA2109. I can locate the documentation for how to define a baseline VA entry in a general sense, which is here...
https://learn.microsoft.com/en-us/azure/templates/microsoft.sql/servers/databases/vulnerabilityassessments/rules/baselines?tabs=json
And then I can locate the description of VA2109 in here ...
https://learn.microsoft.com/en-us/azure/azure-sql/database/sql-database-vulnerability-assessment-rules#authentication-and-authorization
But neither of those tell me how to include more than one user-role mapping. For example, below is what I currently have, which works and lets me specify that a user should have data writer role. But, I also want to specify that the user should have data reader and ddl admin roles.
{
"type": "Microsoft.Sql/servers/databases/vulnerabilityAssessments/rules/baselines",
"apiVersion": "2021-02-01-preview",
"name": "[concat(variables('sqlServerName'), '/', variables('databaseName'), '/default/VA2109/Default')]",
"dependsOn": [
"[resourceId('Microsoft.Sql/servers/databases', variables('sqlServerName'), variables('databaseName'))]"
],
"properties": {
"baselineResults": [
{
"result": ["wibuser", "db_datawriter"]
}
]
}
}
I was able to find an example of what I want using PowerShell. In PowerShell, you can just provide and array of arrays. The PowerShell example can be found here ...
https://learn.microsoft.com/en-us/powershell/module/sqlserver/new-sqlvulnerabilityassessmentbaseline?view=sqlserver-ps#example-2--create-a-new-security-check-baseline-manually
So I adjusted my ARM to do the same thing, but it throws an error saying invalid ARM template. The adjusted ARM I tried looks like below ...
{
"type": "Microsoft.Sql/servers/databases/vulnerabilityAssessments/rules/baselines",
"apiVersion": "2021-02-01-preview",
"name": "[concat(variables('sqlServerName'), '/', variables('databaseName'), '/default/VA2109/Default')]",
"dependsOn": [
"[resourceId('Microsoft.Sql/servers/databases', variables('sqlServerName'), variables('databaseName'))]"
],
"properties": {
"baselineResults": [
{
"result": [
["wibuser", "db_datawriter"],
["wibuser", "db_datareader"]
]
}
]
}
}
Does anybody know how to specify multiple rows in a VA baseline resource when using ARM JSON? Or perhaps know where to find documentation for all of these VA definitions?
Note that baselineResults is an array of rows.
You will need to add each row as an JSON object to that array.
Also, note that each result row should include all columns so you should also include "Principal Type" and "Authentication Type" rows.
It should look something like that:
{
"type": "Microsoft.Sql/servers/databases/vulnerabilityAssessments/rules/baselines",
"apiVersion": "2021-02-01-preview",
"name": "[concat(variables('sqlServerName'), '/', variables('databaseName'), '/default/VA2109/Default')]",
"dependsOn": [
"[resourceId('Microsoft.Sql/servers/databases', variables('sqlServerName'), variables('databaseName'))]"
],
"properties": {
"baselineResults": [
{
"result": ["wibuser", "db_datawriter", "SQL_USER", "NONE"]
},
{
"result": ["wibuser", "db_datareader", "SQL_USER", "NONE"]
}
]
}
}
I added dummy values for "Principal Type" and "Authentication Type" rows, fill your own

arm template virtualNetworkName creation appendix issue

I am trying to get a arm template running and have hit an issue with the virtualnetwork creation.
azuredeploy.json
"virtualNetworkName": {
"type": "string",
"metadata": {
"description": "Name of virtual network to be created"
},
"defaultValue": "autohav2VNET"
},
vnet-net.json
"resources": [
{
"name": "[parameters('virtualNetworkName')]",
"type": "Microsoft.Network/virtualNetworks",
"location": "[parameters('location')]",
"apiVersion": "2015-06-15",
"properties": {
"addressSpace": {
"addressPrefixes": [
"[parameters('virtualNetworkAddressRange')]"
]
},
"subnets": "[parameters('subnets')]"
}
}
]
The issue I am getting is that the vnet gets created with an appendix such as this: autohav2VNETl5g
So when this gets used to create a loadblancer, the names doe not match the defined parameter and the creation fails.
..../virtualNetworks/AUTOHAV2VNET referenced by resource .... /Microsoft.Network/loadBalancers/sqlLoadBalancer was not found.
Any suggestions?
with the data given it impossible to be sure why this is happening. you are probably passing in a value to the parameter virtualNetworkName. because if you wouldn't, than the vnet name would be: autohav2VNET.
ARM templates do not append anything anywhere just because they are arm templates. they only do what you designed them to do.
to help with debugging: how you are invoking the template and full template + full parameters file.

ARM When using reference() in an copy iterator, arm template parser seems to break

I have written a ARM template that dynamically builds out the app settings based on a JSON object parameter. This allows for adding any app setting without having to modify the template:
parameters.json
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"app_settings": {
"value": {
"keyvalue_pairs": [
{
"name": "appsetting1",
"value": "value"
},
{
"name": "ApplicationInsights:InstrumentationKey",
"value": ""
}
]
}
}
}
}
chopped down working template.json file
"resources": [
{
"comments": "",
"type": "microsoft.insights/components",
"kind": "web",
"name": "[variables('app_service_name')]",
"apiVersion": "2014-04-01",
"location": "[resourceGroup().location]",
"tags": {
"[variables('hiddenlink_app_service')]": "Resource"
},
"scale": null,
"properties": {
"ApplicationId": "[variables('app_service_name')]"
}
},
{
"apiVersion": "2015-08-01",
"name": "[concat(variables('app_service_name'),'/stage-slot')]",
"type": "Microsoft.Web/sites/slots",
"tags": {
"displayName": "stage-slot"
},
"location": "[resourceGroup().location]",
"dependsOn": [
"[resourceId('Microsoft.Web/Sites', variables('app_service_name'))]"
],
"properties": {
"clientAffinityEnabled": false,
"siteConfig": {
"copy": [
{
"name": "appSettings",
"count": "[length(parameters('app_settings').keyvalue_pairs)]",
"input": {
"name": "[parameters('app_settings').keyvalue_pairs[copyIndex('appSettings')].name]",
"value": "[parameters('app_settings').keyvalue_pairs[copyIndex('appSettings')].value]"
}
}
]
}
}
}
I now try and conditionally reference the app insights instrumentation key on my app settings hoping to override the app insights instrumentationkey from the resource.
"siteConfig": {
"copy": [
{
"name": "appSettings",
"count": "[length(parameters('app_settings').keyvalue_pairs)]",
"input": {
"name": "[parameters('app_settings').keyvalue_pairs[copyIndex('appSettings')].name]",
"value": "[if(equals(parameters('app_settings').keyvalue_pairs[copyIndex('appSettings')].name,'ApplicationInsights:InstrumentationKey'),reference(variables('appInsightsResource')).InstrumentationKey,parameters('app_settings').keyvalue_pairs[copyIndex('appSettings')].value)]"
}
}
]
}
This started throwing errors saying the if statement needs a boolean first parameter, but I didnt see anything wrong with it so I tried the following snippet and it worked so it leads me to believe that the use of the "reference()" inside a conditional isnt valid:
"siteConfig": {
"copy": [
{
"name": "appSettings",
"count": "[length(parameters('app_settings').keyvalue_pairs)]",
"input": {
"name": "[parameters('app_settings').keyvalue_pairs[copyIndex('appSettings')].name]",
"value": "[if(equals(parameters('app_settings').keyvalue_pairs[copyIndex('appSettings')].name,'ApplicationInsights:InstrumentationKey'),'testvalue',parameters('app_settings').keyvalue_pairs[copyIndex('appSettings')].value)]"
}
}
]
}
Additionally if I remove the whole "if()" and explicitly put "reference(variables('appInsightsResource')).InstrumentationKey" into the value, it outputs the right value so I know that this reference() call works but seems to break down when added inside an "if()" conditional statement.
The question is, is there any way to get this to work? I am trying to dynamically set the Instrumentation key while keeping in tact the ability to pass in a JSON object for my app settings
I'm seeing extremely confusing results with copy properties construct in general. most of the times is blows up with absolutely cryptic errors.
You won’t be able to use the reference() function in the count property – the copy loop is expanded at compile time – reference is evaluated at run-time. also, today I cant reproduce my working example, but i had a working example of reference function working in a copy properties, without if() though. You might want to create a bare minimum example showing how this doesnt work (so only 1 resource ideally). If that doesnt work you might want to raise an issue on github and\or azure feedback
You might be able to work around this by using nested deployments. but generally using properties copy in a clever way is a bit of a pain, due to compile\runtime issues.

How do I use Azure Key Vault secret in linked template

I'm trying to create automation variable off KeyVault secret. I assume I can probably do the same thing what is currently done in main template for retrieving windows password but it fails with non-descriptive error below. Not sure what shall be done next to troubleshoot.
Error
{
"code": "BadRequest",
"message": "{\"Message\":\"The request is invalid.\",\"ModelState\":{\"variable.properties.value\":[\"An error has occurred.\"]}}"
}
Template
{
"name": "mystring",
"type": "variables",
"apiVersion": "2015-10-31",
"dependsOn": [
"[concat('Microsoft.Automation/automationAccounts/', parameters('AutomationAccountName'))]"
],
"properties": {
"value": {
"reference": {
"keyVault": {
"id": "[resourceId(subscription().subscriptionId, 'Utility-RG', 'Microsoft.KeyVault/vaults', 'MyKeyVault')]"
},
"secretName": "WindowsPasswordSecret"
}
},
"description": "test var",
"isEncrypted": false
}
}
That error is indeed helpful, while I have no idea what went wrong there, I can tell you how to work around that, you need to pass the data from the KV to the template (as input parameter) not to the resource. And in the template use parameter to assign value to the object in question.
Reference: https://github.com/4c74356b41/bbbb-is-the-word/blob/master/_arm/parent.json#L151

Resources