Using Azure Policy to Deny or Audit Management Operations

The deep integration between Azure Resource Manager (ARM) and Azure Active Directory (AAD) lights up interesting security features such as role-based access control allowing fine-grained control over who can manage Azure resources. Azure Policy is a new ARM feature that supports global restrictions on the deployment and management of Azure resources. For example, Azure Policy provides the ability to restrict deployments of Virtual Machines to specific sizes and regions – regardless of any other permissions the administrator may have. Azure Policy also supports the ability to audit operations that are then allowed to succeed.

An Azure Policy is implemented by creating a policy definition specifying the policy rules and actions and then assigning it at one of subscription, resource group or resource scope. The policy definition is specified as a JSON document specifying a rule as one or more conditions and an action which is either deny or audit. A deny action ensures that the action is expressly forbidden at the assigned scope regardless of any RBAC authorizations the caller may have. An audit action means that the action is allowed to complete but that an audit message is written to the Azure logs, from which it may subsequently be retrieved.

The conditions in the policy definition rule are based on various fields contained in the operation as well as the source of the action (operation). The rules can use the following data elements:

  • name
  • location
  • type (of resource, eg., Microsoft.Compute/virtualMachines)
  • tags
  • source (resource provider namespace, e.g., Microsoft.Compute)

Azure Policy is described in a post on Azure.com. The REST API for Azure Policy definitions is documented here. The REST API for Azure Policy assignments is documented here.

PowerShell

Azure PowerShell v1 supports Azure Policy with the following cmdlets:

  • Get-AzureRmPolicyAssignment 
  • Get-AzureRmPolicyDefinition 
  • New-AzureRmPolicyAssignment 
  • New-AzureRmPolicyDefinition 
  • Remove-AzureRmPolicyAssignment
  • Remove-AzureRmPolicyDefinition
  • Set-AzureRmPolicyAssignment 
  • Set-AzureRmPolicyDefinition

Example

The following policy rule forbids the creation in the East US region of a storage account created using the Microsoft.Storage resource provider:

$policyRule =
@'
{
  "if":{
    "allOf":[
      {
        "source":"action",
        "equals":"Microsoft.Storage/storageAccounts/write"
      },
      {
        "field":"location",
        "in":[
          "eastus"
        ]
      }
    ]
  },
  "then":{
    "effect":"deny"
  }
}
'@

Had the effect been audit, instead of deny then creation would be allowed but the fact of creation would be explicitly audited.

The following cmdlets create a new policy definition and then assign it as a policy to the specified resource group:

$policy = New-AzureRmPolicyDefinition -Name $policyName -DisplayName "No Storage in East US" -Policy $policyRule

$resourceGroup = New-AzureRmResourceGroup -Name $resourceGroupName -Location "westus"

New-AzureRmPolicyAssignment -Name $policyAssignment -PolicyDefinition $policy -Scope $resourceGroup.ResourceId

With this assignment the following will be denied for all users:

New-AzureRmStorageAccount -ResourceGroupName $resourceGroupName -Location eastus -Name $storageAccountName -Type Standard_LRS

While the following deployment in the West US region will succeed

New-AzureRmStorageAccount -ResourceGroupName $resourceGroupName -Location westus -Name $storageAccountName -Type Standard_LRS

Logging

The Get-AzureRmLog cmdlet can be used to retrieve information about the status of any ARM operation, including failure, as well as the fact that an operation was audited.
The following example retrieves detailed information for all failed operations in the last hour:

Get-AzureRmLog -DetailedOutput -Status Failed

A different timeframe can be selected using the StartTime and EndTime parameters. The output can also be restricted by resource group and resource provider.

The following example retrieves all audit notifications in the last hour (which can again be modified by StartTime and EndTime).

Get-AzureRmLog | Where {$_.OperationName -eq 'Microsoft.Authorization/policies/audit/action'}

Authorization :
Scope : /subscriptions/GUID/resourceGroups/PolicyDemo/
providers/Microsoft.Storage/storageAccounts/policydemo555
Action : Microsoft.Storage/storageAccounts/write
Role : Subscription Admin
Condition :
Caller : admin@orgid.com
CorrelationId : 682c2a4c-1bed-4871-8428-3c58f3e290fe
EventSource : Administrative
EventTimestamp : 10/25/2015 10:18:14 PM
OperationName : Microsoft.Authorization/policies/audit/action
ResourceGroupName : PolicyDemo
ResourceId : /subscriptions/GUID/resourceGroups/PolicyDemo/providers/Microsoft.Storage/storageAccounts/policydemo555
Status :
SubscriptionId : GUID
SubStatus :

This makes it trivial to identify attempts to manage audited resources as well as who attempted the operation.