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>
483 lines
14 KiB
YAML
483 lines
14 KiB
YAML
# Copyright (c) Microsoft Corporation.
|
|
# Licensed under the MIT License.
|
|
|
|
# Complex Policies Test Suite
|
|
# Tests realistic, multi-layer Azure Policy definitions covering combinations of
|
|
# operators, logical combinators, expressions, fields, counts, and effects.
|
|
|
|
cases:
|
|
# =========================================================================
|
|
# Require HTTPS for storage accounts
|
|
# =========================================================================
|
|
|
|
- note: require_https_storage
|
|
policy_rule: |
|
|
{
|
|
"if": {
|
|
"allOf": [
|
|
{
|
|
"field": "type",
|
|
"equals": "Microsoft.Storage/storageAccounts"
|
|
},
|
|
{
|
|
"field": "properties.supportsHttpsTrafficOnly",
|
|
"notEquals": true
|
|
}
|
|
]
|
|
},
|
|
"then": { "effect": "deny" }
|
|
}
|
|
resource:
|
|
type: "Microsoft.Storage/storageAccounts"
|
|
properties:
|
|
supportsHttpsTrafficOnly: false
|
|
want_effect: "deny"
|
|
|
|
# =========================================================================
|
|
# Allowed locations with parameterized effect
|
|
# =========================================================================
|
|
|
|
- note: allowed_locations_parameterized
|
|
policy_rule: |
|
|
{
|
|
"if": {
|
|
"allOf": [
|
|
{
|
|
"field": "location",
|
|
"notIn": "[parameters('allowedLocations')]"
|
|
},
|
|
{
|
|
"field": "location",
|
|
"notEquals": "global"
|
|
},
|
|
{
|
|
"field": "type",
|
|
"notEquals": "Microsoft.AzureActiveDirectory/b2cDirectories"
|
|
}
|
|
]
|
|
},
|
|
"then": {
|
|
"effect": "[parameters('effect')]"
|
|
}
|
|
}
|
|
parameters:
|
|
allowedLocations:
|
|
- "eastus"
|
|
- "westus"
|
|
effect: "deny"
|
|
resource:
|
|
type: "Microsoft.Compute/virtualMachines"
|
|
location: "northeurope"
|
|
want_effect: "deny"
|
|
|
|
# =========================================================================
|
|
# Require tags with parameter-driven enforcement
|
|
# =========================================================================
|
|
|
|
- note: require_tag_environment
|
|
policy_rule: |
|
|
{
|
|
"if": {
|
|
"allOf": [
|
|
{
|
|
"field": "type",
|
|
"notEquals": "Microsoft.Resources/subscriptions"
|
|
},
|
|
{
|
|
"field": "[concat('tags[', parameters('tagName'), ']')]",
|
|
"exists": false
|
|
}
|
|
]
|
|
},
|
|
"then": {
|
|
"effect": "deny",
|
|
"details": {
|
|
"message": "Required tag is missing"
|
|
}
|
|
}
|
|
}
|
|
parameters:
|
|
tagName: "environment"
|
|
resource:
|
|
type: "Microsoft.Compute/virtualMachines"
|
|
tags: {}
|
|
want_effect: "deny"
|
|
|
|
# =========================================================================
|
|
# NSG rule restriction — deny risky inbound ports
|
|
# =========================================================================
|
|
|
|
- note: deny_risky_inbound_nsg
|
|
policy_rule: |
|
|
{
|
|
"if": {
|
|
"allOf": [
|
|
{
|
|
"field": "type",
|
|
"equals": "Microsoft.Network/networkSecurityGroups/securityRules"
|
|
},
|
|
{
|
|
"field": "properties.direction",
|
|
"equals": "Inbound"
|
|
},
|
|
{
|
|
"field": "properties.access",
|
|
"equals": "Allow"
|
|
},
|
|
{
|
|
"anyOf": [
|
|
{
|
|
"field": "properties.destinationPortRange",
|
|
"in": ["22", "3389", "*"]
|
|
},
|
|
{
|
|
"field": "properties.sourceAddressPrefix",
|
|
"in": ["*", "Internet", "0.0.0.0/0"]
|
|
}
|
|
]
|
|
}
|
|
]
|
|
},
|
|
"then": {
|
|
"effect": "deny",
|
|
"details": {
|
|
"message": "Risky inbound NSG rules are not allowed"
|
|
}
|
|
}
|
|
}
|
|
resource:
|
|
type: "Microsoft.Network/networkSecurityGroups/securityRules"
|
|
properties:
|
|
direction: "Inbound"
|
|
access: "Allow"
|
|
destinationPortRange: "22"
|
|
sourceAddressPrefix: "*"
|
|
want_effect: "deny"
|
|
|
|
# =========================================================================
|
|
# Modify — add tags if missing
|
|
# =========================================================================
|
|
|
|
- note: modify_add_tags
|
|
policy_rule: |
|
|
{
|
|
"if": {
|
|
"allOf": [
|
|
{
|
|
"field": "type",
|
|
"equals": "Microsoft.Compute/virtualMachines"
|
|
},
|
|
{
|
|
"anyOf": [
|
|
{ "field": "tags.environment", "exists": false },
|
|
{ "field": "tags.costCenter", "exists": false }
|
|
]
|
|
}
|
|
]
|
|
},
|
|
"then": {
|
|
"effect": "modify",
|
|
"details": {
|
|
"roleDefinitionIds": [
|
|
"/providers/Microsoft.Authorization/roleDefinitions/b24988ac-6180-42a0-ab88-20f7382dd24c"
|
|
],
|
|
"operations": [
|
|
{
|
|
"operation": "addOrReplace",
|
|
"field": "tags['environment']",
|
|
"value": "[if(empty(field('tags.environment')), 'unknown', field('tags.environment'))]"
|
|
},
|
|
{
|
|
"operation": "addOrReplace",
|
|
"field": "tags['costCenter']",
|
|
"value": "[if(empty(field('tags.costCenter')), 'unassigned', field('tags.costCenter'))]"
|
|
}
|
|
]
|
|
}
|
|
}
|
|
}
|
|
resource:
|
|
type: "Microsoft.Compute/virtualMachines"
|
|
tags:
|
|
environment: "prod"
|
|
want_effect: "modify"
|
|
|
|
# =========================================================================
|
|
# Count — deny if too many open NSG rules
|
|
# =========================================================================
|
|
|
|
- note: deny_excessive_open_nsg_rules
|
|
policy_rule: |
|
|
{
|
|
"if": {
|
|
"allOf": [
|
|
{
|
|
"field": "type",
|
|
"equals": "Microsoft.Network/networkSecurityGroups"
|
|
},
|
|
{
|
|
"count": {
|
|
"field": "securityRules[*]",
|
|
"where": {
|
|
"allOf": [
|
|
{
|
|
"field": "securityRules[*].access",
|
|
"equals": "Allow"
|
|
},
|
|
{
|
|
"field": "securityRules[*].direction",
|
|
"equals": "Inbound"
|
|
},
|
|
{
|
|
"field": "securityRules[*].sourceAddressPrefix",
|
|
"equals": "*"
|
|
}
|
|
]
|
|
}
|
|
},
|
|
"greater": 0
|
|
}
|
|
]
|
|
},
|
|
"then": { "effect": "deny" }
|
|
}
|
|
resource:
|
|
type: "Microsoft.Network/networkSecurityGroups"
|
|
securityRules:
|
|
-
|
|
access: "Allow"
|
|
direction: "Inbound"
|
|
sourceAddressPrefix: "*"
|
|
want_effect: "deny"
|
|
|
|
# =========================================================================
|
|
# AuditIfNotExists — require diagnostics settings
|
|
# =========================================================================
|
|
|
|
- note: audit_diagnostics_settings
|
|
policy_rule: |
|
|
{
|
|
"if": {
|
|
"field": "type",
|
|
"equals": "Microsoft.KeyVault/vaults"
|
|
},
|
|
"then": {
|
|
"effect": "auditIfNotExists",
|
|
"details": {
|
|
"type": "Microsoft.Insights/diagnosticSettings",
|
|
"existenceCondition": {
|
|
"allOf": [
|
|
{
|
|
"field": "properties.logs.enabled",
|
|
"equals": true
|
|
},
|
|
{
|
|
"field": "properties.logs.retentionPolicy.enabled",
|
|
"equals": true
|
|
},
|
|
{
|
|
"field": "properties.logs.retentionPolicy.days",
|
|
"greaterOrEquals": 90
|
|
}
|
|
]
|
|
}
|
|
}
|
|
}
|
|
}
|
|
resource:
|
|
type: "Microsoft.KeyVault/vaults"
|
|
host_await:
|
|
- key:
|
|
operation: "lookup_related_resources"
|
|
type: "Microsoft.Insights/diagnosticSettings"
|
|
response: null
|
|
want_effect: "auditIfNotExists"
|
|
|
|
# =========================================================================
|
|
# DeployIfNotExists — deploy monitoring agent
|
|
# =========================================================================
|
|
|
|
- note: deploy_monitoring_agent
|
|
policy_rule: |
|
|
{
|
|
"if": {
|
|
"allOf": [
|
|
{
|
|
"field": "type",
|
|
"equals": "Microsoft.Compute/virtualMachines"
|
|
},
|
|
{
|
|
"field": "properties.storageProfile.imageReference.publisher",
|
|
"equals": "Canonical"
|
|
}
|
|
]
|
|
},
|
|
"then": {
|
|
"effect": "deployIfNotExists",
|
|
"details": {
|
|
"type": "Microsoft.Compute/virtualMachines/extensions",
|
|
"roleDefinitionIds": [
|
|
"/providers/Microsoft.Authorization/roleDefinitions/9980e02c-c2be-4d73-94e8-173b1dc7cf3c"
|
|
],
|
|
"existenceCondition": {
|
|
"allOf": [
|
|
{
|
|
"field": "properties.publisher",
|
|
"equals": "Microsoft.Azure.Monitor"
|
|
},
|
|
{
|
|
"field": "properties.type",
|
|
"equals": "AzureMonitorLinuxAgent"
|
|
}
|
|
]
|
|
},
|
|
"deployment": {
|
|
"properties": {
|
|
"mode": "incremental",
|
|
"template": {
|
|
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
|
|
"contentVersion": "1.0.0.0",
|
|
"parameters": {},
|
|
"resources": []
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
resource:
|
|
type: "Microsoft.Compute/virtualMachines"
|
|
properties:
|
|
storageProfile:
|
|
imageReference:
|
|
publisher: "Canonical"
|
|
host_await:
|
|
- response: null
|
|
want_effect: "deployIfNotExists"
|
|
|
|
# =========================================================================
|
|
# Value count with complex where — required tags
|
|
# =========================================================================
|
|
|
|
- note: required_tags_value_count
|
|
policy_rule: |
|
|
{
|
|
"if": {
|
|
"allOf": [
|
|
{
|
|
"field": "type",
|
|
"notEquals": "Microsoft.Resources/subscriptions"
|
|
},
|
|
{
|
|
"count": {
|
|
"value": "[parameters('requiredTags')]",
|
|
"name": "tagName",
|
|
"where": {
|
|
"field": "[concat('tags[', current('tagName'), ']')]",
|
|
"exists": true
|
|
}
|
|
},
|
|
"notEquals": "[length(parameters('requiredTags'))]"
|
|
}
|
|
]
|
|
},
|
|
"then": {
|
|
"effect": "deny",
|
|
"details": {
|
|
"message": "Not all required tags are present"
|
|
}
|
|
}
|
|
}
|
|
parameters:
|
|
requiredTags:
|
|
- "environment"
|
|
- "costCenter"
|
|
- "owner"
|
|
resource:
|
|
type: "Microsoft.Compute/virtualMachines"
|
|
tags:
|
|
environment: "prod"
|
|
costCenter: "12345"
|
|
want_effect: "deny"
|
|
|
|
# =========================================================================
|
|
# Multi-resource type policy with not
|
|
# =========================================================================
|
|
|
|
- note: multi_type_with_not
|
|
policy_rule: |
|
|
{
|
|
"if": {
|
|
"allOf": [
|
|
{
|
|
"not": {
|
|
"anyOf": [
|
|
{ "field": "type", "equals": "Microsoft.Resources/subscriptions" },
|
|
{ "field": "type", "equals": "Microsoft.Resources/subscriptions/resourceGroups" },
|
|
{ "field": "type", "equals": "Microsoft.Authorization/roleAssignments" }
|
|
]
|
|
}
|
|
},
|
|
{
|
|
"field": "location",
|
|
"notIn": "[parameters('allowedLocations')]"
|
|
}
|
|
]
|
|
},
|
|
"then": {
|
|
"effect": "[parameters('effect')]",
|
|
"details": {
|
|
"message": "Resource location is not in the allowed list"
|
|
}
|
|
}
|
|
}
|
|
parameters:
|
|
allowedLocations:
|
|
- "eastus"
|
|
- "westus"
|
|
- "centralus"
|
|
effect: "deny"
|
|
resource:
|
|
type: "Microsoft.Compute/virtualMachines"
|
|
location: "southeastasia"
|
|
want_effect: "deny"
|
|
|
|
# =========================================================================
|
|
# Condition-free policy (always true if block is trivially satisfied)
|
|
# =========================================================================
|
|
|
|
- note: trivial_allOf_empty
|
|
policy_rule: |
|
|
{
|
|
"if": {
|
|
"allOf": []
|
|
},
|
|
"then": { "effect": "audit" }
|
|
}
|
|
resource:
|
|
type: "anything"
|
|
want_effect: "audit"
|
|
|
|
# =========================================================================
|
|
# Exists mixed with value comparisons
|
|
# =========================================================================
|
|
|
|
- note: exists_and_value_check
|
|
policy_rule: |
|
|
{
|
|
"if": {
|
|
"allOf": [
|
|
{ "field": "type", "equals": "Microsoft.Storage/storageAccounts" },
|
|
{ "field": "properties.networkAcls", "exists": true },
|
|
{ "field": "properties.networkAcls.defaultAction", "notEquals": "Deny" }
|
|
]
|
|
},
|
|
"then": { "effect": "deny" }
|
|
}
|
|
resource:
|
|
type: "Microsoft.Storage/storageAccounts"
|
|
properties:
|
|
networkAcls:
|
|
defaultAction: "Allow"
|
|
want_effect: "deny"
|