Nordlicht Reisen GmbH, a fictional travel agency, has three teams that all work in the same subscription. After a month, resources sit in regions where nobody wanted them, a production group was deleted by accident, and nobody knows anymore which resource belongs to which cost center. Roles (lesson 1.3) say who may do something. This lesson is about the counterpart: what may exist in a scope (Azure Policy), what must not disappear (locks) and what something belongs to (tags). This lesson covers: implement and manage Azure Policy, configure resource locks, apply and manage tags.

Prior knowledge. What policies, locks and tags are is explained in "AZ-900 compact", lessons 3.1 and 3.2. How developers use them in scripts is shown in K3, lesson 3.1.3 (order, tags, locks) and 3.1.5 (rules and data boundary). Here the material is seen from the administrator's side, with the portal and commands.

Implement and manage Azure Policy

The building blocks

Building block What it is Example
Policy definition a rule in JSON: under which condition (if) which effect (then) "Allowed locations"
Initiative (initiative definition, in commands also policy set) a collection of definitions for a common goal "Get Secure" from Microsoft's tutorial
Assignment a definition or initiative applied to a scope "Allowed locations" on the resource group rg-az104-policy

A definition does nothing as long as it isn't assigned. An assignment can point to a management group, a subscription, a resource group or a single resource, and it applies to everything below it. Microsoft notes: If you store definitions higher up (management group or subscription) and make the assignment one level lower, you can use the same definition several times. Microsoft also recommends assigning even a single policy as an initiative: Later, more definitions can be added without the number of assignments growing.

Parameters make a definition general. "Allowed locations" has the parameter listOfAllowedLocations; which regions are allowed is only decided by the assignment.

Effects

The effect is in the then part and determines what happens on a match. Microsoft evaluates them in this order:

  1. disabled: The rule is switched off and isn't evaluated at all.
  2. append and modify: change the request before it goes on (modify adds a tag, for example).
  3. deny: rejects the request.
  4. audit: allows it and records the deviation as non-compliant.
  5. auditIfNotExists, deployIfNotExists: check or create related resources after the resource provider has reported success.
  6. denyAction: blocks certain actions (such as delete) on resources.

Two consequences are relevant for the exam. First: deny takes effect before audit, so that an unwanted resource isn't recorded twice. Second: For existing resources, deny, append and deployIfNotExists change nothing; they only show the resource as non-compliant. Only a remediation task can change them, and only for modify and deployIfNotExists. Microsoft's recommendation for getting started: first audit, then enforce.

When is it evaluated?

A resource is checked when it is created or changed in a scope with an assignment, when a scope gets a new assignment, when an assigned policy is changed, and in the regular cycle once every 24 hours. After a new assignment, it takes about five minutes according to Microsoft until it takes effect on the scope, and then the evaluation of the existing resources begins. If you don't want to wait, you trigger an evaluation:

PowerShell
az policy state trigger-scan --resource-group rg-az104-policy

Azure PowerShell has Start-AzPolicyComplianceScan -ResourceGroupName rg-az104-policy for this.

Assigning: the portal way

  1. Search the portal for Policy (if your portal is set to another language, look for the same item under its translated name; the search box finds both), open Assignments and choose Assign policy.
  2. On the Basics tab, choose the Scope: management group, subscription and optionally a resource group. Under Exclusions you can take sub-scopes out; they start one level below the scope.
  3. Under Policy definition, find the definition, such as "Allowed locations". The filter Type = Built-in shows the built-in ones.
  4. Policy enforcement stays Enabled. If it is Disabled (in the command: DoNotEnforce), Azure evaluates without triggering the effect: the safe dry run.
  5. On Parameters, enter the values; on Remediation, for modify and deployIfNotExists, create the managed identity (mandatory; for "Inherit a tag from the resource group if missing" the portal suggests the role Contributor). Set a message on Non-compliance messages, then Review + create.

Assigning: the command

PowerShell
$rgId = az group show --name rg-az104-policy --query id --output tsv
$def = az policy definition list --query "[?displayName=='Allowed locations'].name" --output tsv
'{"listOfAllowedLocations":{"value":["germanywestcentral"]}}' | Set-Content -Path ./erlaubte-regionen.json
az policy assignment create --name erlaubte-regionen --display-name "Erlaubte Regionen" `
    --scope $rgId --policy $def --params "@erlaubte-regionen.json"

Further parameters of az policy assignment create: --not-scopes (exclusions), --enforcement-mode (Default, DoNotEnforce) and --mi-system-assigned with --location and --role for definitions that need an identity. In Azure PowerShell: New-AzPolicyAssignment with -NotScope and -EnforcementMode.

Creating initiatives

In the portal: Policy → Definitions → + Initiative definition, store it in a management group or subscription, add definitions on Policies, set values on Policy parameters. The same definition may appear several times, with its own reference ID and different parameters. Commands: az policy set-definition, in Azure PowerShell New-AzPolicySetDefinition.

Exclusion or exemption?

Exclusion (notScopes) Exemption
Where part of the assignment a resource of its own that points to the assignment
Applies to a sub-scope below the assignment's scope the exemption's scope: subscription, group or single resource
Category none Waiver (risk accepted) or Mitigated (solved another way)
Expiry none optionally an expiration date

The reason: Azure Policy is an explicit system of prohibitions. A more generous assignment further down doesn't override a denying one further up; you take the scope out or change the denying assignment. In the portal, the assignment has the button Create exemption; by command, az policy exemption create --name … --policy-assignment … --exemption-category Waiver --scope … (optionally --expires-on).

Reading compliance

Under Policy → Compliance, assignments appear with their state. Right after assigning, it says Not started, after the evaluation Compliant or Non-compliant. A click on the assignment shows the individual resources; the Events tab says who made a rejected request. On the command line:

PowerShell
az policy state list --resource-group rg-az104-policy --filter "(isCompliant eq false)"

A rejected deployment shows up on the resource group under Deployments with the status Forbidden; the error details contain the identifiers of the policy objects involved. Important: Azure Policy blocks even when someone is allowed everything through RBAC. Role and policy complement each other (lesson 1.3).