mirror of
https://github.com/microsoft/regorus.git
synced 2026-08-05 02:16:11 +00:00
Extend the Azure Policy parser to handle complete policyRule and
policyDefinition JSON structures, not just standalone constraints.
Policy rule parser (policy_rule.rs):
- Parse top-level { "if": ..., "then": ... } objects
- Extract effect kind (deny, audit, append, modify, etc.) into typed AST
- Parse "details" structurally when it is an object to pull out
existenceCondition as a first-class Constraint; fall back to opaque
JSON for non-object details (e.g. append array form)
- Detect duplicate/missing keys for "if", "then", "effect", "details"
Policy definition parser (policy_definition.rs):
- Handle both wrapped ARM envelope ({ "properties": { ... } }) and
unwrapped (properties-level keys at top level) forms
- Type-extract displayName, description, mode, metadata, parameters,
and policyRule; everything else goes into extra
- Parse parameter definitions with type, defaultValue, allowedValues,
and metadata; detect duplicate parameter names
- Duplicate key detection throughout
Grammar documentation (docs/azure-policy/azurepolicy.ebnf):
- Add formal EBNF grammar covering policy-rule, then-block,
constraints, conditions, all 19 operators, count expressions,
JSON values, and ARM template expressions
Test harness changes:
- Add parse_level field to YAML test cases: "constraint" (default),
"policy_rule", or "policy_definition"
- Un-skip three parse_errors cases that needed policy_rule-level parsing
- Add policy_rule.yaml with 12 cases covering all 9 effect kinds,
existenceCondition, parameterized effects, complex conditions, and
extra key handling
- Add policy_definition.yaml with wrapped, unwrapped, parameterized,
missing-policyRule, and duplicate-key error cases
77 lines
3.2 KiB
EBNF
77 lines
3.2 KiB
EBNF
(* Azure Policy grammar.
|
|
*
|
|
* All key matching is case-insensitive. JSON object keys are unordered,
|
|
* so the ordering shown below is for readability only.
|
|
*)
|
|
|
|
(* ================================================================
|
|
* Policy rule & then block
|
|
* NOTE: Keys may appear in any order; extra keys may appear between
|
|
* the recognized ones. The ordering below is illustrative.
|
|
* ================================================================ *)
|
|
|
|
policy-rule ::= '{' '"if"' ':' constraint ',' '"then"' ':' then-block
|
|
(',' STRING ':' json-value)* '}'
|
|
|
|
then-block ::= '{' '"effect"' ':' STRING
|
|
(',' '"details"' ':' json-value)? '}'
|
|
|
|
(* ================================================================
|
|
* Constraints
|
|
* ================================================================ *)
|
|
|
|
constraint ::= allOf | anyOf | not | condition
|
|
|
|
allOf ::= '{' '"allOf"' ':' '[' (constraint (',' constraint)*)? ']' '}'
|
|
anyOf ::= '{' '"anyOf"' ':' '[' (constraint (',' constraint)*)? ']' '}'
|
|
not ::= '{' '"not"' ':' constraint '}'
|
|
|
|
(* Keys within a condition are unordered; exactly one lhs-entry and one
|
|
* op-entry are required. *)
|
|
condition ::= '{' lhs-entry ',' op-entry '}'
|
|
|
|
lhs-entry ::= field | value-lhs | count
|
|
field ::= '"field"' ':' string-value
|
|
value-lhs ::= '"value"' ':' json-value
|
|
op-entry ::= operator ':' json-value
|
|
|
|
operator ::= '"contains"' | '"containsKey"' | '"equals"' | '"notEquals"'
|
|
| '"greater"' | '"greaterOrEquals"' | '"less"' | '"lessOrEquals"'
|
|
| '"exists"' | '"in"' | '"notIn"'
|
|
| '"like"' | '"notLike"'
|
|
| '"match"' | '"matchInsensitively"'
|
|
| '"notMatch"' | '"notMatchInsensitively"'
|
|
| '"notContains"' | '"notContainsKey"'
|
|
|
|
(* ================================================================
|
|
* Count expressions
|
|
* ================================================================ *)
|
|
|
|
count ::= '"count"' ':' count-inner
|
|
count-inner ::= count-field | count-value
|
|
count-field ::= '{' field (',' where)? '}'
|
|
count-value ::= '{' value-lhs (',' '"name"' ':' STRING)? (',' where)? '}'
|
|
where ::= '"where"' ':' constraint
|
|
|
|
(* ================================================================
|
|
* JSON values & template expressions
|
|
* ================================================================ *)
|
|
|
|
string-value ::= STRING | '"[' string-expr ']"'
|
|
|
|
json-value ::= STRING | NUMBER | BOOL | NULL
|
|
| array | object
|
|
| '"[' string-expr ']"'
|
|
array ::= '[' (json-value (',' json-value)*)? ']'
|
|
object ::= '{' (STRING ':' json-value (',' STRING ':' json-value)*)? '}'
|
|
|
|
(* ================================================================
|
|
* ARM template expression sub-grammar
|
|
* ================================================================ *)
|
|
|
|
string-expr ::= NUMBER | STRING | '-' string-expr | complex-expr
|
|
|
|
complex-expr ::= IDENT
|
|
| complex-expr '.' IDENT
|
|
| complex-expr '(' (string-expr (',' string-expr)*)? ')'
|
|
| complex-expr '[' string-expr ']' |