When enabling sql server vulnerabilityAssessments feature using arm template, following error is thrown when storage account has a firewall on.
"error": {
"code": "InvalidStorageAccountCredentials",
"message": "The provided storage account shared access signature or account storage key is not valid."
}
}
Template part:
{
"type": "Microsoft.Sql/servers/securityAlertPolicies",
"apiVersion": "2017-03-01-preview",
"name": "[concat(variables('sqls01Name'), '/Default')]",
"dependsOn": [
],
"properties": {
"state": "Enabled",
"emailAddresses": "[variables('emailActionGroupAddresses')]",
"emailAccountAdmins": false
}
},
{
"type": "Microsoft.Sql/servers/vulnerabilityAssessments",
"apiVersion": "2018-06-01-preview",
"location": "westeurope",
"name": "[concat(variables('sqls01Name'), '/Default')]",
"dependsOn": [
"[resourceId('Microsoft.Storage/storageAccounts', variables('defenderSa'))]"
],
"properties": {
"storageContainerPath": "[concat('https://',variables('defenderSa'),'.blob.core.windows.net/vulnerability-assessment/')]",
"storageAccountAccessKey": "[listKeys(resourceId('Microsoft.Storage/storageAccounts', variables('defenderSa')), providers('Microsoft.Storage', 'storageAccounts').apiVersions[0]).keys[0].value]",
"recurringScans": {
"isEnabled": true,
"emailSubscriptionAdmins": false,
"emails": "[variables('emailActionGroupAddresses')]"
}
}
},
{
"name": "[variables('defenderSA')]",
"type": "Microsoft.Storage/storageAccounts",
"apiVersion": "2019-06-01",
"location": "westeurope",
"properties": {
"accessTier": "Cool",
"allowBlobPublicAccess": false,
"supportsHttpsTrafficOnly": true,
"networkAcls": {
"bypass": "AzureServices",
"virtualNetworkRules": [{
"id": "[variables('subnetId')]",
"action": "Allow"
}],
"ipRules": [
],
"defaultAction": "Deny"
}
},
"dependsOn": [
],
"sku": {
"name": "Standard_LRS",
"tier": "Standard"
},
"kind": "StorageV2",
"tags": {
}
}
I notices that when enabling the feature from portal following communicate is displayed:
You have selected a storage that is behind a firewall or in a virtual network. Please be aware that using this storage will create a managed identity for the server and it will be granted 'storage blob data contributor' role on the selected storage.
The assignment is indeed created and the assessment works, however when I try to replicate this in arm template with following code it still fails.
{
"type": "Microsoft.Storage/storageAccounts/providers/roleAssignments",
"name": "[concat(variables('defenderSA'),'/Microsoft.Authorization/',guid(variables('sqls01Name')))]",
"apiVersion": "2018-09-01-preview",
"dependsOn": [
"[resourceId('Microsoft.Storage/storageAccounts',variables('defenderSA'))]"
],
"properties": {
"roleDefinitionId": "[concat('/subscriptions/', subscription().subscriptionId, '/providers/Microsoft.Authorization/roleDefinitions/', 'ba92f5b4-2d11-453d-a403-e96b0029c9fe')]",
"principalId": "[reference(resourceId('Microsoft.Sql/servers',variables('sqls01Name')),providers('Microsoft.Sql', 'servers').apiVersions[0],'Full').identity.principalId]"
}
}
Regarding the issue, please refer to the following template
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"clientIp": {
"type": "string",
"defaultValue": "",
"metadata": {
"description": "allow you client to access Azure storage "
}
},
"virtualNetworksName": {
"defaultValue": "testsql09",
"type": "String"
},
"serverName": {
"type": "string",
"defaultValue": "[uniqueString('sql', resourceGroup().id)]",
"metadata": {
"description": "The name of the SQL logical server."
}
},
"location": {
"type": "string",
"defaultValue": "[resourceGroup().location]",
"metadata": {
"description": "Location for all resources."
}
},
"administratorLogin": {
"type": "string",
"defaultValue": "sqladmin",
"metadata": {
"description": "The administrator username of the SQL logical server."
}
},
"administratorLoginPassword": {
"type": "securestring",
"defaultValue": "Password0123!",
"metadata": {
"description": "The administrator password of the SQL logical server."
}
},
"connectionType": {
"defaultValue": "Default",
"allowedValues": [ "Default", "Redirect", "Proxy" ],
"type": "string",
"metadata": {
"description": "SQL logical server connection type."
}
}
},
"variables": {
"serverResourceGroupName": "[resourceGroup().name]",
"subscriptionId": "[subscription().subscriptionId]",
"uniqueStorage": "[uniqueString(variables('subscriptionId'), variables('serverResourceGroupName'), parameters('location'))]",
"storageName": "[tolower(concat('sqlva', variables('uniqueStorage')))]",
"roleAssignmentName": "[guid(resourceId('Microsoft.Storage/storageAccounts', variables('storageName')), variables('storageBlobContributor'), resourceId('Microsoft.Sql/servers', parameters('serverName')))]",
"StorageBlobContributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ba92f5b4-2d11-453d-a403-e96b0029c9fe')]"
},
"resources": [
{
"type": "Microsoft.Network/virtualNetworks",
"apiVersion": "2020-05-01",
"name": "[parameters('virtualNetworksName')]",
"location": "southeastasia",
"properties": {
"addressSpace": {
"addressPrefixes": [
"10.18.0.0/24"
]
},
"subnets": [
{
"name": "default",
"properties": {
"addressPrefix": "10.18.0.0/24",
"serviceEndpoints": [
{
"service": "Microsoft.Storage"
}
],
"delegations": [],
"privateEndpointNetworkPolicies": "Enabled",
"privateLinkServiceNetworkPolicies": "Enabled"
}
}
],
"virtualNetworkPeerings": [],
"enableDdosProtection": false,
"enableVmProtection": false
}
},
{
"type": "Microsoft.Network/virtualNetworks/subnets",
"apiVersion": "2020-05-01",
"name": "[concat(parameters('virtualNetworksName'), '/default')]",
"dependsOn": [
"[resourceId('Microsoft.Network/virtualNetworks', parameters('virtualNetworksName'))]"
],
"properties": {
"addressPrefix": "10.18.0.0/24",
"serviceEndpoints": [
{
"service": "Microsoft.Storage"
}
],
"delegations": [],
"privateEndpointNetworkPolicies": "Enabled",
"privateLinkServiceNetworkPolicies": "Enabled"
}
},
{
"type": "Microsoft.Sql/servers",
"apiVersion": "2019-06-01-preview",
"name": "[parameters('serverName')]",
"location": "[parameters('location')]",
"identity": {
"type": "SystemAssigned"
},
"properties": {
"administratorLogin": "[parameters('administratorLogin')]",
"administratorLoginPassword": "[parameters('administratorLoginPassword')]",
"version": "12.0"
}
},
{
"type": "Microsoft.Sql/servers/databases",
"apiVersion": "2019-06-01-preview",
"name": "[concat(parameters('serverName'), '/test')]",
"location": "[parameters('location')]",
"dependsOn": [
"[resourceId('Microsoft.Sql/servers', parameters('serverName'))]"
],
"sku": {
"name": "Basic",
"tier": "Basic",
"capacity": 5
},
"kind": "v12.0,user",
"properties": {
"collation": "SQL_Latin1_General_CP1_CI_AS",
"maxSizeBytes": 2147483648,
"catalogCollation": "SQL_Latin1_General_CP1_CI_AS",
"zoneRedundant": false,
"readScale": "Disabled",
"storageAccountType": "LRS"
}
},
{
"type": "Microsoft.Sql/servers/securityAlertPolicies",
"apiVersion": "2020-02-02-preview",
"name": "[concat(parameters('serverName'), '/Default')]",
"dependsOn": [
"[resourceId('Microsoft.Sql/servers', parameters('serverName'))]"
],
"properties": {
"state": "Enabled",
"emailAccountAdmins": false
}
},
{
"type": "Microsoft.Sql/servers/vulnerabilityAssessments",
"apiVersion": "2018-06-01-preview",
"name": "[concat(parameters('serverName'), '/Default')]",
"dependsOn": [
"[resourceId('Microsoft.Sql/servers', parameters('serverName'))]",
"[resourceId('Microsoft.Sql/servers/securityAlertPolicies', parameters('serverName'), 'Default')]",
"[resourceId('Microsoft.Storage/storageAccounts', variables('storageName'))]",
"[extensionResourceId(resourceId('Microsoft.Storage/storageAccounts', variables('storageName')), 'Microsoft.Authorization/roleAssignments', variables('roleAssignmentName'))]"
],
"properties": {
"storageContainerPath": "[concat(reference(resourceId('Microsoft.Storage/storageAccounts', variables('storageName'))).primaryEndpoints.blob, 'vulnerability-assessment')]",
"recurringScans": {
"isEnabled": true,
"emailSubscriptionAdmins": false
}
}
},
{
"type": "Microsoft.Sql/servers/connectionPolicies",
"apiVersion": "2014-04-01",
"name": "[concat(parameters('serverName'), '/Default')]",
"dependsOn": [
"[resourceId('Microsoft.Sql/servers', parameters('serverName'))]"
],
"properties": {
"connectionType": "[parameters('connectionType')]"
}
},
{
"type": "Microsoft.Storage/storageAccounts",
"apiVersion": "2019-06-01",
"name": "[variables('storageName')]",
"location": "[parameters('location')]",
"dependsOn": [
"[resourceId('Microsoft.Network/virtualNetworks/subnets', parameters('virtualNetworksName'), 'default')]"
],
"sku": {
"name": "Standard_LRS"
},
"kind": "StorageV2",
"properties": {
"minimumTlsVersion": "TLS1_2",
"allowBlobPublicAccess": true,
"networkAcls": {
"bypass": "AzureServices",
"virtualNetworkRules": [
{
"id": "[resourceId('Microsoft.Network/virtualNetworks/subnets', parameters('virtualNetworksName'), 'default')]",
"action": "Allow",
"state": "Succeeded"
}
],
"ipRules": [
{
"value": "[parameters('clientIp')]",
"action": "Allow"
}
],
"defaultAction": "Deny"
}
}
},
{
"type": "Microsoft.Storage/storageAccounts/providers/roleAssignments",
"apiVersion": "2020-04-01-preview",
"name": "[concat(variables('storageName'), '/Microsoft.Authorization/', variables('roleAssignmentName'))]",
"dependsOn": [
"[resourceId('Microsoft.Sql/servers', parameters('serverName'))]",
"[resourceId('Microsoft.Storage/storageAccounts', variables('storageName'))]"
],
"properties": {
"roleDefinitionId": "[variables('StorageBlobContributor')]",
"principalId": "[reference(resourceId('Microsoft.Sql/servers', parameters('serverName')), '2020-02-02-preview', 'Full').identity.principalId]",
"scope": "[resourceId('Microsoft.Storage/storageAccounts', variables('storageName'))]",
"principalType": "ServicePrincipal"
}
}
]
}