Skip to content

Commit 3269583

Browse files
Merge pull request #96759 from DCtheGeek/dmc-policy-newarrays
Add count expression language details
2 parents c7e24bf + 5154b8b commit 3269583

File tree

2 files changed

+189
-27
lines changed

2 files changed

+189
-27
lines changed

articles/governance/policy/concepts/definition-structure.md

Lines changed: 176 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
---
22
title: Details of the policy definition structure
33
description: Describes how policy definitions are used to establish conventions for Azure resources in your organization.
4-
ms.date: 11/04/2019
4+
ms.date: 11/26/2019
55
ms.topic: conceptual
66
---
77
# Azure Policy definition structure
@@ -63,8 +63,8 @@ All Azure Policy samples are at [Azure Policy samples](../samples/index.md).
6363

6464
## Mode
6565

66-
**Mode** is configured depending on if the policy is targeting an Azure Resource Manager property or a
67-
Resource Provider property.
66+
**Mode** is configured depending on if the policy is targeting an Azure Resource Manager property or
67+
a Resource Provider property.
6868

6969
### Resource Manager modes
7070

@@ -85,7 +85,8 @@ it prevents resources that don't support tags and locations from showing up as n
8585
compliance results. The exception is **resource groups**. Policies that enforce location or tags on
8686
a resource group should set **mode** to `all` and specifically target the
8787
`Microsoft.Resources/subscriptions/resourceGroups` type. For an example, see [Enforce resource group
88-
tags](../samples/enforce-tag-rg.md). For a list of resources that support tags, see [Tag support for Azure resources](../../../azure-resource-manager/tag-support.md).
88+
tags](../samples/enforce-tag-rg.md). For a list of resources that support tags, see
89+
[Tag support for Azure resources](../../../azure-resource-manager/tag-support.md).
8990

9091
### <a name="resource-provider-modes" />Resource Provider modes (preview)
9192

@@ -123,7 +124,8 @@ A parameter has the following properties that are used in the policy definition:
123124

