Posts Azure Policy ideas for Azure Governance
Post
Cancel

Azure Policy ideas for Azure Governance

Rotate Azure VM Passwords with PowerShell Azure Automation and Key Vault - AzureIs.Fun

Azure Policy is a great tool that can help Azure Administrators with enforcing Azure Governance standards and assessment of their environments’ compliance at scale.

Here are 10 Azure Policy ideas that you can use to kick-start with your Azure Governance:

Policy #1: Allow deployment only in specific Azure Region(s)

Limiting resource deployments only to specific Azure Regions is a must-have in any Azure environment. This is usually necessary for geo-compliance requirements, and it will help prevent having resources spread across different Azure Regions by accident.

Here it is how this can be achieved:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
"if": {
    "allOf": [
        {
        "field": "type",
        "equals": "Microsoft.Resources/subscriptions/resourceGroups"
        },
        {
        "field": "location",
        "notIn": "[parameters('listOfAllowedLocations')]"
        }
    ]
},
"then": {
    "effect": "deny"
}

You can find this Built-In Policy for Resource Groups HERE, and my custom policy for Resources HERE.

Policy #2: Prevent creating Resource Groups without a specific set of Tags

This Policy might not be necessary for the environments where you divide your workloads or team on the Subscription or Management Group level, and not by the Resource Groups. Deny Policy like this one might feel intrusive for the users and it can make some automation tasks more complicated.

Still, having Tags like Environment, Description, Owner, SLA … will go a long way with keeping everything organized.

Policy Rule for requiring multiple Tags:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
"if": {
"allOf": [
    {
    "field": "type",
    "equals": "Microsoft.Resources/subscriptions/resourceGroups"
    },
    {
        "not": {
            "field": "[concat('tags[',parameters('Environment'), ']')]",
            "exists": "true"
        }
    },
    {
        "not": {
            "field": "[concat('tags[',parameters('Description'), ']')]",
            "exists": "true"
        }
    }
]
},
"then": {
"effect": "deny"
}

HERE you can find a Policy to require a Tag with specific Name and one of the predefined Values.

HERE is a Policy to require several Tags without checking their Values

Policy #3: Append Resource Locks to Production Resource Groups

There is no un-delete button in Azure. We need to prevent the accidental deletion of resources. The easy way to do that is to automatically append Can’t Delete Locks to all Resource Groups based on the Tag value.

This Policy will use “deployIfNotExists”, and here is how that deployment will look like:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
"then": {
    "effect": "deployIfNotExists",
    "details": {
    "type": "Microsoft.Authorization/locks",
    "existenceCondition": {
        "field": "Microsoft.Authorization/locks/level",
        "equals": "CanNotDelete"
    },
    "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",
        "resources": [
        {
            "type": "Microsoft.Authorization/locks",
            "apiVersion": "2017-04-01",
            "name": "Lock-Delete-ProdRG",
            "properties": {
            "level": "CanNotDelete",
            "notes": "Prevent deletion of the Production Resource Group"
            }
        }
        ]
        }
        }
    }
    }
}
      

In the example above, DoNotDelete resource lock with the name “Lock-Delete-ProdRG” will be deployed to all Resource Groups with Tag Environment and Value Production. You can find that Azure Policy HERE.

Policy #4: Enforce resource naming for Resource Groups

