mirror of
https://github.com/microsoft/regorus.git
synced 2026-08-05 02:16:11 +00:00
Add constraint.rs module that parses Azure Policy JSON constraints into span-annotated AST nodes: - Logical combinators: allOf, anyOf, not - Leaf conditions: field/value with all 19 operators - Count blocks: field-count and value-count with where clauses Public API: parse_constraint() parses a standalone constraint from JSON. Includes YAML-driven test suite with 6 test files covering operators, fields, expressions, logical combinators, count, and parse errors.
555 lines
14 KiB
YAML
555 lines
14 KiB
YAML
# Copyright (c) Microsoft Corporation.
|
|
# Licensed under the MIT License.
|
|
|
|
# ARM Template Expressions Test Suite
|
|
# Tests [parameters(...)], [concat(...)], [field(...)], [if(...)], and other
|
|
# ARM template expression patterns in field, value, and effect positions.
|
|
|
|
cases:
|
|
# =========================================================================
|
|
# parameters() references
|
|
# =========================================================================
|
|
|
|
- note: expr_parameters_in_value
|
|
policy_rule: |
|
|
{
|
|
"if": {
|
|
"value": "[parameters('environment')]",
|
|
"equals": "production"
|
|
},
|
|
"then": { "effect": "deny" }
|
|
}
|
|
parameters:
|
|
environment: "production"
|
|
resource:
|
|
type: "any"
|
|
want_effect: "deny"
|
|
|
|
- note: expr_parameters_in_rhs
|
|
policy_rule: |
|
|
{
|
|
"if": {
|
|
"field": "location",
|
|
"in": "[parameters('allowedLocations')]"
|
|
},
|
|
"then": { "effect": "deny" }
|
|
}
|
|
parameters:
|
|
allowedLocations:
|
|
- "eastus"
|
|
- "westus"
|
|
resource:
|
|
location: "eastus"
|
|
want_effect: "deny"
|
|
|
|
- note: expr_parameters_in_effect
|
|
policy_rule: |
|
|
{
|
|
"if": {
|
|
"field": "type",
|
|
"equals": "Microsoft.Compute/virtualMachines"
|
|
},
|
|
"then": {
|
|
"effect": "[parameters('effect')]"
|
|
}
|
|
}
|
|
parameters:
|
|
effect: "deny"
|
|
resource:
|
|
type: "Microsoft.Compute/virtualMachines"
|
|
want_effect: "deny"
|
|
|
|
# =========================================================================
|
|
# concat()
|
|
# =========================================================================
|
|
|
|
- note: expr_concat_strings
|
|
policy_rule: |
|
|
{
|
|
"if": {
|
|
"value": "[concat('Microsoft.Compute/', 'virtualMachines')]",
|
|
"equals": "Microsoft.Compute/virtualMachines"
|
|
},
|
|
"then": { "effect": "audit" }
|
|
}
|
|
resource:
|
|
type: "any"
|
|
want_effect: "audit"
|
|
|
|
- note: expr_concat_with_parameters
|
|
policy_rule: |
|
|
{
|
|
"if": {
|
|
"value": "[concat(parameters('prefix'), '-vm')]",
|
|
"equals": "prod-vm"
|
|
},
|
|
"then": { "effect": "audit" }
|
|
}
|
|
parameters:
|
|
prefix: "prod"
|
|
resource:
|
|
type: "any"
|
|
want_effect: "audit"
|
|
|
|
- note: expr_concat_nested
|
|
policy_rule: |
|
|
{
|
|
"if": {
|
|
"value": "[concat(concat('a', 'b'), 'c')]",
|
|
"equals": "abc"
|
|
},
|
|
"then": { "effect": "audit" }
|
|
}
|
|
resource:
|
|
type: "any"
|
|
want_effect: "audit"
|
|
|
|
# =========================================================================
|
|
# field() function
|
|
# =========================================================================
|
|
|
|
- note: expr_field_function
|
|
policy_rule: |
|
|
{
|
|
"if": {
|
|
"value": "[field('name')]",
|
|
"contains": "prod"
|
|
},
|
|
"then": { "effect": "audit" }
|
|
}
|
|
resource:
|
|
name: "my-prod-vm"
|
|
want_effect: "audit"
|
|
|
|
- note: expr_field_in_concat
|
|
policy_rule: |
|
|
{
|
|
"if": {
|
|
"value": "[concat(field('type'), '/', field('name'))]",
|
|
"contains": "Microsoft.Compute"
|
|
},
|
|
"then": { "effect": "audit" }
|
|
}
|
|
resource:
|
|
type: "Microsoft.Compute/virtualMachines"
|
|
name: "vm1"
|
|
want_effect: "audit"
|
|
|
|
# =========================================================================
|
|
# if() conditional
|
|
# =========================================================================
|
|
|
|
- note: expr_if_conditional
|
|
policy_rule: |
|
|
{
|
|
"if": {
|
|
"value": "[if(equals(parameters('env'), 'prod'), 'deny', 'audit')]",
|
|
"equals": "deny"
|
|
},
|
|
"then": { "effect": "audit" }
|
|
}
|
|
parameters:
|
|
env: "prod"
|
|
resource:
|
|
type: "any"
|
|
want_effect: "audit"
|
|
|
|
# =========================================================================
|
|
# String functions
|
|
# =========================================================================
|
|
|
|
- note: expr_toLower
|
|
policy_rule: |
|
|
{
|
|
"if": {
|
|
"value": "[toLower(field('name'))]",
|
|
"equals": "my-vm"
|
|
},
|
|
"then": { "effect": "audit" }
|
|
}
|
|
resource:
|
|
name: "My-VM"
|
|
want_effect: "audit"
|
|
|
|
- note: expr_toUpper
|
|
policy_rule: |
|
|
{
|
|
"if": {
|
|
"value": "[toUpper(parameters('prefix'))]",
|
|
"equals": "PROD"
|
|
},
|
|
"then": { "effect": "audit" }
|
|
}
|
|
parameters:
|
|
prefix: "prod"
|
|
resource:
|
|
type: "any"
|
|
want_effect: "audit"
|
|
|
|
- note: expr_replace
|
|
policy_rule: |
|
|
{
|
|
"if": {
|
|
"value": "[replace(field('name'), '-', '_')]",
|
|
"equals": "my_prod_vm"
|
|
},
|
|
"then": { "effect": "audit" }
|
|
}
|
|
resource:
|
|
name: "my-prod-vm"
|
|
want_effect: "audit"
|
|
|
|
- note: expr_substring
|
|
policy_rule: |
|
|
{
|
|
"if": {
|
|
"value": "[substring(field('name'), 0, 4)]",
|
|
"equals": "prod"
|
|
},
|
|
"then": { "effect": "audit" }
|
|
}
|
|
resource:
|
|
name: "prod-vm-01"
|
|
want_effect: "audit"
|
|
|
|
# =========================================================================
|
|
# Numeric functions
|
|
# =========================================================================
|
|
|
|
- note: expr_length
|
|
policy_rule: |
|
|
{
|
|
"if": {
|
|
"value": "[length(parameters('allowedLocations'))]",
|
|
"greater": 0
|
|
},
|
|
"then": { "effect": "audit" }
|
|
}
|
|
parameters:
|
|
allowedLocations:
|
|
- "eastus"
|
|
- "westus"
|
|
resource:
|
|
type: "any"
|
|
want_effect: "audit"
|
|
|
|
- note: expr_add
|
|
policy_rule: |
|
|
{
|
|
"if": {
|
|
"value": "[add(parameters('base'), 1)]",
|
|
"greater": 5
|
|
},
|
|
"then": { "effect": "audit" }
|
|
}
|
|
parameters:
|
|
base: 10
|
|
resource:
|
|
type: "any"
|
|
want_effect: "audit"
|
|
|
|
# =========================================================================
|
|
# Context functions
|
|
# =========================================================================
|
|
|
|
- note: expr_resourceGroup
|
|
policy_rule: |
|
|
{
|
|
"if": {
|
|
"value": "[resourceGroup().location]",
|
|
"notIn": "[parameters('allowedLocations')]"
|
|
},
|
|
"then": { "effect": "deny" }
|
|
}
|
|
parameters:
|
|
allowedLocations:
|
|
- "westus2"
|
|
- "centralus"
|
|
resource:
|
|
type: "any"
|
|
want_effect: "deny"
|
|
|
|
- note: expr_subscription
|
|
policy_rule: |
|
|
{
|
|
"if": {
|
|
"value": "[subscription().subscriptionId]",
|
|
"equals": "00000000-0000-0000-0000-000000000000"
|
|
},
|
|
"then": { "effect": "audit" }
|
|
}
|
|
resource:
|
|
type: "any"
|
|
want_effect: "audit"
|
|
|
|
- note: expr_requestContext_apiVersion
|
|
policy_rule: |
|
|
{
|
|
"if": {
|
|
"value": "[requestContext().apiVersion]",
|
|
"greaterOrEquals": "2021-04-01"
|
|
},
|
|
"then": { "effect": "deny" }
|
|
}
|
|
context:
|
|
resourceGroup:
|
|
name: "myResourceGroup"
|
|
location: "eastus"
|
|
subscription:
|
|
subscriptionId: "00000000-0000-0000-0000-000000000000"
|
|
requestContext:
|
|
apiVersion: "2023-01-01"
|
|
resource:
|
|
type: "any"
|
|
want_effect: "deny"
|
|
|
|
- note: expr_requestContext_apiVersion_older
|
|
policy_rule: |
|
|
{
|
|
"if": {
|
|
"value": "[requestContext().apiVersion]",
|
|
"greaterOrEquals": "2024-06-01"
|
|
},
|
|
"then": { "effect": "deny" }
|
|
}
|
|
context:
|
|
resourceGroup:
|
|
name: "myResourceGroup"
|
|
location: "eastus"
|
|
subscription:
|
|
subscriptionId: "00000000-0000-0000-0000-000000000000"
|
|
requestContext:
|
|
apiVersion: "2023-01-01"
|
|
resource:
|
|
type: "any"
|
|
want_undefined: true
|
|
|
|
- note: expr_policy_assignmentId
|
|
policy_rule: |
|
|
{
|
|
"if": {
|
|
"value": "[policy().assignmentId]",
|
|
"equals": "/subscriptions/sub1/providers/Microsoft.Authorization/policyAssignments/myAssignment"
|
|
},
|
|
"then": { "effect": "audit" }
|
|
}
|
|
context:
|
|
resourceGroup:
|
|
name: "myResourceGroup"
|
|
location: "eastus"
|
|
subscription:
|
|
subscriptionId: "00000000-0000-0000-0000-000000000000"
|
|
policy:
|
|
assignmentId: "/subscriptions/sub1/providers/Microsoft.Authorization/policyAssignments/myAssignment"
|
|
definitionId: "/providers/Microsoft.Authorization/policyDefinitions/myDefinition"
|
|
setDefinitionId: ""
|
|
definitionReferenceId: ""
|
|
resource:
|
|
type: "any"
|
|
want_effect: "audit"
|
|
|
|
- note: expr_policy_definitionId
|
|
policy_rule: |
|
|
{
|
|
"if": {
|
|
"value": "[policy().definitionId]",
|
|
"contains": "myDefinition"
|
|
},
|
|
"then": { "effect": "deny" }
|
|
}
|
|
context:
|
|
resourceGroup:
|
|
name: "myResourceGroup"
|
|
location: "eastus"
|
|
subscription:
|
|
subscriptionId: "00000000-0000-0000-0000-000000000000"
|
|
policy:
|
|
assignmentId: "/subscriptions/sub1/providers/Microsoft.Authorization/policyAssignments/myAssignment"
|
|
definitionId: "/providers/Microsoft.Authorization/policyDefinitions/myDefinition"
|
|
resource:
|
|
type: "any"
|
|
want_effect: "deny"
|
|
|
|
# =========================================================================
|
|
# current() in count contexts
|
|
# =========================================================================
|
|
|
|
- note: expr_current_in_value_count
|
|
policy_rule: |
|
|
{
|
|
"if": {
|
|
"count": {
|
|
"value": "[parameters('requiredTags')]",
|
|
"name": "tagName",
|
|
"where": {
|
|
"value": "[current('tagName')]",
|
|
"notEquals": ""
|
|
}
|
|
},
|
|
"greater": 0
|
|
},
|
|
"then": { "effect": "audit" }
|
|
}
|
|
parameters:
|
|
requiredTags:
|
|
- "environment"
|
|
- "costCenter"
|
|
resource:
|
|
type: "any"
|
|
want_effect: "audit"
|
|
|
|
# =========================================================================
|
|
# Dot and index access in expressions
|
|
# =========================================================================
|
|
|
|
- note: expr_dot_access
|
|
policy_rule: |
|
|
{
|
|
"if": {
|
|
"value": "[resourceGroup().name]",
|
|
"equals": "myResourceGroup"
|
|
},
|
|
"then": { "effect": "audit" }
|
|
}
|
|
resource:
|
|
type: "any"
|
|
want_effect: "audit"
|
|
|
|
- note: expr_index_access
|
|
policy_rule: |
|
|
{
|
|
"if": {
|
|
"value": "[parameters('allowedLocations')[0]]",
|
|
"equals": "eastus"
|
|
},
|
|
"then": { "effect": "audit" }
|
|
}
|
|
parameters:
|
|
allowedLocations:
|
|
- "eastus"
|
|
- "westus"
|
|
resource:
|
|
type: "any"
|
|
want_effect: "audit"
|
|
|
|
# =========================================================================
|
|
# Escaped bracket literals (not expressions)
|
|
# =========================================================================
|
|
|
|
- note: escaped_bracket_literal
|
|
policy_rule: |
|
|
{
|
|
"if": {
|
|
"field": "name",
|
|
"equals": "[[not-an-expression]"
|
|
},
|
|
"then": { "effect": "audit" }
|
|
}
|
|
resource:
|
|
name: "[not-an-expression]"
|
|
want_effect: "audit"
|
|
|
|
# =========================================================================
|
|
# Complex nested expressions
|
|
# =========================================================================
|
|
|
|
- note: expr_complex_nested
|
|
policy_rule: |
|
|
{
|
|
"if": {
|
|
"value": "[if(contains(toLower(field('location')), 'us'), 'allowed', 'blocked')]",
|
|
"equals": "blocked"
|
|
},
|
|
"then": { "effect": "deny" }
|
|
}
|
|
resource:
|
|
location: "northeurope"
|
|
want_effect: "deny"
|
|
|
|
- note: expr_multiple_expression_fields
|
|
policy_rule: |
|
|
{
|
|
"if": {
|
|
"allOf": [
|
|
{
|
|
"value": "[parameters('environment')]",
|
|
"equals": "production"
|
|
},
|
|
{
|
|
"value": "[concat(parameters('prefix'), '-', parameters('suffix'))]",
|
|
"notEquals": ""
|
|
},
|
|
{
|
|
"value": "[length(parameters('allowedLocations'))]",
|
|
"greater": 0
|
|
}
|
|
]
|
|
},
|
|
"then": { "effect": "deny" }
|
|
}
|
|
parameters:
|
|
environment: "production"
|
|
prefix: "prod"
|
|
suffix: "01"
|
|
allowedLocations:
|
|
- "eastus"
|
|
resource:
|
|
type: "any"
|
|
want_effect: "deny"
|
|
|
|
# =========================================================================
|
|
# Unary minus for negative number literals
|
|
# =========================================================================
|
|
|
|
- note: expr_unary_minus_literal
|
|
policy_rule: |
|
|
{
|
|
"if": {
|
|
"value": "[add(-1, 5)]",
|
|
"equals": 4
|
|
},
|
|
"then": { "effect": "deny" }
|
|
}
|
|
resource:
|
|
type: "any"
|
|
want_effect: "deny"
|
|
|
|
- note: expr_unary_minus_float
|
|
policy_rule: |
|
|
{
|
|
"if": {
|
|
"value": "[add(-2.5, 3.5)]",
|
|
"equals": 1
|
|
},
|
|
"then": { "effect": "deny" }
|
|
}
|
|
resource:
|
|
type: "any"
|
|
want_effect: "deny"
|
|
|
|
- note: expr_unary_minus_sub_expression
|
|
policy_rule: |
|
|
{
|
|
"if": {
|
|
"value": "[sub(10, -3)]",
|
|
"equals": 13
|
|
},
|
|
"then": { "effect": "deny" }
|
|
}
|
|
resource:
|
|
type: "any"
|
|
want_effect: "deny"
|
|
|
|
- note: expr_zero_arg_function_call
|
|
policy_rule: |
|
|
{
|
|
"if": {
|
|
"value": "[concat()]",
|
|
"equals": ""
|
|
},
|
|
"then": { "effect": "deny" }
|
|
}
|
|
resource:
|
|
type: "any"
|
|
want_effect: "deny"
|