mirror of
https://github.com/microsoft/regorus.git
synced 2026-08-05 02:16:11 +00:00
YAML-driven test cases for the core Azure Policy compiler. These cover alias resolution, field conditions, logical operators, type coercion, count expressions, template functions, effect compilation, and policy definition parsing. 24 files, each a self-contained scenario exercised by the test runner in the companion code PR. Signed-off-by: Anand Krishnamoorthi <anakrish@microsoft.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
685 lines
17 KiB
YAML
685 lines
17 KiB
YAML
# Copyright (c) Microsoft Corporation.
|
|
# Licensed under the MIT License.
|
|
|
|
# Deep Nesting & Edge-Case Test Suite
|
|
# Tests deeply nested logical combinators, nested ARM expressions,
|
|
# nested count loops, and edge cases around condition-no-match paths.
|
|
|
|
cases:
|
|
# =========================================================================
|
|
# Deep logical combinator nesting (4+ levels)
|
|
# =========================================================================
|
|
|
|
- note: four_level_nesting
|
|
policy_rule: |
|
|
{
|
|
"if": {
|
|
"allOf": [
|
|
{
|
|
"anyOf": [
|
|
{
|
|
"not": {
|
|
"allOf": [
|
|
{ "field": "type", "equals": "Microsoft.Compute/virtualMachines" },
|
|
{ "field": "location", "equals": "westus" }
|
|
]
|
|
}
|
|
},
|
|
{
|
|
"field": "kind", "equals": "linux"
|
|
}
|
|
]
|
|
},
|
|
{ "field": "name", "notEquals": "" }
|
|
]
|
|
},
|
|
"then": { "effect": "audit" }
|
|
}
|
|
resource:
|
|
type: "Microsoft.Compute/virtualMachines"
|
|
location: "eastus"
|
|
kind: "windows"
|
|
name: "my-vm"
|
|
want_effect: "audit"
|
|
|
|
- note: four_level_nesting_no_match
|
|
policy_rule: |
|
|
{
|
|
"if": {
|
|
"allOf": [
|
|
{
|
|
"anyOf": [
|
|
{
|
|
"not": {
|
|
"allOf": [
|
|
{ "field": "type", "equals": "Microsoft.Compute/virtualMachines" },
|
|
{ "field": "location", "equals": "eastus" }
|
|
]
|
|
}
|
|
},
|
|
{
|
|
"field": "kind", "equals": "linux"
|
|
}
|
|
]
|
|
},
|
|
{ "field": "name", "notEquals": "" }
|
|
]
|
|
},
|
|
"then": { "effect": "audit" }
|
|
}
|
|
resource:
|
|
type: "Microsoft.Compute/virtualMachines"
|
|
location: "eastus"
|
|
kind: "windows"
|
|
name: "my-vm"
|
|
want_undefined: true
|
|
|
|
- note: five_level_nesting
|
|
policy_rule: |
|
|
{
|
|
"if": {
|
|
"not": {
|
|
"allOf": [
|
|
{
|
|
"anyOf": [
|
|
{
|
|
"not": {
|
|
"allOf": [
|
|
{ "field": "type", "equals": "Microsoft.Storage/storageAccounts" },
|
|
{ "field": "properties.supportsHttpsTrafficOnly", "equals": true }
|
|
]
|
|
}
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}
|
|
},
|
|
"then": { "effect": "deny" }
|
|
}
|
|
resource:
|
|
type: "Microsoft.Storage/storageAccounts"
|
|
properties:
|
|
supportsHttpsTrafficOnly: true
|
|
want_effect: "deny"
|
|
|
|
# =========================================================================
|
|
# Deeply nested ARM template expressions
|
|
# =========================================================================
|
|
|
|
- note: nested_toLower_concat
|
|
policy_rule: |
|
|
{
|
|
"if": {
|
|
"value": "[toLower(concat(parameters('prefix'), '-', field('name')))]",
|
|
"equals": "prod-myvm"
|
|
},
|
|
"then": { "effect": "audit" }
|
|
}
|
|
parameters:
|
|
prefix: "PROD"
|
|
resource:
|
|
name: "MYVM"
|
|
want_effect: "audit"
|
|
|
|
- note: nested_if_equals_contains
|
|
policy_rule: |
|
|
{
|
|
"if": {
|
|
"value": "[if(contains(field('location'), 'us'), 'allowed', 'blocked')]",
|
|
"equals": "blocked"
|
|
},
|
|
"then": { "effect": "deny" }
|
|
}
|
|
resource:
|
|
location: "northeurope"
|
|
want_effect: "deny"
|
|
|
|
- note: nested_if_equals_allowed
|
|
policy_rule: |
|
|
{
|
|
"if": {
|
|
"value": "[if(contains(field('location'), 'us'), 'allowed', 'blocked')]",
|
|
"equals": "blocked"
|
|
},
|
|
"then": { "effect": "deny" }
|
|
}
|
|
resource:
|
|
location: "eastus"
|
|
want_undefined: true
|
|
|
|
- note: nested_length_of_concat
|
|
policy_rule: |
|
|
{
|
|
"if": {
|
|
"value": "[length(concat(parameters('a'), parameters('b')))]",
|
|
"greater": 6
|
|
},
|
|
"then": { "effect": "audit" }
|
|
}
|
|
parameters:
|
|
a: "hello"
|
|
b: "world"
|
|
resource:
|
|
type: "any"
|
|
want_effect: "audit"
|
|
|
|
- note: nested_add_length_length
|
|
policy_rule: |
|
|
{
|
|
"if": {
|
|
"value": "[add(length(parameters('list1')), length(parameters('list2')))]",
|
|
"equals": 5
|
|
},
|
|
"then": { "effect": "audit" }
|
|
}
|
|
parameters:
|
|
list1: ["a", "b"]
|
|
list2: ["c", "d", "e"]
|
|
resource:
|
|
type: "any"
|
|
want_effect: "audit"
|
|
|
|
- note: triple_nested_replace_toLower
|
|
policy_rule: |
|
|
{
|
|
"if": {
|
|
"value": "[replace(toLower(field('name')), '-', '_')]",
|
|
"equals": "my_vm"
|
|
},
|
|
"then": { "effect": "audit" }
|
|
}
|
|
resource:
|
|
name: "My-VM"
|
|
want_effect: "audit"
|
|
|
|
- note: triple_nested_substring_concat
|
|
policy_rule: |
|
|
{
|
|
"if": {
|
|
"value": "[substring(concat(parameters('prefix'), '-', field('name')), 0, 4)]",
|
|
"equals": "prod"
|
|
},
|
|
"then": { "effect": "audit" }
|
|
}
|
|
parameters:
|
|
prefix: "prod"
|
|
resource:
|
|
name: "myvm"
|
|
want_effect: "audit"
|
|
|
|
# =========================================================================
|
|
# Count inside anyOf (not just allOf)
|
|
# =========================================================================
|
|
|
|
- note: count_inside_anyOf
|
|
policy_rule: |
|
|
{
|
|
"if": {
|
|
"anyOf": [
|
|
{
|
|
"count": {
|
|
"field": "securityRules[*]",
|
|
"where": {
|
|
"field": "securityRules[*].access",
|
|
"equals": "Allow"
|
|
}
|
|
},
|
|
"greater": 5
|
|
},
|
|
{
|
|
"field": "type",
|
|
"equals": "something-else"
|
|
}
|
|
]
|
|
},
|
|
"then": { "effect": "deny" }
|
|
}
|
|
resource:
|
|
type: "Microsoft.Network/networkSecurityGroups"
|
|
securityRules:
|
|
- { access: "Allow" }
|
|
- { access: "Allow" }
|
|
- { access: "Allow" }
|
|
- { access: "Allow" }
|
|
- { access: "Allow" }
|
|
- { access: "Allow" }
|
|
want_effect: "deny"
|
|
|
|
# =========================================================================
|
|
# Count edge cases
|
|
# =========================================================================
|
|
|
|
- note: field_count_empty_array
|
|
policy_rule: |
|
|
{
|
|
"if": {
|
|
"count": {
|
|
"field": "items[*]"
|
|
},
|
|
"equals": 0
|
|
},
|
|
"then": { "effect": "audit" }
|
|
}
|
|
resource:
|
|
items: []
|
|
want_effect: "audit"
|
|
|
|
- note: field_count_where_matches_none
|
|
policy_rule: |
|
|
{
|
|
"if": {
|
|
"count": {
|
|
"field": "securityRules[*]",
|
|
"where": {
|
|
"field": "securityRules[*].access",
|
|
"equals": "SuperAllow"
|
|
}
|
|
},
|
|
"equals": 0
|
|
},
|
|
"then": { "effect": "audit" }
|
|
}
|
|
resource:
|
|
securityRules:
|
|
- { access: "Allow" }
|
|
- { access: "Deny" }
|
|
want_effect: "audit"
|
|
|
|
- note: field_count_where_matches_all
|
|
policy_rule: |
|
|
{
|
|
"if": {
|
|
"count": {
|
|
"field": "items[*]",
|
|
"where": {
|
|
"field": "items[*].enabled",
|
|
"equals": true
|
|
}
|
|
},
|
|
"equals": 3
|
|
},
|
|
"then": { "effect": "audit" }
|
|
}
|
|
resource:
|
|
items:
|
|
- { enabled: true }
|
|
- { enabled: true }
|
|
- { enabled: true }
|
|
want_effect: "audit"
|
|
|
|
- note: value_count_empty_parameter_array
|
|
policy_rule: |
|
|
{
|
|
"if": {
|
|
"count": {
|
|
"value": "[parameters('emptyList')]"
|
|
},
|
|
"equals": 0
|
|
},
|
|
"then": { "effect": "audit" }
|
|
}
|
|
parameters:
|
|
emptyList: []
|
|
resource:
|
|
type: "any"
|
|
want_effect: "audit"
|
|
|
|
- note: value_count_greater_no_match
|
|
policy_rule: |
|
|
{
|
|
"if": {
|
|
"count": {
|
|
"value": ["a", "b"]
|
|
},
|
|
"greater": 5
|
|
},
|
|
"then": { "effect": "deny" }
|
|
}
|
|
resource:
|
|
type: "any"
|
|
want_undefined: true
|
|
|
|
# =========================================================================
|
|
# Count with deeply nested where clauses
|
|
# =========================================================================
|
|
|
|
- note: count_where_allOf_nested_anyOf
|
|
policy_rule: |
|
|
{
|
|
"if": {
|
|
"count": {
|
|
"field": "rules[*]",
|
|
"where": {
|
|
"allOf": [
|
|
{ "field": "rules[*].enabled", "equals": true },
|
|
{
|
|
"anyOf": [
|
|
{ "field": "rules[*].priority", "equals": "high" },
|
|
{ "field": "rules[*].priority", "equals": "critical" }
|
|
]
|
|
}
|
|
]
|
|
}
|
|
},
|
|
"greater": 0
|
|
},
|
|
"then": { "effect": "deny" }
|
|
}
|
|
resource:
|
|
rules:
|
|
- { enabled: true, priority: "low" }
|
|
- { enabled: true, priority: "critical" }
|
|
- { enabled: false, priority: "high" }
|
|
want_effect: "deny"
|
|
|
|
- note: count_where_not_nested
|
|
policy_rule: |
|
|
{
|
|
"if": {
|
|
"count": {
|
|
"field": "items[*]",
|
|
"where": {
|
|
"not": {
|
|
"anyOf": [
|
|
{ "field": "items[*].status", "equals": "approved" },
|
|
{ "field": "items[*].status", "equals": "pending" }
|
|
]
|
|
}
|
|
}
|
|
},
|
|
"greater": 0
|
|
},
|
|
"then": { "effect": "deny" }
|
|
}
|
|
resource:
|
|
items:
|
|
- { status: "approved" }
|
|
- { status: "rejected" }
|
|
- { status: "pending" }
|
|
want_effect: "deny"
|
|
|
|
# =========================================================================
|
|
# Operators with missing/null fields
|
|
# =========================================================================
|
|
|
|
- note: greater_on_missing_field
|
|
policy_rule: |
|
|
{
|
|
"if": {
|
|
"field": "properties.missingProp",
|
|
"greater": 10
|
|
},
|
|
"then": { "effect": "deny" }
|
|
}
|
|
resource:
|
|
properties: {}
|
|
want_undefined: true
|
|
|
|
- note: less_on_missing_field
|
|
policy_rule: |
|
|
{
|
|
"if": {
|
|
"field": "properties.missingProp",
|
|
"less": 100
|
|
},
|
|
"then": { "effect": "deny" }
|
|
}
|
|
resource:
|
|
properties: {}
|
|
want_undefined: true
|
|
|
|
- note: contains_on_missing_field
|
|
policy_rule: |
|
|
{
|
|
"if": {
|
|
"field": "properties.missingProp",
|
|
"contains": "anything"
|
|
},
|
|
"then": { "effect": "deny" }
|
|
}
|
|
resource:
|
|
properties: {}
|
|
want_undefined: true
|
|
|
|
- note: in_on_missing_field
|
|
policy_rule: |
|
|
{
|
|
"if": {
|
|
"field": "properties.missingProp",
|
|
"in": ["a", "b", "c"]
|
|
},
|
|
"then": { "effect": "deny" }
|
|
}
|
|
resource:
|
|
properties: {}
|
|
want_undefined: true
|
|
|
|
- note: like_on_missing_field
|
|
policy_rule: |
|
|
{
|
|
"if": {
|
|
"field": "properties.missingProp",
|
|
"like": "any*"
|
|
},
|
|
"then": { "effect": "deny" }
|
|
}
|
|
resource:
|
|
properties: {}
|
|
want_undefined: true
|
|
|
|
- note: match_on_missing_field
|
|
policy_rule: |
|
|
{
|
|
"if": {
|
|
"field": "properties.missingProp",
|
|
"match": "test-##"
|
|
},
|
|
"then": { "effect": "deny" }
|
|
}
|
|
resource:
|
|
properties: {}
|
|
want_undefined: true
|
|
|
|
- note: notEquals_on_missing_field
|
|
policy_rule: |
|
|
{
|
|
"if": {
|
|
"field": "properties.missingProp",
|
|
"notEquals": "something"
|
|
},
|
|
"then": { "effect": "audit" }
|
|
}
|
|
resource:
|
|
properties: {}
|
|
want_effect: "audit"
|
|
|
|
- note: notIn_on_missing_field
|
|
policy_rule: |
|
|
{
|
|
"if": {
|
|
"field": "properties.missingProp",
|
|
"notIn": ["a", "b"]
|
|
},
|
|
"then": { "effect": "audit" }
|
|
}
|
|
resource:
|
|
properties: {}
|
|
want_effect: "audit"
|
|
|
|
- note: exists_true_on_missing_field
|
|
policy_rule: |
|
|
{
|
|
"if": {
|
|
"field": "properties.missingProp",
|
|
"exists": true
|
|
},
|
|
"then": { "effect": "deny" }
|
|
}
|
|
resource:
|
|
properties: {}
|
|
want_undefined: true
|
|
|
|
# =========================================================================
|
|
# ARM expression functions: equals() and contains() as function calls
|
|
# =========================================================================
|
|
|
|
- note: expr_func_equals
|
|
policy_rule: |
|
|
{
|
|
"if": {
|
|
"value": "[if(equals(field('type'), 'Microsoft.Compute/virtualMachines'), 'vm', 'other')]",
|
|
"equals": "vm"
|
|
},
|
|
"then": { "effect": "audit" }
|
|
}
|
|
resource:
|
|
type: "Microsoft.Compute/virtualMachines"
|
|
want_effect: "audit"
|
|
|
|
- note: expr_func_contains_array
|
|
policy_rule: |
|
|
{
|
|
"if": {
|
|
"value": "[if(contains(parameters('allowedTypes'), field('type')), 'yes', 'no')]",
|
|
"equals": "no"
|
|
},
|
|
"then": { "effect": "deny" }
|
|
}
|
|
parameters:
|
|
allowedTypes:
|
|
- "Microsoft.Storage/storageAccounts"
|
|
- "Microsoft.Compute/virtualMachines"
|
|
resource:
|
|
type: "Microsoft.Network/virtualNetworks"
|
|
want_effect: "deny"
|
|
|
|
# =========================================================================
|
|
# Type coercion edge cases: greaterOrEquals, lessOrEquals, notEquals, notIn
|
|
# =========================================================================
|
|
|
|
- note: coercion_notEquals_string_number
|
|
policy_rule: |
|
|
{
|
|
"if": {
|
|
"field": "properties.port",
|
|
"notEquals": 443
|
|
},
|
|
"then": { "effect": "deny" }
|
|
}
|
|
resource:
|
|
properties:
|
|
port: "80"
|
|
want_effect: "deny"
|
|
|
|
- note: coercion_greaterOrEquals_string_number
|
|
policy_rule: |
|
|
{
|
|
"if": {
|
|
"field": "properties.port",
|
|
"greaterOrEquals": 80
|
|
},
|
|
"then": { "effect": "deny" }
|
|
}
|
|
resource:
|
|
properties:
|
|
port: "80"
|
|
want_effect: "deny"
|
|
|
|
- note: coercion_lessOrEquals_string_number
|
|
policy_rule: |
|
|
{
|
|
"if": {
|
|
"field": "properties.port",
|
|
"lessOrEquals": 443
|
|
},
|
|
"then": { "effect": "deny" }
|
|
}
|
|
resource:
|
|
properties:
|
|
port: "80"
|
|
want_effect: "deny"
|
|
|
|
- note: coercion_notIn_mixed_types
|
|
policy_rule: |
|
|
{
|
|
"if": {
|
|
"field": "properties.port",
|
|
"notIn": [80, 443]
|
|
},
|
|
"then": { "effect": "deny" }
|
|
}
|
|
resource:
|
|
properties:
|
|
port: "8080"
|
|
want_effect: "deny"
|
|
|
|
# =========================================================================
|
|
# Complex real-world: multiple count + combinator + expression
|
|
# =========================================================================
|
|
|
|
- note: complex_nsg_with_tag_and_count
|
|
policy_rule: |
|
|
{
|
|
"if": {
|
|
"allOf": [
|
|
{ "field": "type", "equals": "Microsoft.Network/networkSecurityGroups" },
|
|
{
|
|
"not": {
|
|
"field": "tags.exception",
|
|
"equals": "true"
|
|
}
|
|
},
|
|
{
|
|
"count": {
|
|
"field": "securityRules[*]",
|
|
"where": {
|
|
"allOf": [
|
|
{ "field": "securityRules[*].access", "equals": "Allow" },
|
|
{ "field": "securityRules[*].direction", "equals": "Inbound" },
|
|
{
|
|
"anyOf": [
|
|
{ "field": "securityRules[*].sourceAddressPrefix", "equals": "*" },
|
|
{ "field": "securityRules[*].sourceAddressPrefix", "equals": "Internet" }
|
|
]
|
|
}
|
|
]
|
|
}
|
|
},
|
|
"greater": 0
|
|
}
|
|
]
|
|
},
|
|
"then": { "effect": "deny" }
|
|
}
|
|
resource:
|
|
type: "Microsoft.Network/networkSecurityGroups"
|
|
tags:
|
|
environment: "prod"
|
|
securityRules:
|
|
- { access: "Allow", direction: "Inbound", sourceAddressPrefix: "Internet" }
|
|
- { access: "Deny", direction: "Outbound", sourceAddressPrefix: "10.0.0.0/8" }
|
|
want_effect: "deny"
|
|
|
|
- note: complex_value_count_with_expr_where
|
|
policy_rule: |
|
|
{
|
|
"if": {
|
|
"count": {
|
|
"value": "[parameters('requiredPorts')]",
|
|
"name": "port",
|
|
"where": {
|
|
"value": "[current('port')]",
|
|
"greater": 1024
|
|
}
|
|
},
|
|
"equals": 2
|
|
},
|
|
"then": { "effect": "audit" }
|
|
}
|
|
parameters:
|
|
requiredPorts: [80, 8080, 9090]
|
|
resource:
|
|
type: "any"
|
|
want_effect: "audit"
|