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>
1156 lines
28 KiB
YAML
1156 lines
28 KiB
YAML
# Copyright (c) Microsoft Corporation.
|
||
# Licensed under the MIT License.
|
||
|
||
# Casing & Case-Insensitive Comparison Test Suite
|
||
#
|
||
# Locks down the two-tier case-insensitivity semantics:
|
||
# 1. ARM property keys: OrdinalIgnoreCase (ASCII fold only)
|
||
# 2. Azure Policy condition values: InvariantCultureIgnoreCase (full Unicode
|
||
# case folding via ICU — ß=SS, ffi=FFI, Σ/σ/ς unified, etc.)
|
||
#
|
||
# See docs/azure-policy/casing.md for the full specification.
|
||
|
||
cases:
|
||
# =========================================================================
|
||
# equals — ASCII case-insensitive string values
|
||
# =========================================================================
|
||
|
||
- note: equals_ascii_case_insensitive
|
||
policy_rule: |
|
||
{
|
||
"if": {
|
||
"field": "type",
|
||
"equals": "microsoft.compute/virtualmachines"
|
||
},
|
||
"then": { "effect": "deny" }
|
||
}
|
||
resource:
|
||
type: "Microsoft.Compute/virtualMachines"
|
||
want_effect: "deny"
|
||
|
||
- note: equals_ascii_mixed_case
|
||
policy_rule: |
|
||
{
|
||
"if": {
|
||
"field": "location",
|
||
"equals": "WESTUS2"
|
||
},
|
||
"then": { "effect": "audit" }
|
||
}
|
||
resource:
|
||
location: "westus2"
|
||
want_effect: "audit"
|
||
|
||
- note: equals_ascii_exact_match
|
||
policy_rule: |
|
||
{
|
||
"if": {
|
||
"field": "name",
|
||
"equals": "MyVM"
|
||
},
|
||
"then": { "effect": "audit" }
|
||
}
|
||
resource:
|
||
name: "myvm"
|
||
want_effect: "audit"
|
||
|
||
- note: equals_ascii_no_match
|
||
policy_rule: |
|
||
{
|
||
"if": {
|
||
"field": "name",
|
||
"equals": "MyVM"
|
||
},
|
||
"then": { "effect": "audit" }
|
||
}
|
||
resource:
|
||
name: "OtherVM"
|
||
want_undefined: true
|
||
|
||
# =========================================================================
|
||
# equals — Unicode case folding (InvariantCultureIgnoreCase)
|
||
# =========================================================================
|
||
|
||
- note: equals_unicode_sharp_s
|
||
policy_rule: |
|
||
{
|
||
"if": {
|
||
"field": "tags.description",
|
||
"equals": "Straße"
|
||
},
|
||
"then": { "effect": "deny" }
|
||
}
|
||
resource:
|
||
tags:
|
||
description: "STRASSE"
|
||
want_effect: "deny"
|
||
|
||
- note: equals_unicode_sharp_s_reverse
|
||
policy_rule: |
|
||
{
|
||
"if": {
|
||
"field": "tags.description",
|
||
"equals": "STRASSE"
|
||
},
|
||
"then": { "effect": "deny" }
|
||
}
|
||
resource:
|
||
tags:
|
||
description: "Straße"
|
||
want_effect: "deny"
|
||
|
||
- note: equals_unicode_ligature_ffi
|
||
policy_rule: |
|
||
{
|
||
"if": {
|
||
"field": "tags.label",
|
||
"equals": "ffice"
|
||
},
|
||
"then": { "effect": "audit" }
|
||
}
|
||
resource:
|
||
tags:
|
||
label: "FFICE"
|
||
want_effect: "audit"
|
||
|
||
# =========================================================================
|
||
# notEquals — casing
|
||
# =========================================================================
|
||
|
||
- note: notEquals_case_insensitive_no_trigger
|
||
policy_rule: |
|
||
{
|
||
"if": {
|
||
"field": "location",
|
||
"notEquals": "westus2"
|
||
},
|
||
"then": { "effect": "deny" }
|
||
}
|
||
resource:
|
||
location: "WestUS2"
|
||
want_undefined: true
|
||
|
||
- note: notEquals_case_insensitive_trigger
|
||
policy_rule: |
|
||
{
|
||
"if": {
|
||
"field": "location",
|
||
"notEquals": "eastus"
|
||
},
|
||
"then": { "effect": "deny" }
|
||
}
|
||
resource:
|
||
location: "WestUS2"
|
||
want_effect: "deny"
|
||
|
||
# =========================================================================
|
||
# Tag name case insensitivity
|
||
# =========================================================================
|
||
|
||
- note: tag_name_case_insensitive_lowercase_policy
|
||
policy_rule: |
|
||
{
|
||
"if": {
|
||
"field": "tags.environment",
|
||
"equals": "production"
|
||
},
|
||
"then": { "effect": "deny" }
|
||
}
|
||
resource:
|
||
tags:
|
||
Environment: "production"
|
||
want_effect: "deny"
|
||
|
||
- note: tag_name_case_insensitive_uppercase_policy
|
||
policy_rule: |
|
||
{
|
||
"if": {
|
||
"field": "tags.Environment",
|
||
"equals": "production"
|
||
},
|
||
"then": { "effect": "deny" }
|
||
}
|
||
resource:
|
||
tags:
|
||
environment: "production"
|
||
want_effect: "deny"
|
||
|
||
- note: tag_name_case_insensitive_mixed
|
||
policy_rule: |
|
||
{
|
||
"if": {
|
||
"field": "tags.CostCenter",
|
||
"equals": "finance"
|
||
},
|
||
"then": { "effect": "audit" }
|
||
}
|
||
resource:
|
||
tags:
|
||
costcenter: "finance"
|
||
want_effect: "audit"
|
||
|
||
- note: tag_value_case_insensitive
|
||
policy_rule: |
|
||
{
|
||
"if": {
|
||
"field": "tags.environment",
|
||
"equals": "PRODUCTION"
|
||
},
|
||
"then": { "effect": "deny" }
|
||
}
|
||
resource:
|
||
tags:
|
||
environment: "Production"
|
||
want_effect: "deny"
|
||
|
||
# =========================================================================
|
||
# contains — string case insensitivity
|
||
# =========================================================================
|
||
|
||
- note: contains_string_case_insensitive
|
||
policy_rule: |
|
||
{
|
||
"if": {
|
||
"field": "name",
|
||
"contains": "PROD"
|
||
},
|
||
"then": { "effect": "audit" }
|
||
}
|
||
resource:
|
||
name: "my-prod-vm"
|
||
want_effect: "audit"
|
||
|
||
- note: contains_string_unicode_sharp_s
|
||
policy_rule: |
|
||
{
|
||
"if": {
|
||
"field": "tags.description",
|
||
"contains": "STRASSE"
|
||
},
|
||
"then": { "effect": "audit" }
|
||
}
|
||
resource:
|
||
tags:
|
||
description: "Die Straße ist lang"
|
||
want_effect: "audit"
|
||
|
||
- note: notContains_case_insensitive
|
||
policy_rule: |
|
||
{
|
||
"if": {
|
||
"field": "name",
|
||
"notContains": "PROD"
|
||
},
|
||
"then": { "effect": "audit" }
|
||
}
|
||
resource:
|
||
name: "my-prod-vm"
|
||
want_undefined: true
|
||
|
||
# =========================================================================
|
||
# containsKey — key name case insensitivity
|
||
# =========================================================================
|
||
|
||
- note: containsKey_case_insensitive
|
||
policy_rule: |
|
||
{
|
||
"if": {
|
||
"field": "tags",
|
||
"containsKey": "Environment"
|
||
},
|
||
"then": { "effect": "audit" }
|
||
}
|
||
resource:
|
||
tags:
|
||
environment: "production"
|
||
want_effect: "audit"
|
||
|
||
- note: notContainsKey_case_insensitive
|
||
policy_rule: |
|
||
{
|
||
"if": {
|
||
"field": "tags",
|
||
"notContainsKey": "Environment"
|
||
},
|
||
"then": { "effect": "deny" }
|
||
}
|
||
resource:
|
||
tags:
|
||
environment: "production"
|
||
want_undefined: true
|
||
|
||
# =========================================================================
|
||
# in / notIn — case-insensitive membership
|
||
# =========================================================================
|
||
|
||
- note: in_case_insensitive
|
||
policy_rule: |
|
||
{
|
||
"if": {
|
||
"field": "location",
|
||
"in": ["EASTUS", "WESTUS2", "CENTRALUS"]
|
||
},
|
||
"then": { "effect": "audit" }
|
||
}
|
||
resource:
|
||
location: "westus2"
|
||
want_effect: "audit"
|
||
|
||
- note: in_no_match
|
||
policy_rule: |
|
||
{
|
||
"if": {
|
||
"field": "location",
|
||
"in": ["eastus", "westus2"]
|
||
},
|
||
"then": { "effect": "audit" }
|
||
}
|
||
resource:
|
||
location: "northeurope"
|
||
want_undefined: true
|
||
|
||
- note: notIn_case_insensitive
|
||
policy_rule: |
|
||
{
|
||
"if": {
|
||
"field": "location",
|
||
"notIn": ["EASTUS", "WESTUS2"]
|
||
},
|
||
"then": { "effect": "deny" }
|
||
}
|
||
resource:
|
||
location: "westus2"
|
||
want_undefined: true
|
||
|
||
# =========================================================================
|
||
# greater / less — case-insensitive string ordering
|
||
# =========================================================================
|
||
|
||
- note: greater_string_case_insensitive
|
||
policy_rule: |
|
||
{
|
||
"if": {
|
||
"field": "name",
|
||
"greater": "ALPHA"
|
||
},
|
||
"then": { "effect": "audit" }
|
||
}
|
||
resource:
|
||
name: "beta"
|
||
want_effect: "audit"
|
||
|
||
- note: greater_string_equal_different_case
|
||
policy_rule: |
|
||
{
|
||
"if": {
|
||
"field": "name",
|
||
"greater": "HELLO"
|
||
},
|
||
"then": { "effect": "audit" }
|
||
}
|
||
resource:
|
||
name: "hello"
|
||
want_undefined: true
|
||
|
||
- note: less_string_case_insensitive
|
||
policy_rule: |
|
||
{
|
||
"if": {
|
||
"field": "name",
|
||
"less": "BETA"
|
||
},
|
||
"then": { "effect": "audit" }
|
||
}
|
||
resource:
|
||
name: "alpha"
|
||
want_effect: "audit"
|
||
|
||
- note: greaterOrEquals_string_case_insensitive
|
||
policy_rule: |
|
||
{
|
||
"if": {
|
||
"field": "name",
|
||
"greaterOrEquals": "HELLO"
|
||
},
|
||
"then": { "effect": "audit" }
|
||
}
|
||
resource:
|
||
name: "hello"
|
||
want_effect: "audit"
|
||
|
||
- note: lessOrEquals_string_case_insensitive
|
||
policy_rule: |
|
||
{
|
||
"if": {
|
||
"field": "name",
|
||
"lessOrEquals": "HELLO"
|
||
},
|
||
"then": { "effect": "audit" }
|
||
}
|
||
resource:
|
||
name: "hello"
|
||
want_effect: "audit"
|
||
|
||
# =========================================================================
|
||
# like / notLike — case-insensitive wildcard matching
|
||
# =========================================================================
|
||
|
||
- note: like_case_insensitive
|
||
policy_rule: |
|
||
{
|
||
"if": {
|
||
"field": "name",
|
||
"like": "MY-*-VM"
|
||
},
|
||
"then": { "effect": "audit" }
|
||
}
|
||
resource:
|
||
name: "my-prod-vm"
|
||
want_effect: "audit"
|
||
|
||
- note: like_case_insensitive_no_match
|
||
policy_rule: |
|
||
{
|
||
"if": {
|
||
"field": "name",
|
||
"like": "MY-*-VM"
|
||
},
|
||
"then": { "effect": "audit" }
|
||
}
|
||
resource:
|
||
name: "your-prod-vm"
|
||
want_undefined: true
|
||
|
||
- note: notLike_case_insensitive
|
||
policy_rule: |
|
||
{
|
||
"if": {
|
||
"field": "name",
|
||
"notLike": "MY-*-VM"
|
||
},
|
||
"then": { "effect": "audit" }
|
||
}
|
||
resource:
|
||
name: "my-prod-vm"
|
||
want_undefined: true
|
||
|
||
# =========================================================================
|
||
# match / matchInsensitively
|
||
# =========================================================================
|
||
|
||
- note: match_is_case_sensitive
|
||
policy_rule: |
|
||
{
|
||
"if": {
|
||
"field": "name",
|
||
"match": "abc-##"
|
||
},
|
||
"then": { "effect": "audit" }
|
||
}
|
||
resource:
|
||
name: "abc-12"
|
||
want_effect: "audit"
|
||
|
||
- note: match_case_sensitive_literal_no_match
|
||
policy_rule: |
|
||
{
|
||
"if": {
|
||
"field": "name",
|
||
"match": "abc-##"
|
||
},
|
||
"then": { "effect": "audit" }
|
||
}
|
||
resource:
|
||
name: "ABC-12"
|
||
want_undefined: true
|
||
|
||
- note: matchInsensitively_case_insensitive
|
||
policy_rule: |
|
||
{
|
||
"if": {
|
||
"field": "name",
|
||
"matchInsensitively": "abc-##"
|
||
},
|
||
"then": { "effect": "audit" }
|
||
}
|
||
resource:
|
||
name: "ABC-12"
|
||
want_effect: "audit"
|
||
|
||
# =========================================================================
|
||
# Property key casing (ARM OrdinalIgnoreCase)
|
||
# =========================================================================
|
||
|
||
- note: property_key_case_insensitive
|
||
policy_rule: |
|
||
{
|
||
"if": {
|
||
"field": "properties.enableHttpsTrafficOnly",
|
||
"equals": true
|
||
},
|
||
"then": { "effect": "audit" }
|
||
}
|
||
resource:
|
||
properties:
|
||
EnableHttpsTrafficOnly: true
|
||
want_effect: "audit"
|
||
|
||
# =========================================================================
|
||
# type field — case-insensitive resource type matching
|
||
# =========================================================================
|
||
|
||
- note: type_case_insensitive_upper
|
||
policy_rule: |
|
||
{
|
||
"if": {
|
||
"field": "type",
|
||
"equals": "MICROSOFT.COMPUTE/VIRTUALMACHINES"
|
||
},
|
||
"then": { "effect": "deny" }
|
||
}
|
||
resource:
|
||
type: "Microsoft.Compute/virtualMachines"
|
||
want_effect: "deny"
|
||
|
||
- note: type_case_insensitive_lower
|
||
policy_rule: |
|
||
{
|
||
"if": {
|
||
"field": "type",
|
||
"equals": "microsoft.compute/virtualmachines"
|
||
},
|
||
"then": { "effect": "deny" }
|
||
}
|
||
resource:
|
||
type: "Microsoft.Compute/virtualMachines"
|
||
want_effect: "deny"
|
||
|
||
# =========================================================================
|
||
# contains with array — case-insensitive element matching
|
||
# =========================================================================
|
||
|
||
- note: contains_array_case_insensitive
|
||
policy_rule: |
|
||
{
|
||
"if": {
|
||
"field": "properties.allowedLocations",
|
||
"contains": "WESTUS2"
|
||
},
|
||
"then": { "effect": "audit" }
|
||
}
|
||
resource:
|
||
properties:
|
||
allowedLocations:
|
||
- "eastus"
|
||
- "westus2"
|
||
- "centralus"
|
||
want_effect: "audit"
|
||
|
||
- note: notContains_array_case_insensitive
|
||
policy_rule: |
|
||
{
|
||
"if": {
|
||
"field": "properties.allowedLocations",
|
||
"notContains": "WESTUS2"
|
||
},
|
||
"then": { "effect": "deny" }
|
||
}
|
||
resource:
|
||
properties:
|
||
allowedLocations:
|
||
- "eastus"
|
||
- "westus2"
|
||
want_undefined: true
|
||
|
||
# =========================================================================
|
||
# exists — not affected by casing (boolean check)
|
||
# =========================================================================
|
||
|
||
- note: exists_tag_case_insensitive_name
|
||
policy_rule: |
|
||
{
|
||
"if": {
|
||
"field": "tags.Environment",
|
||
"exists": true
|
||
},
|
||
"then": { "effect": "deny" }
|
||
}
|
||
resource:
|
||
tags:
|
||
environment: "production"
|
||
want_effect: "deny"
|
||
|
||
- note: exists_tag_missing
|
||
policy_rule: |
|
||
{
|
||
"if": {
|
||
"field": "tags.costCenter",
|
||
"exists": false
|
||
},
|
||
"then": { "effect": "deny" }
|
||
}
|
||
resource:
|
||
tags:
|
||
environment: "production"
|
||
want_effect: "deny"
|
||
|
||
# =========================================================================
|
||
# Edge cases: empty strings, numbers, booleans
|
||
# =========================================================================
|
||
|
||
- note: equals_empty_string
|
||
policy_rule: |
|
||
{
|
||
"if": {
|
||
"field": "tags.label",
|
||
"equals": ""
|
||
},
|
||
"then": { "effect": "audit" }
|
||
}
|
||
resource:
|
||
tags:
|
||
label: ""
|
||
want_effect: "audit"
|
||
|
||
- note: equals_number_not_affected_by_casing
|
||
policy_rule: |
|
||
{
|
||
"if": {
|
||
"field": "properties.count",
|
||
"equals": 42
|
||
},
|
||
"then": { "effect": "audit" }
|
||
}
|
||
resource:
|
||
properties:
|
||
count: 42
|
||
want_effect: "audit"
|
||
|
||
- note: equals_boolean_not_affected_by_casing
|
||
policy_rule: |
|
||
{
|
||
"if": {
|
||
"field": "properties.enabled",
|
||
"equals": true
|
||
},
|
||
"then": { "effect": "audit" }
|
||
}
|
||
resource:
|
||
properties:
|
||
enabled: true
|
||
want_effect: "audit"
|
||
|
||
- note: equals_string_number_coercion_with_casing
|
||
policy_rule: |
|
||
{
|
||
"if": {
|
||
"field": "properties.port",
|
||
"equals": "443"
|
||
},
|
||
"then": { "effect": "audit" }
|
||
}
|
||
resource:
|
||
properties:
|
||
port: 443
|
||
want_effect: "audit"
|
||
|
||
# =========================================================================
|
||
# Corner cases: undefined / missing fields
|
||
# =========================================================================
|
||
|
||
- note: equals_missing_field_is_undefined
|
||
policy_rule: |
|
||
{
|
||
"if": {
|
||
"field": "tags.missing",
|
||
"equals": "anything"
|
||
},
|
||
"then": { "effect": "deny" }
|
||
}
|
||
resource:
|
||
tags:
|
||
environment: "production"
|
||
want_undefined: true
|
||
|
||
- note: notEquals_missing_field_fires
|
||
policy_rule: |
|
||
{
|
||
"if": {
|
||
"field": "tags.missing",
|
||
"notEquals": "anything"
|
||
},
|
||
"then": { "effect": "deny" }
|
||
}
|
||
resource:
|
||
tags:
|
||
environment: "production"
|
||
want_effect: "deny"
|
||
|
||
- note: contains_string_missing_field_is_undefined
|
||
policy_rule: |
|
||
{
|
||
"if": {
|
||
"field": "tags.missing",
|
||
"contains": "X"
|
||
},
|
||
"then": { "effect": "audit" }
|
||
}
|
||
resource:
|
||
tags:
|
||
environment: "production"
|
||
want_undefined: true
|
||
|
||
- note: in_missing_field_is_undefined
|
||
policy_rule: |
|
||
{
|
||
"if": {
|
||
"field": "tags.missing",
|
||
"in": ["a", "b"]
|
||
},
|
||
"then": { "effect": "audit" }
|
||
}
|
||
resource:
|
||
tags:
|
||
environment: "production"
|
||
want_undefined: true
|
||
|
||
- note: greater_missing_field_is_undefined
|
||
policy_rule: |
|
||
{
|
||
"if": {
|
||
"field": "tags.missing",
|
||
"greater": "z"
|
||
},
|
||
"then": { "effect": "audit" }
|
||
}
|
||
resource:
|
||
tags:
|
||
environment: "production"
|
||
want_undefined: true
|
||
|
||
# =========================================================================
|
||
# Tag bracket notation — tags['Key'] equivalent to tags.Key
|
||
# =========================================================================
|
||
|
||
- note: tag_bracket_notation_case_insensitive
|
||
policy_rule: |
|
||
{
|
||
"if": {
|
||
"field": "tags['Environment']",
|
||
"equals": "production"
|
||
},
|
||
"then": { "effect": "deny" }
|
||
}
|
||
resource:
|
||
tags:
|
||
environment: "production"
|
||
want_effect: "deny"
|
||
|
||
- note: tag_bracket_notation_value_ci
|
||
policy_rule: |
|
||
{
|
||
"if": {
|
||
"field": "tags['costCenter']",
|
||
"equals": "FINANCE"
|
||
},
|
||
"then": { "effect": "audit" }
|
||
}
|
||
resource:
|
||
tags:
|
||
CostCenter: "finance"
|
||
want_effect: "audit"
|
||
|
||
# =========================================================================
|
||
# String ↔ Bool coercion with mixed casing
|
||
# =========================================================================
|
||
|
||
- note: equals_string_true_uppercase_coercion
|
||
policy_rule: |
|
||
{
|
||
"if": {
|
||
"field": "properties.flag",
|
||
"equals": true
|
||
},
|
||
"then": { "effect": "audit" }
|
||
}
|
||
resource:
|
||
properties:
|
||
flag: "TRUE"
|
||
want_effect: "audit"
|
||
|
||
- note: equals_string_false_mixed_case_coercion
|
||
policy_rule: |
|
||
{
|
||
"if": {
|
||
"field": "properties.flag",
|
||
"equals": false
|
||
},
|
||
"then": { "effect": "audit" }
|
||
}
|
||
resource:
|
||
properties:
|
||
flag: "False"
|
||
want_effect: "audit"
|
||
|
||
# =========================================================================
|
||
# Unicode: Greek sigma variants (Σ/σ/ς all fold to σ)
|
||
# =========================================================================
|
||
|
||
- note: equals_greek_sigma_upper_vs_lower
|
||
policy_rule: |
|
||
{
|
||
"if": {
|
||
"field": "tags.label",
|
||
"equals": "ΣΕΛΑΣ"
|
||
},
|
||
"then": { "effect": "audit" }
|
||
}
|
||
resource:
|
||
tags:
|
||
label: "σελας"
|
||
want_effect: "audit"
|
||
|
||
- note: equals_greek_final_sigma
|
||
policy_rule: |
|
||
{
|
||
"if": {
|
||
"field": "tags.label",
|
||
"equals": "ΚΟΣΜΟΣ"
|
||
},
|
||
"then": { "effect": "audit" }
|
||
}
|
||
resource:
|
||
tags:
|
||
label: "κοσμος"
|
||
want_effect: "audit"
|
||
|
||
# =========================================================================
|
||
# notEquals with Unicode — should NOT fire when values match after folding
|
||
# =========================================================================
|
||
|
||
- note: notEquals_unicode_sharp_s_equal
|
||
policy_rule: |
|
||
{
|
||
"if": {
|
||
"field": "tags.description",
|
||
"notEquals": "STRASSE"
|
||
},
|
||
"then": { "effect": "deny" }
|
||
}
|
||
resource:
|
||
tags:
|
||
description: "Straße"
|
||
want_undefined: true
|
||
|
||
# =========================================================================
|
||
# in/notIn with Unicode values
|
||
# =========================================================================
|
||
|
||
- note: in_unicode_sharp_s_in_array
|
||
policy_rule: |
|
||
{
|
||
"if": {
|
||
"field": "tags.street",
|
||
"in": ["STRASSE", "AVENUE", "BOULEVARD"]
|
||
},
|
||
"then": { "effect": "audit" }
|
||
}
|
||
resource:
|
||
tags:
|
||
street: "Straße"
|
||
want_effect: "audit"
|
||
|
||
- note: notIn_unicode_value_present
|
||
policy_rule: |
|
||
{
|
||
"if": {
|
||
"field": "tags.street",
|
||
"notIn": ["STRASSE", "AVENUE"]
|
||
},
|
||
"then": { "effect": "deny" }
|
||
}
|
||
resource:
|
||
tags:
|
||
street: "Straße"
|
||
want_undefined: true
|
||
|
||
# =========================================================================
|
||
# contains — empty needle/haystack edge cases
|
||
# =========================================================================
|
||
|
||
- note: contains_empty_needle_always_matches
|
||
policy_rule: |
|
||
{
|
||
"if": {
|
||
"field": "name",
|
||
"contains": ""
|
||
},
|
||
"then": { "effect": "audit" }
|
||
}
|
||
resource:
|
||
name: "anything"
|
||
want_effect: "audit"
|
||
|
||
- note: contains_empty_haystack_no_match
|
||
policy_rule: |
|
||
{
|
||
"if": {
|
||
"field": "name",
|
||
"contains": "something"
|
||
},
|
||
"then": { "effect": "audit" }
|
||
}
|
||
resource:
|
||
name: ""
|
||
want_undefined: true
|
||
|
||
- note: notContains_string_truly_absent
|
||
policy_rule: |
|
||
{
|
||
"if": {
|
||
"field": "name",
|
||
"notContains": "STAGING"
|
||
},
|
||
"then": { "effect": "audit" }
|
||
}
|
||
resource:
|
||
name: "my-prod-vm"
|
||
want_effect: "audit"
|
||
|
||
# =========================================================================
|
||
# contains with Unicode ligature as substring
|
||
# =========================================================================
|
||
|
||
- note: contains_unicode_ligature_substring
|
||
policy_rule: |
|
||
{
|
||
"if": {
|
||
"field": "tags.description",
|
||
"contains": "ffice"
|
||
},
|
||
"then": { "effect": "audit" }
|
||
}
|
||
resource:
|
||
tags:
|
||
description: "The OFFICE is closed"
|
||
want_effect: "audit"
|
||
|
||
# =========================================================================
|
||
# containsKey — key truly missing vs case mismatch
|
||
# =========================================================================
|
||
|
||
- note: containsKey_key_truly_missing
|
||
policy_rule: |
|
||
{
|
||
"if": {
|
||
"field": "tags",
|
||
"containsKey": "billing"
|
||
},
|
||
"then": { "effect": "audit" }
|
||
}
|
||
resource:
|
||
tags:
|
||
environment: "production"
|
||
want_undefined: true
|
||
|
||
- note: notContainsKey_key_truly_missing
|
||
policy_rule: |
|
||
{
|
||
"if": {
|
||
"field": "tags",
|
||
"notContainsKey": "billing"
|
||
},
|
||
"then": { "effect": "deny" }
|
||
}
|
||
resource:
|
||
tags:
|
||
environment: "production"
|
||
want_effect: "deny"
|
||
|
||
# =========================================================================
|
||
# greater/less with Unicode — ß folds to "ss" for ordering
|
||
# =========================================================================
|
||
|
||
- note: greater_unicode_sharp_s_equal_after_fold
|
||
policy_rule: |
|
||
{
|
||
"if": {
|
||
"field": "tags.street",
|
||
"greater": "strasse"
|
||
},
|
||
"then": { "effect": "audit" }
|
||
}
|
||
resource:
|
||
tags:
|
||
street: "Straße"
|
||
want_undefined: true
|
||
|
||
- note: lessOrEquals_unicode_sharp_s
|
||
policy_rule: |
|
||
{
|
||
"if": {
|
||
"field": "tags.street",
|
||
"lessOrEquals": "STRASSE"
|
||
},
|
||
"then": { "effect": "audit" }
|
||
}
|
||
resource:
|
||
tags:
|
||
street: "Straße"
|
||
want_effect: "audit"
|
||
|
||
# =========================================================================
|
||
# like with Unicode — input folded before wildcard matching
|
||
# =========================================================================
|
||
|
||
- note: like_unicode_folded_match
|
||
policy_rule: |
|
||
{
|
||
"if": {
|
||
"field": "tags.description",
|
||
"like": "die strasse*"
|
||
},
|
||
"then": { "effect": "audit" }
|
||
}
|
||
resource:
|
||
tags:
|
||
description: "Die Straße ist lang"
|
||
want_effect: "audit"
|
||
|
||
# =========================================================================
|
||
# matchInsensitively with Unicode literals
|
||
# =========================================================================
|
||
|
||
- note: matchInsensitively_unicode_literal
|
||
policy_rule: |
|
||
{
|
||
"if": {
|
||
"field": "tags.code",
|
||
"matchInsensitively": "strasse-##"
|
||
},
|
||
"then": { "effect": "audit" }
|
||
}
|
||
resource:
|
||
tags:
|
||
code: "STRASSE-42"
|
||
want_effect: "audit"
|
||
|
||
# =========================================================================
|
||
# Nested property key casing (deep paths)
|
||
# =========================================================================
|
||
|
||
- note: nested_property_key_deep_path
|
||
policy_rule: |
|
||
{
|
||
"if": {
|
||
"field": "properties.networkProfile.primaryNic",
|
||
"equals": "nic-01"
|
||
},
|
||
"then": { "effect": "audit" }
|
||
}
|
||
resource:
|
||
properties:
|
||
NetworkProfile:
|
||
PrimaryNic: "NIC-01"
|
||
want_effect: "audit"
|
||
|
||
# =========================================================================
|
||
# Multiple tags — lookup finds correct tag by name
|
||
# =========================================================================
|
||
|
||
- note: multiple_tags_lookup_correct_one
|
||
policy_rule: |
|
||
{
|
||
"if": {
|
||
"allOf": [
|
||
{ "field": "tags.Environment", "equals": "production" },
|
||
{ "field": "tags.CostCenter", "equals": "FINANCE" }
|
||
]
|
||
},
|
||
"then": { "effect": "deny" }
|
||
}
|
||
resource:
|
||
tags:
|
||
environment: "PRODUCTION"
|
||
costCenter: "finance"
|
||
want_effect: "deny"
|
||
|
||
# =========================================================================
|
||
# in with single-element array
|
||
# =========================================================================
|
||
|
||
- note: in_single_element_case_insensitive
|
||
policy_rule: |
|
||
{
|
||
"if": {
|
||
"field": "location",
|
||
"in": ["WestUS2"]
|
||
},
|
||
"then": { "effect": "audit" }
|
||
}
|
||
resource:
|
||
location: "westus2"
|
||
want_effect: "audit"
|
||
|
||
# =========================================================================
|
||
# Null value interactions
|
||
# =========================================================================
|
||
|
||
- note: equals_null_explicit
|
||
policy_rule: |
|
||
{
|
||
"if": {
|
||
"field": "properties.optionalField",
|
||
"equals": null
|
||
},
|
||
"then": { "effect": "audit" }
|
||
}
|
||
resource:
|
||
properties:
|
||
optionalField: null
|
||
want_effect: "audit"
|
||
|
||
- note: equals_null_missing_field
|
||
policy_rule: |
|
||
{
|
||
"if": {
|
||
"field": "properties.optionalField",
|
||
"equals": null
|
||
},
|
||
"then": { "effect": "audit" }
|
||
}
|
||
resource:
|
||
properties: {}
|
||
want_effect: "audit"
|
||
|
||
- note: notEquals_null_with_string_value
|
||
policy_rule: |
|
||
{
|
||
"if": {
|
||
"field": "properties.optionalField",
|
||
"notEquals": null
|
||
},
|
||
"then": { "effect": "audit" }
|
||
}
|
||
resource:
|
||
properties:
|
||
optionalField: "has-a-value"
|
||
want_effect: "audit"
|
||
|
||
# =========================================================================
|
||
# String self-comparison with different casing
|
||
# =========================================================================
|
||
|
||
- note: equals_self_different_case
|
||
policy_rule: |
|
||
{
|
||
"if": {
|
||
"field": "name",
|
||
"equals": "My-Production-VM"
|
||
},
|
||
"then": { "effect": "audit" }
|
||
}
|
||
resource:
|
||
name: "MY-PRODUCTION-VM"
|
||
want_effect: "audit"
|