Speaking at Azure Global Bootcamp in Cluj
[/content/images/wordpress/2017/04/2017bootcamp.png] For the 5th year in a row, ITCamp Community is organising Global Azure Boot Camp (https
In a previous post I was talking and demonstrating how to create Custom Role Based Access Controls which could be tailored comply with a company’s requirements. Another company requirement is compliance regarding data governance. Say you have one or multiple Azure Subscriptions and one of the company policies is that nobody should be able to create Azure resources outside a specific region. Some / all of the company’s contracts have a mandatory clause that all the data they produce and keep in the cloud should only reside in a specific geographical region. Microsoft has gone to great lengths to ensure that their cloud services (Azure or Office 365) comply with national, regional, and industry-specific requirements governing the collection and use of individual’s data.
Azure Resource Policies are here to solve this compliance issue as these are subscription wide policies that can be configured to do certain actions on a resource level. The main difference between Azure Resource Policies and Roled Based Access Control (RBAC) is that RBAC focuses on the actions of a user and policies focus on the actions of a resource. For example:
The Contributor RBAC role, grants an user a certain amount of privileges at a subscription or Resource Group level which that user can use to add, remove or modify resources in any way he pleases. Now by having a Resource Policy configured at a subscription or Resource Group level, you can permit or deny certain resources to be created, modified or deleted no matter what the users RBAC role is. So if I have a subscription wide policy in place that only allows resources to be created in the EU then all resources that are created will be analyzed and if they don’t match the policy then the provisioning process is denied. The only user that can add, remove or modify policies are the owners or the users that have access to the Microsoft.Authorization.* resource provider like User Access Administrator.
You first start with a policy definition that’s created using JSON (you can see the schema here: http://schema.management.azure.com/schemas/2015-10-01-preview/policyDefinition.json) and which consists of one or more logical or condition operators that define the action and effect of the policy when a specific condition is achieved.
An example of a policy definition that denies resource creation outside a specific region(s) looks like this:
{ "if" : { "not" : { "field" : "location", "in" : ["northeurope" , "westeurope", "uksouth", "ukwest"] } }, "then" : { "effect" : "deny" } }
The above example says that if the resource that you’re currently provisioning is not in one of the datacenters specified in the “in” block the resource will be blocked from being created.
One of the questions that I frequently get asked when I suggest using policies is what happens with the existing resources that don’t comply with the policy? The answer is nothing. Policies don’t apply retroactively or have that level of power of deleting non-compliant hits, so it’s still the job of the subscription admin to get rid of the non-compliant resources.
You have two options of creating resource policies, one of which is by writing JSON in a PowerShell ISE environment or by writing JSON in an another IDE like Visual Studio Code. For assigning the policies, you can either use the REST API or PowerShell. I for one always use PowerShell, and that’s what I’m going to show right now ?
Taking the example from above, you instantiate a variable with the JSON block in this manner:
$demopolicy = New-AzureRmPolicyDefinition -Name demoPolicy -Description "Policy that allows resource creation only in certain regions" -Policy '{ "if" : { "not" : { "field" : "location", "in" : ["northeurope" , "westeurope", "uksouth", "ukwest"] } }, "then" : { "effect" : "deny" } }'
The $demoPolicy variable is a PSCustomObject that contains information all the information needed for the policy to be applied.
In order to apply the policy, all you need to do is use the New-AzureRmPolicyAssignment cmdlet and reference the variable in the PolicyDefinition parameter and give it a Scope
New-AzureRmPolicyAssignment -Name demoPolicy -PolicyDefinition $demopolicy -Scope /subscriptions/7b888c17-ad4c-41e4-84d0-db91c2705902
For the Scope parameter, you need to provide the ResourceID of an entire subscription or a resource group or a specific resource. You can get the ResourceID by calling the Get-AzureRMResource / Get-AzureRMResourceGroup cmdlets.
Get-AzureRmResource | Sort-Object ResourceType | Format-Table ResourceName, ResourceGroupName, ResourceType, ResourceId -Wrap Get-AzureRmResourceGroup | Format-Table ResourceGroupName, ResourceId -Wrap
We saw in the first example a policy that denies the creation of a resource if the location parameter doesn’t coincide with it.
At the time of writing this post, we have three effects, conditions and logical operators:
Effects:
Effect – Explanation
Deny -> Denies the request if a condition is met and generates an event in the audit log
Audit -> Lets the request pass if a condition is met and generates an event in the audit log
Append -> Adds to the request a defined set of field like certain resource tags if they are not defined
Conditions:
Condition Name -> Syntax
Equals -> “equals”
Like -> “like’
Contains -> “contains”
In -> “in”
ContainsKey -> “containsKey”
Exists -> “exists”
Logical Operators:
Operator Name -> Syntax
Not -> “not”
And -> “allOf”
Or -> “anyOf”
Here are some examples:
This policy appends an department tag when no tags are present in the request:
{ "if": { "field": "tags", "exists": "false" }, "then": { "effect": "append", "details": [ { "field": "tags", "value": {"Deparment":"IT" } } ] } }
This policy audits the action if there are tags in the request in but no department tag:
{ "if": { "allOf": [ { "field": "tags", "exists": "true" }, { "field": "tags.department", "exists": "false" } ] }, "then": { "effect": "audit" } }
This policy denies the creation of a public IP address:
{ "if": { "source": "action", "equals": "Microsoft.Network/publicIPAddresses/write" }, "then": { "effect": "deny" } }
This policy only allows a specific list of resources:
{ "if" : { "not" : { "anyOf" : [ { "source" : "action", "like" : "Microsoft.Resources/*" }, { "source" : "action", "like" : "Microsoft.Compute/*" }, { "source" : "action", "like" : "Microsoft.Storage/*" }, { "source" : "action", "like" : "Microsoft.Network/*" } ] } }, "then": { "effect": "deny" } }
Besides the examples that I provided, Azure has some BuiltIn policies that just need to be assigned:
SQL Server version 12.0 required
This policy ensures all SQL servers use version 12.0.Allow resource creation only in India data centers
Allows resource creation in the following locations only: West India, South India, Central IndiaProhibited resource types
This policy enables you to specify the resource types that your organization cannot deployAllow resource creation only in Japan data centers
Allows resource creation in the following locations only: Japan East, Japan WestStorage account SKUs
This policy enables you to specify a set of storage account SKUs that your organization can deployStorage Account encryption required
This policy ensures encryption for storage accounts is turned onAllow resource creation only in European data centers
Allows resource creation in the following locations only: North Europe, West EuropeAllow resource creation only in United States data centers
Allows resource creation in the following locations only: Central US, East US, East US2, North Central US, South Central US, West USAllow resource creation if ‘environment’ tag value in allowed values
Allows resource creation if the ‘environment’ tag is set to one of the following values: production, dev, test, stagingAllow resource creation only in Asia data centers
Allows resource creation in the following locations only: East Asia, Southeast Asia, West India, South India, Central India, Japan East, Japan WestVirtual Machine SKUs
This policy enables you to specify a set of virtual machine SKUs that your organization can deploy.Allow resource creation if ‘department’ tag set
Allows resource creation only if the ‘department’ tag is setAllow resource creation only in Japan data centers
Allows resource creation in the following locations only: Japan East, Japan WestGeo-compliance
This policy enables you to restrict the locations your organization can specify when deploying resources. Use to enforce your geo-compliance requirements.
This is how you can get the builtin policies. They all have a GUID as a name so that’s what you need when you’re assigning them:
Get-AzureRmPolicyDefinition | Where-Object {$_.Properties.policyType -like "*builtin*"}
The definition and assigning as you saw are different cmdlets which mean that you can remove an assignment from a subscription, resource group or resource without deleting the definition in case you want to use it later.
In order to remove an assignment, you need to call the Remove-AzureRmPolicyAssignment and specify the Scope:
Remove-AzureRmPolicyAssignment -Name regionPolicyAssignment -Scope /subscriptions/########-####-####-####-############/resourceGroups/resource-group-name
Well, the short answer is that every policy event is logged in the Azure Audit Log, the long answer is that while all the policies are logged to the Azure Audit Log, the main problem is that there is no way of filtering the log to see what’s happening with the policies. One fortunate part of the deal is that Deny Effect policies have a SubStatus of Forbidden and that can be searched with PowerShell but the others are tagged with the action type like audit or append. So this part requires a little work from the Azure Team.
The good part is that once you’ve tested it and happy with the policies, then you can be sure that everything works just fine ?
Have a good one!
L.E: I forgot one nice thing that can be done with Azure Resource Policies and that feature is called Resource Locks.
A resource lock is a policy that can be applied to a Resource Group or a Resource and locks it in place with either a read only policy or a nodelete policy. This type of policy can help when you want to prevent accidental deletion of Resource Groups or a particular resource.
Applying a resource lock is very simple, you can either apply it from the Azure Portal, or you can apply it by using the PowerShell cmdlet New-AzureRMResourceLock.