Having each Resource Group named differently can create an unclean-looking environment and cause confusion. Luckily we can [revent different name formats by creating an Azure Policy that will allow only the name format we specify.

Unfortunately, there is no regex support, and we have to specify the name format differently.

Please note that this needs to be well documented so users don’t need to guess what is the name format or to try to get it out from the error message. Check out my article about using Azure Dashboard for Azure Governance to simplify this for your users.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
"if": {
    "allOf": [
    {
    "field": "type",
    "equals": "Microsoft.Resources/subscriptions/resourceGroups"
    },
    {
    "field": "name",
    "notLike": "RG-Prod-*"
    },
    {
    "field": "name",
    "notLike": "RG-Dev-*"
    },
    {
    "field": "name",
    "notLike": "RG-Test-*"
    }
    ]
},
"then": {
    "effect": "deny"
}

You can find this Azure Policy for Resource Group naming HERE.

Policy #5: Enable Azure Backups for Production VMs

Azure Backups can be automated and monitored for worry-free operations, and one of the easiest ways to enforce and audit this configuration is with Azure Policy.

1
2
3
4
{
    "field": "[concat('tags[', parameters('inclusionTagName'), ']')]",
    "in": "[parameters('inclusionTagValue')]"
}

THIS Built-In Policy enables default Azure Backups based on the Tag Value. You can also use it to assign different Backup Policies based on the Tag Value.

Policy #6: Exclude Resource SKUs to prevent overspending

The idea for this Azure Policy is to prevent users from creating large VM sizes, large gateway SKUs, SQL instances, etc. by accident. Creating expensive resources can quickly cause overspending in Azure and by the time we find out it can be too late. After this Policy is applied, users will need to ask for approval before exclusion can be granted.

Here is how that defintion will look like:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
"if": {
    "allOf": [
    {
        "field": "type",
        "equals": "Microsoft.Compute/virtualMachines"
    },
    {
        "field": "Microsoft.Compute/virtualMachines/sku.name",
        "in": "[parameters('listOfNotAllowedSKUs')]"
    }
    ]
},
"then": {
"effect": "Deny"
}

THIS Azure Policy will prevent creating specified VM SKUs. You can easily extend it and add more resource types.

Policy #7: Append Tag containing the time of creation to every resource

This is a valuable piece of information and it can be easily attached to every resource.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
"if": {
    "allOf": [
    {
        "field": "tags['Created-On']",
        "exists": "false"
    }
    ]
},
"then": {
    "effect": "append",
    "details": [
    {
        "field": "tags['Created-On']",
        "value": "[utcNow()]"
    }
    ]
}

THIS Azure Policy will automatically attach creation time to each resource in UTC time format. Please note that this will only work for future resources, and not existing ones.

P.S. You can also append the user who created it, but this requires more than just Policy. More about that in a different post.

Policy #8: Limit Windows VM Resource Name to 15 characters

If the VM Resource Name is longer than 15, Windows will shorten it to 15 characters. That will cause a VM Resource Name in Azure and a machine name inside of Windows to be different. We can prevent that with Azure Policy by limiting VM Resource Name to 15 characters.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
"if": {
    "allOf": [
    {
        "field": "type",
        "equals": "Microsoft.Compute/virtualMachines"
    },
    {
        "value": "[length(field('name'))]",
        "greater": 15
    }
    ]
},
"then": {
    "effect": "deny"
}

HERE is the Azure Policy for that. Please note, this example will limit name length for all VMs. It is not Windows OS specific, but that can be easily added.

Policy #9: Prevent creation of new Virtual Networks

In most cases, you don’t need to/want to create more VNETs after your landing zone is established. However, the main reason for this Azure Policy is to prevent novice users creating new network every time they create a new VM in Azure Portal. Unfortunately default behaviour of the Portal is to offer new Virtual Network, and once VM is created it can’t be easily moved to another network. Therefore preventing creation of new Virtual Networks will make them go back and select existing Virtual Network instead, before they are able to create a VM.

That could be done by simply identifying the resource type:

1
2
3
4
5
6
7
8
9
10
11
"if": {
    "allOf": [
    {
        "field": "type",
        "equals": "Microsoft.Network/virtualNetworks"
    }
    ]
},
"then": {
    "effect": "deny"
}

HERE is the simple Azure Policy to do that.

Policy #10: Audit …

Auditing with Azure Policy is easy, and it gives us an easy-to-understand overview, and we can use it for nearly anything.

Here are a few examples of Auditing Policy to give you an idea what you can use it for:

RBAC: Audit if more than X Owners are configured Subscription

Service-Specific Configuration: Audit if Key Vault Soft Delete is Enabled

Guest OS Configuration: Audit if specific application is installed inside the Linux VMs



If you liked this list of Azure Policies, make sure you follow me on Twitter where i plan to share more ideas in the future.

Thank you for reading. Keep clouding around.

Vukašin Terzić

Updated Mar 13, 2022 2022-03-13T19:31:01+01:00
This post is licensed under CC BY 4.0