Can I add multiple statements or multiple effects with azure policies? - azure

I need to create an Azure policy for adding tags to resources which are being created without tags (eg name, support, costcenter)
The issue is that if for example I create a VM and I add Name tag, but I forget support and costcenter I want that my policy adds this two and keep my Name value tag.
Can I add some condition to modify effect? Or multiples if/then objects in the definition?
Thanks,

Yes, you can add multiples conditional statements.
More information about Combining Logical operators
{
"properties": {
"displayName": "Audit Azure Spring Cloud instances where distributed tracing is not enabled",
"description": "Distributed tracing tools in Azure Spring Cloud allow debugging and monitoring the complex interconnections between microservices in an application. Distributed tracing tools should be enabled and in a healthy state.",
"mode": "Indexed",
"policyRule": {
"if": {
"allOf": [{
"field": "type",
"equals": "Microsoft.AppPlatform/Spring"
},
{
"anyOf": [{
"field": "Microsoft.AppPlatform/Spring/trace.enabled",
"notEquals": "true"
},
{
"field": "Microsoft.AppPlatform/Spring/trace.state",
"notEquals": "Succeeded"
}
]
}
]
},
"then": {
"effect": "audit"
}
}
}
}

Related

How to use VM imageID's in Azure Policy?

Azure has a number of built-in VM agent related policies. E.g. for installing the dependency agent, log analytics agent or the new Azure Monitoring Agent via a deployifnotexists effect.
Examples are:
Configure Linux machines to run Azure Monitor Agent and associate them to a Data Collection Rule
Configure Windows machines to run Azure Monitor Agent and associate them to a Data Collection Rule
Since we are only using CIS images from the marketplace our VM's are ignored in the policy evaluation.
Both these initatives contain a parameter for additional virtual machine image ID's. It accepts an array of image ID's something like: listOfWindowsImageIdToInclude or listOfLinuxImageIdToInclude.
However when I inspect the properties of my VM (ImageReference) the property ID is always empty:
cis image
windows image
If I query the marketplace it shows something like this:
cis images
I already included those Ids in the intiative parameter but without success.
All these built-in policies evaluate a custom image ID as follows:
"anyOf": [
{
"field": "Microsoft.Compute/imageId",
"in": "[parameters('listOfLinuxImageIdToInclude')]"
},
But like I said the image ID of these marketplace images is empty...
Following this documentation (Apply policies to Windows VMs with Azure Resource Manager and Apply policies to Linux VMs with Azure Resource Manager)
Could this policy be:
{
"if": {
"allOf": [
{
"field": "type",
"in": [
"Microsoft.Compute/virtualMachines",
"Microsoft.Compute/VirtualMachineScaleSets"
]
},
{
"not": {
"allOf": [
{
"field": "Microsoft.Compute/imagePublisher",
"in": [
"center-for-internet-security-inc"
]
},
{
"field": "Microsoft.Compute/imageOffer",
"in": [
"cis-ubuntu-linux-2004-11"
]
},
{
"field": "Microsoft.Compute/imageSku",
"in": [
"cis-ubuntu2004-11"
]
},
{
"field": "Microsoft.Compute/imageVersion",
"in": [
"latest"
]
}
]
}
}
]
},
"then": {
"effect": "deny"
}
}
If it doesn't work, please share your JSON policy
Hope this helps!

Azure Policy - GitHub Actions - Authoring Custom Policies

I'm working on testing out using GitHub and GitHub Actions to do policy as code for Azure. I have been successful in following the tutorials that Microsoft has where you export the policy you want to manage to GitHub from the Azure portal. This works fine and I'm able to edit and run the workflows to update Azure with changes to policies.
What I'd like to know is, can you create NEW policies in GitHub and push them to Azure? It seems that you need to first export a custom policy from Azure into GitHub, then you can manage that policy. I say this because when I create a new policy and a workflow for that policy I get the following error in GitHub from the workflow:
> Did not find any policies to create/update. No policy files match the
> given patterns or no changes were detected.
The policy I have in the folder is called "policy.json"
I also see:
Error occured while reading policy in path :
policies/global_tagging_policy. Error : Error: Path :
policies/global_tagging_policy. Property id is missing from the policy
definition. Please add id to the definition file.
That leads me to believe I need an ID prior to being able to push a policy, that says to me that Azure must have assigned one... I can't just make one up.
This is the policy I'm trying to push - just a tagging policy for testing, I don't have an ID in there, I read that you don't need to add one... that Azure would do it for you. Am I wrong?:
{
"properties": {
"displayName": "test-policy",
"description": "this is a test policy",
"mode": "indexed",
"parameters": {
"tagName": {
"type": "String",
"metadata": {
"displayName": "Tag Name",
"description": "Name of the tag, such as 'environment'"
}
},
"tagValue": {
"type": "String",
"metadata": {
"displayName": "Tag Value",
"description": "Value of the tag, such as 'production'"
}
}
}
},
"policyRule": {
"if": {
"allOf": [
{
"field": "type",
"equals": "Microsoft.Resources/subscriptions/resourceGroups"
},
{
"field": "[concat('tags[', parameters('tagName'), ']')]",
"exists": "false"
}
]
},
"then": {
"effect": "modify",
"details": {
"roleDefinitionIds": [
"/providers/microsoft.authorization/roleDefinitions/b24988ac-6180-42a0-ab88-20f7382dd24c"
],
"operations": [
{
"operation": "add",
"field": "[concat('tags[', parameters('tagName'), ']')]",
"value": "[parameters('tagValue')]"
}
]
}
}
}
}
This tripped me up too so I did some exploring of the APIs and files. I've written about this in greater detail here.
To create a custom Policy, Initiative or Assignment file using GitHub Actions you'll need to generate an id, name & type at the root of the JSON.
The name property needs to be unique at the scope you assign it, I use GUIDs for this but you don't have to. Bear in mind if you define/assign at the Management Group scope then the name needs to be 24 characters or less.
The type denotes the type of file, the options are:
Microsoft.Authorization/policyDefinitions --> Policies
Microsoft.Authorization/policySetDefinitions --> Initiatives
Microsoft.Authorization/policyAssignments --> Assignments
The id is a bit more complex, and is a concatenation of the name and type values with other values mixed in.
The prefix depends on the scope which you want to define your Policy/Initiative/Assignment.
For Management Groups it would be:
/providers/Microsoft.Management/managementGroups/00000000-0000-0000-0000-000000000000
Subscriptions would be:
/subscrptions/00000000-0000-0000-0000-000000000000
Resource Groups:
/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/myResourceGroup
This is followed by: providers in all cases
Next is the type value, so whatever you've used for that use again here.
Finally the last segment of the id is the same value you've used for the name property.
In one line that is
/{scope}/providers/{type}/{name}
So as an example:
Policy Definition scoped at a Management Group
{
"id": "/providers/Microsoft.Management/managementGroups/00000000-0000-0000-0000-000000000000/providers/Microsoft.Authorization/policyDefinitions/5f44e572-5d2d-4edf-9d61",
"name": "5f44e572-5d2d-4edf-9d61",
"type": "Microsoft.Authorization/policyDefinitions",
"properties":{}
}
Policy Definition scoped at a Subscription
{
"id": "/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.Authorization/policyDefinitions/8e4a8c58-1938-4467-8698",
"name": "8e4a8c58-1938-4467-8698",
"type": "Microsoft.Authorization/policyDefinitions",
"properties":{}
}
Initiative scoped at a Management Group
{
"id": "/providers/Microsoft.Management/managementGroups/00000000-0000-0000-0000-000000000000/providers/Microsoft.Authorization/policySetDefinitions/be09f23f-0252-4d8a-a805",
"name": "5f44e572-5d2d-4edf-9d61",
"type": "Microsoft.Authorization/policySetDefinitions",
"properties":{}
}
Initiative scoped at a Subscription
{
"id": "/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.Authorization/policySetDefinitions/8e4a8c58-1938-4467-8698",
"name": "8e4a8c58-1938-4467-8698",
"type": "Microsoft.Authorization/policySetDefinitions",
"properties":{}
}

Azure policy forcing the use of Elastic Pool in the any new database

I'm trying to create a policy that will block releasing a database to a resource group if it doesn't have an Elastic Pool in the settings.
Unfortunately, every attempt to set the conditions ends with blocking database releases, regardless of whether they have this option enabled or not.
I tried to use various fields types as a parameter (starting from the simplest as example):
"if": {
"allOf": [
{
"field": "type",
"notEquals": "Microsoft.Sql/servers/elasticPools"
},
"then": {
"effect": "Deny"
}
but it fails every time. How to correctly formulate the condition in JSON for policy to work? Maybe someone has an example of a ready configuration? Maybe is an example of a ready configuration somewhere?
I am working through a similar problem, and it seems the filter needs to be more explicit to work properly. You can see from the example below, I am filtering on databases AND the non-existence of the ElasticPoolID value...
"if": {
"allOf": [
{
"field": "type",
"equals": "Microsoft.Sql/servers/databases"
},
{
"not": {
"field": "Microsoft.Sql/servers/databases/elasticPoolId",
"exists": "true"
}
}
]
},
"then": {
"effect": "audit"
}
I haven't tried it denying creation yet, but it appears to work auditing existing DBs.
You are missing a closed bracket for the allof. You should be able to do this:
"if": {
"field": "type",
"notEquals": "Microsoft.Sql/servers/elasticPools"
},
"then": {
"effect": "Deny"
}

ExistenceCondition in Azure Policy?

I'm currently trying to understand the Azure policies. I think I've got my head around the aliases, but I'm having trouble understanding where to find the correct values for ExistenceCondition equals field
How does it different from the PolicyRule we applied?
Should i keep ExistanceCondition almost same as PolicyRule?
Policy rule i applied :
"if":{
"allOf":[
{
"field":"type",
"equals":"Microsoft.Insights/metricalerts"
},
{
"field":"Microsoft.Insights/metricalerts/enabled",
"equals":"true"
},
{
"field":"Microsoft.Insights/metricalerts/actions[*]",
"less":"1"
}
]
}
ExistenceCondition is the opposite of policyRule in terms of control direction.
In policy rule you proceed only if the condition is true. in ExistenceCondition you proceed only if the condition is false. In the example below in policyRule you filter only the storageAccount then proceed. The deploy happens only if the condition is false (deleteRetentionPolicy.enabled ==false) so it proceeds and deploy. So once deploy is done, it will be deleteRetentionPolicy.enabled ==true
"policyRule": {
"if": {
"allOf": [
{
"field": "type",
"equals": "Microsoft.Storage/storageAccounts"
},
{
"field": "kind",
"in": [
"Storage",
"StorageV2",
"BlobStorage",
"BlockBlobStorage"
]
}
]
},
"then": {
"effect": "DeployIfNotExists",
"details": {
"type": "Microsoft.Storage/storageAccounts/blobServices",
"existenceCondition": {
"field": "Microsoft.Storage/storageAccounts/blobServices/default.deleteRetentionPolicy.enabled",
"equals": true
},
See this example:
https://learn.microsoft.com/en-us/azure/governance/policy/samples/pattern-effect-details#sample-2-explanation
"details": {
"type": "Microsoft.Compute/virtualMachines/extensions",
"existenceCondition": {
"allOf": [{
"field": "Microsoft.Compute/virtualMachines/extensions/publisher",
"equals": "[parameters('publisher')]"
},
{
"field": "Microsoft.Compute/virtualMachines/extensions/type",
"equals": "[parameters('type')]"
}
]
}
}
The existenceCondition uses policy language elements, such as logical
operators, to determine if a matching related resource exists. In this
example, the values checked against each alias are defined in
parameters.
ExistenceCondition apply only to policy with effect AuditIfNotExists and DeployIfNotExists.
In case of AuditIfNotExists
"If any matching related resource evaluates to true, the effect is
satisfied and doesn't trigger the audit."
In case of DeployIfNotExists
"If any matching related resource evaluates to true, the effect is
satisfied and doesn't trigger the deployment."
Existing resource which does not match ExistenceCondition will be marked as non-complaint. Resources filtered out by PolicyRule will not be marked as non-complaint.

Policy and Initiative to copy Tags to resources in Resource Group

I'm struggling to create a parameterized version of the Azure Policy example which copies Tags applied to a Resource Group to any resources within it. This is the example I'm using as inspiration: https://github.com/Azure/azure-policy/tree/master/samples/ResourceGroup/copy-resourcegroup-tag, which is:
{
"if": {
"field": "tags.example",
"exists": "false"
},
"then": {
"effect": "append",
"details": [
{
"field": "tags.example",
"value": "[resourceGroup().tags.example]"
}
]
}
}
We have a number of tags added to Resource Groups, and for billing purposes I need to ensure these are applied to all resources within. I am looking to create an Initiative which contains the same policy several times, each time using a different parameterized tag name. My parameterized version of the example policy looks like this:
"parameters": {
"tagName": {
"type": "String",
"metadata": {
"displayName": "Tag name",
"description": "The tag to copy to child resources"
}
}
},
"policyRule": {
"if": {
"field": "[concat('tags.', parameters('tagName'))]",
"exists": "false"
},
"then": {
"effect": "append",
"details": [
{
"field": "[concat('tags.', parameters('tagName'))]",
"value": "[concat('resourceGroup().tags.', parameters('tagName'))]"
}
]
}
}
When the policy applies I get a result of non-compliant. Viewing the compliance details shows:
Reason for non-compliance
Current value must exist.
Field
tags.ApplicationName
Current value
--
There is a tag called ApplicationName with a value on the Resource Group. The documentation says the reason for "Current value must exist" is the exists condition. This seems counter-intuitive to the way I am expecting this to work - I know it doesn't exist which is why I want to set the value.
Is there any way to debug these beyond assigning the policy and waiting several hours for a result?
Thanks for your help!
I've figured this out, my syntax was wrong, I need to refer to the Tags using keys rather than as attributes, i.e. tags['ApplicationName'] rather than tags.ApplicationName. The policyRule property needs to be:
"policyRule": {
"if": {
"field": "[concat('tags[', parameters('tagName'), ']')]",
"exists": "false"
},
"then": {
"effect": "append",
"details": [
{
"field": "[concat('tags[', parameters('tagName'), ']')]",
"value": "[resourceGroup().tags[parameters('tagName')]]"
}
]
}
}
I also misunderstood how this feature works, it seems that policies with an Append effect can only append at the point of resource creation, not retrospectively on an existing resource. The above policy adds the Tags for new resources but results in a "non-compliant" report for existing resource.
This behavior is as documented here:
"When a policy definition using the append effect is run as part of an evaluation cycle, it doesn't make changes to resources that already exist. Instead, it marks any resource that meets the if condition as non-compliant."

Resources