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:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"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:
After this Select Definitions -> Select + Policy definition at the top of the page:
Provide the following information:
- Definition Location: The management group or subscription in which the policy definition is saved.
- Name: The name of the policy definition – Restrict Azure locations for resources.
- 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.
- Category: Choose from existing options (such as Location), or create a new category for this policy definition
- 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:
After this, select ‘Assignments’ on the left side of the Azure Policy page:
An assignment is a policy that has been assigned to take place within a specific scope. After this, select Assign Policy:
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:
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 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.
[…] our previous blog post, we discussed how we can write custom Azure Policies in accordance with […]
LikeLike
can you write a policy that allow redis to create only when appropriate service endpoints attached to its subnet
LikeLike