Create and Assign Custom Azure Policies for Azure Governance

In our previous blog post, we discussed on using Azure Policies for Azure Governance and staying compliant with the same. We also discussed how we can use built-in Azure Policies to meet the governance criteria and start easily. However, the relationship between business and IT varies a lot from Organization to Organization. So from time to time, you’ll need to create your own Azure Policies and applying them to a scope. Custom Azure policies allows you to be lot more compliant and a lot more flexible. In this blog post, we are going to discuss the same.

Azure Policy Definition Structure

The schema used by Azure Policy can be found here. One can use JSON to create a policy definition. The important elements that need to be defined in the JSON are: mode, parameters, display name, and policy rules.

For example, let’s consider below sample policy to allow to create resources in specific locations only in the Azure to help being geo-location compliant:


{
"properties": {
"displayName": "Allowed locations",
"policyType": "BuiltIn",
"description": "This policy enables you to restrict the locations your organization can specify when deploying resources. Use to enforce your geo-compliance requirements. Excludes resource groups, Microsoft.AzureActiveDirectory/b2cDirectories, and resources that use the 'global' region.",
"mode": "Indexed",
"parameters": {
"listOfAllowedLocations": {
"type": "Array",
"metadata": {
"description": "The list of locations that can be specified when deploying resources.",
"strongType": "location",
"displayName": "Allowed locations"
}
}
},
"policyRule": {
"if": {
"allOf": [
{
"field": "location",
"notIn": "[parameters('listOfAllowedLocations')]"
},
{
"field": "location",
"notEquals": "global"
},
{
"field": "type",
"notEquals": "Microsoft.AzureActiveDirectory/b2cDirectories"
}
]
},
"then": {
"effect": "Deny"
}
}
},
"id": "/providers/Microsoft.Authorization/policyDefinitions/e56962a6-4747-49cd-b67b-bf8b01975c4c",
"type": "Microsoft.Authorization/policyDefinitions",
"name": "e56962a6-4747-49cd-b67b-bf8b01975c4c"
}

Display name and Description

Display name can be used to uniquely identify an Azure Policy and Description helps to provide the context or describe functionality / goals for the said policy.

Policy Type

Policy type defines the type of policy definition. Possible values are NotSpecified, BuiltIn, and Custom.

Mode

Mode is configured depending on if the policy is targeting an Azure Resource Manager property or a Resource Provider property. When applied for Resource Manager, it determines what type of resources will be evaluated against azure policy. The supported modes are:

all – Evaluate Resource Groups and all resource types
indexed – Evaluate Only Resource types which supports usage of tags and locations.

The preferred value to be used should be all in most of the cases. All policy definitions created through the portal use the all mode. If the policy definition doesn’t include a mode value, it defaults to all in Azure PowerShell and to null in Azure CLI. A null mode is the same as using indexed to support backwards compatibility.

Parameters

Parameters help simplify the policy management by reducing the number of policy definitions. By making use of parameters, you can re-use azure policy and supply different values according to the different scenarios.

In this case, by defining parameter for list of allowed locations, it will allow users to provide location when applying Azure Policy. One can also set defaultValue and allowedValues for the parameter. This helps in removing errors while supplying the value of the parameter.

For example, we can specify that the defaultValue is “eastus” and allowedValues are eastus, eastus2, westus, westus2.

Policy Rules

Policy rules are defined using a set of if and then blocks. In the If block, you define one or more conditions that specify when the policy is enforced. In the Then block, you define the effect that happens when the If conditions are fulfilled.

In above sample, we have specified that if the location of Azure Resource is not matching either of allowed locations or global location or if the resource type is Microsoft.AzureActiveDirectory/b2cDirectories, then deny the creation of that resource.

Assign Azure Policy using Azure Portal

Select All Services in the left pane of the Azure Portal, then search for the Policy and select the Policy from the search results:

search for azure policy and select the same

After this Select Definitions -> Select + Policy definition at the top of the page:

select definition to create new azure policy

Provide the following information:

  1. Definition Location: The management group or subscription in which the policy definition is saved.
  2. Name: The name of the policy definition – Restrict Azure locations for resources.
  3. Description: This policy enables you to restrict the locations your organization can specify when deploying resources. Use to enforce your geo-compliance requirements. Excludes resource groups, Microsoft.AzureActiveDirectory/b2cDirectories, and resources that use the ‘global’ region.
  4. Category: Choose from existing options (such as Location), or create a new category for this policy definition
  5. Policy Rule: Add the following code:
    https://gist.github.com/goyalmohit/0cd4506d8150a5ed7f04759f4d47463f