124125
- **name**: The name of your parameter. Used by the `parameters` deployment function within the
125126
policy rule. For more information, see [using a parameter value](#using-a-parameter-value).
126-
- `type`: Determines if the parameter is a **string**, **array**, **object**, **boolean**, **integer**, **float**, or **datetime**.
127+
- `type`: Determines if the parameter is a **string**, **array**, **object**, **boolean**,
128+
**integer**, **float**, or **datetime**.
127129
- `metadata`: Defines subproperties primarily used by the Azure portal to display user-friendly
128130
information:
129131
- `description`: The explanation of what the parameter is used for. Can be used to provide
@@ -467,6 +469,160 @@ starting with abc" is returned instead and compared to **abc**. A resource with
467469
doesn't begin with **abc** still fails the policy rule, but no longer causes an error during
468470
evaluation.
469471

472+
### Count
473+
474+
Conditions that count how many members of an array in the resource payload satisfy a condition
475+
expression can be formed using **count** expression. Common scenarios are checking whether 'at least
476+
one of', 'exactly one of', 'all of', or 'none of' the array members satisfy the condition. **count**
477+
evaluates each array member for a condition expression and sums the _true_ results, which is then
478+
compared to the expression operator.
479+
480+
The structure of the **count** expression is:
481+
482+
```json
483+
{
484+
"count": {
485+
"field": "<[*] alias>",
486+
"where": {
487+
/* condition expression */
488+
}
489+
},
490+
"<condition>": "<compare the count of true condition expression array members to this value>"
491+
}
492+
```
493+
494+
The following properties are used with **count**:
495+
496+
- **count.field** (required): Contains the path to the array and must be an array alias. If the
497+
array is missing, the expression is evaluated to _false_ without considering the condition
498+
expression.
499+
- **count.where** (optional): The condition expression to individually evaluate each [\[\*\]
500+
alias](#understanding-the--alias) array member of **count.field**. If this property is not
501+
provided, all array members with the path of 'field' are evaluated to _true_. Any
502+
[condition](../concepts/definition-structure.md#conditions) can be used inside this property.
503+
[Logical operators](#logical-operators) can be used inside this property to create complex
504+
evaluation requirements.
505+
- **\<condition\>** (required): The value is compared to the number of items that met the
506+
**count.where** condition expression. A numeric
507+
[condition](../concepts/definition-structure.md#conditions) should be used.
508+
509+
#### Count examples
510+
511+
Example 1: Check if an array is empty
512+
513+
```json
514+
{
515+
"count": {
516+
"field": "Microsoft.Network/networkSecurityGroups/securityRules[*]"
517+
},
518+
"equals": 0
519+
}
520+
```
521+
522+
Example 2: Check for only one array member to meet the condition expression
523+
524+
```json
525+
{
526+
"count": {
527+
"field": "Microsoft.Network/networkSecurityGroups/securityRules[*]",
528+
"where": {
529+
"field": "Microsoft.Network/networkSecurityGroups/securityRules[*].description",
530+
"equals": "My unique description"
531+
}
532+
},
533+
"equals": 1
534+
}
535+
```
536+
537+
Example 3: Check for at least one array member to meet the condition expression
538+
539+
```json
540+
{
541+
"count": {
542+
"field": "Microsoft.Network/networkSecurityGroups/securityRules[*]",
543+
"where": {
544+
"field": "Microsoft.Network/networkSecurityGroups/securityRules[*].description",
545+
"equals": "My common description"
546+
}
547+
},
548+
"greaterOrEquals": 1
549+
}
550+
```
551+
552+
Example 4: Check that all object array members meet the condition expression
553+
554+
```json
555+
{
556+
"count": {
557+
"field": "Microsoft.Network/networkSecurityGroups/securityRules[*]",
558+
"where": {
559+
"field": "Microsoft.Network/networkSecurityGroups/securityRules[*].description",
560+
"equals": "description"
561+
}
562+
},
563+
"equals": "[length(field(Microsoft.Network/networkSecurityGroups/securityRules[*]))]"
564+
}
565+
```
566+
567+
Example 5: Check that all string array members meet the condition expression
568+
569+
```json
570+
{
571+
"count": {
572+
"field": "Microsoft.Sql/servers/securityAlertPolicies/emailAddresses[*]",
573+
"where": {
574+
"field": "Microsoft.Sql/servers/securityAlertPolicies/emailAddresses[*]",
575+
"like": "*@contoso.com"
576+
}
577+
},
578+
"equals": "[length(field('Microsoft.Sql/servers/securityAlertPolicies/emailAddresses[*]'))]"
579+
}
580+
```
581+
582+
Example 6: Use **field** inside **value** to check that all array members meet the condition
583+
expression
584+
585+
```json
586+
{
587+
"count": {
588+
"field": "Microsoft.Sql/servers/securityAlertPolicies/emailAddresses[*]",
589+
"where": {
590+
"value": "[last(split(first(field('Microsoft.Sql/servers/securityAlertPolicies/emailAddresses[*]')), '@'))]",
591+
"equals": "contoso.com"
592+
}
593+
},
594+
"equals": "[length(field('Microsoft.Sql/servers/securityAlertPolicies/emailAddresses[*]'))]"
595+
}
596+
```
597+
598+
Example 7: Check that at least one array member matches multiple properties in the condition
599+
expression
600+
601+
```json
602+
{
603+
"count": {
604+
"field": "Microsoft.Network/networkSecurityGroups/securityRules[*]",
605+
"where": {
606+
"allOf": [
607+
{
608+
"field": "Microsoft.Network/networkSecurityGroups/securityRules[*].direction",
609+
"equals": "Inbound"
610+
},
611+
{
612+
"field": "Microsoft.Network/networkSecurityGroups/securityRules[*].access",
613+
"equals": "Allow"
614+
},
615+
{
616+
"field": "Microsoft.Network/networkSecurityGroups/securityRules[*].destinationPortRange",
617+
"equals": "3389"
618+
}
619+
]
620+
}
621+
},
622+
"greater": 0
623+
}
624+
```
625+
470626
### Effect
471627

472628
Azure Policy supports the following types of effect:
@@ -581,21 +737,22 @@ Policy, use one of the following methods:
581737

582738
### Understanding the [*] alias
583739

584-
Several of the aliases that are available have a version that appears as a 'normal' name and
585-
another that has **[\*]** attached to it. For example:
740+
Several of the aliases that are available have a version that appears as a 'normal' name and another
741+
that has **\[\*\]** attached to it. For example:
586742

587743
- `Microsoft.Storage/storageAccounts/networkAcls.ipRules`
588744
- `Microsoft.Storage/storageAccounts/networkAcls.ipRules[*]`
589745

590746
The 'normal' alias represents the field as a single value. This field is for exact match comparison
591747
scenarios when the entire set of values must be exactly as defined, no more and no less.
592748

593-
The **[\*]** alias makes it possible to compare against the value of each element in the array and
749+
The **\[\*\]** alias makes it possible to compare against the value of each element in the array and
594750
specific properties of each element. This approach makes it possible to compare element properties
595-
for 'if none of', 'if any of', or 'if all of' scenarios. Using **ipRules[\*]**, an example would be
596-
validating that every _action_ is _Deny_, but not worrying about how many rules exist or what the
597-
IP _value_ is. This sample rule checks for any matches of **ipRules[\*].value** to **10.0.4.1** and
598-
applies the **effectType** only if it doesn't find at least one match:
751+
for 'if none of', 'if any of', or 'if all of' scenarios. For more complex scenarios, use the
752+
[count](#count) condition expression. Using **ipRules\[\*\]**, an example would be validating that
753+
every _action_ is _Deny_, but not worrying about how many rules exist or what the IP _value_ is.
754+
This sample rule checks for any matches of **ipRules\[\*\].value** to **10.0.4.1** and applies the
755+
**effectType** only if it doesn't find at least one match:
599756

600757
```json
601758
"policyRule": {
@@ -617,14 +774,17 @@ applies the **effectType** only if it doesn't find at least one match:
617774
}
618775
```
619776

620-
For more information, see [evaluating the [\*] alias](../how-to/author-policies-for-arrays.md#evaluating-the--alias).
777+
778+
779+
For more information, see [evaluating the [\*]
780+
alias](../how-to/author-policies-for-arrays.md#evaluating-the--alias).
621781

622782
## Initiatives
623783

624784
Initiatives enable you to group several related policy definitions to simplify assignments and
625785
management because you work with a group as a single item. For example, you can group related
626-
tagging policy definitions into a single initiative. Rather than assigning each policy
627-
individually, you apply the initiative.
786+
tagging policy definitions into a single initiative. Rather than assigning each policy individually,
787+
you apply the initiative.
628788

629789
The following example illustrates how to create an initiative for handling two tags: `costCenter`
630790
and `productName`. It uses two built-in policies to apply the default tag value.
@@ -708,4 +868,4 @@ and `productName`. It uses two built-in policies to apply the default tag value.
708868
- Understand how to [programmatically create policies](../how-to/programmatically-create.md).
709869
- Learn how to [get compliance data](../how-to/get-compliance-data.md).
710870
- Learn how to [remediate non-compliant resources](../how-to/remediate-resources.md).
711-
- Review what a management group is with [Organize your resources with Azure management groups](../../management-groups/overview.md).
871+
- Review what a management group is with [Organize your resources with Azure management groups](../../management-groups/overview.md).

articles/governance/policy/how-to/author-policies-for-arrays.md

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
---
22
title: Author policies for array properties on resources
33
description: Learn to work with array parameters and array language expressions, evaluate the [*] alias, and to append elements with Azure Policy definition rules.
4-
ms.date: 03/06/2019
4+
ms.date: 11/26/2019
55
ms.topic: conceptual
66
---
77
# Author policies for array properties on Azure resources
@@ -15,8 +15,9 @@ used in several different ways:
1515
- Part of a [policy rule](../concepts/definition-structure.md#policy-rule) using the conditions
1616
**in** or **notIn**
1717
- Part of a policy rule that evaluates the [\[\*\]
18-
alias](../concepts/definition-structure.md#understanding-the--alias) to evaluate specific
19-
scenarios such as **None**, **Any**, or **All**
18+
alias](../concepts/definition-structure.md#understanding-the--alias) to evaluate:
19+
- Scenarios such as **None**, **Any**, or **All**
20+
- Complex scenarios with **count**
2021
- In the [append effect](../concepts/effects.md#append) to replace or add to an existing array
2122

2223
This article covers each use by Azure Policy and provides several example definitions.
@@ -160,12 +161,13 @@ expression. To resolve this error message, change `equals` to either `in` or `no
160161

161162
### Evaluating the [*] alias
162163

163-
Aliases that have **[\*]** attached to their name indicate the **type** is an _array_. Instead of
164-
evaluating the value of the entire array, **[\*]** makes it possible to evaluate each element of the
165-
array. There are three scenarios this per item evaluation is useful in: None, Any, and All.
164+
Aliases that have **\[\*\]** attached to their name indicate the **type** is an _array_. Instead of
165+
evaluating the value of the entire array, **\[\*\]** makes it possible to evaluate each element of
166+
the array. There are three standard scenarios this per item evaluation is useful in: None, Any, and
167+
All. For complex scenarios, use [count](../concepts/definition-structure.md#count).
166168

167169
The policy engine triggers the **effect** in **then** only when the **if** rule evaluates as true.
168-
This fact is important to understand in context of the way **[\*]** evaluates each individual
170+
This fact is important to understand in context of the way **\[\*\]** evaluates each individual
169171
element of the array.
170172

171173
The example policy rule for the scenario table below:
@@ -221,11 +223,11 @@ rule and array of existing values above:
221223
## The append effect and arrays
222224

223225
The [append effect](../concepts/effects.md#append) behaves differently depending on if the
224-
**details.field** is a **[\*]** alias or not.
226+
**details.field** is a **\[\*\]** alias or not.
225227

226-
- When not a **[\*]** alias, append replaces the entire array with the **value** property
227-
- When a **[\*]** alias, append adds the **value** property to the existing array or creates the new
228-
array
228+
- When not a **\[\*\]** alias, append replaces the entire array with the **value** property
229+
- When a **\[\*\]** alias, append adds the **value** property to the existing array or creates the
230+
new array
229231

230232
For more information, see the [append examples](../concepts/effects.md#append-examples).
231233

0 commit comments

Comments
 (0)