In my last blog I explained about Azure Policy, concept and creating it. Next action after creating or changing an policy is to see whether is it working or not. Unlike most other azure features where change are propagated immediately, azure policy trigger does not happen immediately after SAVE.
Policy Trigger
Interval of Evaluation of policies depend upon type of policy change (new or update), effect and resource deployment.
Following is the evaluation interval
Compliance evaluation frequency
On change (New/Update policy Assignment) ~ 15 min after resource change
On periodic cadence ~ Every 24 hours
On demand ~ 3 min
Deny Policy enforcement
On creating resource ~ immediately. Policy is evaluated before deploy request is sent to resource provider
On updating resource ~ immediately. Policy is evaluated before deploy request is sent to resource provider
DeployIfNotExists Policy enforcement
On creating resource ~ immediately. Policy is enforced after deployment is succeed for resource creation.
On updating resource ~ immediately. Policy is enforced after deployment is succeed for resource update request.
DeployIfNotExists runs after a Resource Provider has handled a create or update resource request and has returned a success status code. A template deployment occurs if there are no related resources or if the resources defined by ExistenceCondition don’t evaluate to true.
During an evaluation cycle, policy definitions with a DeployIfNotExists effect that match resources are marked as non-compliant, but no action is taken on that resource.
On-demand
As mentioned above, one way to trigger a policy is via REST API. With a call to REST API, Evaluation scan can be triggered for subscription or a resource group.
This scan is an asynchronous process. As such, the REST endpoint to start the scan doesn’t wait until the scan is complete to respond. Instead, it provides a URI to query the status of the requested evaluation.
Following are the URI to trigger policy
POST https://management.azure.com/subscriptions/{subscriptionId}/providers/Microsoft.PolicyInsights/policyStates/latest/triggerEvaluation?api-version=2018-07-01-preview
POST https://management.azure.com/subscriptions/{subscriptionId}/resourceGroups/{YourRG}/providers/Microsoft.PolicyInsights/policyStates/latest/triggerEvaluation?api-version=2018-07-01-preview
Trigger Policy using script.
Since Triggering Policy REST API using a rest client needs token in Authorization and that two a new one quite often, I wrote a powershell script which call REST API and triggers policy
param(
[Parameter(Mandatory= $false)]
[string]$SubscriptionId,
[string]$ResourceGroup
)
function Get-AccessToken {
$context = Get-AzContext
if ($null -eq $account.Account) {
Write-Output("Account Context not found, please login")
Connect-AzAccount
$context = Get-AzContext
}
$cache = $context.TokenCache
$cacheItemToUse = $cache.ReadItems()
$tokenToUse = ($cacheItemToUse | where { $_.ExpiresOn -gt (Get-Date) })[0].accessToken
return $tokenToUse
}
function Trigger-ResourceGroupPolicy {
param (
[string]$ResourceGroup,
[string]$SubscriptionId,
$Headers
)
$url = "https://management.azure.com/subscriptions/$SubscriptionId/resourceGroups/$ResourceGroup/providers/Microsoft.PolicyInsights/policyStates/latest/triggerEvaluation?api-version=2018-07-01-preview"
$response= Invoke-WebRequest -Uri $url -Method Post -Headers $Headers
return $response
}
function Trigger-SubscriptionPolicy {
param (
[string]$SubscriptionId,
$Headers
)
$context = Get-AzContext
$cache = $context.TokenCache
$cacheItemToUse = $cache.ReadItems()
$tokenToUse = ($cacheItemToUse | where { $_.ExpiresOn -gt (Get-Date) })[0].accessToken
$url = "https://management.azure.com/subscriptions/$SubscriptionId/providers/Microsoft.PolicyInsights/policyStates/latest/triggerEvaluation?api-version=2018-07-01-preview"
$response= Invoke-WebRequest -Uri $url -Method Post -Headers $Headers
return $response
}
function Get-Status {
[string]$StatusUrl,
$Headers
$res= Invoke-WebRequest -Uri $StatusUrl -Method Get -Headers $Headers
return $res
}
$token = Get-AccessToken
Set-AzContext -SubscriptionId $SubscriptionId
$headers = @{
Authorization = "Bearer $token"
}
if(($null -eq $ResourceGroup) -or ($ResourceGroup -eq '')){
$res = Trigger-SubscriptionPolicy -SubscriptionId $SubscriptionId -Headers $headers
}
else{
$res = Trigger-ResourceGroupPolicy -ResourceGroup $ResourceGroup -SubscriptionId $SubscriptionId -Headers $headers
}
$statusUrl = $res.Headers.Location
Write-Output "Token is: $($token)"
Write-Output "Status url is: $($res.Headers.Location)"
Get-Status -StatusUrl $statusUrl -Headers $headers
#Write-Output "Run this command: Get-Status -StatusUrl $statusUrl -Headers $headers"
#Invoke-WebRequest -Uri $statusUrl -Method Get -Headers $headers
How compliance works
In an assignment, a resource is Non-compliant if it doesn’t follow policy or initiative rules.
For Audit and Deny :It requires IF statement (in policy rule) to be TRUE then effect takes place. For Audit resource is marked as non-complaint while, and for deny, new deployment (for new or update resource) is denied while existing resource is marked as non-complaint.
For Append, DeployIfNotExists and AuditIfNotExists: It requires IF statement to be TRUE and existence condition to be FALSE to mark resource as non-complaint