I am working on DeployIfNotExist Azure Policy which checks all vnets, checks if specific peering exists and if so checks UDR settings in place. If different than specified, it aims to deploy required UDR.
I am not able to get this to work and the current state is that initial check works fine (non-compliant vnets are reported) but no automatic remediation is done for new/updated vnets. Further, if I do manual remediation, the vnet is still marked as non-compliant.
Azure Policy Policy Rule below.
{
"if": {
"anyOf": [
{
"allOf": [
{
"field": "type",
"equals": "Microsoft.Network/virtualNetworks"
},
{
"field": "Microsoft.Network/virtualNetworks/VirtualNetworkPeerings[*].peeringState",
"equals": "Connected"
},
{
"field": "Microsoft.Network/virtualNetworks/VirtualNetworkPeerings[*].name",
"equals": "peerSpokeToHub"
}
]
},
{
"allOf": [
{
"field": "type",
"equals": "Microsoft.Network/virtualNetworks/VirtualNetworkPeerings"
},
{
"field": "Microsoft.Network/virtualNetworks/virtualNetworkPeerings/remoteVirtualNetwork.id",
"exists": "true"
}
]
}
]
},
"then": {
"effect": "deployIfNotExists",
"details": {
"type": "Microsoft.Network/virtualNetworks/subnets",
"existenceCondition": {
"allOf": [
{
"field": "Microsoft.Network/virtualNetworks/subnets/routeTable.id",
"exists": "true"
},
{
"field": "Microsoft.Network/virtualNetworks/subnets/routeTable.routes[*].name",
"equals": "toNVA"
},
{
"field": "Microsoft.Network/virtualNetworks/subnets/routeTable.routes[*].addressPrefix",
"equals": "0.0.0.0/0"
},
{
"field": "Microsoft.Network/virtualNetworks/subnets/routeTable.routes[*].nextHopType",
"equals": "VirtualAppliance"
},
{
"field": "Microsoft.Network/virtualNetworks/subnets/routeTable.routes[*].nextHopIpAddress",
"in": ["10.0.0.1", "10.0.0.2"]
},
{
"field": "Microsoft.Network/virtualNetworks/subnets/routeTable.routes[*].provisioningState",
"equals": "Succeeded"
}
]
},
"roleDefinitionIds": [
"/providers/Microsoft.Authorization/roleDefinitions/b24988ac-6180-42a0-ab88-20f7382dd24c"
],
"deployment": {
"properties": {
"mode": "incremental",
"template": {
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"vNetName": {
"type": "string",
"metadata": {
"description": "subnet to attach udr"
}
},
"RouteTableName": {
"type": "string",
"metadata": {
"description": "Name of a route table upon remediation"
}
},
"location": {
"type": "string",
"metadata": {
"description": "location of resource"
}
},
"NVAip": {
"type": "string",
"metadata": {
"description": "NVA IP"
}
}
},
"resources": [
{
"name": "[parameters('RouteTableName')]",
"type": "Microsoft.Network/routeTables",
"apiVersion": "2018-11-01",
"location": "[parameters('location')]",
"properties": {
"routes": [
{
"properties": {
"addressPrefix": "0.0.0.0/0",
"nextHopType": "VirtualAppliance",
"nextHopIpAddress": "[parameters('NVAip')]"
},
"name": "toNVA"
}
]
}
},
{
"apiVersion": "2017-08-01",
"name": "apply-routetable-to-subnet",
"type": "Microsoft.Resources/deployments",
"resourceGroup": "[resourceGroup().name]",
"dependsOn": [
"[concat('Microsoft.Network/routeTables/', 'RouteTable')]"
],
"properties": {
"mode": "Incremental",
"template": {
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"resources": [
{
"apiVersion": "2018-08-01",
"type": "Microsoft.Network/virtualNetworks/subnets",
"name": "[concat(parameters('vNetName'),'/default')]",
"location": "[resourceGroup().location]",
"properties": {
"addressPrefix": "[reference(resourceId(resourceGroup().name, 'Microsoft.Network/virtualNetworks/subnets', parameters('vNetName'), 'default'), '2018-03-01').addressPrefix]",
"routeTable": {
"id": "[resourceId('Microsoft.Network/routeTables', parameters('RouteTableName'))]"
},
"networkSecurityGroup": {
"id": "[reference(resourceId(resourceGroup().name, 'Microsoft.Network/virtualNetworks/subnets', parameters('vNetName'), 'default'), '2018-03-01').networkSecurityGroup.id]"
}
}
}
]
}
}
}
]
},
"parameters": {
"vNetName": {
"value": "[field('fullName')]"
},
"RouteTableName": {
"value": "[parameters('RouteTableName')]"
},
"NVAip": {
"value": "[parameters('fortigateIp')]"
},
"location": {
"value": "[field('location')]"
}
}
}
}
}
}
}
This seems like a problem with your ARM template. I would be sure to test it and check it. The ARM VSCode extension now has a what-if testing capability that lets you see what happens when you are to deploy that template.
Related
I am using this code below to attempt to lock just the VM's in a subscription, but the effect is to place a lock on the Resource Groups. How can I make this apply only to vm's only and not the RG?
{
"properties": {
"displayName": "All Azure Vm's should be Delete Locked",
"mode": "Indexed",
"description": "This policy will add an CanNotDelete Resource Lock.",
"metadata": {
"version": "1.1.0",
"category": "Compute"
},
"parameters": {
"effect" : {
"type" : "String",
"metadata" : {
"displayName" : "Effect",
"description" : "Enable a Delete Lock"
},
"allowedValues" : [
"CanNotDelete",
"ReadOnly",
"NotSpecified"
],
"defaultValue": "CanNotDelete"
}
},
"policyRule": {
"if": {
"allOf": [
{
"field": "type",
"equals": "Microsoft.Compute/virtualMachines"
}
]
},
"then": {
"effect": "auditIfNotExists",
"details": {
"type": "Microsoft.Authorization/locks",
"existenceCondition": {
"field": "Microsoft.Authorization/locks/level",
"equals": "CanNotDelete"
}
}
}
}
}
}
Created a policy to place locks on Virtual machines in Azure. Locks are placed on the Resource Group, which does lock the vm, but I only want the lock on the vm and not the resource group.
You are missing the deployment part of deployment template.
https://learn.microsoft.com/en-us/azure/governance/policy/samples/pattern-deploy-resources#deployment-template
You can only assign the resource lock on a single resource, if you do not want to assign it on the resource group:
https://learn.microsoft.com/en-us/azure/azure-resource-manager/templates/scope-extension-resources?tabs=azure-cli#apply-to-resource
For a single resource resource lock, then you need to use and define a scope:
https://learn.microsoft.com/en-us/azure/azure-resource-manager/management/lock-resources?tabs=json#template
Under the "resources": [ you can do multiple deployments, see code #2:
#1
{
"properties": {
"displayName": "All Azure Vm's should be Delete Locked",
"description": "This policy will add an CanNotDelete Resource Lock.",
"mode": "all",
"metadata": {
"version": "1.1.0",
"category": "Compute"
},
"parameters": {
"effect": {
"type": "String",
"metadata": {
"displayName": "Effect",
"description": "Enable a Delete Lock"
},
"allowedValues": [
"CanNotDelete",
"ReadOnly",
"NotSpecified"
],
"defaultValue": "CanNotDelete"
}
},
"policyRule": {
"if": {
"field": "type",
"equals": "Microsoft.Compute/virtualMachines"
},
"then": {
"effect": "DeployIfNotExists",
"details": {
"type": "Microsoft.Authorization/locks",
"existenceCondition": {
"field": "Microsoft.Authorization/locks/level",
"equals": "[parameters('effect')]"
},
"roleDefinitionIds": [
"/providers/Microsoft.Authorization/roleDefinitions/8e3af657-a8ff-443c-a75c-2fe8c4bcb635"
],
"deployment": {
"properties": {
"mode": "incremental",
"template": {
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json",
"contentVersion": "1.0.0.0",
"parameters": {},
"variables": {
"vmName": "vm-niclas01"
},
"resources": [
{
"type": "Microsoft.Authorization/locks",
"apiVersion": "2020-05-01",
"name": "DenyDelete",
"scope": "[concat('Microsoft.Compute/virtualMachines/', variables('vmName'))]",
"properties": {
"level": "CanNotDelete",
"notes": "Prevents deletion of resource."
}
}
]
}
}
}
}
}
}
}
}
#2 - Deploy lock on multiple VMs, not on RG:
{
"properties": {
"displayName": "Test 2 - All Azure Vm's should be Delete Locked",
"policyType": "Custom",
"mode": "All",
"metadata": {
"version": "1.1.0"
},
"parameters": {
"effect": {
"type": "String",
"metadata": {
"displayName": "Effect",
"description": "Enable a Delete Lock"
},
"allowedValues": [
"CanNotDelete",
"ReadOnly",
"NotSpecified"
],
"defaultValue": "CanNotDelete"
},
"vmName": {
"type": "Array",
"metadata": {
"displayName": "VM Names",
"description": "The list of VM names that should have resource locks"
},
"allowedValues": [
"vm-niclas01",
"vm-niclas02",
"vm-linuxniclas"
]
}
},
"policyRule": {
"if": {
"allOf": [
{
"field": "name",
"in": "[parameters('vmName')]"
},
{
"field": "type",
"equals": "Microsoft.Compute/virtualMachines"
}
]
},
"then": {
"effect": "DeployIfNotExists",
"details": {
"type": "Microsoft.Authorization/locks",
"existenceCondition": {
"field": "Microsoft.Authorization/locks/level",
"equals": "[parameters('effect')]"
},
"roleDefinitionIds": [
"/providers/Microsoft.Authorization/roleDefinitions/8e3af657-a8ff-443c-a75c-2fe8c4bcb635"
],
"deployment": {
"properties": {
"mode": "incremental",
"template": {
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json",
"contentVersion": "1.0.0.0",
"parameters": {
"vmName": {
"type": "Array"
}
},
"variables": {
"vmName1": "[concat('/', parameters('vmName')[0])]",
"vmName2": "[concat('/', parameters('vmName')[1])]"
},
"resources": [
{
"type": "Microsoft.Authorization/locks",
"apiVersion": "2020-05-01",
"name": "DenyDelete",
"scope": "[concat('Microsoft.Compute/virtualMachines', variables('vmName1'))]",
"properties": {
"level": "CanNotDelete",
"notes": "Prevents deletion of resource."
}
},
{
"type": "Microsoft.Authorization/locks",
"apiVersion": "2020-05-01",
"name": "DenyDelete",
"scope": "[concat('Microsoft.Compute/virtualMachines/', variables('vmName2'))]",
"properties": {
"level": "CanNotDelete",
"notes": "Prevents deletion of resource."
}
}
],
"outputs": {}
},
"parameters": {
"vmName": {
"value": "[parameters('vmName')]"
}
}
}
}
}
}
}
}
}
3 VMs in the same RG:
Policy assignment with parameter:
Resource Lock deployed:
Resource Lock not deployed, because it is not part of policy parameter:
After looking through the policies I want to merge the policies :
Storage accounts should restrict network access using virtual network rules Storage accounts
should allow access from trusted Microsoft services
[Preview]: Storage account public access should be disallowed
But all the three have different effects and are either audit or deny . What I want is to check the storage accounts and for the three rules and then activate those automatically for new resources .
Any Ideas on how to achieve this ? I am using terraform to deploy the policy definitions and remediations .
You can create the below policy which validates the network rules and deny public access for blob is present or not and then deploys it for the new resources :
{
"mode": "All",
"policyRule": {
"if": {
"allOf": [
{
"field": "type",
"equals": "Microsoft.Storage/storageAccounts"
},
{
"anyOf": [
{
"field": "Microsoft.Storage/storageAccounts/networkAcls.defaultAction",
"notEquals": "Deny"
},
{
"count": {
"field": "Microsoft.Storage/storageAccounts/networkAcls.ipRules[*]"
},
"greaterOrEquals": 1
}
]
},
{
"not": {
"field": "Microsoft.Storage/storageAccounts/allowBlobPublicAccess",
"equals": "false"
}
}
]
},
"then": {
"effect": "deployIfNotExists",
"details": {
"type": "Microsoft.Storage/storageAccounts",
"name": "[field('name')]",
"existenceCondition": {
"field": "Microsoft.Storage/storageAccounts/networkAcls.defaultAction",
"equals": "Deny"
},
"roleDefinitionIds": [
"/providers/Microsoft.Authorization/roleDefinitions/17d1049b-9a84-46fb-8f53-869881c3d3ab"
],
"deployment": {
"properties": {
"mode": "incremental",
"template": {
"$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"name": {
"type": "string"
},
"sku": {
"type": "string"
},
"location": {
"type": "string"
},
"kind": {
"type": "string"
},
"virtualnetworklist": {
"type": "string",
"metadata": {
"description": "The list of locations that can be specified when deploying resources"
},
"defaultValue": "test"
}
},
"resources": [
{
"name": "[parameters('name')]",
"type": "Microsoft.Storage/storageAccounts",
"apiVersion": "2019-06-01",
"location": "[parameters('location')]",
"properties": {
"allowBlobPublicAccess": false,
"networkAcls": {
"bypass": "AzureServices",
"defaultAction": "Deny"
}
},
"dependsOn": [],
"sku": {
"name": "[parameters('sku')]"
},
"kind": "[parameters('kind')]"
}
]
},
"parameters": {
"name": {
"value": "[field('name')]"
},
"sku": {
"value": "[field('Microsoft.Storage/storageAccounts/sku.name')]"
},
"location": {
"value": "[field('location')]"
},
"kind": {
"value": "[field('kind')]"
}
}
}
}
}
}
},
"parameters": {}
}
Output:
I am new to azure policy and i am trying to write a deployifnotexists policy for storage account which will enable point-in-time restore for containers with 300days. It does error while deploying, error saying HttpResourceNotFound and random http request url. I would like to know whether the policy is correct or not and Here is the code i created which i am using:
{
"properties": {
"displayName": "storage-pointintime",
"policyType": "Custom",
"mode": "All",
"metadata": {
},
"parameters": {
"effect": {
"type": "String",
"metadata": {
"displayName": "Effect",
"description": "Enable or disable the execution of the policy."
},
"allowedValues": [
"DeployIfNotExists",
"Deny",
"Audit"
],
"defaultValue": "DeployIfNotExists"
},
"retentionInDays": {
"type": "String",
"metadata": {
"displayName": "Retention Days",
"description": "Set the number of Retention Days."
},
"defaultValue": "300"
}
},
"policyRule": {
"if": {
"allOf": [
{
"field": "type",
"equals": "Microsoft.Storage/storageAccounts"
}
]
},
"then": {
"effect": "[parameters('effect')]",
"details": {
"type": "Microsoft.Storage/storageAccounts/blobServices/restorePolicy",
"roleDefinitionIds": [
"/providers/Microsoft.Authorization/roleDefinitions/<id>"
],
"existenceCondition": {
"field": "Microsoft.Storage/storageAccounts/blobServices/restorePolicy.days",
"equals": "[parameters('retentionInDays')]"
},
"deployment": {
"properties": {
"mode": "incremental",
"template": {
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"storageAccounts": {
"type": "string"
},
"retentionDays": {
"type": "string"
}
},
"resources": [
{
"name": "[concat(parameters('storageAccounts'),'/default')]",
"type": "Microsoft.Storage/storageAccounts/blobServices/restorePolicy",
"apiVersion": "2021-04-01",
"properties": {
"retentionInDays": "[parameters('retentionDays')]"
}
}
]
},
"retentionDays": {
"value": "[parameters('retentionInDays')]"
}
}
}
}
}
}
}
}
If you want to enable point-in-time restore for containers, the type should be Microsoft.Storage/storageAccounts/blobServices. Azure ARM template does not provide type Microsoft.Storage/storageAccounts/blobServices/restorePolicy.
For example
{
"name": "[concat(parameters('storageAccountName'), '/default')]",
"type": "Microsoft.Storage/storageAccounts/blobServices",
"apiVersion": "2019-06-01",
"properties": {
"restorePolicy": {
"enabled": "[parameters('isContainerRestoreEnabled')]",
"days": "[parameters('containerRestorePeriodDays')]"
},
"deleteRetentionPolicy": {
"enabled": "[parameters('isBlobSoftDeleteEnabled')]",
"days": "[parameters('blobSoftDeleteRetentionDays')]"
},
"containerDeleteRetentionPolicy": {
"enabled": "[parameters('isContainerSoftDeleteEnabled')]"
},
"changeFeed": {
"enabled": "[parameters('changeFeed')]"
},
"isVersioningEnabled": "[parameters('isVersioningEnabled')]"
},
"dependsOn": [
"[concat('Microsoft.Storage/storageAccounts/', parameters('storageAccountName'))]"
]
}
For more details, please refer to here and here.
I am trying to create an automated process that adds the Azure Active Directory on a SQL Server to an Azure group once the SQL server deploys. The group I want to add too is a security group. I am thinking about using Azure policy to implement this. What would the policy rule look like? If there is a better Azure service/feature to implement my task what is it?
Here is sample policy definition that has worked for me which evaluates and provides the complaint and non-complaint resources on the existing resources. Also kindly note, during an evaluation cycle, policy definitions with a "DeployIfNotExists" effect that match resources are marked as non-compliant, but no action is taken on that resource. Existing non-compliant resources can be remediated with a remediation task.
{
"mode": "All",
"policyRule": {
"if": {
"allOf": [
{
"field": "type",
"equals": "Microsoft.Sql/servers"
}
]
},
"then": {
"effect": "deployIfNotExists",
"details": {
"type": "Microsoft.Sql/servers/administrators",
"existenceCondition": {
"allOf": [
{
"field": "Microsoft.Sql/servers/administrators/administratorType",
"equals": "ActiveDirectory"
},
{
"field": "Microsoft.Sql/servers/administrators/login",
"equals": "xxxx#xxxxxx.com"
},
{
"field": "Microsoft.Sql/servers/administrators/sid",
"equals": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxxx"
},
{
"field": "Microsoft.Sql/servers/administrators/tenantId",
"equals": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxxx"
}
]
},
"deployment": {
"properties": {
"mode": "incremental",
"template": {
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"location": {
"type": "string"
},
"sqlServerName": {
"type": "string"
}
},
"variables": {},
"resources": [
{
"name": "[parameters('sqlServerName')]",
"type": "Microsoft.Sql/servers",
"apiVersion": "2019-06-01-preview",
"location": "[parameters('location')]",
"resources": [
{
"type": "Microsoft.Sql/servers/administrators",
"apiVersion": "2019-06-01-preview",
"name": "[concat(parameters('sqlServerName'), '/ActiveDirectory')]",
"dependsOn": [
"[resourceId('Microsoft.Sql/servers', parameters('sqlServerName'))]"
],
"properties": {
"administratorType": "ActiveDirectory",
"login": "xxxx#xxxxxx.com",
"sid": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxxx",
"tenantId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxxx"
}
}
]
}
]
},
"parameters": {
"sqlServerName": {
"value": "[field('Name')]"
},
"location": {
"value": "[field('Location')]"
}
}
}
},
"roleDefinitionIds": [
"/providers/Microsoft.Authorization/roleDefinitions/b24988ac-6180-42a0-ab88-20f7382dd24c",
"/providers/Microsoft.Authorization/roleDefinitions/8e3af657-a8ff-443c-a75c-2fe8c4bcb635"
]
}
}
},
"parameters": {}
}
I am trying to develop an Azure Policy (json) ensuring that for a given SQL Server with Auditing enabled (no need to check that), retention days period has been set to a value greater than X (let's say 90 days in my case).
I tried to use deployIfNotExists effect, with an existenceCondition on retentionDays field (greater than 90). In the deployment part, I set the field to 365.
I assigned the policy to a resource group in which I have a SQL Server with Auditing and retention days equal to 20.
But still, the policy appears as 'Compliant' and retentionDays remains the same. Here is the code :
"if": {
"field": "type",
"equals": "Microsoft.Sql/servers"
},
"then": {
"effect": "deployIfNotExists",
"details": {
"type": "Microsoft.Sql/servers/auditingSettings",
"roleDefinitionIds": [
"/providers/Microsoft.Authorization/roleDefinitions/XXXXXXXX"
],
"existenceCondition": {
"field": "Microsoft.Sql/servers/auditingSettings/retentionDays",
"greater": "90"
},
"deployment": {
"properties": {
"mode": "incremental",
"template": {
"$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"resourceName": {
"type": "string"
},
"location": {
"type": "string"
},
"retentionDays": {
"type": "string"
}
},
"variables": {},
"resources": [{
"type": "Microsoft.Sql/servers/auditingSettings",
"apiVersion": "2017-03-01-preview",
"name": "[concat(parameters('resourceName'), '/Default')]",
"location": "[parameters('location')]",
"dependsOn": [],
"properties": {
"retentionDays": "[parameters('retentionDays')]"
}
}],
"outputs": {}
},
"parameters": {
"location": {
"value": "[field('location')]"
},
"resourceName": {
"value": "[field('name')]"
},
"retentionDays": {
"value": "365"
}
}
}
}
}
}
I am wondering if I am using the right alias at the right place. Any clue ?
Thanks!
Here's my code that works!!!!
{
"properties": {
"displayName": "deploy-sql-db-backupshorttermretentionpolicies",
"policyType": "Custom",
"mode": "All",
"description": "Deploy If Not Exists backupshorttermretentionpolicies",
"parameters": {
"effect": {
"type": "String",
"metadata": {
"displayName": "Effect",
"description": "Enable or disable the execution of the policy."
},
"allowedValues": [
"DeployIfNotExists",
"Disabled"
],
"defaultValue": "DeployIfNotExists"
},
"retentionDays": {
"type": "String",
"metadata": {
"displayName": "Retention Days",
"description": "Set the number of Backup Retention Days."
},
"defaultValue": "35"
}
},
"policyRule": {
"if": {
"field": "type",
"equals": "Microsoft.Sql/servers/databases"
},
"then": {
"effect": "[parameters('effect')]",
"details": {
"type": "Microsoft.Sql/servers/databases/backupShortTermRetentionPolicies",
"name": "default",
"roleDefinitionIds": [
"/providers/microsoft.authorization/roleDefinitions/####
],
"existenceCondition": {
"field": "Microsoft.Sql/servers/databases/backupShortTermRetentionPolicies/retentionDays",
"equals": "[parameters('retentionDays')]"
},
"deployment": {
"properties": {
"mode": "incremental",
"template": {
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"serverName": {
"type": "string"
},
"shortTermRetention": {
"type": "string"
}
},
"resources": [
{
"name": "[concat(parameters('serverName'),'/default')]",
"type": "Microsoft.Sql/servers/databases/backupShortTermRetentionPolicies",
"apiVersion": "2017-10-01-preview",
"properties": {
"retentionDays": "[parameters('shortTermRetention')]"
}
}
]
},
"parameters": {
"serverName": {
"value": "[field('fullname')]"
},
"shortTermRetention": {
"value": "[parameters('retentionDays')]"
}
}
}
}
}
}
}
}
}