After this, select Save.

Assign Azure Policy

To assign an Azure Policy, one first need to go to All Services -> Search for ‘Policy’ and then selecting it:

search for azure policy and select the same

After this, select ‘Assignments’ on the left side of the Azure Policy page:

select assignment from left panel

An assignment is a policy that has been assigned to take place within a specific scope. After this, select Assign Policy:

select assign policy from assignment page

On the Assign Policy page, define scope by clicking the ellipsis and selecting either a management group / subscription /resource group. Optionally, select a resource group. We’ll leave this to subscription level in our case.

Once the scope is defined, click on the ellipsis next for the policy definition field and select the Azure Policy, that we create above.

Once the scope is defined, click on the ellipsis next for the policy definition field and select the Azure Policy, that you want to apply. Select the policy that we created earlier and click on Assign:

assign custom azure policy

Create a policy definition with PowerShell

To use below commands, you’ll need to have latest az PowerShell Module installed on your system.

Create Policy definition with PowerShell

We can create policy definition using the New-AzPolicyDefinition cmdlet:

$definition = New-AzPolicyDefinition -Name "allowed-locations" -DisplayName "Allowed locations" -description "This policy enables you to restrict the locations your organization can specify when deploying resources. Use to enforce your geo-compliance requirements. Excludes resource groups, Microsoft.AzureActiveDirectory/b2cDirectories, and resources that use the 'global' region." -Policy 'https://raw.githubusercontent.com/Azure/azure-policy/master/samples/built-in-policy/allowed-locations/azurepolicy.rules.json' -Parameter 'https://raw.githubusercontent.com/Azure/azure-policy/master/samples/built-in-policy/allowed-locations/azurepolicy.parameters.json' -Mode Indexed

Instead of using file hosted on GitHub or any other cloud storage service provider, you can also use a local file. Next, we need to define the scope of the policy by using below command:

$scope = Get-AzSubscription -Name 'Your Subscription'

After this, we need to supply the value of the parameters:

$policyparam = '{ "listOfAllowedLocations": { "value": [ "eastus2", "westus" ] } }'

Now, we can assign the policy using below command:

$assignment = New-AzPolicyAssignment -Name 'allowed-locations-assignment' -DisplayName 'Allowed locations Assignment' -Scope $scope.ResourceId -PolicyDefinition $definition -PolicyParameter $policyparam

View policy definitions with PowerShell

We can view all existing policy definitions using Get-AzPolicyDefinition cmdlet. The output will also include built-in policy definitions. Due to this, output is usually very large and we would often need to filter by using name or id of the policy that we are interested in.

To view a select policy, pass the name of the policy using Name parameter:

Get-AzPolicyDefinition -Name allowed-locations

You should see an output like below:
view azure policy definition using powershell

View Policy assignments using PowerShell

We can view the policy assignments using Get-AzPolicyAssignment cmdlet:

Get-AzPolicyAssignment

Remove Policy assignments and definitions

We can remove the policy assignments and definitions using below commands:

# Remove the Policy Assignment
Remove-AzPolicyAssignment -Id 'Assignment ID'

# Remove the Policy Definition
Remove-AzPolicyDefinition -Id 'Policy definition ID'

Summary and Notes

Using Custom Azure Policies allows you to be implement and be compliant with a lot more of Organizational initiatives. You can select and choose the scope of the policies as well as manage your resources across subscriptions. The logic used for Policy Rules can be very much complex and you can also make use of resource group functions with some exceptions.

For further reading, refer below resources:

Azure Policy definition structure – https://docs.microsoft.com/en-us/azure/governance/policy/concepts/definition-structure
Sample Azure Policies – https://docs.microsoft.com/en-us/azure/governance/policy/samples/
Create policies – https://docs.microsoft.com/en-us/azure/governance/policy/how-to/programmatically-create

If you are viewing this post on mobile, the source code might not be visible due to feature restrictions set by AMP. In such case, open this blog post in desktop based browser.

The source code used in this blog post can be found here at GitHub and is available under blog/8630 and master branches.

2 thoughts on “Create and Assign Custom Azure Policies for Azure Governance

Leave a comment