aboutsummaryrefslogtreecommitdiff
path: root/benchmarks
diff options
context:
space:
mode:
authorJakob L. Kreuze2023-12-21 13:20:58 -0500
committerJakob L. Kreuze2023-12-21 13:20:58 -0500
commitbe7067d632aa665c20f96d3b344a84c95b0f8ff8 (patch)
treefc5564a72cc42c8a21d3e943f645afcaae78f5a5 /benchmarks
parent5918f84a1a05881d93d9fab83104feca9981bfaa (diff)
Check-in remaining files
Diffstat (limited to 'benchmarks')
-rw-r--r--benchmarks/Xacml.lean1111
-rw-r--r--benchmarks/authzforce-harness.bash23
-rw-r--r--benchmarks/collection.sh2
-rw-r--r--benchmarks/excluded.txt1822
-rw-r--r--benchmarks/hyperfine-iia001.json212
-rw-r--r--benchmarks/hyperfine-iia003.json208
-rw-r--r--benchmarks/hyperfine-iia006.json206
-rw-r--r--benchmarks/lean-harness.bash7
-rw-r--r--benchmarks/rego-harness.bash12
-rw-r--r--benchmarks/rego/iia003.json1
-rw-r--r--benchmarks/rego/iia003.rego815
-rw-r--r--benchmarks/rego/iia006.json1
-rw-r--r--benchmarks/rego/iia006.rego827
-rw-r--r--benchmarks/rego/iia007.rego829
-rw-r--r--benchmarks/rego/iia1.json1
-rw-r--r--benchmarks/rego/iia1.rego815
16 files changed, 6892 insertions, 0 deletions
diff --git a/benchmarks/Xacml.lean b/benchmarks/Xacml.lean
new file mode 100644
index 0000000..8211c74
--- /dev/null
+++ b/benchmarks/Xacml.lean
@@ -0,0 +1,1111 @@
+------------------------------------------------------------------------
+---- Atoms -------------------------------------------------------------
+------------------------------------------------------------------------
+--
+-- # References
+--
+-- - 7.6 Match evaluation
+--
+------------------------------------------------------------------------
+
+inductive MatchResult where
+ | is_match : MatchResult
+ | no_match : MatchResult
+ | indeterminate : MatchResult
+deriving DecidableEq, BEq, Repr
+
+inductive Decision where
+ | permit : Decision
+ | deny : Decision
+ | indeterminate : Decision
+ | not_applicable : Decision
+deriving DecidableEq, BEq, Repr
+
+-- This type is used to implement the semantics described in § 7.10 (Extended
+-- Indeterminate). It is only relevant to combining algorithms.
+inductive Decision' where
+ | permit : Decision'
+ | deny : Decision'
+ | indeterminate : Decision'
+ | indeterminate_d : Decision'
+ | indeterminate_p : Decision'
+ | indeterminate_dp : Decision'
+ | not_applicable : Decision'
+deriving DecidableEq, BEq, Repr
+
+def Decision'.downcast : Decision' → Decision
+ | Decision'.permit => Decision.permit
+ | Decision'.deny => Decision.deny
+ | Decision'.indeterminate => Decision.indeterminate
+ | Decision'.indeterminate_d => Decision.indeterminate
+ | Decision'.indeterminate_p => Decision.indeterminate
+ | Decision'.indeterminate_dp => Decision.indeterminate
+ | Decision'.not_applicable => Decision.not_applicable
+
+instance : Coe Decision' Decision where
+ coe := Decision'.downcast
+
+inductive EffectType where
+ | permit : EffectType
+ | deny : EffectType
+deriving DecidableEq, BEq, Repr
+
+namespace EffectType
+ def to_decision (e : EffectType) : Decision :=
+ match e with
+ | EffectType.permit => Decision.permit
+ | EffectType.deny => Decision.deny
+
+ def to_decision' (e : EffectType) : Decision' :=
+ match e with
+ | EffectType.permit => Decision'.permit
+ | EffectType.deny => Decision'.deny
+end EffectType
+
+------------------------------------------------------------------------
+---- Values ------------------------------------------------------------
+------------------------------------------------------------------------
+--
+-- From A.2 Data-types: "Although XML instances represent all data-types
+-- as strings, an XACML PDP must operate on types of data that, while
+-- they have string representations, are not just strings. Types such as
+-- Boolean, integer, and double MUST be converted from their XML string
+-- representations to values that can be compared with values in their
+-- domain of discourse, such as numbers."
+--
+-- The standard enumerates the types that must be supported by any
+-- conforming implementaiton. This is represented in `XmlType`, and
+-- `Value` is the representation of a value payload with its associated
+-- type.
+--
+------------------------------------------------------------------------
+
+inductive XmlType
+ | string : XmlType
+ | boolean : XmlType
+ | integer : XmlType
+ | double : XmlType
+ | time : XmlType
+ | date : XmlType
+ | dateTime : XmlType
+ | anyURI : XmlType
+ | hexBinary : XmlType
+ | base64Binary : XmlType
+ | dayTimeDuration : XmlType
+ | yearMonthDuration : XmlType
+ | x500Name : XmlType
+ | rfc822Name : XmlType
+ | ipAddress : XmlType
+ | dnsName : XmlType
+deriving DecidableEq, BEq, Repr
+
+def Primitive : Type := XmlType × String
+deriving DecidableEq, BEq, Repr
+
+def Primitive.mk (type : XmlType) (inner : String) : Primitive := (type, inner)
+
+notation:65 "#<" lhs:65 "," rhs:66 ">" => Primitive.mk lhs rhs
+
+instance : Coe Bool Primitive where
+ coe b :=
+ match b with
+ | true => #<XmlType.boolean, "True">
+ | false => #<XmlType.boolean, "False">
+
+-- Per 7.4 Expression evaluation,
+--
+-- "XACML defines an evaluation result of "Indeterminate", which is said
+-- to be the result of an invalid expression, or an operational error
+-- occurring during the evaluation of the expression."
+
+instance : Coe (Option Primitive) Primitive where
+ coe b :=
+ match b with
+ | Option.none => #<XmlType.boolean, "Indeterminate">
+ | Option.some a => a
+
+structure Bag where
+ contents: List Primitive
+deriving BEq, DecidableEq, Repr
+
+-- def Bag.beq (b₁ b₂ : Bag) : Bool :=
+-- b₁.contents.all (fun x => b₂.contents.count x == b₁.contents.count x)
+
+-- instance : BEq Bag where
+-- beq := Bag.beq
+
+inductive Value where
+ | primitive (p : Primitive) : Value
+ | bag (b : Bag) : Value
+deriving DecidableEq, Repr
+
+def Value.beq (v₁ v₂ : Value) : Bool :=
+ match v₁ with
+ | Value.primitive p₁ =>
+ match v₂ with
+ | Value.primitive p₂ => p₁ == p₂
+ | Value.bag _ => false
+ | Value.bag b₁ =>
+ match v₂ with
+ | Value.primitive _ => false
+ | Value.bag b₂ => b₁ == b₂
+
+instance : BEq Value where
+ beq := Value.beq
+
+instance : Coe (Option Value) Value where
+ coe b :=
+ match b with
+ | Option.none => Value.primitive (#<XmlType.boolean, "Indeterminate">)
+ | Option.some a => a
+
+instance : Coe (Option Value) MatchResult where
+ coe b :=
+ match b with
+ | Option.some (Value.primitive (XmlType.boolean, "True")) => MatchResult.is_match
+ | Option.some (Value.primitive (XmlType.boolean, "False")) => MatchResult.no_match
+ | _ => MatchResult.indeterminate
+
+------------------------------------------------------------------------
+---- Attributes---------------------------------------------------------
+------------------------------------------------------------------------
+--
+-- # References
+--
+-- - 5.46 Element <Attribute>
+-- - 5.42 Element <Request>
+--
+-- Attributes are categories into <Attributes> elements. In this
+-- implementation, categories are rolled up - every attribute carries
+-- the category of its enclosing <Attributes> element.
+--
+------------------------------------------------------------------------
+
+structure Attribute where
+ category : String
+ identifier : String
+ issuer : Option String
+ value : Primitive
+deriving DecidableEq, Repr
+
+def Attribute.beq (a₁ a₂ : Attribute) : Bool :=
+ match a₁ with
+ | { category := category₁,
+ identifier := identifier₁,
+ issuer := issuer₁,
+ value := value₁ } =>
+ match a₂ with
+ | { category := category₂,
+ identifier := identifier₂,
+ issuer := issuer₂,
+ value := value₂ } =>
+ category₁ == category₂
+ && identifier₁ == identifier₂
+ && issuer₁ == issuer₂
+ && value₁ == value₂
+
+instance : BEq Attribute where
+ beq := Attribute.beq
+
+-- More than one attribute with a particular (category, identifier, issuer) can
+-- exist in a `Request`. Indeed, this is how poly-valued attributes are
+-- represented.
+
+def Request : Type := List Attribute
+deriving Repr
+
+---
+
+def Identifier : Type := String
+deriving DecidableEq, BEq, Repr
+
+inductive RuleCombinatorAlgorithm where
+ | deny_overrides : RuleCombinatorAlgorithm
+ | ordered_deny_overrides : RuleCombinatorAlgorithm
+ | permit_overrides : RuleCombinatorAlgorithm
+ | ordered_permit_overrides : RuleCombinatorAlgorithm
+ | deny_unless_permit : RuleCombinatorAlgorithm
+ | permit_unless_deny : RuleCombinatorAlgorithm
+ | first_applicable : RuleCombinatorAlgorithm
+ | legacy_deny_overrides : RuleCombinatorAlgorithm
+ | legacy_ordered_deny_overrides : RuleCombinatorAlgorithm
+ | legacy_permit_overrides : RuleCombinatorAlgorithm
+ | legacy_ordered_permit_overrides : RuleCombinatorAlgorithm
+
+namespace RuleCombinatorAlgorithm
+ -- The output of a combining algorithm which does not track the extended set
+ -- of “Indeterminate” values MUST be treated as “Indeterminate{DP}” for the
+ -- value “Indeterminate” by a combining algorithm which tracks the extended
+ -- set of “Indeterminate” values. A combining algorithm which does not track
+ -- the extended set of “Indeterminate” values MUST treat the output of a
+ -- combining algorithm which tracks the extended set of “Indeterminate” values
+ -- as an “Indeterminate” for any of the possible values of the extended set of
+ -- “Indeterminate”.
+
+ def eval_deny_overrides (results : List Decision') : Decision' :=
+ if results.elem Decision'.deny then Decision'.deny else
+ if results.elem Decision'.indeterminate_dp then Decision'.indeterminate_dp else
+ if results.elem Decision'.indeterminate_d ∧ results.elem Decision'.indeterminate_p then Decision'.indeterminate_dp else
+ if results.elem Decision'.indeterminate_d then Decision'.indeterminate_d else
+ if results.elem Decision'.permit then Decision'.permit else
+ if results.elem Decision'.indeterminate_p then Decision'.indeterminate_p else
+ Decision'.not_applicable
+ def eval_ordered_deny_overrides : List Decision' -> Decision' := eval_deny_overrides
+
+ def eval_permit_overrides (results : List Decision') : Decision' :=
+ if results.elem Decision'.permit then Decision'.permit else
+ if results.elem Decision'.indeterminate_dp then Decision'.indeterminate_dp else
+ if results.elem Decision'.indeterminate_d ∧ results.elem Decision'.indeterminate_p then Decision'.indeterminate_dp else
+ if results.elem Decision'.indeterminate_p then Decision'.indeterminate_p else
+ if results.elem Decision'.deny then Decision'.deny else
+ if results.elem Decision'.indeterminate_d then Decision'.indeterminate_d else
+ Decision'.not_applicable
+ def eval_ordered_permit_overrides : List Decision' -> Decision' := eval_permit_overrides
+
+ def eval_deny_unless_permit (results : List Decision') : Decision' :=
+ if results.elem Decision'.permit then Decision'.permit else Decision'.deny
+
+ def eval_permit_unless_deny (results : List Decision') : Decision' :=
+ if results.elem Decision'.deny then Decision'.deny else Decision'.permit
+
+ -- The non-normative part of the specification asserts that "If an error
+ -- occurs while evaluating the target or condition of a rule, then the
+ -- evaluation SHALL halt, and the policy shall evaluate to "Indeterminate",
+ -- with the appropriate error status."
+ --
+ -- This behavior isn't spelled out in the normative part, because errors are
+ -- represented as an Indeterminate.
+ def eval_first_applicable (results : List Decision') : Decision' :=
+ match (results.filter (fun d => d != Decision'.not_applicable)).get? 0 with
+ | some a => a
+ | none => Decision'.not_applicable
+
+ def eval_legacy_deny_overrides (results : List Decision') : Decision' :=
+ -- Note that "any rule having Effect=Deny evaluates to Indeterminate"
+ -- corresponds to indeterminate_d, and "any rule having Effect=Permit
+ -- evaluates to Indeterminate" corresponds to indeterminate_p.
+ if results.elem Decision'.deny then Decision'.deny else
+ if results.elem Decision'.indeterminate_d then Decision'.indeterminate else
+ if results.elem Decision'.permit then Decision'.permit else
+ if results.elem Decision'.indeterminate_p then Decision'.indeterminate else
+ Decision'.not_applicable
+ def eval_legacy_ordered_deny_overrides : List Decision' -> Decision' := eval_legacy_deny_overrides
+
+ -- See the comment for `eval_legacy_deny_overrides_rule`.
+ def eval_legacy_permit_overrides (results : List Decision') : Decision' :=
+ if results.elem Decision'.permit then Decision'.permit else
+ if results.elem Decision'.indeterminate_p then Decision'.indeterminate else
+ if results.elem Decision'.deny then Decision'.deny else
+ if results.elem Decision'.indeterminate_d then Decision'.indeterminate else
+ Decision'.not_applicable
+ def eval_legacy_ordered_permit_overrides : List Decision' -> Decision' := eval_legacy_permit_overrides
+end RuleCombinatorAlgorithm
+
+inductive PolicyCombinatorAlgorithm where
+ | deny_overrides : PolicyCombinatorAlgorithm
+ | ordered_deny_overrides : PolicyCombinatorAlgorithm
+ | permit_overrides : PolicyCombinatorAlgorithm
+ | ordered_permit_overrides : PolicyCombinatorAlgorithm
+ | deny_unless_permit : PolicyCombinatorAlgorithm
+ | permit_unless_deny : PolicyCombinatorAlgorithm
+ | first_applicable : PolicyCombinatorAlgorithm
+ | only_one_applicable : PolicyCombinatorAlgorithm
+ | legacy_deny_overrides : PolicyCombinatorAlgorithm
+ | legacy_ordered_deny_overrides : PolicyCombinatorAlgorithm
+ | legacy_permit_overrides : PolicyCombinatorAlgorithm
+ | legacy_ordered_permit_overrides : PolicyCombinatorAlgorithm
+
+namespace PolicyCombinatorAlgorithm
+ def eval_deny_overrides := RuleCombinatorAlgorithm.eval_deny_overrides
+ def eval_ordered_deny_overrides := RuleCombinatorAlgorithm.eval_ordered_deny_overrides
+ def eval_permit_overrides := RuleCombinatorAlgorithm.eval_permit_overrides
+ def eval_ordered_permit_overrides := RuleCombinatorAlgorithm.eval_ordered_permit_overrides
+ def eval_deny_unless_permit := RuleCombinatorAlgorithm.eval_deny_unless_permit
+ def eval_permit_unless_deny := RuleCombinatorAlgorithm.eval_permit_unless_deny
+ def eval_first_applicable := RuleCombinatorAlgorithm.eval_first_applicable
+
+ -- The non-normative part of the specification asserts that "If an error
+ -- occurs while evaluating the target or condition of a rule, then the
+ -- evaluation SHALL halt, and the policy shall evaluate to "Indeterminate",
+ -- with the appropriate error status."
+ --
+ -- This behavior isn't spelled out in the normative part, because errors are
+ -- represented as an Indeterminate.
+ def eval_only_one_applicable (results : List Decision') : Decision' :=
+ match results.filter (fun d => d != Decision'.not_applicable) with
+ | [] => Decision'.not_applicable
+ | [a] => a
+ | _ => Decision'.indeterminate
+
+ def eval_legacy_deny_overrides (results : List Decision') : Decision' :=
+ if results.elem Decision'.deny then Decision'.deny else
+ if results.elem Decision'.indeterminate then Decision'.deny else
+ if results.elem Decision'.permit then Decision'.permit else
+ Decision'.not_applicable
+ def eval_legacy_ordered_deny_overrides : List Decision' -> Decision' := eval_legacy_deny_overrides
+
+ -- See the comment for `eval_legacy_deny_overrides`.
+ def eval_legacy_permit_overrides (results : List Decision') : Decision' :=
+ if results.elem Decision'.permit then Decision'.permit else
+ if results.elem Decision'.deny then Decision'.deny else
+ if results.elem Decision'.indeterminate then Decision'.indeterminate else
+ Decision'.not_applicable
+ def eval_legacy_ordered_permit_overrides : List Decision' -> Decision' := eval_legacy_permit_overrides
+end PolicyCombinatorAlgorithm
+
+inductive StatusCode
+ | ok : StatusCode
+ | missing_attribute : StatusCode
+ | syntax_error : StatusCode
+ | processing_error : StatusCode
+deriving DecidableEq, BEq, Repr
+
+structure AttributeDesignator where
+ category : String
+ identifier : String
+ type : XmlType
+ issuer : Option String
+ must_be_present : Bool
+deriving DecidableEq, BEq, Repr
+
+namespace AttributeDesignator
+ -- A named attribute SHALL match an attribute if the values of their
+ -- respective Category, AttributeId, DataType and Issuer attributes
+ -- match. The attribute designator’s Category MUST match, by
+ -- identifier equality, the Category of the <Attributes> element in
+ -- which the attribute is present. The attribute designator’s
+ -- AttributeId MUST match, by identifier equality, the AttributeId of
+ -- the attribute. The attribute designator’s DataType MUST match, by
+ -- identifier equality, the DataType of the same attribute.
+ --
+ -- If the Issuer attribute is present in the attribute designator,
+ -- then it MUST match, using the
+ -- “urn:oasis:names:tc:xacml:1.0:function:string-equal” function, the
+ -- Issuer of the same attribute. If the Issuer is not present in the
+ -- attribute designator, then the matching of the attribute to the
+ -- named attribute SHALL be governed by AttributeId and DataType
+ -- attributes alone.
+ def matches? (designator : AttributeDesignator) (attr : Attribute) : Bool :=
+ attr.category == designator.category
+ && attr.identifier == designator.identifier
+ && attr.value.fst == designator.type
+ && (attr.issuer == Option.none ∨ attr.issuer == designator.issuer)
+
+ def eval (designator : AttributeDesignator) (context : List Attribute) : Sum Value (List StatusCode) :=
+ let found := context.filter designator.matches?
+ let found := found.map (fun x => x.value)
+ if designator.must_be_present then
+ match found with
+ | [] => Sum.inr $ [StatusCode.missing_attribute]
+ | _ => Sum.inl $ Value.bag (Bag.mk found)
+ else Sum.inl $ Value.bag (Bag.mk found)
+end AttributeDesignator
+
+def matches? (designator : AttributeDesignator) (attr : Attribute) : Prop :=
+ designator.category == attr.category ∧
+ designator.identifier == attr.identifier ∧
+ designator.type == attr.value.fst ∧
+ match (designator.issuer, attr.issuer) with
+ | (none, _) => True
+ | (some issuer₁, some issuer₂) => issuer₁ == issuer₂
+ | _ => False
+
+def FunctionID : Type := String
+deriving DecidableEq, BEq, Repr
+
+-- "The <Expression> element is not used directly in a policy. The <Expression>
+-- element signifies that an element that extends the ExpressionType and is a
+-- member of the <Expression> element substitution group SHALL appear in its
+-- place."
+--
+-- We omit the `<xacml:AttributeSelector>` case because this model of XACML does
+-- not include it, and we exclude the `<xacml:VariableReference>` case because
+-- we erase variable references in the compiler.
+
+inductive Expression where
+ -- Note well that `apply` accepts a list of Values, not a list of Expressions,
+ -- as its arguments. The compiler is responsible for ensuring that the
+ -- arguments in a function call are fully evaluated.
+ --
+ -- Lean is quite strict about recursion being bounded, which is a little hard
+ -- to prove in our case! Fortunately, we can punt the job of proving that to
+ -- the compiler.
+ | apply (function : FunctionID) (args: List Value) : Expression
+ | attribute_designator (inner : AttributeDesignator) : Expression
+ | attribute_value (inner : Value) : Expression
+ | function (function : FunctionID) : Expression
+deriving DecidableEq, BEq, Repr
+
+namespace Expression
+ def apply_eval (name : FunctionID) (args : List Value) : Option Value :=
+ if name == "urn:oasis:names:tc:xacml:1.0:function:string-equal" then
+ match args with
+ | [Value.primitive (XmlType.string, lhs),
+ Value.primitive (XmlType.string, rhs)] =>
+ Value.primitive (lhs == rhs)
+ | _ => Value.primitive (#<XmlType.boolean, "Indeterminate">)
+ else if name == "urn:oasis:names:tc:xacml:1.0:function:anyURI-equal" then
+ match args with
+ | [Value.primitive (XmlType.anyURI, lhs),
+ Value.primitive (XmlType.anyURI, rhs)] =>
+ Value.primitive (lhs == rhs)
+ | _ => Value.primitive (#<XmlType.boolean, "Indeterminate">)
+ else if name == "urn:oasis:names:tc:xacml:1.0:function:integer-equal" then
+ match args with
+ | [Value.primitive (XmlType.integer, lhs),
+ Value.primitive (XmlType.integer, rhs)] =>
+ Value.primitive (lhs == rhs)
+ | _ => Value.primitive (#<XmlType.boolean, "Indeterminate">)
+ else Option.none
+
+ def eval (expression : Expression) (context : Request) : Option Value :=
+ -- The return type of `<Apply>` may be made more specific by type unification.
+ --
+ -- The evaluation result can be specified to be "Indeterminate"; we encode
+ -- this as `Option.none` here for ergonomics, but we do give an instance for
+ -- `Coe (Option Value) Value`.
+ --
+ -- § 7.6 enumerates but does not describe the semantics for:
+ --
+ -- - <xacml:AttributeValue>
+ -- - <xacml:AttributeDesignator>
+ -- - <xacml:AttributeSelector>
+ -- - <xacml:Apply>
+ -- - <xacml:Function>
+ -- - <xacml:VariableReference>
+ match expression with
+ | Expression.apply name args => apply_eval name args
+ | Expression.attribute_designator inner =>
+ match inner.eval context with
+ | Sum.inl res => res
+ | Sum.inr _ => Option.none
+ | Expression.attribute_value inner => some inner
+ | _ => Option.none
+end Expression
+
+structure Match where
+ function : Identifier
+ designator : AttributeDesignator
+ value : Value
+deriving DecidableEq, BEq, Repr
+def AllOf : Type := List Match
+deriving DecidableEq, BEq, Repr
+def AnyOf : Type := List AllOf
+deriving DecidableEq, BEq, Repr
+def Target : Type := List AnyOf
+deriving DecidableEq, BEq, Repr
+
+instance : Membership AllOf AnyOf where
+ mem := fun x y => y.contains x
+
+namespace Match
+ -- The evaluation semantics for a matching element is as follows.
+ --
+ -- 1. If an operational error were to occur while evaluating the
+ -- <AttributeDesignator> or <AttributeSelector> element, then the
+ -- result of the entire expression SHALL be "Indeterminate".
+ --
+ -- 2. If the <AttributeDesignator> or <AttributeSelector> element were
+ -- to evaluate to an empty bag, then the result of the expression
+ -- SHALL be "False".
+ --
+ -- 3. Otherwise, the MatchId function SHALL be applied between the
+ -- <AttributeValue> and each element of the bag returned from the
+ -- <AttributeDesignator> or <AttributeSelector> element.
+ -- a. If at least one of those function applications were to evaluate
+ -- to "True", then the result of the entire expression SHALL be
+ -- "True".
+ -- b. Otherwise, if at least one of the function applications results
+ -- in "Indeterminate", then the result SHALL be "Indeterminate".
+ -- c. Finally, if all function applications evaluate to "False", then
+ -- the result of the entire expression SHALL be "False".
+ def eval (m : Match) (context : Request) : Option Value :=
+ match m with
+ | Match.mk fn designator value =>
+ match designator.eval context with
+ | Sum.inl result =>
+ let results := match result with
+ -- Otherwise, the MatchId function SHALL be applied between the
+ -- <AttributeValue> and each element of the bag returned from the
+ -- <AttributeDesignator> or <AttributeSelector> element.
+ | (Value.bag (Bag.mk attrs)) =>
+ attrs.map fun attr =>
+ let args := [value, Value.primitive attr]
+ (Expression.apply fn args).eval context
+ | (Value.primitive attr) =>
+ -- TODO: Prove that this case is impossible.
+ let args := [value, Value.primitive attr]
+ [(Expression.apply fn args).eval context]
+
+ let results := results.map (fun (x : Option Value) => (x : Value))
+ -- If at least one of those function applications were to evaluate to
+ -- "True", then the result of the entire expression SHALL be "True".
+ if results.elem (Value.primitive (#<XmlType.boolean, "True">)) then
+ (Value.primitive (#<XmlType.boolean, "True">))
+ -- Otherwise, if at least one of the function applications results in
+ -- "Indeterminate", then the result SHALL be "Indeterminate".
+ else if results.elem (Value.primitive (#<XmlType.boolean, "Indeterminate">)) then
+ (Value.primitive (#<XmlType.boolean, "Indeterminate">))
+ -- The `else` arm handles the following cases:
+ --
+ -- If the <AttributeDesignator> or <AttributeSelector> element were to
+ -- evaluate to an empty bag, then the result of the expression SHALL
+ -- be "False".
+ --
+ -- Finally, if all function applications evaluate to "False", then the
+ -- result of the entire expression SHALL be "False".
+ else
+ Value.primitive (#<XmlType.boolean, "False">)
+ -- If an operational error were to occur while evaluating the
+ -- <AttributeDesignator> or <AttributeSelector> element, then the result
+ -- of the entire expression SHALL be "Indeterminate".
+ | Sum.inr _ => Option.none
+end Match
+
+namespace AllOf
+ def eval (conj : AllOf) (context : Request) : MatchResult :=
+ let result := conj.map (fun x => x.eval context)
+ let result := result.map (fun (x : Option Value) => (x : Value))
+ if result.all (fun x => x == Value.primitive (XmlType.boolean, "True")) then MatchResult.is_match
+ else if result.all (fun x => x != Value.primitive (XmlType.boolean, "False")) ∧
+ result.elem (Value.primitive (XmlType.boolean, "Indeterminate"))
+ then MatchResult.indeterminate
+ else MatchResult.no_match
+end AllOf
+
+namespace AnyOf
+ def eval (disj : AnyOf) (context : Request) : MatchResult :=
+ -- match disj with
+ -- | [] => MatchResult.is_match
+ -- | List.cons x xs => match x.eval context with
+ -- | MatchResult.is_match => MatchResult.is_match
+ -- | MatchResult.no_match =>
+ -- let rest := AnyOf.eval xs context
+ -- if rest == MatchResult.no_match then MatchResult.no_match else rest
+ -- | MatchResult.indeterminate =>
+ -- let rest := AnyOf.eval xs context
+ -- if rest == MatchResult.no_match then MatchResult.indeterminate else rest
+ if disj.isEmpty then MatchResult.is_match else
+ let result := disj.map (fun x => x.eval context)
+ if result.any (fun x => x == MatchResult.is_match) then MatchResult.is_match
+ else if result.elem MatchResult.indeterminate then MatchResult.indeterminate
+ else MatchResult.no_match
+end AnyOf
+
+namespace Target
+ def eval (target : Target) (context : Request) : MatchResult :=
+ match target with
+ -- An empty target matches any request.
+ | [] => MatchResult.is_match
+ | xs =>
+ let results := xs.map (fun disj => disj.eval context)
+ -- Otherwise the target value SHALL be "Match" if all the AnyOf
+ -- specified in the target match values in the request context.
+ if results.all (fun result => result == MatchResult.is_match) then
+ MatchResult.is_match
+ -- Otherwise, if any one of the AnyOf specified in the target is “No
+ -- Match”, then the target SHALL be “No Match”.
+ else if results.any (fun result => result == MatchResult.no_match) then
+ MatchResult.no_match
+ -- Otherwise, the target SHALL be “Indeterminate”.
+ else MatchResult.indeterminate
+end Target
+
+structure Obligation where
+ assignments : List Attribute
+ identifier : String
+deriving DecidableEq, BEq, Repr
+
+structure Advice where
+ assignments : List Attribute
+ identifier : String
+deriving DecidableEq, BEq, Repr
+
+structure AttributeAssignmentExpression where
+ category : String
+ identifier : String
+ issuer : Option String
+ expression : Expression
+deriving DecidableEq, BEq, Repr
+
+namespace AttributeAssignmentExpression
+ def eval (assignment : AttributeAssignmentExpression) (context : Request) : Option Attribute :=
+ match assignment.expression.eval context with
+ | some (Value.primitive inner) =>
+ Attribute.mk
+ assignment.category
+ assignment.identifier
+ assignment.issuer
+ inner
+ | _ => none
+end AttributeAssignmentExpression
+
+structure ObligationExpression where
+ assignments : List AttributeAssignmentExpression
+ identifier : String
+ fulfill_on : Decision
+deriving DecidableEq, BEq, Repr
+
+namespace ObligationExpression
+ def eval (obligation : ObligationExpression) (context : Request) : Option Obligation :=
+ let assignments := obligation.assignments.map (fun x => AttributeAssignmentExpression.eval x context)
+ if assignments.all Option.isSome then
+ Obligation.mk
+ (List.filterMap id assignments)
+ obligation.identifier
+ else none
+end ObligationExpression
+
+structure AdviceExpression where
+ assignments : List AttributeAssignmentExpression
+ identifier : String
+ applies_to : Decision
+deriving DecidableEq, BEq, Repr
+
+namespace AdviceExpression
+ def eval (advice : AdviceExpression) (context : Request) : Option Advice :=
+ let assignments := advice.assignments.map (fun x => AttributeAssignmentExpression.eval x context)
+ if assignments.all Option.isSome then
+ Advice.mk
+ (List.filterMap id assignments)
+ advice.identifier
+ else none
+end AdviceExpression
+
+structure ResultAuxiliary where
+ status : Option (List StatusCode)
+ obligations : List Obligation
+ advice : List Advice
+deriving DecidableEq, BEq, Repr
+
+structure ResultAuxiliary' where
+ status : Option (List StatusCode)
+ obligations : List ObligationExpression
+ advice : List AdviceExpression
+deriving DecidableEq, BEq, Repr
+
+def collect_option {α : Type} (xs : List (Option α)) : Option (List α) :=
+ match xs with
+ | [] => some []
+ | some x :: xs' =>
+ match collect_option xs' with
+ | some xs' => some (x :: xs')
+ | none => none
+ | none :: _ => none
+
+namespace ResultAuxiliary'
+ def eval (result : ResultAuxiliary') (context : Request) : Option ResultAuxiliary :=
+ let advice :=
+ collect_option (List.map (fun x => AdviceExpression.eval x context) result.advice)
+ let obligations :=
+ collect_option (List.map (fun x => ObligationExpression.eval x context) result.obligations)
+ match (obligations, advice) with
+ | (some obligations, some advice) =>
+ some { status := result.status, obligations, advice }
+ | _ => none
+end ResultAuxiliary'
+
+structure MissingAttributeDetail where
+ category : String
+ identifier : String
+ issuer : Option String
+ value : Option Value
+ type : XmlType
+deriving DecidableEq, BEq, Repr
+
+def Result : Type := Decision' × (Option ResultAuxiliary)
+def Result' : Type := Decision' × (Option ResultAuxiliary')
+
+namespace Result'
+ def eval (result : Result') (context : Request) : Result :=
+ match result.snd with
+ | some aux =>
+ let advices := aux.advice.map (fun advice => AdviceExpression.eval advice context)
+ let obligations := aux.obligations.map (fun x => ObligationExpression.eval x context)
+ if advices.any Option.isNone || obligations.any Option.isNone then
+ (Decision'.indeterminate, none)
+ else
+ (
+ result.fst,
+ ResultAuxiliary.mk
+ aux.status
+ (List.filterMap id obligations)
+ (List.filterMap id advices)
+ )
+ | none => (result.fst, none)
+end Result'
+
+structure Rule where
+ target : Target
+ condition : Option Expression
+ effect : EffectType
+ obligations : List ObligationExpression
+ advice : List AdviceExpression
+
+namespace Rule
+ def eval (rule : Rule) (context : Request) : Result' :=
+ let (decision : Decision') :=
+ -- The "no target" case is handled within `Target.eval`, returning
+ -- `MatchResult.is_match` when the target is empty.
+ match rule.target.eval context with
+ | MatchResult.is_match =>
+ let condition :=
+ match rule.condition with
+ | some condition =>
+ -- The condition value SHALL be "True" if the <Condition> element
+ -- evaluates to "True".
+ let result := condition.eval context
+ if result == some (Value.primitive (#<XmlType.boolean, "True">)) then result
+ -- Its value SHALL be "False" if the <Condition> element evaluates to
+ -- "False".
+ else if result == some (Value.primitive (#<XmlType.boolean, "False">)) then result
+ -- The condition value SHALL be "Indeterminate", if the expression
+ -- contained in the <Condition> element evaluates to "Indeterminate."
+ else Value.primitive (#<XmlType.boolean, "Indeterminate">)
+ -- The condition value SHALL be "True" if the <Condition> element is absent.
+ | none => Value.primitive (#<XmlType.boolean, "True">)
+ match condition with
+ | some (Value.primitive (XmlType.boolean, "False")) => Decision'.not_applicable
+ | some (Value.primitive (XmlType.boolean, "True")) =>
+ match rule.effect with
+ | EffectType.permit => Decision'.permit
+ | EffectType.deny => Decision'.deny
+ -- | (#<XmlType.boolean, "Indeterminate">) =>
+ | _ =>
+ if rule.effect == EffectType.permit then
+ Decision'.indeterminate_p else
+ Decision'.indeterminate_d
+ | MatchResult.no_match => Decision'.not_applicable
+ | MatchResult.indeterminate =>
+ if rule.effect == EffectType.permit then
+ Decision'.indeterminate_p else
+ Decision'.indeterminate_d
+ let advices :=
+ rule.advice.filter
+ (fun advice => advice.applies_to == (decision : Decision))
+ let obligations :=
+ rule.obligations.filter
+ (fun obligation => obligation.fulfill_on == (decision : Decision))
+ (
+ decision,
+ ResultAuxiliary'.mk
+ none
+ obligations
+ advices
+ )
+end Rule
+
+structure Policy where
+ combinator : RuleCombinatorAlgorithm
+ target : Target
+ obligations : List ObligationExpression
+ advice : List AdviceExpression
+
+namespace Policy
+ def eval (policy : Policy) (child_results : List Result') (context : Request) : Result' :=
+ let combinator :=
+ match policy.combinator with
+ | RuleCombinatorAlgorithm.deny_overrides => RuleCombinatorAlgorithm.eval_deny_overrides
+ | RuleCombinatorAlgorithm.ordered_deny_overrides => RuleCombinatorAlgorithm.eval_ordered_deny_overrides
+ | RuleCombinatorAlgorithm.permit_overrides => RuleCombinatorAlgorithm.eval_permit_overrides
+ | RuleCombinatorAlgorithm.ordered_permit_overrides => RuleCombinatorAlgorithm.eval_ordered_permit_overrides
+ | RuleCombinatorAlgorithm.deny_unless_permit => RuleCombinatorAlgorithm.eval_deny_unless_permit
+ | RuleCombinatorAlgorithm.permit_unless_deny => RuleCombinatorAlgorithm.eval_permit_unless_deny
+ | RuleCombinatorAlgorithm.first_applicable => RuleCombinatorAlgorithm.eval_first_applicable
+ | RuleCombinatorAlgorithm.legacy_deny_overrides => RuleCombinatorAlgorithm.eval_legacy_deny_overrides
+ | RuleCombinatorAlgorithm.legacy_ordered_deny_overrides => RuleCombinatorAlgorithm.eval_legacy_ordered_deny_overrides
+ | RuleCombinatorAlgorithm.legacy_permit_overrides => RuleCombinatorAlgorithm.eval_legacy_permit_overrides
+ | RuleCombinatorAlgorithm.legacy_ordered_permit_overrides => RuleCombinatorAlgorithm.eval_legacy_ordered_permit_overrides
+ let (decision : Decision') := combinator (List.map Prod.fst child_results)
+ let (decision : Decision') :=
+ match policy.target.eval context with
+ | MatchResult.is_match => decision
+ | MatchResult.no_match => Decision'.not_applicable
+ | MatchResult.indeterminate =>
+ match decision with
+ | Decision'.not_applicable => Decision'.not_applicable
+ | Decision'.permit => Decision'.indeterminate_p
+ | Decision'.deny => Decision'.indeterminate_d
+ | Decision'.indeterminate => Decision'.indeterminate_dp
+ | Decision'.indeterminate_dp => Decision'.indeterminate_dp
+ | Decision'.indeterminate_p => Decision'.indeterminate_p
+ | Decision'.indeterminate_d => Decision'.indeterminate_d
+ let advices :=
+ policy.advice.filter
+ (fun advice => advice.applies_to == (decision : Decision))
+ ++
+ List.join
+ (child_results.filterMap
+ (fun x => match x.snd with
+ | some y => y.advice
+ | none => none))
+ let obligations :=
+ policy.obligations.filter
+ (fun obligation => obligation.fulfill_on == (decision : Decision))
+ ++
+ List.join
+ (child_results.filterMap
+ (fun x => match x.snd with
+ | some y => y.obligations
+ | none => none))
+ (
+ decision,
+ ResultAuxiliary'.mk
+ none
+ obligations
+ advices
+ )
+end Policy
+
+structure PolicySet where
+ combinator : PolicyCombinatorAlgorithm
+ target : Target
+ obligations : List ObligationExpression
+ advice : List AdviceExpression
+
+namespace PolicySet
+ def eval (policyset : PolicySet) (child_results : List Result') (context : Request) : Result' :=
+ let combinator :=
+ match policyset.combinator with
+ | PolicyCombinatorAlgorithm.deny_overrides => PolicyCombinatorAlgorithm.eval_deny_overrides
+ | PolicyCombinatorAlgorithm.ordered_deny_overrides => PolicyCombinatorAlgorithm.eval_ordered_deny_overrides
+ | PolicyCombinatorAlgorithm.permit_overrides => PolicyCombinatorAlgorithm.eval_permit_overrides
+ | PolicyCombinatorAlgorithm.ordered_permit_overrides => PolicyCombinatorAlgorithm.eval_ordered_permit_overrides
+ | PolicyCombinatorAlgorithm.deny_unless_permit => PolicyCombinatorAlgorithm.eval_deny_unless_permit
+ | PolicyCombinatorAlgorithm.permit_unless_deny => PolicyCombinatorAlgorithm.eval_permit_unless_deny
+ | PolicyCombinatorAlgorithm.first_applicable => PolicyCombinatorAlgorithm.eval_first_applicable
+ | PolicyCombinatorAlgorithm.only_one_applicable => PolicyCombinatorAlgorithm.eval_only_one_applicable
+ | PolicyCombinatorAlgorithm.legacy_deny_overrides => PolicyCombinatorAlgorithm.eval_legacy_deny_overrides
+ | PolicyCombinatorAlgorithm.legacy_ordered_deny_overrides => PolicyCombinatorAlgorithm.eval_legacy_ordered_deny_overrides
+ | PolicyCombinatorAlgorithm.legacy_permit_overrides => PolicyCombinatorAlgorithm.eval_legacy_permit_overrides
+ | PolicyCombinatorAlgorithm.legacy_ordered_permit_overrides => PolicyCombinatorAlgorithm.eval_legacy_ordered_permit_overrides
+ let (decision : Decision') := combinator (List.map Prod.fst child_results)
+ let (decision : Decision') :=
+ match policyset.target.eval context with
+ | MatchResult.is_match => decision
+ | MatchResult.no_match => Decision'.not_applicable
+ | MatchResult.indeterminate =>
+ match decision with
+ | Decision'.not_applicable => Decision'.not_applicable
+ | Decision'.permit => Decision'.indeterminate_p
+ | Decision'.deny => Decision'.indeterminate_d
+ | Decision'.indeterminate => Decision'.indeterminate_dp
+ | Decision'.indeterminate_dp => Decision'.indeterminate_dp
+ | Decision'.indeterminate_p => Decision'.indeterminate_p
+ | Decision'.indeterminate_d => Decision'.indeterminate_d
+ let advices :=
+ policyset.advice.filter
+ (fun advice => advice.applies_to == (decision : Decision))
+ ++
+ List.join
+ (child_results.filterMap
+ (fun x => match x.snd with
+ | some y => y.advice
+ | none => none))
+ let obligations :=
+ policyset.obligations.filter
+ (fun obligation => obligation.fulfill_on == (decision : Decision))
+ ++
+ List.join
+ (child_results.filterMap
+ (fun x => match x.snd with
+ | some y => y.obligations
+ | none => none))
+ (
+ decision,
+ ResultAuxiliary'.mk
+ none
+ obligations
+ advices
+ )
+end PolicySet
+
+inductive PolicyElement where
+ | PolicySet (ps : PolicySet)
+ | Policy (p : Policy)
+ | Rule (r : Rule)
+
+def PolicyElement.eval (context : Request) : PolicyElement -> List Result' -> Result'
+ | PolicySet ps, results => ps.eval results context
+ | Policy p, results => p.eval results context
+ | Rule r, _ => r.eval context
+
+inductive ElementTree where
+ | Node (e : PolicyElement) (xs : List ElementTree)
+
+def ElementTree.eval' (context : Request) : ElementTree -> List Result' -> Result'
+ | ElementTree.Node e [], results => PolicyElement.eval context e results
+ | ElementTree.Node e (x :: xs), results =>
+ ElementTree.eval'
+ context
+ (ElementTree.Node e xs)
+ ((ElementTree.eval' context x []) :: results)
+
+def ElementTree.eval (context : Request) (et : ElementTree) : Result' :=
+ ElementTree.eval' context et []
+
+-- let results := policy.rules.map (fun rule => rule.eval context)
+
+def is_indeterminate (x : Expression) : Bool :=
+ match x with
+ | Expression.attribute_value (Value.primitive (XmlType.boolean, "Indeterminate")) => true
+ | _ => false
+
+def make_response
+ (decision : Decision)
+ (status : Option (List StatusCode))
+ (obligations : List Obligation)
+ (advice : List Advice)
+: Decision × ResultAuxiliary :=
+ let obligations := obligations.map (fun expr => Obligation.mk expr.assignments expr.identifier)
+ let advice := advice.map (fun expr => Advice.mk expr.assignments expr.identifier)
+ -- If any of the attribute assignment expressions in an obligation or
+ -- advice expression with a matching FulfillOn or AppliesTo attribute
+ -- evaluates to “Indeterminate”, then the whole rule, policy, or
+ -- policy set SHALL be “Indeterminate”. If the FulfillOn or AppliesTo
+ -- attribute does not match the result of the combining algorithm or
+ -- the rule evaluation, then any indeterminate in an obligation or
+ -- advice expression has no effect.
+ -- if obligations.
+ let decision :=
+ -- if obligations.any
+ -- (fun obligation => obligation.assignments.any
+ -- (fun assignment => is_indeterminate assignment.expression)) ∨
+ -- advice.any
+ -- (fun advice => advice.assignments.any
+ -- (fun assignment => is_indeterminate assignment.expression))
+ -- then
+ -- Decision.indeterminate
+ -- else
+ decision
+ (
+ decision,
+ ResultAuxiliary.mk
+ status
+ (obligations.map (fun expr => Obligation.mk expr.assignments expr.identifier))
+ (advice.map (fun expr => Advice.mk expr.assignments expr.identifier))
+ )
+
+def combine_response_aux (x y : ResultAuxiliary) : ResultAuxiliary :=
+ match (x, y) with
+ | (ResultAuxiliary.mk status₁ obligations₁ advice₁,
+ ResultAuxiliary.mk _ obligations₂ advice₂) =>
+ ResultAuxiliary.mk
+ status₁
+ (obligations₁ ++ obligations₂)
+ (advice₁ ++ advice₂)
+
+def Choice : Type := List (Decision × ResultAuxiliary)
+deriving DecidableEq, BEq, Repr
+
+def xml_of_decision (decision : Decision) :=
+ match decision with
+ | Decision.permit => "<Decision>Permit</Decision>"
+ | Decision.deny => "<Decision>Deny</Decision>"
+ | Decision.indeterminate => "<Decision>Indeterminate</Decision>"
+ | Decision.not_applicable => "<Decision>NotApplicable</Decision>"
+
+def string_of_status_code (code : StatusCode) :=
+ match code with
+ | StatusCode.ok => "urn:oasis:names:tc:xacml:1.0:status:ok"
+ | StatusCode.missing_attribute => "urn:oasis:names:tc:xacml:1.0:status:missing-attribute"
+ | StatusCode.syntax_error => "urn:oasis:names:tc:xacml:1.0:status:syntax-error"
+ | StatusCode.processing_error => "urn:oasis:names:tc:xacml:1.0:status:processing-error"
+
+def xml_of_status_code (status : List StatusCode) :=
+ match status with
+ | primary :: [] => String.join [
+ "<StatusCode Value=\"",
+ string_of_status_code primary,
+ "\"/>"]
+ | primary :: rest => String.join [
+ "<StatusCode Value=\"",
+ string_of_status_code primary,
+ "\">",
+ xml_of_status_code rest, "</StatusCode>"]
+ | _ => ""
+
+def xml_of_status (status : List StatusCode) :=
+ match status with
+ | [] => ""
+ | codes => String.join ["<Status>", xml_of_status_code codes, "</Status>"]
+
+def xml_of_xmltype : XmlType -> String
+ | XmlType.string => "http://www.w3.org/2001/XMLSchema#string"
+ | XmlType.boolean => "http://www.w3.org/2001/XMLSchema#boolean"
+ | XmlType.integer => "http://www.w3.org/2001/XMLSchema#integer"
+ | XmlType.double => "http://www.w3.org/2001/XMLSchema#double"
+ | XmlType.time => "http://www.w3.org/2001/XMLSchema#time"
+ | XmlType.date => "http://www.w3.org/2001/XMLSchema#date"
+ | XmlType.dateTime => "http://www.w3.org/2001/XMLSchema#dateTime"
+ | XmlType.dayTimeDuration => "http://www.w3.org/2001/XMLSchema#dayTimeDuration"
+ | XmlType.yearMonthDuration => "http://www.w3.org/2001/XMLSchema#yearMonthDuration"
+ | XmlType.anyURI => "http://www.w3.org/2001/XMLSchema#anyURI"
+ | XmlType.hexBinary => "http://www.w3.org/2001/XMLSchema#hexBinary"
+ | XmlType.base64Binary => "http://www.w3.org/2001/XMLSchema#base64Binary"
+ | XmlType.rfc822Name => "urn:oasis:names:tc:xacml:1.0:data-type:rfc822Name"
+ | XmlType.x500Name => "urn:oasis:names:tc:xacml:1.0:data-type:x500Name"
+ | XmlType.ipAddress => "urn:oasis:names:tc:xacml:2.0:data-type:ipAddress"
+ | XmlType.dnsName => "urn:oasis:names:tc:xacml:2.0:data-type:dnsName"
+
+def xml_of_attribute_assignment (assignment : Attribute) :=
+ String.join [
+ "<AttributeAssignment AttributeId=\"",
+ assignment.identifier,
+ "\" DataType=\"",
+ xml_of_xmltype assignment.value.fst,
+ "\" Category=\"",
+ assignment.category,
+ (match assignment.issuer with
+ | some issuer => String.join ["\" Issuer=\"", issuer]
+ | none => ""),
+ "\"/>"
+ ]
+
+def xml_of_obligation (obligation : Obligation) :=
+ String.join [
+ "<Obligation ObligationId=\"",
+ obligation.identifier,
+ "\">",
+ String.join (List.map xml_of_attribute_assignment obligation.assignments),
+ "</Obligation>"
+ ]
+
+def xml_of_obligations (obligations : List Obligation) :=
+ String.join ["<Obligations>", String.join (List.map xml_of_obligation obligations), "</Obligations>"]
+
+def xml_of_advice (advice : Advice) :=
+ String.join [
+ "<Advice AdviceId=\"",
+ advice.identifier,
+ "\">",
+ String.join (List.map xml_of_attribute_assignment advice.assignments),
+ "</Advice>"
+ ]
+
+def xml_of_advices (advices : List Advice) :=
+ String.join ["<AssociatedAdvice>", String.join (List.map xml_of_advice advices), "</AssociatedAdvice>"]
+
+def xml_of_response (response : Result) :=
+ String.join [
+ "<?xml version=\"1.0\" encoding=\"UTF-8\"?>",
+ "<Response xmlns=\"urn:oasis:names:tc:xacml:3.0:core:schema:wd-17\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">",
+ "<Result>",
+ xml_of_decision response.fst,
+ (match response.snd with
+ | some {status, obligations, advice} =>
+ String.join [
+ (match status with
+ | some status => xml_of_status status
+ | none => "<Status><StatusCode Value=\"urn:oasis:names:tc:xacml:1.0:status:ok\"/></Status>"),
+ (match obligations with
+ | [] => ""
+ | _ => xml_of_obligations obligations),
+ (match advice with
+ | [] => ""
+ | _ => xml_of_advices advice)
+ ]
+ | none => ""),
+ "</Result>",
+ "</Response>"
+ ]
diff --git a/benchmarks/authzforce-harness.bash b/benchmarks/authzforce-harness.bash
new file mode 100644
index 0000000..f339446
--- /dev/null
+++ b/benchmarks/authzforce-harness.bash
@@ -0,0 +1,23 @@
+#!/usr/bin/env bash
+
+NAME="$(basename $1)"
+if [ $NAME = "IIA001" ]; then
+ NAME="IIA1"
+fi
+
+cat > /tmp/pdp.xml <<EOF
+<?xml version="1.0" encoding="UTF-8"?>
+<pdp xmlns="http://authzforce.github.io/core/xmlns/pdp/8"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ version="8.0">
+ <policyProvider id="rootPolicyProvider" xsi:type="StaticPolicyProvider">
+ <policyLocation>$1/Policy.xml</policyLocation>
+ </policyProvider>
+ <rootPolicyRef>urn:oasis:names:tc:xacml:2.0:conformance-test:$NAME:policy</rootPolicyRef>
+ <ioProcChain>
+ <requestPreproc>urn:ow2:authzforce:feature:pdp:request-preproc:xacml-json:default-lax</requestPreproc>
+ <resultPostproc>urn:ow2:authzforce:feature:pdp:result-postproc:xacml-json:default</resultPostproc>
+ </ioProcChain>
+</pdp>
+EOF
+java -jar /tmp/authzforce-ce-core-pdp-cli-21.0.1.jar /tmp/pdp.xml $1/Request.xml
diff --git a/benchmarks/collection.sh b/benchmarks/collection.sh
new file mode 100644
index 0000000..e502788
--- /dev/null
+++ b/benchmarks/collection.sh
@@ -0,0 +1,2 @@
+export BENCHMARK=/tmp/core/pdp-testutils/src/test/resources/conformance/xacml-3.0-from-2.0-ct/mandatory/IIA001
+/tmp/hyperfine/target/release/hyperfine --export-json=hyperfine-iia001.json "bash authzforce-harness.bash $BENCHMARK" "bash lean-harness.bash $BENCHMARK" "bash rego-harness.bash $BENCHMARK"
diff --git a/benchmarks/excluded.txt b/benchmarks/excluded.txt
new file mode 100644
index 0000000..2bfb31b
--- /dev/null
+++ b/benchmarks/excluded.txt
@@ -0,0 +1,1822 @@
+mandatory/IIA008/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:anyURI-equal
+urn:oasis:names:tc:xacml:1.0:function:string-equal
+urn:oasis:names:tc:xacml:1.0:function:string-is-in
+
+mandatory/IIA009/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:anyURI-equal
+urn:oasis:names:tc:xacml:1.0:function:string-equal
+urn:oasis:names:tc:xacml:1.0:function:string-is-in
+
+mandatory/IIA016_FIXED/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:time-equal
+urn:oasis:names:tc:xacml:1.0:function:time-one-and-only
+
+mandatory/IIA017/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-equal
+urn:oasis:names:tc:xacml:1.0:function:time-bag-size
+
+mandatory/IIA018_FIXED/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:date-equal
+urn:oasis:names:tc:xacml:1.0:function:date-one-and-only
+
+mandatory/IIA019/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:date-bag-size
+urn:oasis:names:tc:xacml:1.0:function:integer-equal
+
+mandatory/IIA020_FIXED/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:dateTime-equal
+urn:oasis:names:tc:xacml:1.0:function:dateTime-one-and-only
+
+mandatory/IIA021/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:dateTime-bag-size
+urn:oasis:names:tc:xacml:1.0:function:integer-equal
+
+mandatory/IIB008/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:anyURI-equal
+urn:oasis:names:tc:xacml:1.0:function:string-equal
+urn:oasis:names:tc:xacml:1.0:function:string-regexp-match
+
+mandatory/IIB009/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:anyURI-equal
+urn:oasis:names:tc:xacml:1.0:function:string-equal
+urn:oasis:names:tc:xacml:1.0:function:string-regexp-match
+
+mandatory/IIB014/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:anyURI-equal
+urn:oasis:names:tc:xacml:1.0:function:string-equal
+urn:oasis:names:tc:xacml:1.0:function:x500Name-equal
+
+mandatory/IIB015/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:anyURI-equal
+urn:oasis:names:tc:xacml:1.0:function:string-equal
+urn:oasis:names:tc:xacml:1.0:function:x500Name-equal
+
+mandatory/IIB026/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:anyURI-equal
+urn:oasis:names:tc:xacml:1.0:function:dateTime-equal
+urn:oasis:names:tc:xacml:1.0:function:string-equal
+
+mandatory/IIB027/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:anyURI-equal
+urn:oasis:names:tc:xacml:1.0:function:dateTime-equal
+urn:oasis:names:tc:xacml:1.0:function:string-equal
+
+mandatory/IIC001/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-greater-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:integer-subtract
+
+mandatory/IIC002/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-greater-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:integer-subtract
+
+mandatory/IIC004/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-greater-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:integer-subtract
+
+mandatory/IIC007/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-greater-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:integer-subtract
+
+mandatory/IIC008/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:string-is-in
+
+mandatory/IIC009/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:string-is-in
+
+mandatory/IIC010/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-greater-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:integer-subtract
+
+mandatory/IIC011/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-greater-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:integer-subtract
+
+mandatory/IIC012/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:integer-subtract
+
+mandatory/IIC013/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-add
+urn:oasis:names:tc:xacml:1.0:function:integer-greater-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only
+
+mandatory/IIC014/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-add
+urn:oasis:names:tc:xacml:1.0:function:integer-greater-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only
+
+mandatory/IIC015/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:double-add
+urn:oasis:names:tc:xacml:1.0:function:double-greater-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:double-one-and-only
+
+mandatory/IIC016/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-greater-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:integer-subtract
+
+mandatory/IIC017/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:double-greater-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:double-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:double-subtract
+
+mandatory/IIC018/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-greater-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:integer-multiply
+urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only
+
+mandatory/IIC019/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:double-greater-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:double-multiply
+urn:oasis:names:tc:xacml:1.0:function:double-one-and-only
+
+mandatory/IIC020/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-divide
+urn:oasis:names:tc:xacml:1.0:function:integer-greater-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only
+
+mandatory/IIC021/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:double-divide
+urn:oasis:names:tc:xacml:1.0:function:double-greater-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:double-one-and-only
+
+mandatory/IIC022/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-equal
+urn:oasis:names:tc:xacml:1.0:function:integer-mod
+urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only
+
+mandatory/IIC024/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:double-greater-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:double-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:round
+
+mandatory/IIC025/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:double-greater-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:double-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:floor
+
+mandatory/IIC026/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-abs
+urn:oasis:names:tc:xacml:1.0:function:integer-greater-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:integer-subtract
+
+mandatory/IIC027/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:double-abs
+urn:oasis:names:tc:xacml:1.0:function:double-greater-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:double-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:double-subtract
+
+mandatory/IIC028/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:double-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:double-to-integer
+urn:oasis:names:tc:xacml:1.0:function:integer-greater-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:integer-subtract
+
+mandatory/IIC029/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:double-greater-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:integer-subtract
+urn:oasis:names:tc:xacml:1.0:function:integer-to-double
+
+mandatory/IIC030/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-equal
+urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:integer-subtract
+
+mandatory/IIC031/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-equal
+urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:integer-subtract
+
+mandatory/IIC032/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:double-equal
+urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:integer-subtract
+urn:oasis:names:tc:xacml:1.0:function:integer-to-double
+
+mandatory/IIC033/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:double-equal
+urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:integer-subtract
+urn:oasis:names:tc:xacml:1.0:function:integer-to-double
+
+mandatory/IIC034/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:boolean-equal
+urn:oasis:names:tc:xacml:1.0:function:integer-greater-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:integer-subtract
+
+mandatory/IIC035/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:boolean-equal
+urn:oasis:names:tc:xacml:1.0:function:integer-greater-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:integer-subtract
+
+mandatory/IIC038/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:rfc822Name-equal
+urn:oasis:names:tc:xacml:1.0:function:rfc822Name-one-and-only
+
+
+mandatory/IIC039/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:rfc822Name-equal
+urn:oasis:names:tc:xacml:1.0:function:rfc822Name-one-and-only
+
+
+mandatory/IIC040/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:x500Name-equal
+urn:oasis:names:tc:xacml:1.0:function:x500Name-one-and-only
+
+
+mandatory/IIC041/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:x500Name-equal
+urn:oasis:names:tc:xacml:1.0:function:x500Name-one-and-only
+
+
+mandatory/IIC042/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:date-equal
+urn:oasis:names:tc:xacml:1.0:function:date-one-and-only
+
+
+mandatory/IIC043/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:date-equal
+urn:oasis:names:tc:xacml:1.0:function:date-one-and-only
+
+
+mandatory/IIC044/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:time-equal
+urn:oasis:names:tc:xacml:1.0:function:time-one-and-only
+
+
+mandatory/IIC045/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:time-equal
+urn:oasis:names:tc:xacml:1.0:function:time-one-and-only
+
+
+mandatory/IIC046/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:dateTime-equal
+urn:oasis:names:tc:xacml:1.0:function:dateTime-one-and-only
+
+
+mandatory/IIC047/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:dateTime-equal
+urn:oasis:names:tc:xacml:1.0:function:dateTime-one-and-only
+
+mandatory/IIC048/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:hexBinary-equal
+urn:oasis:names:tc:xacml:1.0:function:hexBinary-one-and-only
+
+mandatory/IIC049/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:hexBinary-equal
+urn:oasis:names:tc:xacml:1.0:function:hexBinary-one-and-only
+
+mandatory/IIC050/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:base64Binary-equal
+urn:oasis:names:tc:xacml:1.0:function:base64Binary-one-and-only
+
+mandatory/IIC051/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:base64Binary-equal
+urn:oasis:names:tc:xacml:1.0:function:base64Binary-one-and-only
+
+mandatory/IIC056/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:or
+urn:oasis:names:tc:xacml:1.0:function:string-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:string-regexp-match
+
+mandatory/IIC057/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:or
+urn:oasis:names:tc:xacml:1.0:function:string-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:string-regexp-match
+
+mandatory/IIC058/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-greater-than
+urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:integer-subtract
+
+mandatory/IIC059/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-greater-than
+urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:integer-subtract
+
+mandatory/IIC060/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:double-greater-than
+urn:oasis:names:tc:xacml:1.0:function:double-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:double-subtract
+
+mandatory/IIC061/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:double-greater-than
+urn:oasis:names:tc:xacml:1.0:function:double-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:double-subtract
+
+mandatory/IIC062/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:string-greater-than
+urn:oasis:names:tc:xacml:1.0:function:string-one-and-only
+
+mandatory/IIC063/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:string-greater-than
+urn:oasis:names:tc:xacml:1.0:function:string-one-and-only
+
+mandatory/IIC064/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:date-greater-than
+urn:oasis:names:tc:xacml:1.0:function:date-one-and-only
+
+mandatory/IIC065/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:date-greater-than
+urn:oasis:names:tc:xacml:1.0:function:date-one-and-only
+
+mandatory/IIC066/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:time-greater-than
+urn:oasis:names:tc:xacml:1.0:function:time-one-and-only
+
+mandatory/IIC067/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:time-greater-than
+urn:oasis:names:tc:xacml:1.0:function:time-one-and-only
+
+mandatory/IIC068/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:dateTime-greater-than
+urn:oasis:names:tc:xacml:1.0:function:dateTime-one-and-only
+
+mandatory/IIC069/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:dateTime-greater-than
+urn:oasis:names:tc:xacml:1.0:function:dateTime-one-and-only
+
+mandatory/IIC070/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-greater-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:integer-subtract
+
+mandatory/IIC071/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-greater-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:integer-subtract
+
+mandatory/IIC072/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:double-greater-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:double-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:double-subtract
+
+mandatory/IIC073/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:double-greater-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:double-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:double-subtract
+
+mandatory/IIC074/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:string-greater-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:string-one-and-only
+
+mandatory/IIC075/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:string-greater-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:string-one-and-only
+
+mandatory/IIC076/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:date-greater-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:date-one-and-only
+
+mandatory/IIC077/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:date-greater-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:date-one-and-only
+
+mandatory/IIC078/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:time-greater-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:time-one-and-only
+
+mandatory/IIC079/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:time-greater-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:time-one-and-only
+
+mandatory/IIC080/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:dateTime-greater-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:dateTime-one-and-only
+
+mandatory/IIC081/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:dateTime-greater-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:dateTime-one-and-only
+
+mandatory/IIC082/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:rfc822Name-match
+urn:oasis:names:tc:xacml:1.0:function:rfc822Name-one-and-only
+
+mandatory/IIC083/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:rfc822Name-match
+urn:oasis:names:tc:xacml:1.0:function:rfc822Name-one-and-only
+
+mandatory/IIC084/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:x500Name-match
+urn:oasis:names:tc:xacml:1.0:function:x500Name-one-and-only
+
+mandatory/IIC085/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:x500Name-match
+urn:oasis:names:tc:xacml:1.0:function:x500Name-one-and-only
+
+mandatory/IIC086/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:and
+urn:oasis:names:tc:xacml:1.0:function:integer-greater-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:string-equal
+urn:oasis:names:tc:xacml:1.0:function:string-one-and-only
+
+mandatory/IIC087/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:and
+urn:oasis:names:tc:xacml:1.0:function:integer-greater-than
+urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:string-equal
+urn:oasis:names:tc:xacml:1.0:function:string-one-and-only
+
+mandatory/IIC090/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-greater-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:or
+urn:oasis:names:tc:xacml:1.0:function:string-equal
+urn:oasis:names:tc:xacml:1.0:function:string-one-and-only
+
+mandatory/IIC091/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-greater-than
+urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:or
+urn:oasis:names:tc:xacml:1.0:function:string-equal
+urn:oasis:names:tc:xacml:1.0:function:string-one-and-only
+
+mandatory/IIC094/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-greater-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:n-of
+urn:oasis:names:tc:xacml:1.0:function:string-equal
+urn:oasis:names:tc:xacml:1.0:function:string-one-and-only
+
+mandatory/IIC095/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-greater-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:n-of
+urn:oasis:names:tc:xacml:1.0:function:string-equal
+urn:oasis:names:tc:xacml:1.0:function:string-one-and-only
+
+mandatory/IIC100/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:string-equal
+urn:oasis:names:tc:xacml:1.0:function:string-normalize-space
+urn:oasis:names:tc:xacml:1.0:function:string-one-and-only
+
+mandatory/IIC101/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:string-equal
+urn:oasis:names:tc:xacml:1.0:function:string-normalize-to-lower-case
+urn:oasis:names:tc:xacml:1.0:function:string-one-and-only
+
+mandatory/IIC102/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:dateTime-equal
+urn:oasis:names:tc:xacml:1.0:function:dateTime-one-and-only
+
+mandatory/IIC103/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:dateTime-equal
+urn:oasis:names:tc:xacml:1.0:function:dateTime-one-and-only
+
+mandatory/IIC104/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:dateTime-equal
+urn:oasis:names:tc:xacml:1.0:function:dateTime-one-and-only
+
+mandatory/IIC105/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:dateTime-equal
+urn:oasis:names:tc:xacml:1.0:function:dateTime-one-and-only
+
+mandatory/IIC106/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:date-equal
+urn:oasis:names:tc:xacml:1.0:function:date-one-and-only
+
+mandatory/IIC107/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:date-equal
+urn:oasis:names:tc:xacml:1.0:function:date-one-and-only
+
+mandatory/IIC108/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:string-less-than
+urn:oasis:names:tc:xacml:1.0:function:string-one-and-only
+
+mandatory/IIC109/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:string-less-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:string-one-and-only
+
+mandatory/IIC110/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-less-than
+urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only
+
+mandatory/IIC111/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:double-less-than
+urn:oasis:names:tc:xacml:1.0:function:double-one-and-only
+
+mandatory/IIC112/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-less-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only
+
+mandatory/IIC113/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:double-less-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:double-one-and-only
+
+mandatory/IIC114/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:time-less-than
+urn:oasis:names:tc:xacml:1.0:function:time-one-and-only
+
+mandatory/IIC115/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:time-less-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:time-one-and-only
+
+mandatory/IIC116/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:dateTime-less-than
+urn:oasis:names:tc:xacml:1.0:function:dateTime-one-and-only
+
+mandatory/IIC117/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:dateTime-less-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:dateTime-one-and-only
+
+mandatory/IIC118/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:date-less-than
+urn:oasis:names:tc:xacml:1.0:function:date-one-and-only
+
+mandatory/IIC119/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:date-less-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:date-one-and-only
+
+mandatory/IIC120/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-equal
+urn:oasis:names:tc:xacml:1.0:function:string-bag-size
+
+mandatory/IIC121/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-equal
+urn:oasis:names:tc:xacml:1.0:function:string-bag
+urn:oasis:names:tc:xacml:1.0:function:string-bag-size
+urn:oasis:names:tc:xacml:1.0:function:string-one-and-only
+
+mandatory/IIC123/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:boolean-bag-size
+urn:oasis:names:tc:xacml:1.0:function:integer-equal
+
+mandatory/IIC124/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:boolean-is-in
+
+mandatory/IIC125/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:boolean-bag
+urn:oasis:names:tc:xacml:1.0:function:boolean-bag-size
+urn:oasis:names:tc:xacml:1.0:function:boolean-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:integer-equal
+
+mandatory/IIC126/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-bag-size
+urn:oasis:names:tc:xacml:1.0:function:integer-equal
+
+mandatory/IIC127/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-is-in
+
+mandatory/IIC128/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-bag
+urn:oasis:names:tc:xacml:1.0:function:integer-bag-size
+urn:oasis:names:tc:xacml:1.0:function:integer-equal
+urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only
+
+mandatory/IIC129/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:double-bag-size
+urn:oasis:names:tc:xacml:1.0:function:integer-equal
+
+mandatory/IIC130/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:double-is-in
+
+mandatory/IIC131/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:double-bag
+urn:oasis:names:tc:xacml:1.0:function:double-bag-size
+urn:oasis:names:tc:xacml:1.0:function:double-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:integer-equal
+
+mandatory/IIC132/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:date-bag-size
+urn:oasis:names:tc:xacml:1.0:function:integer-equal
+
+mandatory/IIC133/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:date-is-in
+
+mandatory/IIC134/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:date-bag
+urn:oasis:names:tc:xacml:1.0:function:date-bag-size
+urn:oasis:names:tc:xacml:1.0:function:date-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:integer-equal
+
+mandatory/IIC135/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-equal
+urn:oasis:names:tc:xacml:1.0:function:time-bag-size
+
+mandatory/IIC136/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:time-is-in
+
+mandatory/IIC137/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-equal
+urn:oasis:names:tc:xacml:1.0:function:time-bag
+urn:oasis:names:tc:xacml:1.0:function:time-bag-size
+urn:oasis:names:tc:xacml:1.0:function:time-one-and-only
+
+mandatory/IIC138/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:dateTime-bag-size
+urn:oasis:names:tc:xacml:1.0:function:integer-equal
+
+mandatory/IIC139/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:dateTime-is-in
+
+mandatory/IIC140/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:dateTime-bag
+urn:oasis:names:tc:xacml:1.0:function:dateTime-bag-size
+urn:oasis:names:tc:xacml:1.0:function:dateTime-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:integer-equal
+
+mandatory/IIC141/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:anyURI-bag-size
+urn:oasis:names:tc:xacml:1.0:function:integer-equal
+
+mandatory/IIC142/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:anyURI-is-in
+
+mandatory/IIC143/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:anyURI-bag
+urn:oasis:names:tc:xacml:1.0:function:anyURI-bag-size
+urn:oasis:names:tc:xacml:1.0:function:anyURI-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:integer-equal
+
+mandatory/IIC144/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:hexBinary-bag-size
+urn:oasis:names:tc:xacml:1.0:function:integer-equal
+
+mandatory/IIC145/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:hexBinary-is-in
+
+mandatory/IIC146/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:hexBinary-bag
+urn:oasis:names:tc:xacml:1.0:function:hexBinary-bag-size
+urn:oasis:names:tc:xacml:1.0:function:hexBinary-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:integer-equal
+
+mandatory/IIC147/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:base64Binary-bag-size
+urn:oasis:names:tc:xacml:1.0:function:integer-equal
+
+mandatory/IIC148/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:base64Binary-is-in
+
+mandatory/IIC149/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:base64Binary-bag
+urn:oasis:names:tc:xacml:1.0:function:base64Binary-bag-size
+urn:oasis:names:tc:xacml:1.0:function:base64Binary-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:integer-equal
+
+mandatory/IIC158/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-equal
+urn:oasis:names:tc:xacml:1.0:function:x500Name-bag-size
+
+mandatory/IIC159/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:x500Name-is-in
+
+mandatory/IIC160/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-equal
+urn:oasis:names:tc:xacml:1.0:function:x500Name-bag
+urn:oasis:names:tc:xacml:1.0:function:x500Name-bag-size
+urn:oasis:names:tc:xacml:1.0:function:x500Name-one-and-only
+
+mandatory/IIC161/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-equal
+urn:oasis:names:tc:xacml:1.0:function:rfc822Name-bag-size
+
+mandatory/IIC162/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:rfc822Name-is-in
+
+mandatory/IIC163/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-equal
+urn:oasis:names:tc:xacml:1.0:function:rfc822Name-bag
+urn:oasis:names:tc:xacml:1.0:function:rfc822Name-bag-size
+urn:oasis:names:tc:xacml:1.0:function:rfc822Name-one-and-only
+
+mandatory/IIC165/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:string-regexp-match
+
+mandatory/IIC166/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:string-bag
+urn:oasis:names:tc:xacml:1.0:function:string-regexp-match
+
+mandatory/IIC167/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:all-of-any
+urn:oasis:names:tc:xacml:1.0:function:string-bag
+urn:oasis:names:tc:xacml:1.0:function:string-regexp-match
+
+mandatory/IIC168/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:any-of-all
+urn:oasis:names:tc:xacml:1.0:function:string-bag
+urn:oasis:names:tc:xacml:1.0:function:string-regexp-match
+
+mandatory/IIC169/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:all-of-all
+urn:oasis:names:tc:xacml:1.0:function:string-bag
+urn:oasis:names:tc:xacml:1.0:function:string-regexp-match
+
+mandatory/IIC170/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:string-equal
+urn:oasis:names:tc:xacml:1.0:function:string-normalize-space
+
+mandatory/IIC171/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-equal
+urn:oasis:names:tc:xacml:1.0:function:string-bag
+urn:oasis:names:tc:xacml:1.0:function:string-bag-size
+urn:oasis:names:tc:xacml:1.0:function:string-intersection
+
+mandatory/IIC172/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:string-at-least-one-member-of
+urn:oasis:names:tc:xacml:1.0:function:string-bag
+
+mandatory/IIC173/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-equal
+urn:oasis:names:tc:xacml:1.0:function:string-bag
+urn:oasis:names:tc:xacml:1.0:function:string-bag-size
+urn:oasis:names:tc:xacml:1.0:function:string-union
+
+mandatory/IIC174/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:string-bag
+urn:oasis:names:tc:xacml:1.0:function:string-subset
+
+mandatory/IIC175/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:string-bag
+urn:oasis:names:tc:xacml:1.0:function:string-set-equals
+
+mandatory/IIC176/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:boolean-bag
+urn:oasis:names:tc:xacml:1.0:function:boolean-bag-size
+urn:oasis:names:tc:xacml:1.0:function:boolean-intersection
+urn:oasis:names:tc:xacml:1.0:function:integer-equal
+
+mandatory/IIC177/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:boolean-at-least-one-member-of
+urn:oasis:names:tc:xacml:1.0:function:boolean-bag
+
+mandatory/IIC178/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:boolean-bag
+urn:oasis:names:tc:xacml:1.0:function:boolean-bag-size
+urn:oasis:names:tc:xacml:1.0:function:boolean-union
+urn:oasis:names:tc:xacml:1.0:function:integer-equal
+
+mandatory/IIC179/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:boolean-bag
+urn:oasis:names:tc:xacml:1.0:function:boolean-subset
+
+mandatory/IIC180/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:boolean-bag
+urn:oasis:names:tc:xacml:1.0:function:boolean-set-equals
+
+mandatory/IIC181/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-bag
+urn:oasis:names:tc:xacml:1.0:function:integer-bag-size
+urn:oasis:names:tc:xacml:1.0:function:integer-equal
+urn:oasis:names:tc:xacml:1.0:function:integer-intersection
+
+mandatory/IIC182/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-at-least-one-member-of
+urn:oasis:names:tc:xacml:1.0:function:integer-bag
+
+mandatory/IIC183/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-bag
+urn:oasis:names:tc:xacml:1.0:function:integer-bag-size
+urn:oasis:names:tc:xacml:1.0:function:integer-equal
+urn:oasis:names:tc:xacml:1.0:function:integer-union
+
+mandatory/IIC184/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-bag
+urn:oasis:names:tc:xacml:1.0:function:integer-subset
+
+mandatory/IIC185/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-bag
+urn:oasis:names:tc:xacml:1.0:function:integer-set-equals
+
+mandatory/IIC186/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:double-bag
+urn:oasis:names:tc:xacml:1.0:function:double-bag-size
+urn:oasis:names:tc:xacml:1.0:function:double-intersection
+urn:oasis:names:tc:xacml:1.0:function:integer-equal
+
+mandatory/IIC187/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:double-at-least-one-member-of
+urn:oasis:names:tc:xacml:1.0:function:double-bag
+
+mandatory/IIC188/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:double-bag
+urn:oasis:names:tc:xacml:1.0:function:double-bag-size
+urn:oasis:names:tc:xacml:1.0:function:double-union
+urn:oasis:names:tc:xacml:1.0:function:integer-equal
+
+mandatory/IIC189/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:double-bag
+urn:oasis:names:tc:xacml:1.0:function:double-subset
+
+mandatory/IIC190/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:double-bag
+urn:oasis:names:tc:xacml:1.0:function:double-set-equals
+
+mandatory/IIC191/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:date-bag
+urn:oasis:names:tc:xacml:1.0:function:date-bag-size
+urn:oasis:names:tc:xacml:1.0:function:date-intersection
+urn:oasis:names:tc:xacml:1.0:function:integer-equal
+
+mandatory/IIC192/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:date-at-least-one-member-of
+urn:oasis:names:tc:xacml:1.0:function:date-bag
+
+mandatory/IIC193/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:date-bag
+urn:oasis:names:tc:xacml:1.0:function:date-bag-size
+urn:oasis:names:tc:xacml:1.0:function:date-union
+urn:oasis:names:tc:xacml:1.0:function:integer-equal
+
+mandatory/IIC194/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:date-bag
+urn:oasis:names:tc:xacml:1.0:function:date-subset
+
+mandatory/IIC195/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:date-bag
+urn:oasis:names:tc:xacml:1.0:function:date-set-equals
+
+mandatory/IIC196/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-equal
+urn:oasis:names:tc:xacml:1.0:function:time-bag
+urn:oasis:names:tc:xacml:1.0:function:time-bag-size
+urn:oasis:names:tc:xacml:1.0:function:time-intersection
+
+mandatory/IIC197/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:time-at-least-one-member-of
+urn:oasis:names:tc:xacml:1.0:function:time-bag
+
+mandatory/IIC198/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-equal
+urn:oasis:names:tc:xacml:1.0:function:time-bag
+urn:oasis:names:tc:xacml:1.0:function:time-bag-size
+urn:oasis:names:tc:xacml:1.0:function:time-union
+
+mandatory/IIC199/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:time-bag
+urn:oasis:names:tc:xacml:1.0:function:time-subset
+
+mandatory/IIC200/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:time-bag
+urn:oasis:names:tc:xacml:1.0:function:time-set-equals
+
+mandatory/IIC201/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:dateTime-bag
+urn:oasis:names:tc:xacml:1.0:function:dateTime-bag-size
+urn:oasis:names:tc:xacml:1.0:function:dateTime-intersection
+urn:oasis:names:tc:xacml:1.0:function:integer-equal
+
+mandatory/IIC202/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:dateTime-at-least-one-member-of
+urn:oasis:names:tc:xacml:1.0:function:dateTime-bag
+
+mandatory/IIC203/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:dateTime-bag
+urn:oasis:names:tc:xacml:1.0:function:dateTime-bag-size
+urn:oasis:names:tc:xacml:1.0:function:dateTime-union
+urn:oasis:names:tc:xacml:1.0:function:integer-equal
+
+mandatory/IIC204/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:dateTime-bag
+urn:oasis:names:tc:xacml:1.0:function:dateTime-subset
+
+mandatory/IIC205/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:dateTime-bag
+urn:oasis:names:tc:xacml:1.0:function:dateTime-set-equals
+
+mandatory/IIC206/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:anyURI-bag
+urn:oasis:names:tc:xacml:1.0:function:anyURI-bag-size
+urn:oasis:names:tc:xacml:1.0:function:anyURI-intersection
+urn:oasis:names:tc:xacml:1.0:function:integer-equal
+
+mandatory/IIC207/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:anyURI-at-least-one-member-of
+urn:oasis:names:tc:xacml:1.0:function:anyURI-bag
+
+mandatory/IIC208/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:anyURI-bag
+urn:oasis:names:tc:xacml:1.0:function:anyURI-bag-size
+urn:oasis:names:tc:xacml:1.0:function:anyURI-union
+urn:oasis:names:tc:xacml:1.0:function:integer-equal
+
+mandatory/IIC209/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:anyURI-bag
+urn:oasis:names:tc:xacml:1.0:function:anyURI-subset
+
+mandatory/IIC210/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:anyURI-bag
+urn:oasis:names:tc:xacml:1.0:function:anyURI-set-equals
+
+mandatory/IIC211/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-equal
+urn:oasis:names:tc:xacml:1.0:function:x500Name-bag
+urn:oasis:names:tc:xacml:1.0:function:x500Name-bag-size
+urn:oasis:names:tc:xacml:1.0:function:x500Name-intersection
+
+mandatory/IIC212/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:x500Name-at-least-one-member-of
+urn:oasis:names:tc:xacml:1.0:function:x500Name-bag
+
+mandatory/IIC213/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-equal
+urn:oasis:names:tc:xacml:1.0:function:x500Name-bag
+urn:oasis:names:tc:xacml:1.0:function:x500Name-bag-size
+urn:oasis:names:tc:xacml:1.0:function:x500Name-union
+
+mandatory/IIC214/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:x500Name-bag
+urn:oasis:names:tc:xacml:1.0:function:x500Name-subset
+
+mandatory/IIC215/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:x500Name-bag
+urn:oasis:names:tc:xacml:1.0:function:x500Name-set-equals
+
+mandatory/IIC216/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-equal
+urn:oasis:names:tc:xacml:1.0:function:rfc822Name-bag
+urn:oasis:names:tc:xacml:1.0:function:rfc822Name-bag-size
+urn:oasis:names:tc:xacml:1.0:function:rfc822Name-intersection
+
+mandatory/IIC217/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:rfc822Name-at-least-one-member-of
+urn:oasis:names:tc:xacml:1.0:function:rfc822Name-bag
+
+mandatory/IIC218/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-equal
+urn:oasis:names:tc:xacml:1.0:function:rfc822Name-bag
+urn:oasis:names:tc:xacml:1.0:function:rfc822Name-bag-size
+urn:oasis:names:tc:xacml:1.0:function:rfc822Name-union
+
+mandatory/IIC219/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:rfc822Name-bag
+urn:oasis:names:tc:xacml:1.0:function:rfc822Name-subset
+
+mandatory/IIC220/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:rfc822Name-bag
+urn:oasis:names:tc:xacml:1.0:function:rfc822Name-set-equals
+
+mandatory/IIC221/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:hexBinary-bag
+urn:oasis:names:tc:xacml:1.0:function:hexBinary-bag-size
+urn:oasis:names:tc:xacml:1.0:function:hexBinary-intersection
+urn:oasis:names:tc:xacml:1.0:function:integer-equal
+
+mandatory/IIC222/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:hexBinary-at-least-one-member-of
+urn:oasis:names:tc:xacml:1.0:function:hexBinary-bag
+
+mandatory/IIC223/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:hexBinary-bag
+urn:oasis:names:tc:xacml:1.0:function:hexBinary-bag-size
+urn:oasis:names:tc:xacml:1.0:function:hexBinary-union
+urn:oasis:names:tc:xacml:1.0:function:integer-equal
+
+mandatory/IIC224/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:hexBinary-bag
+urn:oasis:names:tc:xacml:1.0:function:hexBinary-subset
+
+mandatory/IIC225/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:hexBinary-bag
+urn:oasis:names:tc:xacml:1.0:function:hexBinary-set-equals
+
+mandatory/IIC226/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:base64Binary-bag
+urn:oasis:names:tc:xacml:1.0:function:base64Binary-bag-size
+urn:oasis:names:tc:xacml:1.0:function:base64Binary-intersection
+urn:oasis:names:tc:xacml:1.0:function:integer-equal
+
+mandatory/IIC227/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:base64Binary-at-least-one-member-of
+urn:oasis:names:tc:xacml:1.0:function:base64Binary-bag
+
+mandatory/IIC228/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:base64Binary-bag
+urn:oasis:names:tc:xacml:1.0:function:base64Binary-bag-size
+urn:oasis:names:tc:xacml:1.0:function:base64Binary-union
+urn:oasis:names:tc:xacml:1.0:function:integer-equal
+
+mandatory/IIC229/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:base64Binary-bag
+urn:oasis:names:tc:xacml:1.0:function:base64Binary-subset
+
+mandatory/IIC230/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:base64Binary-bag
+urn:oasis:names:tc:xacml:1.0:function:base64Binary-set-equals
+
+mandatory/IIC350/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:double-equal
+urn:oasis:names:tc:xacml:1.0:function:double-one-and-only
+
+mandatory/IIC351/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:double-equal
+urn:oasis:names:tc:xacml:1.0:function:double-one-and-only
+
+mandatory/IIC352/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:double-equal
+urn:oasis:names:tc:xacml:1.0:function:double-one-and-only
+
+mandatory/IIC353/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:double-equal
+urn:oasis:names:tc:xacml:1.0:function:double-one-and-only
+
+mandatory/IIC354/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:double-equal
+urn:oasis:names:tc:xacml:1.0:function:double-one-and-only
+
+mandatory/IIC355/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:double-equal
+urn:oasis:names:tc:xacml:1.0:function:double-one-and-only
+
+mandatory/IIC356/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:double-less-than
+urn:oasis:names:tc:xacml:1.0:function:double-one-and-only
+
+mandatory/IIC357/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:double-greater-than
+urn:oasis:names:tc:xacml:1.0:function:double-one-and-only
+
+mandatory/IIC358/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:double-add
+urn:oasis:names:tc:xacml:1.0:function:double-equal
+urn:oasis:names:tc:xacml:1.0:function:double-one-and-only
+
+mandatory/IIC359/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:double-equal
+urn:oasis:names:tc:xacml:1.0:function:double-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:double-subtract
+
+mandatory/IID001/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-greater-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:integer-subtract
+urn:oasis:names:tc:xacml:1.0:function:string-equal
+
+mandatory/IID002/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-greater-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:integer-subtract
+urn:oasis:names:tc:xacml:1.0:function:string-equal
+urn:oasis:names:tc:xacml:1.0:function:string-one-and-only
+
+mandatory/IID003/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-greater-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:integer-subtract
+urn:oasis:names:tc:xacml:1.0:function:string-equal
+
+mandatory/IID004/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-greater-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:integer-subtract
+urn:oasis:names:tc:xacml:1.0:function:string-equal
+urn:oasis:names:tc:xacml:1.0:function:string-one-and-only
+
+mandatory/IID005/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-greater-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:integer-subtract
+urn:oasis:names:tc:xacml:1.0:function:string-equal
+
+mandatory/IID006/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-greater-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:integer-subtract
+urn:oasis:names:tc:xacml:1.0:function:string-equal
+urn:oasis:names:tc:xacml:1.0:function:string-one-and-only
+
+mandatory/IID007/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-greater-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:integer-subtract
+urn:oasis:names:tc:xacml:1.0:function:string-equal
+
+mandatory/IID008/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-greater-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:integer-subtract
+urn:oasis:names:tc:xacml:1.0:function:string-equal
+urn:oasis:names:tc:xacml:1.0:function:string-one-and-only
+
+mandatory/IID009/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-greater-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:integer-subtract
+urn:oasis:names:tc:xacml:1.0:function:string-equal
+urn:oasis:names:tc:xacml:1.0:function:string-one-and-only
+
+mandatory/IID010/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-greater-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:integer-subtract
+urn:oasis:names:tc:xacml:1.0:function:string-equal
+urn:oasis:names:tc:xacml:1.0:function:string-one-and-only
+
+mandatory/IID011/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-greater-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:integer-subtract
+urn:oasis:names:tc:xacml:1.0:function:string-equal
+
+mandatory/IID012/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-greater-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:integer-subtract
+urn:oasis:names:tc:xacml:1.0:function:string-equal
+urn:oasis:names:tc:xacml:1.0:function:string-one-and-only
+
+mandatory/IID013/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-greater-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:integer-subtract
+urn:oasis:names:tc:xacml:1.0:function:string-equal
+urn:oasis:names:tc:xacml:1.0:function:string-one-and-only
+
+mandatory/IID014/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-greater-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:integer-subtract
+urn:oasis:names:tc:xacml:1.0:function:string-equal
+urn:oasis:names:tc:xacml:1.0:function:string-one-and-only
+
+mandatory/IID015/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-greater-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:integer-subtract
+urn:oasis:names:tc:xacml:1.0:function:string-equal
+
+mandatory/IID016/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-greater-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:integer-subtract
+urn:oasis:names:tc:xacml:1.0:function:string-equal
+urn:oasis:names:tc:xacml:1.0:function:string-one-and-only
+
+mandatory/IID017/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-greater-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:integer-subtract
+urn:oasis:names:tc:xacml:1.0:function:string-equal
+
+mandatory/IID018/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-greater-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:integer-subtract
+urn:oasis:names:tc:xacml:1.0:function:string-equal
+urn:oasis:names:tc:xacml:1.0:function:string-one-and-only
+
+mandatory/IID019/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-greater-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:integer-subtract
+urn:oasis:names:tc:xacml:1.0:function:string-equal
+
+mandatory/IID020/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-greater-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:integer-subtract
+urn:oasis:names:tc:xacml:1.0:function:string-equal
+urn:oasis:names:tc:xacml:1.0:function:string-one-and-only
+
+mandatory/IID021/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-greater-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:integer-subtract
+urn:oasis:names:tc:xacml:1.0:function:string-equal
+
+mandatory/IID022/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-greater-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:integer-subtract
+urn:oasis:names:tc:xacml:1.0:function:string-equal
+urn:oasis:names:tc:xacml:1.0:function:string-one-and-only
+
+mandatory/IID023/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-greater-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:integer-subtract
+urn:oasis:names:tc:xacml:1.0:function:string-equal
+
+mandatory/IID024/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-greater-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:integer-subtract
+urn:oasis:names:tc:xacml:1.0:function:string-equal
+urn:oasis:names:tc:xacml:1.0:function:string-one-and-only
+
+mandatory/IID025/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-greater-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:integer-subtract
+urn:oasis:names:tc:xacml:1.0:function:string-equal
+
+mandatory/IID026/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-greater-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:integer-less-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:integer-subtract
+urn:oasis:names:tc:xacml:1.0:function:string-equal
+urn:oasis:names:tc:xacml:1.0:function:string-one-and-only
+
+mandatory/IID027/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-greater-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:integer-less-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:integer-subtract
+urn:oasis:names:tc:xacml:1.0:function:string-equal
+urn:oasis:names:tc:xacml:1.0:function:string-one-and-only
+
+mandatory/IID028/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-greater-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:integer-less-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:integer-subtract
+urn:oasis:names:tc:xacml:1.0:function:string-equal
+urn:oasis:names:tc:xacml:1.0:function:string-one-and-only
+
+mandatory/IID300/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-greater-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:integer-subtract
+urn:oasis:names:tc:xacml:1.0:function:string-equal
+urn:oasis:names:tc:xacml:1.0:function:string-one-and-only
+
+mandatory/IID301/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-greater-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:integer-subtract
+urn:oasis:names:tc:xacml:1.0:function:string-equal
+
+mandatory/IID302/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-greater-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:integer-subtract
+urn:oasis:names:tc:xacml:1.0:function:string-equal
+urn:oasis:names:tc:xacml:1.0:function:string-one-and-only
+
+mandatory/IID303/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-greater-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:integer-subtract
+urn:oasis:names:tc:xacml:1.0:function:string-equal
+urn:oasis:names:tc:xacml:1.0:function:string-one-and-only
+
+mandatory/IID304/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-greater-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:integer-subtract
+urn:oasis:names:tc:xacml:1.0:function:string-equal
+
+mandatory/IID305/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-greater-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:integer-subtract
+urn:oasis:names:tc:xacml:1.0:function:string-equal
+urn:oasis:names:tc:xacml:1.0:function:string-one-and-only
+
+mandatory/IID306/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-greater-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:integer-subtract
+urn:oasis:names:tc:xacml:1.0:function:string-equal
+
+mandatory/IID307/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-greater-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:integer-subtract
+urn:oasis:names:tc:xacml:1.0:function:string-equal
+urn:oasis:names:tc:xacml:1.0:function:string-one-and-only
+
+mandatory/IID308/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-greater-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:integer-subtract
+urn:oasis:names:tc:xacml:1.0:function:string-equal
+urn:oasis:names:tc:xacml:1.0:function:string-one-and-only
+
+mandatory/IID309/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-greater-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:integer-subtract
+urn:oasis:names:tc:xacml:1.0:function:string-equal
+
+mandatory/IID310/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-greater-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:integer-subtract
+urn:oasis:names:tc:xacml:1.0:function:string-equal
+urn:oasis:names:tc:xacml:1.0:function:string-one-and-only
+
+mandatory/IID311/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-greater-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:integer-subtract
+urn:oasis:names:tc:xacml:1.0:function:string-equal
+urn:oasis:names:tc:xacml:1.0:function:string-one-and-only
+
+mandatory/IID312/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-greater-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:integer-subtract
+urn:oasis:names:tc:xacml:1.0:function:string-equal
+urn:oasis:names:tc:xacml:1.0:function:string-one-and-only
+
+mandatory/IID313/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-greater-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:integer-subtract
+urn:oasis:names:tc:xacml:1.0:function:string-equal
+urn:oasis:names:tc:xacml:1.0:function:string-one-and-only
+
+mandatory/IID314/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-greater-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:integer-subtract
+urn:oasis:names:tc:xacml:1.0:function:string-equal
+
+mandatory/IID315/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-greater-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:integer-subtract
+urn:oasis:names:tc:xacml:1.0:function:string-equal
+urn:oasis:names:tc:xacml:1.0:function:string-one-and-only
+
+mandatory/IID316/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-greater-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:integer-subtract
+urn:oasis:names:tc:xacml:1.0:function:string-equal
+urn:oasis:names:tc:xacml:1.0:function:string-one-and-only
+
+mandatory/IID317/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-greater-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:integer-subtract
+urn:oasis:names:tc:xacml:1.0:function:string-equal
+urn:oasis:names:tc:xacml:1.0:function:string-one-and-only
+
+mandatory/IID318/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-greater-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:integer-subtract
+urn:oasis:names:tc:xacml:1.0:function:string-equal
+urn:oasis:names:tc:xacml:1.0:function:string-one-and-only
+
+mandatory/IID319/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-greater-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:integer-subtract
+urn:oasis:names:tc:xacml:1.0:function:string-equal
+
+mandatory/IID320/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-greater-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:integer-subtract
+urn:oasis:names:tc:xacml:1.0:function:string-equal
+urn:oasis:names:tc:xacml:1.0:function:string-one-and-only
+
+mandatory/IID330/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-greater-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:integer-subtract
+urn:oasis:names:tc:xacml:1.0:function:string-equal
+urn:oasis:names:tc:xacml:1.0:function:string-one-and-only
+
+mandatory/IID331/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-greater-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:integer-subtract
+urn:oasis:names:tc:xacml:1.0:function:string-equal
+urn:oasis:names:tc:xacml:1.0:function:string-one-and-only
+
+mandatory/IID332/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-greater-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:integer-subtract
+urn:oasis:names:tc:xacml:1.0:function:string-equal
+urn:oasis:names:tc:xacml:1.0:function:string-one-and-only
+
+mandatory/IID333/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-greater-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:integer-subtract
+urn:oasis:names:tc:xacml:1.0:function:string-equal
+urn:oasis:names:tc:xacml:1.0:function:string-one-and-only
+
+mandatory/IID340/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-greater-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:integer-subtract
+urn:oasis:names:tc:xacml:1.0:function:string-equal
+urn:oasis:names:tc:xacml:1.0:function:string-one-and-only
+
+mandatory/IID341/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-greater-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:integer-subtract
+urn:oasis:names:tc:xacml:1.0:function:string-equal
+urn:oasis:names:tc:xacml:1.0:function:string-one-and-only
+
+mandatory/IID342/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-greater-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:integer-subtract
+urn:oasis:names:tc:xacml:1.0:function:string-equal
+urn:oasis:names:tc:xacml:1.0:function:string-one-and-only
+
+mandatory/IID343/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-greater-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:integer-subtract
+urn:oasis:names:tc:xacml:1.0:function:string-equal
+urn:oasis:names:tc:xacml:1.0:function:string-one-and-only
+
+mandatory/IIF311/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-greater-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:integer-subtract
+urn:oasis:names:tc:xacml:1.0:function:string-equal
+
+mandatory/IIIA001/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-greater-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:integer-subtract
+urn:oasis:names:tc:xacml:1.0:function:string-equal
+
+mandatory/IIIA002/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-greater-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:integer-subtract
+urn:oasis:names:tc:xacml:1.0:function:string-equal
+urn:oasis:names:tc:xacml:1.0:function:string-one-and-only
+
+mandatory/IIIA003/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-greater-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:integer-subtract
+urn:oasis:names:tc:xacml:1.0:function:string-equal
+
+mandatory/IIIA004/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-greater-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:integer-subtract
+urn:oasis:names:tc:xacml:1.0:function:string-equal
+urn:oasis:names:tc:xacml:1.0:function:string-one-and-only
+
+mandatory/IIIA005/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-greater-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:integer-subtract
+urn:oasis:names:tc:xacml:1.0:function:string-equal
+urn:oasis:names:tc:xacml:1.0:function:string-one-and-only
+
+mandatory/IIIA006/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-greater-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:integer-subtract
+urn:oasis:names:tc:xacml:1.0:function:string-equal
+urn:oasis:names:tc:xacml:1.0:function:string-one-and-only
+
+mandatory/IIIA007/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-greater-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:integer-subtract
+urn:oasis:names:tc:xacml:1.0:function:string-equal
+
+mandatory/IIIA008/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-greater-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:integer-subtract
+urn:oasis:names:tc:xacml:1.0:function:string-equal
+urn:oasis:names:tc:xacml:1.0:function:string-one-and-only
+
+mandatory/IIIA009/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-greater-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:integer-subtract
+urn:oasis:names:tc:xacml:1.0:function:string-equal
+
+mandatory/IIIA010/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-greater-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:integer-subtract
+urn:oasis:names:tc:xacml:1.0:function:string-equal
+urn:oasis:names:tc:xacml:1.0:function:string-one-and-only
+
+mandatory/IIIA011/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-greater-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:integer-subtract
+urn:oasis:names:tc:xacml:1.0:function:string-equal
+
+mandatory/IIIA012/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-greater-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:integer-subtract
+urn:oasis:names:tc:xacml:1.0:function:string-equal
+urn:oasis:names:tc:xacml:1.0:function:string-one-and-only
+
+mandatory/IIIA013/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-greater-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:integer-subtract
+urn:oasis:names:tc:xacml:1.0:function:string-equal
+
+mandatory/IIIA014/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-greater-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:integer-subtract
+urn:oasis:names:tc:xacml:1.0:function:string-equal
+urn:oasis:names:tc:xacml:1.0:function:string-one-and-only
+
+mandatory/IIIA015/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-greater-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:integer-subtract
+urn:oasis:names:tc:xacml:1.0:function:string-equal
+
+mandatory/IIIA016/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-greater-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:integer-subtract
+urn:oasis:names:tc:xacml:1.0:function:string-equal
+urn:oasis:names:tc:xacml:1.0:function:string-one-and-only
+
+mandatory/IIIA017/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-greater-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:integer-subtract
+urn:oasis:names:tc:xacml:1.0:function:string-equal
+urn:oasis:names:tc:xacml:1.0:function:string-one-and-only
+
+mandatory/IIIA018/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-greater-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:integer-subtract
+urn:oasis:names:tc:xacml:1.0:function:string-equal
+urn:oasis:names:tc:xacml:1.0:function:string-one-and-only
+
+mandatory/IIIA019/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-greater-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:integer-subtract
+urn:oasis:names:tc:xacml:1.0:function:string-equal
+
+mandatory/IIIA020/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-greater-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:integer-subtract
+urn:oasis:names:tc:xacml:1.0:function:string-equal
+urn:oasis:names:tc:xacml:1.0:function:string-one-and-only
+
+mandatory/IIIA021/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-greater-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:integer-subtract
+urn:oasis:names:tc:xacml:1.0:function:string-equal
+
+mandatory/IIIA022/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-greater-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:integer-subtract
+urn:oasis:names:tc:xacml:1.0:function:string-equal
+urn:oasis:names:tc:xacml:1.0:function:string-one-and-only
+
+mandatory/IIIA023/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-greater-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:integer-subtract
+urn:oasis:names:tc:xacml:1.0:function:string-equal
+
+mandatory/IIIA024/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-greater-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:integer-subtract
+urn:oasis:names:tc:xacml:1.0:function:string-equal
+urn:oasis:names:tc:xacml:1.0:function:string-one-and-only
+
+mandatory/IIIA025/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-greater-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:integer-subtract
+urn:oasis:names:tc:xacml:1.0:function:string-equal
+
+mandatory/IIIA026/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-greater-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:integer-less-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:integer-subtract
+urn:oasis:names:tc:xacml:1.0:function:string-equal
+urn:oasis:names:tc:xacml:1.0:function:string-one-and-only
+
+mandatory/IIIA027/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-greater-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:integer-less-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:integer-subtract
+urn:oasis:names:tc:xacml:1.0:function:string-equal
+urn:oasis:names:tc:xacml:1.0:function:string-one-and-only
+
+mandatory/IIIA028/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-greater-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:integer-less-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:integer-subtract
+urn:oasis:names:tc:xacml:1.0:function:string-equal
+urn:oasis:names:tc:xacml:1.0:function:string-one-and-only
+
+mandatory/IIIA301/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-greater-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:integer-subtract
+urn:oasis:names:tc:xacml:1.0:function:string-equal
+
+mandatory/IIIA302/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-greater-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:integer-subtract
+urn:oasis:names:tc:xacml:1.0:function:string-equal
+urn:oasis:names:tc:xacml:1.0:function:string-one-and-only
+
+mandatory/IIIA303/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-greater-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:integer-subtract
+urn:oasis:names:tc:xacml:1.0:function:string-equal
+
+mandatory/IIIA304/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-greater-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:integer-subtract
+urn:oasis:names:tc:xacml:1.0:function:string-equal
+urn:oasis:names:tc:xacml:1.0:function:string-one-and-only
+
+mandatory/IIIA305/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-greater-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:integer-subtract
+urn:oasis:names:tc:xacml:1.0:function:string-equal
+urn:oasis:names:tc:xacml:1.0:function:string-one-and-only
+
+mandatory/IIIA306/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-greater-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:integer-subtract
+urn:oasis:names:tc:xacml:1.0:function:string-equal
+urn:oasis:names:tc:xacml:1.0:function:string-one-and-only
+
+mandatory/IIIA307/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-greater-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:integer-subtract
+urn:oasis:names:tc:xacml:1.0:function:string-equal
+
+mandatory/IIIA308/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-greater-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:integer-subtract
+urn:oasis:names:tc:xacml:1.0:function:string-equal
+urn:oasis:names:tc:xacml:1.0:function:string-one-and-only
+
+mandatory/IIIA309/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-greater-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:integer-subtract
+urn:oasis:names:tc:xacml:1.0:function:string-equal
+
+mandatory/IIIA310/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-greater-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:integer-subtract
+urn:oasis:names:tc:xacml:1.0:function:string-equal
+urn:oasis:names:tc:xacml:1.0:function:string-one-and-only
+
+mandatory/IIIA311/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-greater-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:integer-subtract
+urn:oasis:names:tc:xacml:1.0:function:string-equal
+
+mandatory/IIIA312/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-greater-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:integer-subtract
+urn:oasis:names:tc:xacml:1.0:function:string-equal
+urn:oasis:names:tc:xacml:1.0:function:string-one-and-only
+
+mandatory/IIIA313/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-greater-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:integer-subtract
+urn:oasis:names:tc:xacml:1.0:function:string-equal
+
+mandatory/IIIA314/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-greater-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:integer-subtract
+urn:oasis:names:tc:xacml:1.0:function:string-equal
+urn:oasis:names:tc:xacml:1.0:function:string-one-and-only
+
+mandatory/IIIA315/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-greater-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:integer-subtract
+urn:oasis:names:tc:xacml:1.0:function:string-equal
+
+mandatory/IIIA316/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-greater-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:integer-subtract
+urn:oasis:names:tc:xacml:1.0:function:string-equal
+urn:oasis:names:tc:xacml:1.0:function:string-one-and-only
+
+mandatory/IIIA317/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-greater-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:integer-subtract
+urn:oasis:names:tc:xacml:1.0:function:string-equal
+urn:oasis:names:tc:xacml:1.0:function:string-one-and-only
+
+mandatory/IIIA318/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-greater-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:integer-subtract
+urn:oasis:names:tc:xacml:1.0:function:string-equal
+urn:oasis:names:tc:xacml:1.0:function:string-one-and-only
+
+mandatory/IIIA319/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-greater-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:integer-subtract
+urn:oasis:names:tc:xacml:1.0:function:string-equal
+
+mandatory/IIIA320/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-greater-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:integer-subtract
+urn:oasis:names:tc:xacml:1.0:function:string-equal
+urn:oasis:names:tc:xacml:1.0:function:string-one-and-only
+
+mandatory/IIIA321/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-greater-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:integer-subtract
+urn:oasis:names:tc:xacml:1.0:function:string-equal
+
+mandatory/IIIA322/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-greater-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:integer-subtract
+urn:oasis:names:tc:xacml:1.0:function:string-equal
+urn:oasis:names:tc:xacml:1.0:function:string-one-and-only
+
+mandatory/IIIA323/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-greater-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:integer-subtract
+urn:oasis:names:tc:xacml:1.0:function:string-equal
+
+mandatory/IIIA324/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-greater-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:integer-subtract
+urn:oasis:names:tc:xacml:1.0:function:string-equal
+urn:oasis:names:tc:xacml:1.0:function:string-one-and-only
+
+mandatory/IIIA325/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-greater-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:integer-subtract
+urn:oasis:names:tc:xacml:1.0:function:string-equal
+
+mandatory/IIIA326/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-greater-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:integer-less-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:integer-subtract
+urn:oasis:names:tc:xacml:1.0:function:string-equal
+urn:oasis:names:tc:xacml:1.0:function:string-one-and-only
+
+mandatory/IIIA327/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-greater-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:integer-less-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:integer-subtract
+urn:oasis:names:tc:xacml:1.0:function:string-equal
+urn:oasis:names:tc:xacml:1.0:function:string-one-and-only
+
+mandatory/IIIA328/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-greater-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:integer-less-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:integer-subtract
+urn:oasis:names:tc:xacml:1.0:function:string-equal
+urn:oasis:names:tc:xacml:1.0:function:string-one-and-only
+
+mandatory/IIIA329/Policy.xml:
+urn:oasis:names:tc:xacml:1.0:function:integer-greater-than-or-equal
+urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only
+urn:oasis:names:tc:xacml:1.0:function:integer-subtract
+urn:oasis:names:tc:xacml:1.0:function:string-equal
diff --git a/benchmarks/hyperfine-iia001.json b/benchmarks/hyperfine-iia001.json
new file mode 100644
index 0000000..5cfd002
--- /dev/null
+++ b/benchmarks/hyperfine-iia001.json
@@ -0,0 +1,212 @@
+{
+ "results": [
+ {
+ "command": "authzforce",
+ "mean": 1.8461527814999996,
+ "stddev": 0.06199174539502622,
+ "median": 1.8238858158,
+ "user": 5.36704266,
+ "system": 0.20038110000000003,
+ "min": 1.7681575743,
+ "max": 1.9531087263,
+ "times": [
+ 1.7985675612999998,
+ 1.8072159603,
+ 1.7681575743,
+ 1.8040717123,
+ 1.8547239183,
+ 1.9046467713,
+ 1.8049998702999999,
+ 1.8405556713,
+ 1.9531087263,
+ 1.9254800493
+ ],
+ "exit_codes": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "command": "lean",
+ "mean": 4.419457606,
+ "stddev": 0.008869787618510696,
+ "median": 4.417610675300001,
+ "user": 4.370591760000001,
+ "system": 0.052795999999999996,
+ "min": 4.4061337973,
+ "max": 4.4311239923,
+ "times": [
+ 4.4094097333,
+ 4.4160989583,
+ 4.4191223923,
+ 4.4280726193,
+ 4.4061337973,
+ 4.4246227593,
+ 4.4309326733,
+ 4.4138470893,
+ 4.4152120453000006,
+ 4.4311239923
+ ],
+ "exit_codes": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "command": "opa",
+ "mean": 0.04686065166507937,
+ "stddev": 0.0007439499827213784,
+ "median": 0.046807240300000004,
+ "user": 0.04948119015873017,
+ "system": 0.009103655555555559,
+ "min": 0.04563805730000001,
+ "max": 0.04922981230000001,
+ "times": [
+ 0.0461474123,
+ 0.048303486300000004,
+ 0.04922981230000001,
+ 0.04705487430000001,
+ 0.047513765300000003,
+ 0.047122320300000006,
+ 0.0468518003,
+ 0.046828386300000004,
+ 0.04866176530000001,
+ 0.04631246530000001,
+ 0.04743980330000001,
+ 0.04692121330000001,
+ 0.046232237300000006,
+ 0.04820853530000001,
+ 0.046098580300000004,
+ 0.0464998053,
+ 0.046051025300000006,
+ 0.04594847430000001,
+ 0.0466571013,
+ 0.047440779300000006,
+ 0.04737457230000001,
+ 0.04633055130000001,
+ 0.048487699300000006,
+ 0.04748818430000001,
+ 0.047259265300000006,
+ 0.0467570813,
+ 0.046098668300000006,
+ 0.04598046630000001,
+ 0.04675927230000001,
+ 0.0469496723,
+ 0.0461157873,
+ 0.046176294300000004,
+ 0.0473107253,
+ 0.0468981113,
+ 0.0460657043,
+ 0.045878819300000005,
+ 0.0476590813,
+ 0.046807240300000004,
+ 0.04664132830000001,
+ 0.046108756300000005,
+ 0.046206166300000004,
+ 0.046065450300000005,
+ 0.04714411030000001,
+ 0.048273055300000006,
+ 0.04725586130000001,
+ 0.04637673330000001,
+ 0.04669826330000001,
+ 0.04711734730000001,
+ 0.0476596763,
+ 0.046422681300000004,
+ 0.047071346300000004,
+ 0.0469502373,
+ 0.046924527300000005,
+ 0.04647903330000001,
+ 0.046374657300000004,
+ 0.046936907300000004,
+ 0.046474964300000005,
+ 0.04658955630000001,
+ 0.046119356300000004,
+ 0.046911354300000006,
+ 0.0464168043,
+ 0.047443984300000006,
+ 0.04563805730000001
+ ],
+ "exit_codes": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ }
+ ]
+}
diff --git a/benchmarks/hyperfine-iia003.json b/benchmarks/hyperfine-iia003.json
new file mode 100644
index 0000000..ecc7a79
--- /dev/null
+++ b/benchmarks/hyperfine-iia003.json
@@ -0,0 +1,208 @@
+{
+ "results": [
+ {
+ "command": "authzforce",
+ "mean": 1.8539233053999997,
+ "stddev": 0.07045118765524386,
+ "median": 1.8637640012,
+ "user": 5.5190032,
+ "system": 0.19728234,
+ "min": 1.7220111481999998,
+ "max": 1.9277803882,
+ "times": [
+ 1.7220111481999998,
+ 1.7490110442,
+ 1.8364869041999998,
+ 1.8772167472,
+ 1.8431721002,
+ 1.9068409922,
+ 1.9116545762,
+ 1.8503112552,
+ 1.9147478982,
+ 1.9277803882
+ ],
+ "exit_codes": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "command": "lean",
+ "mean": 4.419570566399999,
+ "stddev": 0.010926697857862277,
+ "median": 4.4211140677,
+ "user": 4.3713518,
+ "system": 0.052455339999999996,
+ "min": 4.4019222472,
+ "max": 4.4339212692,
+ "times": [
+ 4.4339212692,
+ 4.4114070332,
+ 4.416890663199999,
+ 4.4229281052,
+ 4.425064122199999,
+ 4.4252808622,
+ 4.4193000302,
+ 4.4051925292,
+ 4.4337988022,
+ 4.4019222472
+ ],
+ "exit_codes": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "command": "opa",
+ "mean": 0.04684904405245902,
+ "stddev": 0.0007265745663278671,
+ "median": 0.046686584200000006,
+ "user": 0.04951623770491803,
+ "system": 0.008924961311475412,
+ "min": 0.04590612720000001,
+ "max": 0.04947239020000001,
+ "times": [
+ 0.047505085200000005,
+ 0.0477891012,
+ 0.04766807220000001,
+ 0.04757789120000001,
+ 0.046627629200000006,
+ 0.046532016200000005,
+ 0.04672034220000001,
+ 0.0460801522,
+ 0.04666791320000001,
+ 0.046594200200000005,
+ 0.047600413200000004,
+ 0.0461862882,
+ 0.046681552200000004,
+ 0.04754236220000001,
+ 0.04673284120000001,
+ 0.047990504200000006,
+ 0.04669201320000001,
+ 0.046056508200000006,
+ 0.046408807200000006,
+ 0.047217328200000006,
+ 0.047256917200000005,
+ 0.046044935200000005,
+ 0.045964099200000004,
+ 0.04947239020000001,
+ 0.047289161200000006,
+ 0.046399726200000005,
+ 0.046341788200000004,
+ 0.046582481200000005,
+ 0.04590612720000001,
+ 0.046078393200000005,
+ 0.047378041200000005,
+ 0.046084784200000006,
+ 0.047149540200000006,
+ 0.046272840200000005,
+ 0.04670162420000001,
+ 0.046520495200000005,
+ 0.04646542520000001,
+ 0.047481608200000004,
+ 0.048442480200000006,
+ 0.046686584200000006,
+ 0.045997991200000005,
+ 0.047016423200000004,
+ 0.046089728200000006,
+ 0.04778034120000001,
+ 0.0489142242,
+ 0.04689554320000001,
+ 0.046330581200000005,
+ 0.0460137752,
+ 0.0473294802,
+ 0.046463515200000007,
+ 0.0472964062,
+ 0.0465713462,
+ 0.046739780200000004,
+ 0.047043988200000005,
+ 0.0468881052,
+ 0.0469259912,
+ 0.0463439402,
+ 0.046318177200000005,
+ 0.046465140200000005,
+ 0.046179928200000005,
+ 0.04679681820000001
+ ],
+ "exit_codes": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ }
+ ]
+}
diff --git a/benchmarks/hyperfine-iia006.json b/benchmarks/hyperfine-iia006.json
new file mode 100644
index 0000000..7d8d698
--- /dev/null
+++ b/benchmarks/hyperfine-iia006.json
@@ -0,0 +1,206 @@
+{
+ "results": [
+ {
+ "command": "authzforce",
+ "mean": 1.8722544155799998,
+ "stddev": 0.0448476189551403,
+ "median": 1.87713420668,
+ "user": 5.29085678,
+ "system": 0.19428865999999995,
+ "min": 1.8023647006799999,
+ "max": 1.93418314468,
+ "times": [
+ 1.91022297268,
+ 1.8098531996799998,
+ 1.87232539068,
+ 1.8023647006799999,
+ 1.83828486468,
+ 1.90194070568,
+ 1.91359825268,
+ 1.88194302268,
+ 1.93418314468,
+ 1.85782790168
+ ],
+ "exit_codes": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "command": "lean",
+ "mean": 4.53456651428,
+ "stddev": 0.009934426084958611,
+ "median": 4.53884667318,
+ "user": 4.48431508,
+ "system": 0.05463736,
+ "min": 4.518855267679999,
+ "max": 4.54707742168,
+ "times": [
+ 4.53892170468,
+ 4.54263477868,
+ 4.52490095668,
+ 4.54707742168,
+ 4.5387716416799995,
+ 4.540713494679999,
+ 4.52622729668,
+ 4.54329805368,
+ 4.52426452668,
+ 4.518855267679999
+ ],
+ "exit_codes": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ },
+ {
+ "command": "opa",
+ "mean": 0.04826780581333333,
+ "stddev": 0.0009917655763182548,
+ "median": 0.04805647418,
+ "user": 0.050686930000000005,
+ "system": 0.009130410000000002,
+ "min": 0.04688597268,
+ "max": 0.051628061680000004,
+ "times": [
+ 0.04802554868,
+ 0.04710740268,
+ 0.04863815768,
+ 0.048210658680000004,
+ 0.04965373968,
+ 0.05114789668,
+ 0.048087399680000004,
+ 0.04963996468,
+ 0.04848601568,
+ 0.04776453168,
+ 0.047728559680000004,
+ 0.04891648668,
+ 0.04876128368,
+ 0.04833371168,
+ 0.04959416168,
+ 0.04831524168,
+ 0.04784011068,
+ 0.04791020968,
+ 0.04737187868,
+ 0.048367496680000004,
+ 0.04715601768,
+ 0.04828764868,
+ 0.04840128568,
+ 0.04751085468,
+ 0.04908777768,
+ 0.04972917968,
+ 0.04848996868,
+ 0.04743947068,
+ 0.04810144268,
+ 0.04880705868,
+ 0.05105722568,
+ 0.04761976368,
+ 0.04743746368,
+ 0.04802172868,
+ 0.04780610868,
+ 0.04784965268,
+ 0.047334945680000004,
+ 0.04755185368,
+ 0.04794043268,
+ 0.04697354768,
+ 0.04813416268,
+ 0.04743428468,
+ 0.04769424868,
+ 0.04976519068,
+ 0.04848638568,
+ 0.051628061680000004,
+ 0.04754968568,
+ 0.04715066668,
+ 0.04769493568,
+ 0.04880571868,
+ 0.04883541968,
+ 0.04823892868,
+ 0.04769713568,
+ 0.04727608968,
+ 0.04817077868,
+ 0.04893817868,
+ 0.04800505268,
+ 0.04767638868,
+ 0.04749717868,
+ 0.04688597268
+ ],
+ "exit_codes": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ }
+ ]
+}
diff --git a/benchmarks/lean-harness.bash b/benchmarks/lean-harness.bash
new file mode 100644
index 0000000..e59b3da
--- /dev/null
+++ b/benchmarks/lean-harness.bash
@@ -0,0 +1,7 @@
+#!/usr/bin/env bash
+
+COMPILE_REQUEST="../xacml-proofs/compiler/_build/default/bin/request.exe"
+COMPILE_POLICY="../xacml-proofs/compiler/_build/default/bin/main.exe"
+
+cat Xacml.lean <($COMPILE_REQUEST $1/Request.xml) <($COMPILE_POLICY $1/Policy.xml) > /tmp/test.lean
+lean /tmp/test.lean
diff --git a/benchmarks/rego-harness.bash b/benchmarks/rego-harness.bash
new file mode 100644
index 0000000..48dbc5d
--- /dev/null
+++ b/benchmarks/rego-harness.bash
@@ -0,0 +1,12 @@
+#!/usr/bin/env bash
+
+NAME="$(basename $1)"
+if [ $NAME = "IIA001" ]; then
+ NAME="iia1"
+elif [ $NAME = "IIA003" ]; then
+ NAME="iia003"
+elif [ $NAME = "IIA006" ]; then
+ NAME="iia006"
+fi
+
+opa eval -f raw --data rego/$NAME.rego -i rego/$NAME.json 'data.equivalence.allow'
diff --git a/benchmarks/rego/iia003.json b/benchmarks/rego/iia003.json
new file mode 100644
index 0000000..660d7c1
--- /dev/null
+++ b/benchmarks/rego/iia003.json
@@ -0,0 +1 @@
+{"request": [{"category":"urn:oasis:names:tc:xacml:1.0:subject-category:access-subject","identifier":"urn:oasis:names:tc:xacml:1.0:subject:subject-id","value":{"kind":"primitive","type":"http://www.w3.org/2001/XMLSchema#string","value":"Julius Hibbert"}},{"category":"urn:oasis:names:tc:xacml:3.0:attribute-category:resource","identifier":"urn:oasis:names:tc:xacml:1.0:resource:resource-id","value":{"kind":"primitive","type":"http://www.w3.org/2001/XMLSchema#anyURI","value":"http://medico.com/record/patient/BartSimpson"}},{"category":"urn:oasis:names:tc:xacml:3.0:attribute-category:action","identifier":"urn:oasis:names:tc:xacml:1.0:action:action-id","value":{"kind":"primitive","type":"http://www.w3.org/2001/XMLSchema#string","value":"read"}}]}
diff --git a/benchmarks/rego/iia003.rego b/benchmarks/rego/iia003.rego
new file mode 100644
index 0000000..87482c8
--- /dev/null
+++ b/benchmarks/rego/iia003.rego
@@ -0,0 +1,815 @@
+package equivalence
+
+import future.keywords.every
+import future.keywords.if
+import future.keywords.in
+
+########################################################################
+# Data Types
+########################################################################
+
+## MatchResult
+
+# - is_match => { "match_result": true }
+# - no_match => { "match_result": false }
+# - indeterminate => { "match_result": "indeterminate" }
+
+## Decision
+
+# - permit => { "decision": "permit" }
+# - deny => { "decision": "deny" }
+# - not_applicable => { "decision": "not_applicable" }
+# - indeterminate => { "decision": "indeterminate" }
+
+## Extended Decision
+
+# - permit => { "decision_extended": "permit" }
+# - deny => { "decision_extended": "deny" }
+# - not_applicable => { "decision_extended": "not_applicable" }
+# - indeterminate => { "decision_extended": "indeterminate" }
+# - indeterminate_d => { "decision_extended": "indeterminate_d" }
+# - indeterminate_p => { "decision_extended": "indeterminate_p" }
+# - indeterminate_dp => { "decision_extended": "indeterminate_dp" }
+
+lift_decision_indeterminate({ "decision": "not_applicable" }) := { "decision": "not_applicable" }
+lift_decision_indeterminate({ "decision": "permit" }) := { "decision": "indeterminate_p" }
+lift_decision_indeterminate({ "decision": "deny" }) := { "decision": "indeterminate_d" }
+lift_decision_indeterminate({ "decision": "indeterminate" }) := { "decision": "indeterminate_dp" }
+lift_decision_indeterminate({ "decision": "indeterminate_dp" }) := { "decision": "indeterminate_dp" }
+lift_decision_indeterminate({ "decision": "indeterminate_p" }) := { "decision": "indeterminate_p" }
+lift_decision_indeterminate({ "decision": "indeterminate_d" }) := { "decision": "indeterminate_d" }
+
+## Value
+
+# - { "kind": "primitive",
+# "type": string,
+# "value": string }
+# - { "kind": "bag",
+# "values": ... }
+
+### Booleans
+
+true_value := { "kind": "primitive", "type": "boolean", "value": true }
+false_value := { "kind": "primitive", "type": "boolean", "value": false }
+indeterminate_value := { "kind": "primitive", "type": "boolean" }
+
+is_indeterminate(value) if { is_null(value.value) }
+
+## StatusCode
+
+# - ok => { "status": "ok" }
+# - missing_attribute => { "status": "missing_attribute" }
+# - syntax_error => { "status": "syntax_error" }
+# - processing_error => { "status": "processing_error" }
+
+## AttributeDesignator
+
+# - { category : string
+# identifier : string
+# type : string
+# issuer : string or null
+# must_be_present : boolean }
+
+## Expression
+
+# - { "expression": "apply",
+# "function": string,
+# "args": [string, ...] }
+# - { "expression": "attribute_designator",
+# "inner": AttributeDesignator }
+# - { "expression": "attribute_value",
+# "inner": Value }
+# - { "expression": "function"
+# "function": string }
+
+## Match
+
+# - { "function": string,
+# "designator": AttributeDesignator,
+# "value": Value }
+
+## Obligation
+
+# - { "assignments": [Attribute, ...],
+# "identifier": string }
+
+## ObligationExpression
+
+# - { "assignments": [AttributeAssignmentExpression, ...],
+# "identifier": string,
+# "fulfill_on": Decision }
+
+## Advice
+
+# - { "assignments": [Attribute, ...],
+# "identifier": string }
+
+## AdviceExpression
+
+# - { "assignments": [AttributeAssignmentExpression, ...],
+# "identifier": string,
+# "applies_to": Decision }
+
+## AttributeAssignmentExpression
+
+# - { "category": string,
+# "identifier": string,
+# "issuer": string or null,
+# "expression": Expression }
+
+## Target: [[[Expression, ...], ...], ...]
+
+## Rule
+
+# - { "target": Target,
+# "condition": Expression or null,
+# "effect": "permit" or "deny",
+# "obligations": [ObligationExpression, ...],
+# "advice": [AdviceExpression, ...] }
+
+## Policy
+
+# - { "combinator": string,
+# "target": Target,
+# "obligations": [ObligationExpression, ...],
+# "advice": [AdviceExpression, ...] }
+
+## PolicySet
+
+# - { "combinator": string,
+# "target": Target,
+# "obligations": [ObligationExpression, ...],
+# "advice": [AdviceExpression, ...] }
+
+# We assume the request attributes are stored in `input.request` as an array or set of
+#
+# { category : string
+# identifier : string
+# issuer : string or null
+# value : [Value, ...] }
+
+########################################################################
+# Match Functions
+########################################################################
+
+apply_xacml_function(
+ "urn:oasis:names:tc:xacml:1.0:function:string-equal",
+ [{ "kind": "primitive",
+ "type": "http://www.w3.org/2001/XMLSchema#string",
+ "value": a },
+ { "kind": "primitive",
+ "type": "http://www.w3.org/2001/XMLSchema#string",
+ "value": b }]) := true_value if {
+ a == b
+} else := false_value
+apply_xacml_function(
+ "urn:oasis:names:tc:xacml:1.0:function:anyURI-equal",
+ [{ "kind": "primitive",
+ "type": "http://www.w3.org/2001/XMLSchema#anyURI",
+ "value": a },
+ { "kind": "primitive",
+ "type": "http://www.w3.org/2001/XMLSchema#anyURI",
+ "value": b }]) := true_value if {
+ a == b
+} else := false_value
+
+########################################################################
+# AttributeDesignator
+########################################################################
+
+designator_matches(designator, attribute) if {
+ attribute.category == designator.category
+ attribute.identifier == designator.identifier
+ attribute.value.type == designator.type
+ not attribute.attr.issuer
+}
+
+designator_matches(designator, attribute) if {
+ attribute.category == designator.category
+ attribute.identifier == designator.identifier
+ attribute.value.type == designator.type
+ attribute.attr.issuer == designator.issuer
+}
+
+evaluate_designator(designator) := { "kind": "bag", "values": xs } if {
+ xs := [y.value | y := input.request[_]; designator_matches(designator, y)]
+ count(xs) > 1
+}
+
+evaluate_designator(designator) := xs[0] if {
+ xs := [y.value | y := input.request[_]; designator_matches(designator, y)]
+ count(xs) == 1
+}
+
+evaluate_designator(designator) := { "kind": "bag", "values": xs } if {
+ xs := [y.value | y := input.request[_]; designator_matches(designator, y)]
+ count(xs) == 0
+ not designator.must_be_present
+}
+
+evaluate_designator(designator) := { "status": "missing_attribute" } if {
+ xs := [y.value | y := input.request[_]; designator_matches(designator, y)]
+ count(xs) == 0
+ designator.must_be_present
+}
+
+#########################################################################
+# Match
+########################################################################
+
+evaluate_match(match) := { "match_result": true_value } if {
+ designator_result := evaluate_designator(match.designator)
+
+ # Designator evaluates without error.
+ designator_result
+
+ some x in designator_result.values
+ apply_xacml_function(match.function, [x, match.value]).value == true
+} else := { "match_result": true_value } if {
+ designator_result := evaluate_designator(match.designator)
+
+ # Designator evaluates without error.
+ designator_result
+
+ apply_xacml_function(match.function, [designator_result, match.value]).value == true
+} else := { "match_result": indeterminate_value } if {
+ designator_result := evaluate_designator(match.designator)
+
+ # Designator evaluates without error.
+ designator_result
+
+ some x in designator_result
+ is_indeterminate(apply_xacml_function(match.function, [x, match.value]))
+} else := { "match_result": false_value } if {
+ designator_result := evaluate_designator(match.designator)
+
+ # Designator evaluates without error.
+ designator_result
+} else := { "match_result": indeterminate_value }
+
+# Last case runs when evaluating the designator results in an error.
+
+evaluate_all_of(conj) := { "match_result": true_value } if {
+ every x in conj {
+ evaluate_match(x).match_result.value == true
+ }
+} else := { "match_result": "indeterminate" } if {
+ some x in conj
+ is_indeterminate(evaluate_match(x).match_result)
+} else := { "match_result": "no_match" }
+
+evaluate_any_of([]) := { "match_result": true_value }
+evaluate_any_of(disj) := { "match_result": true_value } if {
+ some x in disj
+ evaluate_all_of(x) == { "match_result": true_value }
+} else := { "match_result": "indeterminate" } if {
+ some x in disj
+ evaluate_all_of(x) == { "match_result": true_value }
+} else := { "match_result": "no_match" }
+
+
+########################################################################
+# Target
+########################################################################
+
+evaluate_target([]) := { "match_result": true_value }
+evaluate_target(xs) := { "match_result": true_value } if {
+ every disj in xs {
+ evaluate_any_of(disj).match_result.value == true
+ }
+} else := { "match_result": false_value } if {
+ some disj in xs
+ evaluate_any_of(disj).match_result == "no_match"
+} else := { "match_result": indeterminate_value }
+
+########################################################################
+# Expression
+########################################################################
+
+evaluate_expression({ "expression": "apply", "function": function_name, "args": args }) := x if {
+ x := apply_xacml_function(function_name, args)
+}
+evaluate_expression({ "expression": "attribute_designator", "inner": designator }) := x if {
+ x := evaluate_designator(designator)
+}
+evaluate_expression({ "expression": "attribute_value", "inner": value }) := x if {
+ x := value
+}
+evaluate_expression({ "expression": "function", "function": name }) := x if {
+ x := name
+}
+
+########################################################################
+# Obligations and Advice
+########################################################################
+
+evaluate_attribute_assignment_expression(expr) := assignment {
+ { "kind": "primitive", "value": inner } = evaluate_expression(expr.expression)
+ assignment := { "category": expr.category,
+ "identifier": expr.identifier,
+ "issuer": expr.issuer,
+ "value": inner }
+}
+
+evaluate_obligation_expression(obligation_expression) := obligation {
+ assignments := [evaluate_attribute_assignment_expression(expr) | expr := obligation_expression.assignments[_]]
+ obligation := { "assignments": assignments, "identifier": obligation_expression.identifier }
+}
+
+evaluate_advice_expression(advice_expression) := advice {
+ assignments := [evaluate_attribute_assignment_expression(expr) | expr := advice_expression.assignments[_]]
+ advice := { "assignments": assignments, "identifier": advice_expression.identifier }
+}
+
+
+########################################################################
+# Rule
+########################################################################
+
+# Condition is specified and applicable
+evaluate_rule_decision(rule) := { "decision_extended": decision } {
+ evaluate_target(rule.target).match_result.value == true
+
+ is_object(rule.condition)
+ evaluate_expression(rule.condition) == true
+
+ decision := rule.effect
+}
+# Condition is specified and not applicable
+evaluate_rule_decision(rule) := { "decision_extended": "not_applicable" } {
+ evaluate_target(rule.target).match_result.value == true
+ evaluate_expression(rule.condition) == false
+}
+# Condition is indeterminate
+evaluate_rule_decision(rule) := { "decision_extended": "indeterminate_p" } {
+ evaluate_target(rule.target).match_result.value == true
+ condition := evaluate_expression(rule.condition)
+ is_null(condition)
+ rule.effect == "permit"
+}
+evaluate_rule_decision(rule) := { "decision_extended": "indeterminate_d" } {
+ evaluate_target(rule.target).match_result.value == true
+ condition := evaluate_expression(rule.condition)
+ is_null(condition)
+ rule.effect == "deny"
+}
+# Condition is unspecified
+evaluate_rule_decision(rule) := { "decision_extended": decision } {
+ evaluate_target(rule.target).match_result.value == true
+ decision := rule.effect
+}
+
+evaluate_rule_decision(rule) := { "decision_extended": "not_applicable" } {
+ evaluate_target(rule.target).match_result.value == false
+}
+evaluate_rule_decision(rule) := { "decision_extended": "indeterminate_p" } {
+ is_indeterminate(evaluate_target(rule.target))
+ rule.effect == "permit"
+}
+evaluate_rule_decision(rule) := { "decision_extended": "indeterminate_d" } {
+ is_indeterminate(evaluate_target(rule.target))
+ rule.effect == "permit"
+}
+
+evaluate_rule_advices(rule) := { "advice": advice } if {
+ decision := evaluate_rule_decision(rule)
+ advice := [expr | expr := rule.advice[_]; expr.applies_to == decision ]
+}
+
+evaluate_rule_obligations(rule) := { "obligations": obligations } if {
+ decision := evaluate_rule_decision(rule)
+ obligations := [expr | expr := rule.obligations[_]; expr.fulfill_on == decision ]
+}
+
+########################################################################
+# Policy
+########################################################################
+
+evaluate_rule_combinator("deny_overrides", results) := { "decision_extended": "deny" } if {
+ some result in results
+ result.decision_extended == "deny"
+} else := { "decision_extended": "indeterminate_dp" } if {
+ some result in results
+ result.decision_extended == "indeterminate_dp"
+} else := { "decision_extended": "indeterminate_dp" } if {
+ some result1 in results
+ some result2 in results
+ result1.decision_extended == "indeterminate_d"
+ result1.decision_extended == "indeterminate_p"
+} else := { "decision_extended": "indeterminate_d" } if {
+ some result in results
+ result.decision_extended == "indeterminate_d"
+} else := { "decision_extended": "permit" } if {
+ some result in results
+ result.decision_extended == "permit"
+} else := { "decision_extended": "indeterminate_p" } if {
+ some result in results
+ result.decision_extended == "indeterminate_p"
+} else := { "decision_extended": "not_applicable" }
+
+evaluate_rule_combinator("ordered_deny_overrides", results) := { "decision_extended": "deny" } if {
+ some result in results
+ result.decision_extended == "deny"
+} else := { "decision_extended": "indeterminate_dp" } if {
+ some result in results
+ result.decision_extended == "indeterminate_dp"
+} else := { "decision_extended": "indeterminate_dp" } if {
+ some result1 in results
+ some result2 in results
+ result1.decision_extended == "indeterminate_d"
+ result1.decision_extended == "indeterminate_p"
+} else := { "decision_extended": "indeterminate_d" } if {
+ some result in results
+ result.decision_extended == "indeterminate_d"
+} else := { "decision_extended": "permit" } if {
+ some result in results
+ result.decision_extended == "permit"
+} else := { "decision_extended": "indeterminate_p" } if {
+ some result in results
+ result.decision_extended == "indeterminate_p"
+} else := { "decision_extended": "not_applicable" }
+
+evaluate_rule_combinator("permit_overrides", results) := { "decision_extended": "permit" } if {
+ some result in results
+ result.decision_extended == "permit"
+} else := { "decision_extended": "indeterminate_dp" } if {
+ some result in results
+ result.decision_extended == "indeterminate_dp"
+} else := { "decision_extended": "indeterminate_dp" } if {
+ some result1 in results
+ some result2 in results
+ result1.decision_extended == "indeterminate_d"
+ result1.decision_extended == "indeterminate_p"
+} else := { "decision_extended": "indeterminate_p" } if {
+ some result in results
+ result.decision_extended == "indeterminate_p"
+} else := { "decision_extended": "deny" } if {
+ some result in results
+ result.decision_extended == "deny"
+} else := { "decision_extended": "indeterminate_d" } if {
+ some result in results
+ result.decision_extended == "indeterminate_d"
+} else := { "decision_extended": "not_applicable" }
+
+evaluate_rule_combinator("ordered_permit_overrides", results) := { "decision_extended": "permit" } if {
+ some result in results
+ result.decision_extended == "permit"
+} else := { "decision_extended": "indeterminate_dp" } if {
+ some result in results
+ result.decision_extended == "indeterminate_dp"
+} else := { "decision_extended": "indeterminate_dp" } if {
+ some result1 in results
+ some result2 in results
+ result1.decision_extended == "indeterminate_d"
+ result1.decision_extended == "indeterminate_p"
+} else := { "decision_extended": "indeterminate_p" } if {
+ some result in results
+ result.decision_extended == "indeterminate_p"
+} else := { "decision_extended": "deny" } if {
+ some result in results
+ result.decision_extended == "deny"
+} else := { "decision_extended": "indeterminate_d" } if {
+ some result in results
+ result.decision_extended == "indeterminate_d"
+} else := { "decision_extended": "not_applicable" }
+
+evaluate_rule_combinator("deny_unless_permit", results) := { "decision_extended": "permit" } if {
+ some result in results
+ result.decision_extended == "permit"
+} else := { "decision_extended": "deny" }
+
+evaluate_rule_combinator("permit_unless_deny", results) := { "decision_extended": "deny" } if {
+ some result in results
+ result.decision_extended == "deny"
+} else := { "decision_extended": "permit" }
+
+evaluate_rule_combinator("first_applicable", results) := result if {
+ indices := [i | results[i].decision_extended != "not_applicable"]
+ count(indices) > 0
+ result := results[max(indices)]
+ result.decision_extended == "deny"
+} else := { "decision_extended": "not_applicable" }
+
+evaluate_rule_combinator("legacy_deny_overrides", results) := { "decision_extended": "deny" } if {
+ some result in results
+ result.decision_extended == "deny"
+} else := { "decision_extended": "indeterminate" } if {
+ some result in results
+ result.decision_extended == "indeterminate_d"
+} else := { "decision_extended": "permit" } if {
+ some result in results
+ result.decision_extended == "permit"
+} else := { "decision_extended": "indeterminate" } if {
+ some result in results
+ result.decision_extended == "indeterminate_p"
+} else := { "decision_extended": "not_applicable" }
+
+evaluate_rule_combinator("ordered_legacy_deny_overrides", results) := { "decision_extended": "deny" } if {
+ some result in results
+ result.decision_extended == "deny"
+} else := { "decision_extended": "indeterminate" } if {
+ some result in results
+ result.decision_extended == "indeterminate_d"
+} else := { "decision_extended": "permit" } if {
+ some result in results
+ result.decision_extended == "permit"
+} else := { "decision_extended": "indeterminate" } if {
+ some result in results
+ result.decision_extended == "indeterminate_p"
+} else := { "decision_extended": "not_applicable" }
+
+evaluate_rule_combinator("legacy_permit_overrides", results) := { "decision_extended": "permit" } if {
+ some result in results
+ result.decision_extended == "permit"
+} else := { "decision_extended": "indeterminate" } if {
+ some result in results
+ result.decision_extended == "indeterminate_p"
+} else := { "decision_extended": "deny" } if {
+ some result in results
+ result.decision_extended == "deny"
+} else := { "decision_extended": "indeterminate" } if {
+ some result in results
+ result.decision_extended == "indeterminate_d"
+} else := { "decision_extended": "not_applicable" }
+
+evaluate_rule_combinator("ordered_legacy_permit_overrides", results) := { "decision_extended": "permit" } if {
+ some result in results
+ result.decision_extended == "permit"
+} else := { "decision_extended": "indeterminate" } if {
+ some result in results
+ result.decision_extended == "indeterminate_p"
+} else := { "decision_extended": "deny" } if {
+ some result in results
+ result.decision_extended == "deny"
+} else := { "decision_extended": "indeterminate" } if {
+ some result in results
+ result.decision_extended == "indeterminate_d"
+} else := { "decision_extended": "not_applicable" }
+
+# child_results := [result | rule := policy.rules[_]; result := evaluate_rule_decision(rule)]
+evaluate_policy_decision(policy, child_results) := decision if {
+ evaluate_target(policy.target).match_result.value == true
+ decision := evaluate_rule_combinator(policy.combinator, child_results)
+} else := decision if {
+ is_indeterminate(evaluate_target(policy.target))
+ decision := lift_decision_indeterminate(evaluate_rule_combinator(policy.combinator, child_results))
+} else := { "decision_extended": "not_applicable" }
+
+# children_advice := [advice | rule := policy.rules[_]; expr := evaluate_rule_advices(rule); advice := expr[_]]
+evaluate_policy_advices(policy, child_results, children_advice) := { "advice" : advice } if {
+ decision := evaluate_policy_decision(policy, child_results)
+ policy_advice := [expr | expr := policy.advice[_]; expr.applies_to == decision ]
+ advice := array.concat(policy_advice, children_advice)
+}
+
+# children_obligations := [obligation | rule := policy.rules[_]; expr := evaluate_rule_obligations(rule); obligation := expr[_]]
+evaluate_policy_obligations(policy, child_results, children_obligations) := { "obligations" : obligations } if {
+ decision := evaluate_policy_decision(policy, child_results)
+ policy_obligations := [expr | expr := policy.obligations[_]; expr.applies_to == decision ]
+ obligations := array.concat(policy_obligations, children_obligations)
+}
+
+########################################################################
+# PolicySet
+########################################################################
+
+evaluate_policy_combinator("deny_overrides", results) := { "decision_extended": "deny" } if {
+ some result in results
+ result.decision_extended == "deny"
+} else := { "decision_extended": "indeterminate_dp" } if {
+ some result in results
+ result.decision_extended == "indeterminate_dp"
+} else := { "decision_extended": "indeterminate_dp" } if {
+ some result1 in results
+ some result2 in results
+ result1.decision_extended == "indeterminate_d"
+ result1.decision_extended == "indeterminate_p"
+} else := { "decision_extended": "indeterminate_d" } if {
+ some result in results
+ result.decision_extended == "indeterminate_d"
+} else := { "decision_extended": "permit" } if {
+ some result in results
+ result.decision_extended == "permit"
+} else := { "decision_extended": "indeterminate_p" } if {
+ some result in results
+ result.decision_extended == "indeterminate_p"
+} else := { "decision_extended": "not_applicable" }
+
+evaluate_policy_combinator("ordered_deny_overrides", results) := { "decision_extended": "deny" } if {
+ some result in results
+ result.decision_extended == "deny"
+} else := { "decision_extended": "indeterminate_dp" } if {
+ some result in results
+ result.decision_extended == "indeterminate_dp"
+} else := { "decision_extended": "indeterminate_dp" } if {
+ some result1 in results
+ some result2 in results
+ result1.decision_extended == "indeterminate_d"
+ result1.decision_extended == "indeterminate_p"
+} else := { "decision_extended": "indeterminate_d" } if {
+ some result in results
+ result.decision_extended == "indeterminate_d"
+} else := { "decision_extended": "permit" } if {
+ some result in results
+ result.decision_extended == "permit"
+} else := { "decision_extended": "indeterminate_p" } if {
+ some result in results
+ result.decision_extended == "indeterminate_p"
+} else := { "decision_extended": "not_applicable" }
+
+evaluate_policy_combinator("permit_overrides", results) := { "decision_extended": "permit" } if {
+ some result in results
+ result.decision_extended == "permit"
+} else := { "decision_extended": "indeterminate_dp" } if {
+ some result in results
+ result.decision_extended == "indeterminate_dp"
+} else := { "decision_extended": "indeterminate_dp" } if {
+ some result1 in results
+ some result2 in results
+ result1.decision_extended == "indeterminate_d"
+ result1.decision_extended == "indeterminate_p"
+} else := { "decision_extended": "indeterminate_p" } if {
+ some result in results
+ result.decision_extended == "indeterminate_p"
+} else := { "decision_extended": "deny" } if {
+ some result in results
+ result.decision_extended == "deny"
+} else := { "decision_extended": "indeterminate_d" } if {
+ some result in results
+ result.decision_extended == "indeterminate_d"
+} else := { "decision_extended": "not_applicable" }
+
+evaluate_policy_combinator("ordered_permit_overrides", results) := { "decision_extended": "permit" } if {
+ some result in results
+ result.decision_extended == "permit"
+} else := { "decision_extended": "indeterminate_dp" } if {
+ some result in results
+ result.decision_extended == "indeterminate_dp"
+} else := { "decision_extended": "indeterminate_dp" } if {
+ some result1 in results
+ some result2 in results
+ result1.decision_extended == "indeterminate_d"
+ result1.decision_extended == "indeterminate_p"
+} else := { "decision_extended": "indeterminate_p" } if {
+ some result in results
+ result.decision_extended == "indeterminate_p"
+} else := { "decision_extended": "deny" } if {
+ some result in results
+ result.decision_extended == "deny"
+} else := { "decision_extended": "indeterminate_d" } if {
+ some result in results
+ result.decision_extended == "indeterminate_d"
+} else := { "decision_extended": "not_applicable" }
+
+evaluate_policy_combinator("deny_unless_permit", results) := { "decision_extended": "permit" } if {
+ some result in results
+ result.decision_extended == "permit"
+} else := { "decision_extended": "deny" }
+
+evaluate_policy_combinator("permit_unless_deny", results) := { "decision_extended": "deny" } if {
+ some result in results
+ result.decision_extended == "deny"
+} else := { "decision_extended": "permit" }
+
+evaluate_policy_combinator("first_applicable", results) := result if {
+ indices := [i | results[i].decision_extended != "not_applicable"]
+ count(indices) > 0
+ result := results[max(indices)]
+ result.decision_extended == "deny"
+} else := { "decision_extended": "not_applicable" }
+
+evaluate_policy_combinator("only_one_applicable", results) := result if {
+ applicable := [result | result := results[i]; result.decision_extended != "not_applicable"]
+ count(applicable) == 1
+ result := applicable[0]
+} else := { "decision_extended": "not_applicable" }
+
+evaluate_policy_combinator("legacy_deny_overrides", results) := { "decision_extended": "deny" } if {
+ some result in results
+ result.decision_extended == "deny"
+} else := { "decision_extended": "deny" } if {
+ some result in results
+ result.decision_extended == "indeterminate"
+} else := { "decision_extended": "permit" } if {
+ some result in results
+ result.decision_extended == "permit"
+} else := { "decision_extended": "not_applicable" }
+
+evaluate_policy_combinator("ordered_legacy_deny_overrides", results) := { "decision_extended": "deny" } if {
+ some result in results
+ result.decision_extended == "deny"
+} else := { "decision_extended": "deny" } if {
+ some result in results
+ result.decision_extended == "indeterminate"
+} else := { "decision_extended": "permit" } if {
+ some result in results
+ result.decision_extended == "permit"
+} else := { "decision_extended": "not_applicable" }
+
+evaluate_policy_combinator("legacy_permit_overrides", results) := { "decision_extended": "permit" } if {
+ some result in results
+ result.decision_extended == "permit"
+} else := { "decision_extended": "deny" } if {
+ some result in results
+ result.decision_extended == "deny"
+} else := { "decision_extended": "indeterminate" } if {
+ some result in results
+ result.decision_extended == "indeterminate"
+} else := { "decision_extended": "not_applicable" }
+
+evaluate_policy_combinator("ordered_legacy_permit_overrides", results) := { "decision_extended": "permit" } if {
+ some result in results
+ result.decision_extended == "permit"
+} else := { "decision_extended": "indeterminate" } if {
+ some result in results
+ result.decision_extended == "indeterminate_p"
+} else := { "decision_extended": "deny" } if {
+ some result in results
+ result.decision_extended == "deny"
+} else := { "decision_extended": "indeterminate" } if {
+ some result in results
+ result.decision_extended == "indeterminate_d"
+} else := { "decision_extended": "not_applicable" }
+
+evaluate_policyset_decision(policyset, child_results) := decision if {
+ evaluate_target(policyset.target).match_result.value == true
+ decision := evaluate_policy_combinator(policyset.combinator, child_results)
+} else := decision if {
+ is_indeterminate(evaluate_target(policyset.target))
+ decision := lift_decision_indeterminate(evaluate_policy_combinator(policyset.combinator, child_results))
+} else := { "decision_extended": "not_applicable" }
+
+evaluate_policyset_advices(policyset, child_results, child_advice) := { "advice" : advice } if {
+ decision := evaluate_policyset_decision(policyset, child_results)
+ policyset_advice := [expr | expr := policyset.advice[_]; expr.applies_to == decision ]
+ advice := array.concat(policyset_advice, child_advice)
+}
+
+evaluate_policyset_obligations(policyset, child_results, child_obligations) := { "obligations" : obligations } if {
+ decision := evaluate_policyset_decision(policyset, child_results)
+ policyset_obligations := [expr | expr := policyset.obligations[_]; expr.applies_to == decision ]
+ obligations := array.concat(policyset_obligations, child_obligations)
+}
+
+IIA003_policy := {
+ "combinator": "deny_overrides",
+ "target": [],
+ "obligations": [],
+ "advice": []
+}
+
+IIA003_rule := {
+ "target": [[[{ "function": "urn:oasis:names:tc:xacml:1.0:function:string-equal",
+ "designator": {
+ "identifier": "urn:oasis:names:tc:xacml:2.0:conformance-test:attribute:bogus",
+ "category": "urn:oasis:names:tc:xacml:1.0:subject-category:access-subject",
+ "type": "http://www.w3.org/2001/XMLSchema#string",
+ "must_be_present": false
+ },
+ "value": {
+ "kind": "primitive",
+ "type": "http://www.w3.org/2001/XMLSchema#string",
+ "value": "Physician"
+ }}]],
+ [[{ "function": "urn:oasis:names:tc:xacml:1.0:function:anyURI-equal",
+ "designator": {
+ "identifier": "urn:oasis:names:tc:xacml:1.0:resource:resource-id",
+ "category": "urn:oasis:names:tc:xacml:3.0:attribute-category:resource",
+ "type": "http://www.w3.org/2001/XMLSchema#anyURI",
+ "must_be_present": false
+ },
+ "value": {
+ "kind": "primitive",
+ "type": "http://www.w3.org/2001/XMLSchema#anyURI",
+ "value": "http://medico.com/record/patient/BartSimpson"
+ }}]],
+ [[{ "function": "urn:oasis:names:tc:xacml:1.0:function:string-equal",
+ "designator": {
+ "identifier": "urn:oasis:names:tc:xacml:1.0:action:action-id",
+ "category": "urn:oasis:names:tc:xacml:3.0:attribute-category:action",
+ "type": "http://www.w3.org/2001/XMLSchema#string",
+ "must_be_present": false
+ },
+ "value": {
+ "kind": "primitive",
+ "type": "http://www.w3.org/2001/XMLSchema#string",
+ "value": "read"
+ }}],
+ [{ "function": "urn:oasis:names:tc:xacml:1.0:function:string-equal",
+ "designator": {
+ "identifier": "urn:oasis:names:tc:xacml:1.0:action:action-id",
+ "category": "urn:oasis:names:tc:xacml:3.0:attribute-category:action",
+ "type": "http://www.w3.org/2001/XMLSchema#string",
+ "must_be_present": false
+ },
+ "value": {
+ "kind": "primitive",
+ "type": "http://www.w3.org/2001/XMLSchema#string",
+ "value": "write"
+ }}]]],
+ "effect": "permit",
+ "obligations": [],
+ "advice": []
+}
+
+allow := evaluate_policyset_decision(IIA003_policy, [evaluate_rule_decision(IIA003_rule)])
diff --git a/benchmarks/rego/iia006.json b/benchmarks/rego/iia006.json
new file mode 100644
index 0000000..51b1edc
--- /dev/null
+++ b/benchmarks/rego/iia006.json
@@ -0,0 +1 @@
+{"request": [{"category":"urn:oasis:names:tc:xacml:1.0:subject-category:access-subject","identifier":"urn:oasis:names:tc:xacml:1.0:subject:subject-id","value":{"kind":"primitive","type":"http://www.w3.org/2001/XMLSchema#string","value":"Julius Hibbert"}},{"category":"urn:oasis:names:tc:xacml:1.0:subject-category:access-subject","identifier":"urn:oasis:names:tc:xacml:2.0:conformance-test:some-attribute","value":{"kind":"primitive","type":"http://www.w3.org/2001/XMLSchema#string","value":"riddle me this"}},{"category":"urn:oasis:names:tc:xacml:3.0:attribute-category:resource","identifier":"urn:oasis:names:tc:xacml:1.0:resource:resource-id","value":{"kind":"primitive","type":"http://www.w3.org/2001/XMLSchema#anyURI","value":"http://medico.com/record/patient/BartSimpson"}},{"category":"urn:oasis:names:tc:xacml:3.0:attribute-category:action","identifier":"urn:oasis:names:tc:xacml:1.0:action:action-id","value":{"kind":"primitive","type":"http://www.w3.org/2001/XMLSchema#string","value":"read"}}]}
diff --git a/benchmarks/rego/iia006.rego b/benchmarks/rego/iia006.rego
new file mode 100644
index 0000000..6a83b14
--- /dev/null
+++ b/benchmarks/rego/iia006.rego
@@ -0,0 +1,827 @@
+package equivalence
+
+import future.keywords.every
+import future.keywords.if
+import future.keywords.in
+
+########################################################################
+# Data Types
+########################################################################
+
+## MatchResult
+
+# - is_match => { "match_result": true }
+# - no_match => { "match_result": false }
+# - indeterminate => { "match_result": "indeterminate" }
+
+## Decision
+
+# - permit => { "decision": "permit" }
+# - deny => { "decision": "deny" }
+# - not_applicable => { "decision": "not_applicable" }
+# - indeterminate => { "decision": "indeterminate" }
+
+## Extended Decision
+
+# - permit => { "decision_extended": "permit" }
+# - deny => { "decision_extended": "deny" }
+# - not_applicable => { "decision_extended": "not_applicable" }
+# - indeterminate => { "decision_extended": "indeterminate" }
+# - indeterminate_d => { "decision_extended": "indeterminate_d" }
+# - indeterminate_p => { "decision_extended": "indeterminate_p" }
+# - indeterminate_dp => { "decision_extended": "indeterminate_dp" }
+
+lift_decision_indeterminate({ "decision": "not_applicable" }) := { "decision": "not_applicable" }
+lift_decision_indeterminate({ "decision": "permit" }) := { "decision": "indeterminate_p" }
+lift_decision_indeterminate({ "decision": "deny" }) := { "decision": "indeterminate_d" }
+lift_decision_indeterminate({ "decision": "indeterminate" }) := { "decision": "indeterminate_dp" }
+lift_decision_indeterminate({ "decision": "indeterminate_dp" }) := { "decision": "indeterminate_dp" }
+lift_decision_indeterminate({ "decision": "indeterminate_p" }) := { "decision": "indeterminate_p" }
+lift_decision_indeterminate({ "decision": "indeterminate_d" }) := { "decision": "indeterminate_d" }
+
+## Value
+
+# - { "kind": "primitive",
+# "type": string,
+# "value": string }
+# - { "kind": "bag",
+# "values": ... }
+
+### Booleans
+
+true_value := { "kind": "primitive", "type": "boolean", "value": true }
+false_value := { "kind": "primitive", "type": "boolean", "value": false }
+indeterminate_value := { "kind": "primitive", "type": "boolean" }
+
+is_indeterminate(value) if { is_null(value.value) }
+
+## StatusCode
+
+# - ok => { "status": "ok" }
+# - missing_attribute => { "status": "missing_attribute" }
+# - syntax_error => { "status": "syntax_error" }
+# - processing_error => { "status": "processing_error" }
+
+## AttributeDesignator
+
+# - { category : string
+# identifier : string
+# type : string
+# issuer : string or null
+# must_be_present : boolean }
+
+## Expression
+
+# - { "expression": "apply",
+# "function": string,
+# "args": [string, ...] }
+# - { "expression": "attribute_designator",
+# "inner": AttributeDesignator }
+# - { "expression": "attribute_value",
+# "inner": Value }
+# - { "expression": "function"
+# "function": string }
+
+## Match
+
+# - { "function": string,
+# "designator": AttributeDesignator,
+# "value": Value }
+
+## Obligation
+
+# - { "assignments": [Attribute, ...],
+# "identifier": string }
+
+## ObligationExpression
+
+# - { "assignments": [AttributeAssignmentExpression, ...],
+# "identifier": string,
+# "fulfill_on": Decision }
+
+## Advice
+
+# - { "assignments": [Attribute, ...],
+# "identifier": string }
+
+## AdviceExpression
+
+# - { "assignments": [AttributeAssignmentExpression, ...],
+# "identifier": string,
+# "applies_to": Decision }
+
+## AttributeAssignmentExpression
+
+# - { "category": string,
+# "identifier": string,
+# "issuer": string or null,
+# "expression": Expression }
+
+## Target: [[[Expression, ...], ...], ...]
+
+## Rule
+
+# - { "target": Target,
+# "condition": Expression or null,
+# "effect": "permit" or "deny",
+# "obligations": [ObligationExpression, ...],
+# "advice": [AdviceExpression, ...] }
+
+## Policy
+
+# - { "combinator": string,
+# "target": Target,
+# "obligations": [ObligationExpression, ...],
+# "advice": [AdviceExpression, ...] }
+
+## PolicySet
+
+# - { "combinator": string,
+# "target": Target,
+# "obligations": [ObligationExpression, ...],
+# "advice": [AdviceExpression, ...] }
+
+# We assume the request attributes are stored in `input.request` as an array or set of
+#
+# { category : string
+# identifier : string
+# issuer : string or null
+# value : [Value, ...] }
+
+########################################################################
+# Match Functions
+########################################################################
+
+apply_xacml_function(
+ "urn:oasis:names:tc:xacml:1.0:function:string-equal",
+ [{ "kind": "primitive",
+ "type": "http://www.w3.org/2001/XMLSchema#string",
+ "value": a },
+ { "kind": "primitive",
+ "type": "http://www.w3.org/2001/XMLSchema#string",
+ "value": b }]) := true_value if {
+ a == b
+} else := false_value
+apply_xacml_function(
+ "urn:oasis:names:tc:xacml:1.0:function:anyURI-equal",
+ [{ "kind": "primitive",
+ "type": "http://www.w3.org/2001/XMLSchema#anyURI",
+ "value": a },
+ { "kind": "primitive",
+ "type": "http://www.w3.org/2001/XMLSchema#anyURI",
+ "value": b }]) := true_value if {
+ a == b
+} else := false_value
+
+########################################################################
+# AttributeDesignator
+########################################################################
+
+designator_matches(designator, attribute) if {
+ attribute.category == designator.category
+ attribute.identifier == designator.identifier
+ attribute.value.type == designator.type
+ not attribute.attr.issuer
+}
+
+designator_matches(designator, attribute) if {
+ attribute.category == designator.category
+ attribute.identifier == designator.identifier
+ attribute.value.type == designator.type
+ attribute.attr.issuer == designator.issuer
+}
+
+evaluate_designator(designator) := { "kind": "bag", "values": xs } if {
+ xs := [y.value | y := input.request[_]; designator_matches(designator, y)]
+ count(xs) > 1
+}
+
+evaluate_designator(designator) := xs[0] if {
+ xs := [y.value | y := input.request[_]; designator_matches(designator, y)]
+ count(xs) == 1
+}
+
+evaluate_designator(designator) := { "kind": "bag", "values": xs } if {
+ xs := [y.value | y := input.request[_]; designator_matches(designator, y)]
+ count(xs) == 0
+ not designator.must_be_present
+}
+
+evaluate_designator(designator) := { "status": "missing_attribute" } if {
+ xs := [y.value | y := input.request[_]; designator_matches(designator, y)]
+ count(xs) == 0
+ designator.must_be_present
+}
+
+#########################################################################
+# Match
+########################################################################
+
+evaluate_match(match) := { "match_result": true_value } if {
+ designator_result := evaluate_designator(match.designator)
+
+ # Designator evaluates without error.
+ designator_result
+
+ some x in designator_result.values
+ apply_xacml_function(match.function, [x, match.value]).value == true
+} else := { "match_result": true_value } if {
+ designator_result := evaluate_designator(match.designator)
+
+ # Designator evaluates without error.
+ designator_result
+
+ apply_xacml_function(match.function, [designator_result, match.value]).value == true
+} else := { "match_result": indeterminate_value } if {
+ designator_result := evaluate_designator(match.designator)
+
+ # Designator evaluates without error.
+ designator_result
+
+ some x in designator_result
+ is_indeterminate(apply_xacml_function(match.function, [x, match.value]))
+} else := { "match_result": false_value } if {
+ designator_result := evaluate_designator(match.designator)
+
+ # Designator evaluates without error.
+ designator_result
+} else := { "match_result": indeterminate_value }
+
+# Last case runs when evaluating the designator results in an error.
+
+evaluate_all_of(conj) := { "match_result": true_value } if {
+ every x in conj {
+ evaluate_match(x).match_result.value == true
+ }
+} else := { "match_result": "indeterminate" } if {
+ some x in conj
+ is_indeterminate(evaluate_match(x).match_result)
+} else := { "match_result": "no_match" }
+
+evaluate_any_of([]) := { "match_result": true_value }
+evaluate_any_of(disj) := { "match_result": true_value } if {
+ some x in disj
+ evaluate_all_of(x) == { "match_result": true_value }
+} else := { "match_result": "indeterminate" } if {
+ some x in disj
+ evaluate_all_of(x) == { "match_result": true_value }
+} else := { "match_result": "no_match" }
+
+
+########################################################################
+# Target
+########################################################################
+
+evaluate_target([]) := { "match_result": true_value }
+evaluate_target(xs) := { "match_result": true_value } if {
+ every disj in xs {
+ evaluate_any_of(disj).match_result.value == true
+ }
+} else := { "match_result": false_value } if {
+ some disj in xs
+ evaluate_any_of(disj).match_result.value == false
+} else := { "match_result": indeterminate_value }
+
+########################################################################
+# Expression
+########################################################################
+
+evaluate_expression({ "expression": "apply", "function": function_name, "args": args }) := x if {
+ x := apply_xacml_function(function_name, args)
+}
+evaluate_expression({ "expression": "attribute_designator", "inner": designator }) := x if {
+ x := evaluate_designator(designator)
+}
+evaluate_expression({ "expression": "attribute_value", "inner": value }) := x if {
+ x := value
+}
+evaluate_expression({ "expression": "function", "function": name }) := x if {
+ x := name
+}
+
+########################################################################
+# Obligations and Advice
+########################################################################
+
+evaluate_attribute_assignment_expression(expr) := assignment {
+ { "kind": "primitive", "value": inner } = evaluate_expression(expr.expression)
+ assignment := { "category": expr.category,
+ "identifier": expr.identifier,
+ "issuer": expr.issuer,
+ "value": inner }
+}
+
+evaluate_obligation_expression(obligation_expression) := obligation {
+ assignments := [evaluate_attribute_assignment_expression(expr) | expr := obligation_expression.assignments[_]]
+ obligation := { "assignments": assignments, "identifier": obligation_expression.identifier }
+}
+
+evaluate_advice_expression(advice_expression) := advice {
+ assignments := [evaluate_attribute_assignment_expression(expr) | expr := advice_expression.assignments[_]]
+ advice := { "assignments": assignments, "identifier": advice_expression.identifier }
+}
+
+
+########################################################################
+# Rule
+########################################################################
+
+# Condition is specified and applicable
+evaluate_rule_decision(rule) := { "decision_extended": decision } {
+ evaluate_target(rule.target).match_result.value == true
+
+ is_object(rule.condition)
+ evaluate_expression(rule.condition) == true
+
+ decision := rule.effect
+}
+# Condition is specified and not applicable
+evaluate_rule_decision(rule) := { "decision_extended": "not_applicable" } {
+ evaluate_target(rule.target).match_result.value == true
+ evaluate_expression(rule.condition) == false
+}
+# Condition is indeterminate
+evaluate_rule_decision(rule) := { "decision_extended": "indeterminate_p" } {
+ evaluate_target(rule.target).match_result.value == true
+ condition := evaluate_expression(rule.condition)
+ is_null(condition)
+ rule.effect == "permit"
+}
+evaluate_rule_decision(rule) := { "decision_extended": "indeterminate_d" } {
+ evaluate_target(rule.target).match_result.value == true
+ condition := evaluate_expression(rule.condition)
+ is_null(condition)
+ rule.effect == "deny"
+}
+# Condition is unspecified
+evaluate_rule_decision(rule) := { "decision_extended": decision } {
+ evaluate_target(rule.target).match_result.value == true
+ decision := rule.effect
+}
+
+evaluate_rule_decision(rule) := { "decision_extended": "not_applicable" } {
+ evaluate_target(rule.target).match_result.value == false
+}
+evaluate_rule_decision(rule) := { "decision_extended": "indeterminate_p" } {
+ is_indeterminate(evaluate_target(rule.target))
+ rule.effect == "permit"
+}
+evaluate_rule_decision(rule) := { "decision_extended": "indeterminate_d" } {
+ is_indeterminate(evaluate_target(rule.target))
+ rule.effect == "permit"
+}
+
+evaluate_rule_advices(rule) := { "advice": advice } if {
+ decision := evaluate_rule_decision(rule)
+ advice := [expr | expr := rule.advice[_]; expr.applies_to == decision ]
+}
+
+evaluate_rule_obligations(rule) := { "obligations": obligations } if {
+ decision := evaluate_rule_decision(rule)
+ obligations := [expr | expr := rule.obligations[_]; expr.fulfill_on == decision ]
+}
+
+########################################################################
+# Policy
+########################################################################
+
+evaluate_rule_combinator("deny_overrides", results) := { "decision_extended": "deny" } if {
+ some result in results
+ result.decision_extended == "deny"
+} else := { "decision_extended": "indeterminate_dp" } if {
+ some result in results
+ result.decision_extended == "indeterminate_dp"
+} else := { "decision_extended": "indeterminate_dp" } if {
+ some result1 in results
+ some result2 in results
+ result1.decision_extended == "indeterminate_d"
+ result1.decision_extended == "indeterminate_p"
+} else := { "decision_extended": "indeterminate_d" } if {
+ some result in results
+ result.decision_extended == "indeterminate_d"
+} else := { "decision_extended": "permit" } if {
+ some result in results
+ result.decision_extended == "permit"
+} else := { "decision_extended": "indeterminate_p" } if {
+ some result in results
+ result.decision_extended == "indeterminate_p"
+} else := { "decision_extended": "not_applicable" }
+
+evaluate_rule_combinator("ordered_deny_overrides", results) := { "decision_extended": "deny" } if {
+ some result in results
+ result.decision_extended == "deny"
+} else := { "decision_extended": "indeterminate_dp" } if {
+ some result in results
+ result.decision_extended == "indeterminate_dp"
+} else := { "decision_extended": "indeterminate_dp" } if {
+ some result1 in results
+ some result2 in results
+ result1.decision_extended == "indeterminate_d"
+ result1.decision_extended == "indeterminate_p"
+} else := { "decision_extended": "indeterminate_d" } if {
+ some result in results
+ result.decision_extended == "indeterminate_d"
+} else := { "decision_extended": "permit" } if {
+ some result in results
+ result.decision_extended == "permit"
+} else := { "decision_extended": "indeterminate_p" } if {
+ some result in results
+ result.decision_extended == "indeterminate_p"
+} else := { "decision_extended": "not_applicable" }
+
+evaluate_rule_combinator("permit_overrides", results) := { "decision_extended": "permit" } if {
+ some result in results
+ result.decision_extended == "permit"
+} else := { "decision_extended": "indeterminate_dp" } if {
+ some result in results
+ result.decision_extended == "indeterminate_dp"
+} else := { "decision_extended": "indeterminate_dp" } if {
+ some result1 in results
+ some result2 in results
+ result1.decision_extended == "indeterminate_d"
+ result1.decision_extended == "indeterminate_p"
+} else := { "decision_extended": "indeterminate_p" } if {
+ some result in results
+ result.decision_extended == "indeterminate_p"
+} else := { "decision_extended": "deny" } if {
+ some result in results
+ result.decision_extended == "deny"
+} else := { "decision_extended": "indeterminate_d" } if {
+ some result in results
+ result.decision_extended == "indeterminate_d"
+} else := { "decision_extended": "not_applicable" }
+
+evaluate_rule_combinator("ordered_permit_overrides", results) := { "decision_extended": "permit" } if {
+ some result in results
+ result.decision_extended == "permit"
+} else := { "decision_extended": "indeterminate_dp" } if {
+ some result in results
+ result.decision_extended == "indeterminate_dp"
+} else := { "decision_extended": "indeterminate_dp" } if {
+ some result1 in results
+ some result2 in results
+ result1.decision_extended == "indeterminate_d"
+ result1.decision_extended == "indeterminate_p"
+} else := { "decision_extended": "indeterminate_p" } if {
+ some result in results
+ result.decision_extended == "indeterminate_p"
+} else := { "decision_extended": "deny" } if {
+ some result in results
+ result.decision_extended == "deny"
+} else := { "decision_extended": "indeterminate_d" } if {
+ some result in results
+ result.decision_extended == "indeterminate_d"
+} else := { "decision_extended": "not_applicable" }
+
+evaluate_rule_combinator("deny_unless_permit", results) := { "decision_extended": "permit" } if {
+ some result in results
+ result.decision_extended == "permit"
+} else := { "decision_extended": "deny" }
+
+evaluate_rule_combinator("permit_unless_deny", results) := { "decision_extended": "deny" } if {
+ some result in results
+ result.decision_extended == "deny"
+} else := { "decision_extended": "permit" }
+
+evaluate_rule_combinator("first_applicable", results) := result if {
+ indices := [i | results[i].decision_extended != "not_applicable"]
+ count(indices) > 0
+ result := results[max(indices)]
+ result.decision_extended == "deny"
+} else := { "decision_extended": "not_applicable" }
+
+evaluate_rule_combinator("legacy_deny_overrides", results) := { "decision_extended": "deny" } if {
+ some result in results
+ result.decision_extended == "deny"
+} else := { "decision_extended": "indeterminate" } if {
+ some result in results
+ result.decision_extended == "indeterminate_d"
+} else := { "decision_extended": "permit" } if {
+ some result in results
+ result.decision_extended == "permit"
+} else := { "decision_extended": "indeterminate" } if {
+ some result in results
+ result.decision_extended == "indeterminate_p"
+} else := { "decision_extended": "not_applicable" }
+
+evaluate_rule_combinator("ordered_legacy_deny_overrides", results) := { "decision_extended": "deny" } if {
+ some result in results
+ result.decision_extended == "deny"
+} else := { "decision_extended": "indeterminate" } if {
+ some result in results
+ result.decision_extended == "indeterminate_d"
+} else := { "decision_extended": "permit" } if {
+ some result in results
+ result.decision_extended == "permit"
+} else := { "decision_extended": "indeterminate" } if {
+ some result in results
+ result.decision_extended == "indeterminate_p"
+} else := { "decision_extended": "not_applicable" }
+
+evaluate_rule_combinator("legacy_permit_overrides", results) := { "decision_extended": "permit" } if {
+ some result in results
+ result.decision_extended == "permit"
+} else := { "decision_extended": "indeterminate" } if {
+ some result in results
+ result.decision_extended == "indeterminate_p"
+} else := { "decision_extended": "deny" } if {
+ some result in results
+ result.decision_extended == "deny"
+} else := { "decision_extended": "indeterminate" } if {
+ some result in results
+ result.decision_extended == "indeterminate_d"
+} else := { "decision_extended": "not_applicable" }
+
+evaluate_rule_combinator("ordered_legacy_permit_overrides", results) := { "decision_extended": "permit" } if {
+ some result in results
+ result.decision_extended == "permit"
+} else := { "decision_extended": "indeterminate" } if {
+ some result in results
+ result.decision_extended == "indeterminate_p"
+} else := { "decision_extended": "deny" } if {
+ some result in results
+ result.decision_extended == "deny"
+} else := { "decision_extended": "indeterminate" } if {
+ some result in results
+ result.decision_extended == "indeterminate_d"
+} else := { "decision_extended": "not_applicable" }
+
+# child_results := [result | rule := policy.rules[_]; result := evaluate_rule_decision(rule)]
+evaluate_policy_decision(policy, child_results) := decision if {
+ evaluate_target(policy.target).match_result.value == true
+ decision := evaluate_rule_combinator(policy.combinator, child_results)
+} else := decision if {
+ is_indeterminate(evaluate_target(policy.target))
+ decision := lift_decision_indeterminate(evaluate_rule_combinator(policy.combinator, child_results))
+} else := { "decision_extended": "not_applicable" }
+
+# children_advice := [advice | rule := policy.rules[_]; expr := evaluate_rule_advices(rule); advice := expr[_]]
+evaluate_policy_advices(policy, child_results, children_advice) := { "advice" : advice } if {
+ decision := evaluate_policy_decision(policy, child_results)
+ policy_advice := [expr | expr := policy.advice[_]; expr.applies_to == decision ]
+ advice := array.concat(policy_advice, children_advice)
+}
+
+# children_obligations := [obligation | rule := policy.rules[_]; expr := evaluate_rule_obligations(rule); obligation := expr[_]]
+evaluate_policy_obligations(policy, child_results, children_obligations) := { "obligations" : obligations } if {
+ decision := evaluate_policy_decision(policy, child_results)
+ policy_obligations := [expr | expr := policy.obligations[_]; expr.applies_to == decision ]
+ obligations := array.concat(policy_obligations, children_obligations)
+}
+
+########################################################################
+# PolicySet
+########################################################################
+
+evaluate_policy_combinator("deny_overrides", results) := { "decision_extended": "deny" } if {
+ some result in results
+ result.decision_extended == "deny"
+} else := { "decision_extended": "indeterminate_dp" } if {
+ some result in results
+ result.decision_extended == "indeterminate_dp"
+} else := { "decision_extended": "indeterminate_dp" } if {
+ some result1 in results
+ some result2 in results
+ result1.decision_extended == "indeterminate_d"
+ result1.decision_extended == "indeterminate_p"
+} else := { "decision_extended": "indeterminate_d" } if {
+ some result in results
+ result.decision_extended == "indeterminate_d"
+} else := { "decision_extended": "permit" } if {
+ some result in results
+ result.decision_extended == "permit"
+} else := { "decision_extended": "indeterminate_p" } if {
+ some result in results
+ result.decision_extended == "indeterminate_p"
+} else := { "decision_extended": "not_applicable" }
+
+evaluate_policy_combinator("ordered_deny_overrides", results) := { "decision_extended": "deny" } if {
+ some result in results
+ result.decision_extended == "deny"
+} else := { "decision_extended": "indeterminate_dp" } if {
+ some result in results
+ result.decision_extended == "indeterminate_dp"
+} else := { "decision_extended": "indeterminate_dp" } if {
+ some result1 in results
+ some result2 in results
+ result1.decision_extended == "indeterminate_d"
+ result1.decision_extended == "indeterminate_p"
+} else := { "decision_extended": "indeterminate_d" } if {
+ some result in results
+ result.decision_extended == "indeterminate_d"
+} else := { "decision_extended": "permit" } if {
+ some result in results
+ result.decision_extended == "permit"
+} else := { "decision_extended": "indeterminate_p" } if {
+ some result in results
+ result.decision_extended == "indeterminate_p"
+} else := { "decision_extended": "not_applicable" }
+
+evaluate_policy_combinator("permit_overrides", results) := { "decision_extended": "permit" } if {
+ some result in results
+ result.decision_extended == "permit"
+} else := { "decision_extended": "indeterminate_dp" } if {
+ some result in results
+ result.decision_extended == "indeterminate_dp"
+} else := { "decision_extended": "indeterminate_dp" } if {
+ some result1 in results
+ some result2 in results
+ result1.decision_extended == "indeterminate_d"
+ result1.decision_extended == "indeterminate_p"
+} else := { "decision_extended": "indeterminate_p" } if {
+ some result in results
+ result.decision_extended == "indeterminate_p"
+} else := { "decision_extended": "deny" } if {
+ some result in results
+ result.decision_extended == "deny"
+} else := { "decision_extended": "indeterminate_d" } if {
+ some result in results
+ result.decision_extended == "indeterminate_d"
+} else := { "decision_extended": "not_applicable" }
+
+evaluate_policy_combinator("ordered_permit_overrides", results) := { "decision_extended": "permit" } if {
+ some result in results
+ result.decision_extended == "permit"
+} else := { "decision_extended": "indeterminate_dp" } if {
+ some result in results
+ result.decision_extended == "indeterminate_dp"
+} else := { "decision_extended": "indeterminate_dp" } if {
+ some result1 in results
+ some result2 in results
+ result1.decision_extended == "indeterminate_d"
+ result1.decision_extended == "indeterminate_p"
+} else := { "decision_extended": "indeterminate_p" } if {
+ some result in results
+ result.decision_extended == "indeterminate_p"
+} else := { "decision_extended": "deny" } if {
+ some result in results
+ result.decision_extended == "deny"
+} else := { "decision_extended": "indeterminate_d" } if {
+ some result in results
+ result.decision_extended == "indeterminate_d"
+} else := { "decision_extended": "not_applicable" }
+
+evaluate_policy_combinator("deny_unless_permit", results) := { "decision_extended": "permit" } if {
+ some result in results
+ result.decision_extended == "permit"
+} else := { "decision_extended": "deny" }
+
+evaluate_policy_combinator("permit_unless_deny", results) := { "decision_extended": "deny" } if {
+ some result in results
+ result.decision_extended == "deny"
+} else := { "decision_extended": "permit" }
+
+evaluate_policy_combinator("first_applicable", results) := result if {
+ indices := [i | results[i].decision_extended != "not_applicable"]
+ count(indices) > 0
+ result := results[max(indices)]
+ result.decision_extended == "deny"
+} else := { "decision_extended": "not_applicable" }
+
+evaluate_policy_combinator("only_one_applicable", results) := result if {
+ applicable := [result | result := results[i]; result.decision_extended != "not_applicable"]
+ count(applicable) == 1
+ result := applicable[0]
+} else := { "decision_extended": "not_applicable" }
+
+evaluate_policy_combinator("legacy_deny_overrides", results) := { "decision_extended": "deny" } if {
+ some result in results
+ result.decision_extended == "deny"
+} else := { "decision_extended": "deny" } if {
+ some result in results
+ result.decision_extended == "indeterminate"
+} else := { "decision_extended": "permit" } if {
+ some result in results
+ result.decision_extended == "permit"
+} else := { "decision_extended": "not_applicable" }
+
+evaluate_policy_combinator("ordered_legacy_deny_overrides", results) := { "decision_extended": "deny" } if {
+ some result in results
+ result.decision_extended == "deny"
+} else := { "decision_extended": "deny" } if {
+ some result in results
+ result.decision_extended == "indeterminate"
+} else := { "decision_extended": "permit" } if {
+ some result in results
+ result.decision_extended == "permit"
+} else := { "decision_extended": "not_applicable" }
+
+evaluate_policy_combinator("legacy_permit_overrides", results) := { "decision_extended": "permit" } if {
+ some result in results
+ result.decision_extended == "permit"
+} else := { "decision_extended": "deny" } if {
+ some result in results
+ result.decision_extended == "deny"
+} else := { "decision_extended": "indeterminate" } if {
+ some result in results
+ result.decision_extended == "indeterminate"
+} else := { "decision_extended": "not_applicable" }
+
+evaluate_policy_combinator("ordered_legacy_permit_overrides", results) := { "decision_extended": "permit" } if {
+ some result in results
+ result.decision_extended == "permit"
+} else := { "decision_extended": "indeterminate" } if {
+ some result in results
+ result.decision_extended == "indeterminate_p"
+} else := { "decision_extended": "deny" } if {
+ some result in results
+ result.decision_extended == "deny"
+} else := { "decision_extended": "indeterminate" } if {
+ some result in results
+ result.decision_extended == "indeterminate_d"
+} else := { "decision_extended": "not_applicable" }
+
+evaluate_policyset_decision(policyset, child_results) := decision if {
+ evaluate_target(policyset.target).match_result.value == true
+ decision := evaluate_policy_combinator(policyset.combinator, child_results)
+} else := decision if {
+ is_indeterminate(evaluate_target(policyset.target))
+ decision := lift_decision_indeterminate(evaluate_policy_combinator(policyset.combinator, child_results))
+} else := { "decision_extended": "not_applicable" }
+
+evaluate_policyset_advices(policyset, child_results, child_advice) := { "advice" : advice } if {
+ decision := evaluate_policyset_decision(policyset, child_results)
+ policyset_advice := [expr | expr := policyset.advice[_]; expr.applies_to == decision ]
+ advice := array.concat(policyset_advice, child_advice)
+}
+
+evaluate_policyset_obligations(policyset, child_results, child_obligations) := { "obligations" : obligations } if {
+ decision := evaluate_policyset_decision(policyset, child_results)
+ policyset_obligations := [expr | expr := policyset.obligations[_]; expr.applies_to == decision ]
+ obligations := array.concat(policyset_obligations, child_obligations)
+}
+
+IIA006_policy := {
+ "combinator": "deny_overrides",
+ "target": [],
+ "obligations": [],
+ "advice": []
+}
+
+IIA006_rule := {
+ "target": [[[{ "function": "urn:oasis:names:tc:xacml:1.0:function:string-equal",
+ "designator": {
+ "identifier": "urn:oasis:names:tc:xacml:1.0:subject:subject-id",
+ "category": "urn:oasis:names:tc:xacml:1.0:subject-category:access-subject",
+ "type": "http://www.w3.org/2001/XMLSchema#string",
+ "must_be_present": false
+ },
+ "value": {
+ "kind": "primitive",
+ "type": "http://www.w3.org/2001/XMLSchema#string",
+ "value": "Julius Hibbert"
+ }},
+ { "function": "urn:oasis:names:tc:xacml:1.0:function:string-equal",
+ "designator": {
+ "identifier": "urn:oasis:names:tc:xacml:2.0:conformance-test:some-attribute",
+ "category": "urn:oasis:names:tc:xacml:1.0:subject-category:access-subject",
+ "type": "http://www.w3.org/2001/XMLSchema#string",
+ "must_be_present": false
+ },
+ "value": {
+ "kind": "primitive",
+ "type": "http://www.w3.org/2001/XMLSchema#string",
+ "value": "riddle me this"
+ }}]],
+ [[{ "function": "urn:oasis:names:tc:xacml:1.0:function:anyURI-equal",
+ "designator": {
+ "identifier": "urn:oasis:names:tc:xacml:1.0:resource:resource-id",
+ "category": "urn:oasis:names:tc:xacml:3.0:attribute-category:resource",
+ "type": "http://www.w3.org/2001/XMLSchema#anyURI",
+ "must_be_present": false
+ },
+ "value": {
+ "kind": "primitive",
+ "type": "http://www.w3.org/2001/XMLSchema#anyURI",
+ "value": "http://medico.com/record/patient/BartSimpson"
+ }}]],
+ [[{ "function": "urn:oasis:names:tc:xacml:1.0:function:string-equal",
+ "designator": {
+ "identifier": "urn:oasis:names:tc:xacml:1.0:action:action-id",
+ "category": "urn:oasis:names:tc:xacml:3.0:attribute-category:action",
+ "type": "http://www.w3.org/2001/XMLSchema#string",
+ "must_be_present": false
+ },
+ "value": {
+ "kind": "primitive",
+ "type": "http://www.w3.org/2001/XMLSchema#string",
+ "value": "read"
+ }}],
+ [{ "function": "urn:oasis:names:tc:xacml:1.0:function:string-equal",
+ "designator": {
+ "identifier": "urn:oasis:names:tc:xacml:1.0:action:action-id",
+ "category": "urn:oasis:names:tc:xacml:3.0:attribute-category:action",
+ "type": "http://www.w3.org/2001/XMLSchema#string",
+ "must_be_present": false
+ },
+ "value": {
+ "kind": "primitive",
+ "type": "http://www.w3.org/2001/XMLSchema#string",
+ "value": "write"
+ }}]]],
+ "effect": "permit",
+ "obligations": [],
+ "advice": []
+}
+
+allow := evaluate_policyset_decision(IIA006_policy, [evaluate_rule_decision(IIA006_rule)])
diff --git a/benchmarks/rego/iia007.rego b/benchmarks/rego/iia007.rego
new file mode 100644
index 0000000..b4aa619
--- /dev/null
+++ b/benchmarks/rego/iia007.rego
@@ -0,0 +1,829 @@
+package equivalence
+
+import future.keywords.every
+import future.keywords.if
+import future.keywords.in
+
+########################################################################
+# Data Types
+########################################################################
+
+## MatchResult
+
+# - is_match => { "match_result": true }
+# - no_match => { "match_result": false }
+# - indeterminate => { "match_result": "indeterminate" }
+
+## Decision
+
+# - permit => { "decision": "permit" }
+# - deny => { "decision": "deny" }
+# - not_applicable => { "decision": "not_applicable" }
+# - indeterminate => { "decision": "indeterminate" }
+
+## Extended Decision
+
+# - permit => { "decision_extended": "permit" }
+# - deny => { "decision_extended": "deny" }
+# - not_applicable => { "decision_extended": "not_applicable" }
+# - indeterminate => { "decision_extended": "indeterminate" }
+# - indeterminate_d => { "decision_extended": "indeterminate_d" }
+# - indeterminate_p => { "decision_extended": "indeterminate_p" }
+# - indeterminate_dp => { "decision_extended": "indeterminate_dp" }
+
+lift_decision_indeterminate({ "decision": "not_applicable" }) := { "decision": "not_applicable" }
+lift_decision_indeterminate({ "decision": "permit" }) := { "decision": "indeterminate_p" }
+lift_decision_indeterminate({ "decision": "deny" }) := { "decision": "indeterminate_d" }
+lift_decision_indeterminate({ "decision": "indeterminate" }) := { "decision": "indeterminate_dp" }
+lift_decision_indeterminate({ "decision": "indeterminate_dp" }) := { "decision": "indeterminate_dp" }
+lift_decision_indeterminate({ "decision": "indeterminate_p" }) := { "decision": "indeterminate_p" }
+lift_decision_indeterminate({ "decision": "indeterminate_d" }) := { "decision": "indeterminate_d" }
+
+## Value
+
+# - { "kind": "primitive",
+# "type": string,
+# "value": string }
+# - { "kind": "bag",
+# "values": ... }
+
+### Booleans
+
+true_value := { "kind": "primitive", "type": "boolean", "value": true }
+false_value := { "kind": "primitive", "type": "boolean", "value": false }
+indeterminate_value := { "kind": "primitive", "type": "boolean" }
+
+is_indeterminate(value) if { is_null(value.value) }
+
+## StatusCode
+
+# - ok => { "status": "ok" }
+# - missing_attribute => { "status": "missing_attribute" }
+# - syntax_error => { "status": "syntax_error" }
+# - processing_error => { "status": "processing_error" }
+
+## AttributeDesignator
+
+# - { category : string
+# identifier : string
+# type : string
+# issuer : string or null
+# must_be_present : boolean }
+
+## Expression
+
+# - { "expression": "apply",
+# "function": string,
+# "args": [string, ...] }
+# - { "expression": "attribute_designator",
+# "inner": AttributeDesignator }
+# - { "expression": "attribute_value",
+# "inner": Value }
+# - { "expression": "function"
+# "function": string }
+
+## Match
+
+# - { "function": string,
+# "designator": AttributeDesignator,
+# "value": Value }
+
+## Obligation
+
+# - { "assignments": [Attribute, ...],
+# "identifier": string }
+
+## ObligationExpression
+
+# - { "assignments": [AttributeAssignmentExpression, ...],
+# "identifier": string,
+# "fulfill_on": Decision }
+
+## Advice
+
+# - { "assignments": [Attribute, ...],
+# "identifier": string }
+
+## AdviceExpression
+
+# - { "assignments": [AttributeAssignmentExpression, ...],
+# "identifier": string,
+# "applies_to": Decision }
+
+## AttributeAssignmentExpression
+
+# - { "category": string,
+# "identifier": string,
+# "issuer": string or null,
+# "expression": Expression }
+
+## Target: [[[Expression, ...], ...], ...]
+
+## Rule
+
+# - { "target": Target,
+# "condition": Expression or null,
+# "effect": "permit" or "deny",
+# "obligations": [ObligationExpression, ...],
+# "advice": [AdviceExpression, ...] }
+
+## Policy
+
+# - { "combinator": string,
+# "target": Target,
+# "obligations": [ObligationExpression, ...],
+# "advice": [AdviceExpression, ...] }
+
+## PolicySet
+
+# - { "combinator": string,
+# "target": Target,
+# "obligations": [ObligationExpression, ...],
+# "advice": [AdviceExpression, ...] }
+
+# We assume the request attributes are stored in `input.request` as an array or set of
+#
+# { category : string
+# identifier : string
+# issuer : string or null
+# value : [Value, ...] }
+
+########################################################################
+# Match Functions
+########################################################################
+
+apply_xacml_function(
+ "urn:oasis:names:tc:xacml:1.0:function:string-equal",
+ [{ "kind": "primitive",
+ "type": "http://www.w3.org/2001/XMLSchema#string",
+ "value": a },
+ { "kind": "primitive",
+ "type": "http://www.w3.org/2001/XMLSchema#string",
+ "value": b }]) := true_value if {
+ a == b
+} else := false_value
+apply_xacml_function(
+ "urn:oasis:names:tc:xacml:1.0:function:anyURI-equal",
+ [{ "kind": "primitive",
+ "type": "http://www.w3.org/2001/XMLSchema#anyURI",
+ "value": a },
+ { "kind": "primitive",
+ "type": "http://www.w3.org/2001/XMLSchema#anyURI",
+ "value": b }]) := true_value if {
+ a == b
+} else := false_value
+
+########################################################################
+# AttributeDesignator
+########################################################################
+
+designator_matches(designator, attribute) if {
+ attribute.category == designator.category
+ attribute.identifier == designator.identifier
+ attribute.value.type == designator.type
+ not attribute.attr.issuer
+}
+
+designator_matches(designator, attribute) if {
+ attribute.category == designator.category
+ attribute.identifier == designator.identifier
+ attribute.value.type == designator.type
+ attribute.attr.issuer == designator.issuer
+}
+
+evaluate_designator(designator) := { "kind": "bag", "values": xs } if {
+ xs := [y.value | y := input.request[_]; designator_matches(designator, y)]
+ count(xs) > 1
+}
+
+evaluate_designator(designator) := xs[0] if {
+ xs := [y.value | y := input.request[_]; designator_matches(designator, y)]
+ count(xs) == 1
+}
+
+evaluate_designator(designator) := { "kind": "bag", "values": xs } if {
+ xs := [y.value | y := input.request[_]; designator_matches(designator, y)]
+ count(xs) == 0
+ not designator.must_be_present
+}
+
+evaluate_designator(designator) := { "status": "missing_attribute" } if {
+ xs := [y.value | y := input.request[_]; designator_matches(designator, y)]
+ count(xs) == 0
+ designator.must_be_present
+}
+
+#########################################################################
+# Match
+########################################################################
+
+evaluate_match(match) := { "match_result": true_value } if {
+ designator_result := evaluate_designator(match.designator)
+
+ # Designator evaluates without error.
+ designator_result
+
+ some x in designator_result.values
+ apply_xacml_function(match.function, [x, match.value]).value == true
+} else := { "match_result": true_value } if {
+ designator_result := evaluate_designator(match.designator)
+
+ # Designator evaluates without error.
+ designator_result
+
+ apply_xacml_function(match.function, [designator_result, match.value]).value == true
+} else := { "match_result": indeterminate_value } if {
+ designator_result := evaluate_designator(match.designator)
+
+ # Designator evaluates without error.
+ designator_result
+
+ some x in designator_result
+ is_indeterminate(apply_xacml_function(match.function, [x, match.value]))
+} else := { "match_result": false_value } if {
+ designator_result := evaluate_designator(match.designator)
+
+ # Designator evaluates without error.
+ designator_result
+} else := { "match_result": indeterminate_value, "status": designator_result.status } if {
+ designator_result := evaluate_designator(match.designator)
+}
+
+# Last case runs when evaluating the designator results in an error.
+
+evaluate_all_of(conj) := { "match_result": true_value } if {
+ every x in conj {
+ evaluate_match(x).match_result.value == true
+ }
+} else := { "match_result": "indeterminate", "status": x.status } if {
+ some x in conj
+ is_indeterminate(evaluate_match(x).match_result)
+} else := { "match_result": "no_match" }
+
+evaluate_any_of([]) := { "match_result": true_value }
+evaluate_any_of(disj) := { "match_result": true_value } if {
+ some x in disj
+ evaluate_all_of(x) == { "match_result": true_value }
+} else := { "match_result": "indeterminate", "status": x.status } if {
+ some x in disj
+ is_indeterminate(evaluate_all_of(x))
+} else := { "match_result": "no_match" }
+
+
+########################################################################
+# Target
+########################################################################
+
+evaluate_target([]) := { "match_result": true_value }
+evaluate_target(xs) := { "match_result": true_value } if {
+ every disj in xs {
+ evaluate_any_of(disj).match_result.value == true
+ }
+} else := { "match_result": false_value } if {
+ some disj in xs
+ evaluate_any_of(disj).match_result == "no_match"
+} else := { "match_result": indeterminate_value }
+
+########################################################################
+# Expression
+########################################################################
+
+evaluate_expression({ "expression": "apply", "function": function_name, "args": args }) := x if {
+ x := apply_xacml_function(function_name, args)
+}
+evaluate_expression({ "expression": "attribute_designator", "inner": designator }) := x if {
+ x := evaluate_designator(designator)
+}
+evaluate_expression({ "expression": "attribute_value", "inner": value }) := x if {
+ x := value
+}
+evaluate_expression({ "expression": "function", "function": name }) := x if {
+ x := name
+}
+
+########################################################################
+# Obligations and Advice
+########################################################################
+
+evaluate_attribute_assignment_expression(expr) := assignment {
+ { "kind": "primitive", "value": inner } = evaluate_expression(expr.expression)
+ assignment := { "category": expr.category,
+ "identifier": expr.identifier,
+ "issuer": expr.issuer,
+ "value": inner }
+}
+
+evaluate_obligation_expression(obligation_expression) := obligation {
+ assignments := [evaluate_attribute_assignment_expression(expr) | expr := obligation_expression.assignments[_]]
+ obligation := { "assignments": assignments, "identifier": obligation_expression.identifier }
+}
+
+evaluate_advice_expression(advice_expression) := advice {
+ assignments := [evaluate_attribute_assignment_expression(expr) | expr := advice_expression.assignments[_]]
+ advice := { "assignments": assignments, "identifier": advice_expression.identifier }
+}
+
+
+########################################################################
+# Rule
+########################################################################
+
+# Condition is specified and applicable
+evaluate_rule_decision(rule) := { "decision_extended": decision } {
+ evaluate_target(rule.target).match_result.value == true
+
+ is_object(rule.condition)
+ evaluate_expression(rule.condition) == true
+
+ decision := rule.effect
+}
+# Condition is specified and not applicable
+evaluate_rule_decision(rule) := { "decision_extended": "not_applicable" } {
+ evaluate_target(rule.target).match_result.value == true
+ evaluate_expression(rule.condition) == false
+}
+# Condition is indeterminate
+evaluate_rule_decision(rule) := { "decision_extended": "indeterminate_p" } {
+ evaluate_target(rule.target).match_result.value == true
+ condition := evaluate_expression(rule.condition)
+ is_null(condition)
+ rule.effect == "permit"
+}
+evaluate_rule_decision(rule) := { "decision_extended": "indeterminate_d" } {
+ evaluate_target(rule.target).match_result.value == true
+ condition := evaluate_expression(rule.condition)
+ is_null(condition)
+ rule.effect == "deny"
+}
+# Condition is unspecified
+evaluate_rule_decision(rule) := { "decision_extended": decision } {
+ evaluate_target(rule.target).match_result.value == true
+ decision := rule.effect
+}
+
+evaluate_rule_decision(rule) := { "decision_extended": "not_applicable" } {
+ evaluate_target(rule.target).match_result.value == false
+}
+evaluate_rule_decision(rule) := { "decision_extended": "indeterminate_p" } {
+ is_indeterminate(evaluate_target(rule.target))
+ rule.effect == "permit"
+}
+evaluate_rule_decision(rule) := { "decision_extended": "indeterminate_d" } {
+ is_indeterminate(evaluate_target(rule.target))
+ rule.effect == "permit"
+}
+
+evaluate_rule_advices(rule) := { "advice": advice } if {
+ decision := evaluate_rule_decision(rule)
+ advice := [expr | expr := rule.advice[_]; expr.applies_to == decision ]
+}
+
+evaluate_rule_obligations(rule) := { "obligations": obligations } if {
+ decision := evaluate_rule_decision(rule)
+ obligations := [expr | expr := rule.obligations[_]; expr.fulfill_on == decision ]
+}
+
+########################################################################
+# Policy
+########################################################################
+
+evaluate_rule_combinator("deny_overrides", results) := { "decision_extended": "deny" } if {
+ some result in results
+ result.decision_extended == "deny"
+} else := { "decision_extended": "indeterminate_dp" } if {
+ some result in results
+ result.decision_extended == "indeterminate_dp"
+} else := { "decision_extended": "indeterminate_dp" } if {
+ some result1 in results
+ some result2 in results
+ result1.decision_extended == "indeterminate_d"
+ result1.decision_extended == "indeterminate_p"
+} else := { "decision_extended": "indeterminate_d" } if {
+ some result in results
+ result.decision_extended == "indeterminate_d"
+} else := { "decision_extended": "permit" } if {
+ some result in results
+ result.decision_extended == "permit"
+} else := { "decision_extended": "indeterminate_p" } if {
+ some result in results
+ result.decision_extended == "indeterminate_p"
+} else := { "decision_extended": "not_applicable" }
+
+evaluate_rule_combinator("ordered_deny_overrides", results) := { "decision_extended": "deny" } if {
+ some result in results
+ result.decision_extended == "deny"
+} else := { "decision_extended": "indeterminate_dp" } if {
+ some result in results
+ result.decision_extended == "indeterminate_dp"
+} else := { "decision_extended": "indeterminate_dp" } if {
+ some result1 in results
+ some result2 in results
+ result1.decision_extended == "indeterminate_d"
+ result1.decision_extended == "indeterminate_p"
+} else := { "decision_extended": "indeterminate_d" } if {
+ some result in results
+ result.decision_extended == "indeterminate_d"
+} else := { "decision_extended": "permit" } if {
+ some result in results
+ result.decision_extended == "permit"
+} else := { "decision_extended": "indeterminate_p" } if {
+ some result in results
+ result.decision_extended == "indeterminate_p"
+} else := { "decision_extended": "not_applicable" }
+
+evaluate_rule_combinator("permit_overrides", results) := { "decision_extended": "permit" } if {
+ some result in results
+ result.decision_extended == "permit"
+} else := { "decision_extended": "indeterminate_dp" } if {
+ some result in results
+ result.decision_extended == "indeterminate_dp"
+} else := { "decision_extended": "indeterminate_dp" } if {
+ some result1 in results
+ some result2 in results
+ result1.decision_extended == "indeterminate_d"
+ result1.decision_extended == "indeterminate_p"
+} else := { "decision_extended": "indeterminate_p" } if {
+ some result in results
+ result.decision_extended == "indeterminate_p"
+} else := { "decision_extended": "deny" } if {
+ some result in results
+ result.decision_extended == "deny"
+} else := { "decision_extended": "indeterminate_d" } if {
+ some result in results
+ result.decision_extended == "indeterminate_d"
+} else := { "decision_extended": "not_applicable" }
+
+evaluate_rule_combinator("ordered_permit_overrides", results) := { "decision_extended": "permit" } if {
+ some result in results
+ result.decision_extended == "permit"
+} else := { "decision_extended": "indeterminate_dp" } if {
+ some result in results
+ result.decision_extended == "indeterminate_dp"
+} else := { "decision_extended": "indeterminate_dp" } if {
+ some result1 in results
+ some result2 in results
+ result1.decision_extended == "indeterminate_d"
+ result1.decision_extended == "indeterminate_p"
+} else := { "decision_extended": "indeterminate_p" } if {
+ some result in results
+ result.decision_extended == "indeterminate_p"
+} else := { "decision_extended": "deny" } if {
+ some result in results
+ result.decision_extended == "deny"
+} else := { "decision_extended": "indeterminate_d" } if {
+ some result in results
+ result.decision_extended == "indeterminate_d"
+} else := { "decision_extended": "not_applicable" }
+
+evaluate_rule_combinator("deny_unless_permit", results) := { "decision_extended": "permit" } if {
+ some result in results
+ result.decision_extended == "permit"
+} else := { "decision_extended": "deny" }
+
+evaluate_rule_combinator("permit_unless_deny", results) := { "decision_extended": "deny" } if {
+ some result in results
+ result.decision_extended == "deny"
+} else := { "decision_extended": "permit" }
+
+evaluate_rule_combinator("first_applicable", results) := result if {
+ indices := [i | results[i].decision_extended != "not_applicable"]
+ count(indices) > 0
+ result := results[max(indices)]
+ result.decision_extended == "deny"
+} else := { "decision_extended": "not_applicable" }
+
+evaluate_rule_combinator("legacy_deny_overrides", results) := { "decision_extended": "deny" } if {
+ some result in results
+ result.decision_extended == "deny"
+} else := { "decision_extended": "indeterminate" } if {
+ some result in results
+ result.decision_extended == "indeterminate_d"
+} else := { "decision_extended": "permit" } if {
+ some result in results
+ result.decision_extended == "permit"
+} else := { "decision_extended": "indeterminate" } if {
+ some result in results
+ result.decision_extended == "indeterminate_p"
+} else := { "decision_extended": "not_applicable" }
+
+evaluate_rule_combinator("ordered_legacy_deny_overrides", results) := { "decision_extended": "deny" } if {
+ some result in results
+ result.decision_extended == "deny"
+} else := { "decision_extended": "indeterminate" } if {
+ some result in results
+ result.decision_extended == "indeterminate_d"
+} else := { "decision_extended": "permit" } if {
+ some result in results
+ result.decision_extended == "permit"
+} else := { "decision_extended": "indeterminate" } if {
+ some result in results
+ result.decision_extended == "indeterminate_p"
+} else := { "decision_extended": "not_applicable" }
+
+evaluate_rule_combinator("legacy_permit_overrides", results) := { "decision_extended": "permit" } if {
+ some result in results
+ result.decision_extended == "permit"
+} else := { "decision_extended": "indeterminate" } if {
+ some result in results
+ result.decision_extended == "indeterminate_p"
+} else := { "decision_extended": "deny" } if {
+ some result in results
+ result.decision_extended == "deny"
+} else := { "decision_extended": "indeterminate" } if {
+ some result in results
+ result.decision_extended == "indeterminate_d"
+} else := { "decision_extended": "not_applicable" }
+
+evaluate_rule_combinator("ordered_legacy_permit_overrides", results) := { "decision_extended": "permit" } if {
+ some result in results
+ result.decision_extended == "permit"
+} else := { "decision_extended": "indeterminate" } if {
+ some result in results
+ result.decision_extended == "indeterminate_p"
+} else := { "decision_extended": "deny" } if {
+ some result in results
+ result.decision_extended == "deny"
+} else := { "decision_extended": "indeterminate" } if {
+ some result in results
+ result.decision_extended == "indeterminate_d"
+} else := { "decision_extended": "not_applicable" }
+
+# child_results := [result | rule := policy.rules[_]; result := evaluate_rule_decision(rule)]
+evaluate_policy_decision(policy, child_results) := decision if {
+ evaluate_target(policy.target).match_result.value == true
+ decision := evaluate_rule_combinator(policy.combinator, child_results)
+} else := decision if {
+ is_indeterminate(evaluate_target(policy.target))
+ decision := lift_decision_indeterminate(evaluate_rule_combinator(policy.combinator, child_results))
+} else := { "decision_extended": "not_applicable" }
+
+# children_advice := [advice | rule := policy.rules[_]; expr := evaluate_rule_advices(rule); advice := expr[_]]
+evaluate_policy_advices(policy, child_results, children_advice) := { "advice" : advice } if {
+ decision := evaluate_policy_decision(policy, child_results)
+ policy_advice := [expr | expr := policy.advice[_]; expr.applies_to == decision ]
+ advice := array.concat(policy_advice, children_advice)
+}
+
+# children_obligations := [obligation | rule := policy.rules[_]; expr := evaluate_rule_obligations(rule); obligation := expr[_]]
+evaluate_policy_obligations(policy, child_results, children_obligations) := { "obligations" : obligations } if {
+ decision := evaluate_policy_decision(policy, child_results)
+ policy_obligations := [expr | expr := policy.obligations[_]; expr.applies_to == decision ]
+ obligations := array.concat(policy_obligations, children_obligations)
+}
+
+########################################################################
+# PolicySet
+########################################################################
+
+evaluate_policy_combinator("deny_overrides", results) := { "decision_extended": "deny" } if {
+ some result in results
+ result.decision_extended == "deny"
+} else := { "decision_extended": "indeterminate_dp" } if {
+ some result in results
+ result.decision_extended == "indeterminate_dp"
+} else := { "decision_extended": "indeterminate_dp" } if {
+ some result1 in results
+ some result2 in results
+ result1.decision_extended == "indeterminate_d"
+ result1.decision_extended == "indeterminate_p"
+} else := { "decision_extended": "indeterminate_d" } if {
+ some result in results
+ result.decision_extended == "indeterminate_d"
+} else := { "decision_extended": "permit" } if {
+ some result in results
+ result.decision_extended == "permit"
+} else := { "decision_extended": "indeterminate_p" } if {
+ some result in results
+ result.decision_extended == "indeterminate_p"
+} else := { "decision_extended": "not_applicable" }
+
+evaluate_policy_combinator("ordered_deny_overrides", results) := { "decision_extended": "deny" } if {
+ some result in results
+ result.decision_extended == "deny"
+} else := { "decision_extended": "indeterminate_dp" } if {
+ some result in results
+ result.decision_extended == "indeterminate_dp"
+} else := { "decision_extended": "indeterminate_dp" } if {
+ some result1 in results
+ some result2 in results
+ result1.decision_extended == "indeterminate_d"
+ result1.decision_extended == "indeterminate_p"
+} else := { "decision_extended": "indeterminate_d" } if {
+ some result in results
+ result.decision_extended == "indeterminate_d"
+} else := { "decision_extended": "permit" } if {
+ some result in results
+ result.decision_extended == "permit"
+} else := { "decision_extended": "indeterminate_p" } if {
+ some result in results
+ result.decision_extended == "indeterminate_p"
+} else := { "decision_extended": "not_applicable" }
+
+evaluate_policy_combinator("permit_overrides", results) := { "decision_extended": "permit" } if {
+ some result in results
+ result.decision_extended == "permit"
+} else := { "decision_extended": "indeterminate_dp" } if {
+ some result in results
+ result.decision_extended == "indeterminate_dp"
+} else := { "decision_extended": "indeterminate_dp" } if {
+ some result1 in results
+ some result2 in results
+ result1.decision_extended == "indeterminate_d"
+ result1.decision_extended == "indeterminate_p"
+} else := { "decision_extended": "indeterminate_p" } if {
+ some result in results
+ result.decision_extended == "indeterminate_p"
+} else := { "decision_extended": "deny" } if {
+ some result in results
+ result.decision_extended == "deny"
+} else := { "decision_extended": "indeterminate_d" } if {
+ some result in results
+ result.decision_extended == "indeterminate_d"
+} else := { "decision_extended": "not_applicable" }
+
+evaluate_policy_combinator("ordered_permit_overrides", results) := { "decision_extended": "permit" } if {
+ some result in results
+ result.decision_extended == "permit"
+} else := { "decision_extended": "indeterminate_dp" } if {
+ some result in results
+ result.decision_extended == "indeterminate_dp"
+} else := { "decision_extended": "indeterminate_dp" } if {
+ some result1 in results
+ some result2 in results
+ result1.decision_extended == "indeterminate_d"
+ result1.decision_extended == "indeterminate_p"
+} else := { "decision_extended": "indeterminate_p" } if {
+ some result in results
+ result.decision_extended == "indeterminate_p"
+} else := { "decision_extended": "deny" } if {
+ some result in results
+ result.decision_extended == "deny"
+} else := { "decision_extended": "indeterminate_d" } if {
+ some result in results
+ result.decision_extended == "indeterminate_d"
+} else := { "decision_extended": "not_applicable" }
+
+evaluate_policy_combinator("deny_unless_permit", results) := { "decision_extended": "permit" } if {
+ some result in results
+ result.decision_extended == "permit"
+} else := { "decision_extended": "deny" }
+
+evaluate_policy_combinator("permit_unless_deny", results) := { "decision_extended": "deny" } if {
+ some result in results
+ result.decision_extended == "deny"
+} else := { "decision_extended": "permit" }
+
+evaluate_policy_combinator("first_applicable", results) := result if {
+ indices := [i | results[i].decision_extended != "not_applicable"]
+ count(indices) > 0
+ result := results[max(indices)]
+ result.decision_extended == "deny"
+} else := { "decision_extended": "not_applicable" }
+
+evaluate_policy_combinator("only_one_applicable", results) := result if {
+ applicable := [result | result := results[i]; result.decision_extended != "not_applicable"]
+ count(applicable) == 1
+ result := applicable[0]
+} else := { "decision_extended": "not_applicable" }
+
+evaluate_policy_combinator("legacy_deny_overrides", results) := { "decision_extended": "deny" } if {
+ some result in results
+ result.decision_extended == "deny"
+} else := { "decision_extended": "deny" } if {
+ some result in results
+ result.decision_extended == "indeterminate"
+} else := { "decision_extended": "permit" } if {
+ some result in results
+ result.decision_extended == "permit"
+} else := { "decision_extended": "not_applicable" }
+
+evaluate_policy_combinator("ordered_legacy_deny_overrides", results) := { "decision_extended": "deny" } if {
+ some result in results
+ result.decision_extended == "deny"
+} else := { "decision_extended": "deny" } if {
+ some result in results
+ result.decision_extended == "indeterminate"
+} else := { "decision_extended": "permit" } if {
+ some result in results
+ result.decision_extended == "permit"
+} else := { "decision_extended": "not_applicable" }
+
+evaluate_policy_combinator("legacy_permit_overrides", results) := { "decision_extended": "permit" } if {
+ some result in results
+ result.decision_extended == "permit"
+} else := { "decision_extended": "deny" } if {
+ some result in results
+ result.decision_extended == "deny"
+} else := { "decision_extended": "indeterminate" } if {
+ some result in results
+ result.decision_extended == "indeterminate"
+} else := { "decision_extended": "not_applicable" }
+
+evaluate_policy_combinator("ordered_legacy_permit_overrides", results) := { "decision_extended": "permit" } if {
+ some result in results
+ result.decision_extended == "permit"
+} else := { "decision_extended": "indeterminate" } if {
+ some result in results
+ result.decision_extended == "indeterminate_p"
+} else := { "decision_extended": "deny" } if {
+ some result in results
+ result.decision_extended == "deny"
+} else := { "decision_extended": "indeterminate" } if {
+ some result in results
+ result.decision_extended == "indeterminate_d"
+} else := { "decision_extended": "not_applicable" }
+
+evaluate_policyset_decision(policyset, child_results) := decision if {
+ evaluate_target(policyset.target).match_result.value == true
+ decision := evaluate_policy_combinator(policyset.combinator, child_results)
+} else := decision if {
+ is_indeterminate(evaluate_target(policyset.target))
+ decision := lift_decision_indeterminate(evaluate_policy_combinator(policyset.combinator, child_results))
+} else := { "decision_extended": "not_applicable" }
+
+evaluate_policyset_advices(policyset, child_results, child_advice) := { "advice" : advice } if {
+ decision := evaluate_policyset_decision(policyset, child_results)
+ policyset_advice := [expr | expr := policyset.advice[_]; expr.applies_to == decision ]
+ advice := array.concat(policyset_advice, child_advice)
+}
+
+evaluate_policyset_obligations(policyset, child_results, child_obligations) := { "obligations" : obligations } if {
+ decision := evaluate_policyset_decision(policyset, child_results)
+ policyset_obligations := [expr | expr := policyset.obligations[_]; expr.applies_to == decision ]
+ obligations := array.concat(policyset_obligations, child_obligations)
+}
+
+IIA007_policy := {
+ "combinator": "deny_overrides",
+ "target": [],
+ "obligations": [],
+ "advice": []
+}
+
+IIA007_rule := {
+ "target": [[[{ "function": "urn:oasis:names:tc:xacml:1.0:function:string-equal",
+ "designator": {
+ "identifier": "urn:oasis:names:tc:xacml:1.0:subject:subject-id",
+ "category": "urn:oasis:names:tc:xacml:1.0:subject-category:access-subject",
+ "type": "http://www.w3.org/2001/XMLSchema#string",
+ "must_be_present": true
+ },
+ "value": {
+ "kind": "primitive",
+ "type": "http://www.w3.org/2001/XMLSchema#string",
+ "value": "Julius Hibbert"
+ }},
+ { "function": "urn:oasis:names:tc:xacml:1.0:function:string-equal",
+ "designator": {
+ "identifier": "urn:oasis:names:tc:xacml:2.0:conformance-test:some-attribute",
+ "category": "urn:oasis:names:tc:xacml:1.0:subject-category:access-subject",
+ "type": "http://www.w3.org/2001/XMLSchema#string",
+ "must_be_present": true
+ },
+ "value": {
+ "kind": "primitive",
+ "type": "http://www.w3.org/2001/XMLSchema#string",
+ "value": "riddle me this"
+ }}]],
+ [[{ "function": "urn:oasis:names:tc:xacml:1.0:function:anyURI-equal",
+ "designator": {
+ "identifier": "urn:oasis:names:tc:xacml:1.0:resource:resource-id",
+ "category": "urn:oasis:names:tc:xacml:3.0:attribute-category:resource",
+ "type": "http://www.w3.org/2001/XMLSchema#anyURI",
+ "must_be_present": false
+ },
+ "value": {
+ "kind": "primitive",
+ "type": "http://www.w3.org/2001/XMLSchema#anyURI",
+ "value": "http://medico.com/record/patient/BartSimpson"
+ }}]],
+ [[{ "function": "urn:oasis:names:tc:xacml:1.0:function:string-equal",
+ "designator": {
+ "identifier": "urn:oasis:names:tc:xacml:1.0:action:action-id",
+ "category": "urn:oasis:names:tc:xacml:3.0:attribute-category:action",
+ "type": "http://www.w3.org/2001/XMLSchema#string",
+ "must_be_present": false
+ },
+ "value": {
+ "kind": "primitive",
+ "type": "http://www.w3.org/2001/XMLSchema#string",
+ "value": "read"
+ }}],
+ [{ "function": "urn:oasis:names:tc:xacml:1.0:function:string-equal",
+ "designator": {
+ "identifier": "urn:oasis:names:tc:xacml:1.0:action:action-id",
+ "category": "urn:oasis:names:tc:xacml:3.0:attribute-category:action",
+ "type": "http://www.w3.org/2001/XMLSchema#string",
+ "must_be_present": false
+ },
+ "value": {
+ "kind": "primitive",
+ "type": "http://www.w3.org/2001/XMLSchema#string",
+ "value": "write"
+ }}]]],
+ "effect": "permit",
+ "obligations": [],
+ "advice": []
+}
+
+allow := evaluate_policyset_decision(IIA007_policy, [evaluate_rule_decision(IIA007_rule)])
diff --git a/benchmarks/rego/iia1.json b/benchmarks/rego/iia1.json
new file mode 100644
index 0000000..660d7c1
--- /dev/null
+++ b/benchmarks/rego/iia1.json
@@ -0,0 +1 @@
+{"request": [{"category":"urn:oasis:names:tc:xacml:1.0:subject-category:access-subject","identifier":"urn:oasis:names:tc:xacml:1.0:subject:subject-id","value":{"kind":"primitive","type":"http://www.w3.org/2001/XMLSchema#string","value":"Julius Hibbert"}},{"category":"urn:oasis:names:tc:xacml:3.0:attribute-category:resource","identifier":"urn:oasis:names:tc:xacml:1.0:resource:resource-id","value":{"kind":"primitive","type":"http://www.w3.org/2001/XMLSchema#anyURI","value":"http://medico.com/record/patient/BartSimpson"}},{"category":"urn:oasis:names:tc:xacml:3.0:attribute-category:action","identifier":"urn:oasis:names:tc:xacml:1.0:action:action-id","value":{"kind":"primitive","type":"http://www.w3.org/2001/XMLSchema#string","value":"read"}}]}
diff --git a/benchmarks/rego/iia1.rego b/benchmarks/rego/iia1.rego
new file mode 100644
index 0000000..f7c2a04
--- /dev/null
+++ b/benchmarks/rego/iia1.rego
@@ -0,0 +1,815 @@
+package equivalence
+
+import future.keywords.every
+import future.keywords.if
+import future.keywords.in
+
+########################################################################
+# Data Types
+########################################################################
+
+## MatchResult
+
+# - is_match => { "match_result": true }
+# - no_match => { "match_result": false }
+# - indeterminate => { "match_result": "indeterminate" }
+
+## Decision
+
+# - permit => { "decision": "permit" }
+# - deny => { "decision": "deny" }
+# - not_applicable => { "decision": "not_applicable" }
+# - indeterminate => { "decision": "indeterminate" }
+
+## Extended Decision
+
+# - permit => { "decision_extended": "permit" }
+# - deny => { "decision_extended": "deny" }
+# - not_applicable => { "decision_extended": "not_applicable" }
+# - indeterminate => { "decision_extended": "indeterminate" }
+# - indeterminate_d => { "decision_extended": "indeterminate_d" }
+# - indeterminate_p => { "decision_extended": "indeterminate_p" }
+# - indeterminate_dp => { "decision_extended": "indeterminate_dp" }
+
+lift_decision_indeterminate({ "decision": "not_applicable" }) := { "decision": "not_applicable" }
+lift_decision_indeterminate({ "decision": "permit" }) := { "decision": "indeterminate_p" }
+lift_decision_indeterminate({ "decision": "deny" }) := { "decision": "indeterminate_d" }
+lift_decision_indeterminate({ "decision": "indeterminate" }) := { "decision": "indeterminate_dp" }
+lift_decision_indeterminate({ "decision": "indeterminate_dp" }) := { "decision": "indeterminate_dp" }
+lift_decision_indeterminate({ "decision": "indeterminate_p" }) := { "decision": "indeterminate_p" }
+lift_decision_indeterminate({ "decision": "indeterminate_d" }) := { "decision": "indeterminate_d" }
+
+## Value
+
+# - { "kind": "primitive",
+# "type": string,
+# "value": string }
+# - { "kind": "bag",
+# "values": ... }
+
+### Booleans
+
+true_value := { "kind": "primitive", "type": "boolean", "value": true }
+false_value := { "kind": "primitive", "type": "boolean", "value": false }
+indeterminate_value := { "kind": "primitive", "type": "boolean" }
+
+is_indeterminate(value) if { is_null(value.value) }
+
+## StatusCode
+
+# - ok => { "status": "ok" }
+# - missing_attribute => { "status": "missing_attribute" }
+# - syntax_error => { "status": "syntax_error" }
+# - processing_error => { "status": "processing_error" }
+
+## AttributeDesignator
+
+# - { category : string
+# identifier : string
+# type : string
+# issuer : string or null
+# must_be_present : boolean }
+
+## Expression
+
+# - { "expression": "apply",
+# "function": string,
+# "args": [string, ...] }
+# - { "expression": "attribute_designator",
+# "inner": AttributeDesignator }
+# - { "expression": "attribute_value",
+# "inner": Value }
+# - { "expression": "function"
+# "function": string }
+
+## Match
+
+# - { "function": string,
+# "designator": AttributeDesignator,
+# "value": Value }
+
+## Obligation
+
+# - { "assignments": [Attribute, ...],
+# "identifier": string }
+
+## ObligationExpression
+
+# - { "assignments": [AttributeAssignmentExpression, ...],
+# "identifier": string,
+# "fulfill_on": Decision }
+
+## Advice
+
+# - { "assignments": [Attribute, ...],
+# "identifier": string }
+
+## AdviceExpression
+
+# - { "assignments": [AttributeAssignmentExpression, ...],
+# "identifier": string,
+# "applies_to": Decision }
+
+## AttributeAssignmentExpression
+
+# - { "category": string,
+# "identifier": string,
+# "issuer": string or null,
+# "expression": Expression }
+
+## Target: [[[Expression, ...], ...], ...]
+
+## Rule
+
+# - { "target": Target,
+# "condition": Expression or null,
+# "effect": "permit" or "deny",
+# "obligations": [ObligationExpression, ...],
+# "advice": [AdviceExpression, ...] }
+
+## Policy
+
+# - { "combinator": string,
+# "target": Target,
+# "obligations": [ObligationExpression, ...],
+# "advice": [AdviceExpression, ...] }
+
+## PolicySet
+
+# - { "combinator": string,
+# "target": Target,
+# "obligations": [ObligationExpression, ...],
+# "advice": [AdviceExpression, ...] }
+
+# We assume the request attributes are stored in `input.request` as an array or set of
+#
+# { category : string
+# identifier : string
+# issuer : string or null
+# value : [Value, ...] }
+
+########################################################################
+# Match Functions
+########################################################################
+
+apply_xacml_function(
+ "urn:oasis:names:tc:xacml:1.0:function:string-equal",
+ [{ "kind": "primitive",
+ "type": "http://www.w3.org/2001/XMLSchema#string",
+ "value": a },
+ { "kind": "primitive",
+ "type": "http://www.w3.org/2001/XMLSchema#string",
+ "value": b }]) := true_value if {
+ a == b
+} else := false_value
+apply_xacml_function(
+ "urn:oasis:names:tc:xacml:1.0:function:anyURI-equal",
+ [{ "kind": "primitive",
+ "type": "http://www.w3.org/2001/XMLSchema#anyURI",
+ "value": a },
+ { "kind": "primitive",
+ "type": "http://www.w3.org/2001/XMLSchema#anyURI",
+ "value": b }]) := true_value if {
+ a == b
+} else := false_value
+
+########################################################################
+# AttributeDesignator
+########################################################################
+
+designator_matches(designator, attribute) if {
+ attribute.category == designator.category
+ attribute.identifier == designator.identifier
+ attribute.value.type == designator.type
+ not attribute.attr.issuer
+}
+
+designator_matches(designator, attribute) if {
+ attribute.category == designator.category
+ attribute.identifier == designator.identifier
+ attribute.value.type == designator.type
+ attribute.attr.issuer == designator.issuer
+}
+
+evaluate_designator(designator) := { "kind": "bag", "values": xs } if {
+ xs := [y.value | y := input.request[_]; designator_matches(designator, y)]
+ count(xs) > 1
+}
+
+evaluate_designator(designator) := xs[0] if {
+ xs := [y.value | y := input.request[_]; designator_matches(designator, y)]
+ count(xs) == 1
+}
+
+evaluate_designator(designator) := { "kind": "bag", "values": xs } if {
+ xs := [y.value | y := input.request[_]; designator_matches(designator, y)]
+ count(xs) == 0
+ not designator.must_be_present
+}
+
+evaluate_designator(designator) := { "status": "missing_attribute" } if {
+ xs := [y.value | y := input.request[_]; designator_matches(designator, y)]
+ count(xs) == 0
+ designator.must_be_present
+}
+
+#########################################################################
+# Match
+########################################################################
+
+evaluate_match(match) := { "match_result": true_value } if {
+ designator_result := evaluate_designator(match.designator)
+
+ # Designator evaluates without error.
+ designator_result
+
+ some x in designator_result.values
+ apply_xacml_function(match.function, [x, match.value]).value == true
+} else := { "match_result": true_value } if {
+ designator_result := evaluate_designator(match.designator)
+
+ # Designator evaluates without error.
+ designator_result
+
+ apply_xacml_function(match.function, [designator_result, match.value]).value == true
+} else := { "match_result": indeterminate_value } if {
+ designator_result := evaluate_designator(match.designator)
+
+ # Designator evaluates without error.
+ designator_result
+
+ some x in designator_result
+ is_indeterminate(apply_xacml_function(match.function, [x, match.value]))
+} else := { "match_result": false_value } if {
+ designator_result := evaluate_designator(match.designator)
+
+ # Designator evaluates without error.
+ designator_result
+} else := { "match_result": indeterminate_value }
+
+# Last case runs when evaluating the designator results in an error.
+
+evaluate_all_of(conj) := { "match_result": true_value } if {
+ every x in conj {
+ evaluate_match(x).match_result.value == true
+ }
+} else := { "match_result": "indeterminate" } if {
+ some x in conj
+ is_indeterminate(evaluate_match(x).match_result)
+} else := { "match_result": "no_match" }
+
+evaluate_any_of([]) := { "match_result": true_value }
+evaluate_any_of(disj) := { "match_result": true_value } if {
+ some x in disj
+ evaluate_all_of(x) == { "match_result": true_value }
+} else := { "match_result": "indeterminate" } if {
+ some x in disj
+ evaluate_all_of(x) == { "match_result": true_value }
+} else := { "match_result": "no_match" }
+
+
+########################################################################
+# Target
+########################################################################
+
+evaluate_target([]) := { "match_result": true_value }
+evaluate_target(xs) := { "match_result": true_value } if {
+ every disj in xs {
+ evaluate_any_of(disj).match_result.value == true
+ }
+} else := { "match_result": false_value } if {
+ some disj in xs
+ evaluate_any_of(disj).match_result.value == false
+} else := { "match_result": indeterminate_value }
+
+########################################################################
+# Expression
+########################################################################
+
+evaluate_expression({ "expression": "apply", "function": function_name, "args": args }) := x if {
+ x := apply_xacml_function(function_name, args)
+}
+evaluate_expression({ "expression": "attribute_designator", "inner": designator }) := x if {
+ x := evaluate_designator(designator)
+}
+evaluate_expression({ "expression": "attribute_value", "inner": value }) := x if {
+ x := value
+}
+evaluate_expression({ "expression": "function", "function": name }) := x if {
+ x := name
+}
+
+########################################################################
+# Obligations and Advice
+########################################################################
+
+evaluate_attribute_assignment_expression(expr) := assignment {
+ { "kind": "primitive", "value": inner } = evaluate_expression(expr.expression)
+ assignment := { "category": expr.category,
+ "identifier": expr.identifier,
+ "issuer": expr.issuer,
+ "value": inner }
+}
+
+evaluate_obligation_expression(obligation_expression) := obligation {
+ assignments := [evaluate_attribute_assignment_expression(expr) | expr := obligation_expression.assignments[_]]
+ obligation := { "assignments": assignments, "identifier": obligation_expression.identifier }
+}
+
+evaluate_advice_expression(advice_expression) := advice {
+ assignments := [evaluate_attribute_assignment_expression(expr) | expr := advice_expression.assignments[_]]
+ advice := { "assignments": assignments, "identifier": advice_expression.identifier }
+}
+
+
+########################################################################
+# Rule
+########################################################################
+
+# Condition is specified and applicable
+evaluate_rule_decision(rule) := { "decision_extended": decision } {
+ evaluate_target(rule.target).match_result.value == true
+
+ is_object(rule.condition)
+ evaluate_expression(rule.condition) == true
+
+ decision := rule.effect
+}
+# Condition is specified and not applicable
+evaluate_rule_decision(rule) := { "decision_extended": "not_applicable" } {
+ evaluate_target(rule.target).match_result.value == true
+ evaluate_expression(rule.condition) == false
+}
+# Condition is indeterminate
+evaluate_rule_decision(rule) := { "decision_extended": "indeterminate_p" } {
+ evaluate_target(rule.target).match_result.value == true
+ condition := evaluate_expression(rule.condition)
+ is_null(condition)
+ rule.effect == "permit"
+}
+evaluate_rule_decision(rule) := { "decision_extended": "indeterminate_d" } {
+ evaluate_target(rule.target).match_result.value == true
+ condition := evaluate_expression(rule.condition)
+ is_null(condition)
+ rule.effect == "deny"
+}
+# Condition is unspecified
+evaluate_rule_decision(rule) := { "decision_extended": decision } {
+ evaluate_target(rule.target).match_result.value == true
+ decision := rule.effect
+}
+
+evaluate_rule_decision(rule) := { "decision_extended": "not_applicable" } {
+ evaluate_target(rule.target).match_result.value == false
+}
+evaluate_rule_decision(rule) := { "decision_extended": "indeterminate_p" } {
+ is_indeterminate(evaluate_target(rule.target))
+ rule.effect == "permit"
+}
+evaluate_rule_decision(rule) := { "decision_extended": "indeterminate_d" } {
+ is_indeterminate(evaluate_target(rule.target))
+ rule.effect == "permit"
+}
+
+evaluate_rule_advices(rule) := { "advice": advice } if {
+ decision := evaluate_rule_decision(rule)
+ advice := [expr | expr := rule.advice[_]; expr.applies_to == decision ]
+}
+
+evaluate_rule_obligations(rule) := { "obligations": obligations } if {
+ decision := evaluate_rule_decision(rule)
+ obligations := [expr | expr := rule.obligations[_]; expr.fulfill_on == decision ]
+}
+
+########################################################################
+# Policy
+########################################################################
+
+evaluate_rule_combinator("deny_overrides", results) := { "decision_extended": "deny" } if {
+ some result in results
+ result.decision_extended == "deny"
+} else := { "decision_extended": "indeterminate_dp" } if {
+ some result in results
+ result.decision_extended == "indeterminate_dp"
+} else := { "decision_extended": "indeterminate_dp" } if {
+ some result1 in results
+ some result2 in results
+ result1.decision_extended == "indeterminate_d"
+ result1.decision_extended == "indeterminate_p"
+} else := { "decision_extended": "indeterminate_d" } if {
+ some result in results
+ result.decision_extended == "indeterminate_d"
+} else := { "decision_extended": "permit" } if {
+ some result in results
+ result.decision_extended == "permit"
+} else := { "decision_extended": "indeterminate_p" } if {
+ some result in results
+ result.decision_extended == "indeterminate_p"
+} else := { "decision_extended": "not_applicable" }
+
+evaluate_rule_combinator("ordered_deny_overrides", results) := { "decision_extended": "deny" } if {
+ some result in results
+ result.decision_extended == "deny"
+} else := { "decision_extended": "indeterminate_dp" } if {
+ some result in results
+ result.decision_extended == "indeterminate_dp"
+} else := { "decision_extended": "indeterminate_dp" } if {
+ some result1 in results
+ some result2 in results
+ result1.decision_extended == "indeterminate_d"
+ result1.decision_extended == "indeterminate_p"
+} else := { "decision_extended": "indeterminate_d" } if {
+ some result in results
+ result.decision_extended == "indeterminate_d"
+} else := { "decision_extended": "permit" } if {
+ some result in results
+ result.decision_extended == "permit"
+} else := { "decision_extended": "indeterminate_p" } if {
+ some result in results
+ result.decision_extended == "indeterminate_p"
+} else := { "decision_extended": "not_applicable" }
+
+evaluate_rule_combinator("permit_overrides", results) := { "decision_extended": "permit" } if {
+ some result in results
+ result.decision_extended == "permit"
+} else := { "decision_extended": "indeterminate_dp" } if {
+ some result in results
+ result.decision_extended == "indeterminate_dp"
+} else := { "decision_extended": "indeterminate_dp" } if {
+ some result1 in results
+ some result2 in results
+ result1.decision_extended == "indeterminate_d"
+ result1.decision_extended == "indeterminate_p"
+} else := { "decision_extended": "indeterminate_p" } if {
+ some result in results
+ result.decision_extended == "indeterminate_p"
+} else := { "decision_extended": "deny" } if {
+ some result in results
+ result.decision_extended == "deny"
+} else := { "decision_extended": "indeterminate_d" } if {
+ some result in results
+ result.decision_extended == "indeterminate_d"
+} else := { "decision_extended": "not_applicable" }
+
+evaluate_rule_combinator("ordered_permit_overrides", results) := { "decision_extended": "permit" } if {
+ some result in results
+ result.decision_extended == "permit"
+} else := { "decision_extended": "indeterminate_dp" } if {
+ some result in results
+ result.decision_extended == "indeterminate_dp"
+} else := { "decision_extended": "indeterminate_dp" } if {
+ some result1 in results
+ some result2 in results
+ result1.decision_extended == "indeterminate_d"
+ result1.decision_extended == "indeterminate_p"
+} else := { "decision_extended": "indeterminate_p" } if {
+ some result in results
+ result.decision_extended == "indeterminate_p"
+} else := { "decision_extended": "deny" } if {
+ some result in results
+ result.decision_extended == "deny"
+} else := { "decision_extended": "indeterminate_d" } if {
+ some result in results
+ result.decision_extended == "indeterminate_d"
+} else := { "decision_extended": "not_applicable" }
+
+evaluate_rule_combinator("deny_unless_permit", results) := { "decision_extended": "permit" } if {
+ some result in results
+ result.decision_extended == "permit"
+} else := { "decision_extended": "deny" }
+
+evaluate_rule_combinator("permit_unless_deny", results) := { "decision_extended": "deny" } if {
+ some result in results
+ result.decision_extended == "deny"
+} else := { "decision_extended": "permit" }
+
+evaluate_rule_combinator("first_applicable", results) := result if {
+ indices := [i | results[i].decision_extended != "not_applicable"]
+ count(indices) > 0
+ result := results[max(indices)]
+ result.decision_extended == "deny"
+} else := { "decision_extended": "not_applicable" }
+
+evaluate_rule_combinator("legacy_deny_overrides", results) := { "decision_extended": "deny" } if {
+ some result in results
+ result.decision_extended == "deny"
+} else := { "decision_extended": "indeterminate" } if {
+ some result in results
+ result.decision_extended == "indeterminate_d"
+} else := { "decision_extended": "permit" } if {
+ some result in results
+ result.decision_extended == "permit"
+} else := { "decision_extended": "indeterminate" } if {
+ some result in results
+ result.decision_extended == "indeterminate_p"
+} else := { "decision_extended": "not_applicable" }
+
+evaluate_rule_combinator("ordered_legacy_deny_overrides", results) := { "decision_extended": "deny" } if {
+ some result in results
+ result.decision_extended == "deny"
+} else := { "decision_extended": "indeterminate" } if {
+ some result in results
+ result.decision_extended == "indeterminate_d"
+} else := { "decision_extended": "permit" } if {
+ some result in results
+ result.decision_extended == "permit"
+} else := { "decision_extended": "indeterminate" } if {
+ some result in results
+ result.decision_extended == "indeterminate_p"
+} else := { "decision_extended": "not_applicable" }
+
+evaluate_rule_combinator("legacy_permit_overrides", results) := { "decision_extended": "permit" } if {
+ some result in results
+ result.decision_extended == "permit"
+} else := { "decision_extended": "indeterminate" } if {
+ some result in results
+ result.decision_extended == "indeterminate_p"
+} else := { "decision_extended": "deny" } if {
+ some result in results
+ result.decision_extended == "deny"
+} else := { "decision_extended": "indeterminate" } if {
+ some result in results
+ result.decision_extended == "indeterminate_d"
+} else := { "decision_extended": "not_applicable" }
+
+evaluate_rule_combinator("ordered_legacy_permit_overrides", results) := { "decision_extended": "permit" } if {
+ some result in results
+ result.decision_extended == "permit"
+} else := { "decision_extended": "indeterminate" } if {
+ some result in results
+ result.decision_extended == "indeterminate_p"
+} else := { "decision_extended": "deny" } if {
+ some result in results
+ result.decision_extended == "deny"
+} else := { "decision_extended": "indeterminate" } if {
+ some result in results
+ result.decision_extended == "indeterminate_d"
+} else := { "decision_extended": "not_applicable" }
+
+# child_results := [result | rule := policy.rules[_]; result := evaluate_rule_decision(rule)]
+evaluate_policy_decision(policy, child_results) := decision if {
+ evaluate_target(policy.target).match_result.value == true
+ decision := evaluate_rule_combinator(policy.combinator, child_results)
+} else := decision if {
+ is_indeterminate(evaluate_target(policy.target))
+ decision := lift_decision_indeterminate(evaluate_rule_combinator(policy.combinator, child_results))
+} else := { "decision_extended": "not_applicable" }
+
+# children_advice := [advice | rule := policy.rules[_]; expr := evaluate_rule_advices(rule); advice := expr[_]]
+evaluate_policy_advices(policy, child_results, children_advice) := { "advice" : advice } if {
+ decision := evaluate_policy_decision(policy, child_results)
+ policy_advice := [expr | expr := policy.advice[_]; expr.applies_to == decision ]
+ advice := array.concat(policy_advice, children_advice)
+}
+
+# children_obligations := [obligation | rule := policy.rules[_]; expr := evaluate_rule_obligations(rule); obligation := expr[_]]
+evaluate_policy_obligations(policy, child_results, children_obligations) := { "obligations" : obligations } if {
+ decision := evaluate_policy_decision(policy, child_results)
+ policy_obligations := [expr | expr := policy.obligations[_]; expr.applies_to == decision ]
+ obligations := array.concat(policy_obligations, children_obligations)
+}
+
+########################################################################
+# PolicySet
+########################################################################
+
+evaluate_policy_combinator("deny_overrides", results) := { "decision_extended": "deny" } if {
+ some result in results
+ result.decision_extended == "deny"
+} else := { "decision_extended": "indeterminate_dp" } if {
+ some result in results
+ result.decision_extended == "indeterminate_dp"
+} else := { "decision_extended": "indeterminate_dp" } if {
+ some result1 in results
+ some result2 in results
+ result1.decision_extended == "indeterminate_d"
+ result1.decision_extended == "indeterminate_p"
+} else := { "decision_extended": "indeterminate_d" } if {
+ some result in results
+ result.decision_extended == "indeterminate_d"
+} else := { "decision_extended": "permit" } if {
+ some result in results
+ result.decision_extended == "permit"
+} else := { "decision_extended": "indeterminate_p" } if {
+ some result in results
+ result.decision_extended == "indeterminate_p"
+} else := { "decision_extended": "not_applicable" }
+
+evaluate_policy_combinator("ordered_deny_overrides", results) := { "decision_extended": "deny" } if {
+ some result in results
+ result.decision_extended == "deny"
+} else := { "decision_extended": "indeterminate_dp" } if {
+ some result in results
+ result.decision_extended == "indeterminate_dp"
+} else := { "decision_extended": "indeterminate_dp" } if {
+ some result1 in results
+ some result2 in results
+ result1.decision_extended == "indeterminate_d"
+ result1.decision_extended == "indeterminate_p"
+} else := { "decision_extended": "indeterminate_d" } if {
+ some result in results
+ result.decision_extended == "indeterminate_d"
+} else := { "decision_extended": "permit" } if {
+ some result in results
+ result.decision_extended == "permit"
+} else := { "decision_extended": "indeterminate_p" } if {
+ some result in results
+ result.decision_extended == "indeterminate_p"
+} else := { "decision_extended": "not_applicable" }
+
+evaluate_policy_combinator("permit_overrides", results) := { "decision_extended": "permit" } if {
+ some result in results
+ result.decision_extended == "permit"
+} else := { "decision_extended": "indeterminate_dp" } if {
+ some result in results
+ result.decision_extended == "indeterminate_dp"
+} else := { "decision_extended": "indeterminate_dp" } if {
+ some result1 in results
+ some result2 in results
+ result1.decision_extended == "indeterminate_d"
+ result1.decision_extended == "indeterminate_p"
+} else := { "decision_extended": "indeterminate_p" } if {
+ some result in results
+ result.decision_extended == "indeterminate_p"
+} else := { "decision_extended": "deny" } if {
+ some result in results
+ result.decision_extended == "deny"
+} else := { "decision_extended": "indeterminate_d" } if {
+ some result in results
+ result.decision_extended == "indeterminate_d"
+} else := { "decision_extended": "not_applicable" }
+
+evaluate_policy_combinator("ordered_permit_overrides", results) := { "decision_extended": "permit" } if {
+ some result in results
+ result.decision_extended == "permit"
+} else := { "decision_extended": "indeterminate_dp" } if {
+ some result in results
+ result.decision_extended == "indeterminate_dp"
+} else := { "decision_extended": "indeterminate_dp" } if {
+ some result1 in results
+ some result2 in results
+ result1.decision_extended == "indeterminate_d"
+ result1.decision_extended == "indeterminate_p"
+} else := { "decision_extended": "indeterminate_p" } if {
+ some result in results
+ result.decision_extended == "indeterminate_p"
+} else := { "decision_extended": "deny" } if {
+ some result in results
+ result.decision_extended == "deny"
+} else := { "decision_extended": "indeterminate_d" } if {
+ some result in results
+ result.decision_extended == "indeterminate_d"
+} else := { "decision_extended": "not_applicable" }
+
+evaluate_policy_combinator("deny_unless_permit", results) := { "decision_extended": "permit" } if {
+ some result in results
+ result.decision_extended == "permit"
+} else := { "decision_extended": "deny" }
+
+evaluate_policy_combinator("permit_unless_deny", results) := { "decision_extended": "deny" } if {
+ some result in results
+ result.decision_extended == "deny"
+} else := { "decision_extended": "permit" }
+
+evaluate_policy_combinator("first_applicable", results) := result if {
+ indices := [i | results[i].decision_extended != "not_applicable"]
+ count(indices) > 0
+ result := results[max(indices)]
+ result.decision_extended == "deny"
+} else := { "decision_extended": "not_applicable" }
+
+evaluate_policy_combinator("only_one_applicable", results) := result if {
+ applicable := [result | result := results[i]; result.decision_extended != "not_applicable"]
+ count(applicable) == 1
+ result := applicable[0]
+} else := { "decision_extended": "not_applicable" }
+
+evaluate_policy_combinator("legacy_deny_overrides", results) := { "decision_extended": "deny" } if {
+ some result in results
+ result.decision_extended == "deny"
+} else := { "decision_extended": "deny" } if {
+ some result in results
+ result.decision_extended == "indeterminate"
+} else := { "decision_extended": "permit" } if {
+ some result in results
+ result.decision_extended == "permit"
+} else := { "decision_extended": "not_applicable" }
+
+evaluate_policy_combinator("ordered_legacy_deny_overrides", results) := { "decision_extended": "deny" } if {
+ some result in results
+ result.decision_extended == "deny"
+} else := { "decision_extended": "deny" } if {
+ some result in results
+ result.decision_extended == "indeterminate"
+} else := { "decision_extended": "permit" } if {
+ some result in results
+ result.decision_extended == "permit"
+} else := { "decision_extended": "not_applicable" }
+
+evaluate_policy_combinator("legacy_permit_overrides", results) := { "decision_extended": "permit" } if {
+ some result in results
+ result.decision_extended == "permit"
+} else := { "decision_extended": "deny" } if {
+ some result in results
+ result.decision_extended == "deny"
+} else := { "decision_extended": "indeterminate" } if {
+ some result in results
+ result.decision_extended == "indeterminate"
+} else := { "decision_extended": "not_applicable" }
+
+evaluate_policy_combinator("ordered_legacy_permit_overrides", results) := { "decision_extended": "permit" } if {
+ some result in results
+ result.decision_extended == "permit"
+} else := { "decision_extended": "indeterminate" } if {
+ some result in results
+ result.decision_extended == "indeterminate_p"
+} else := { "decision_extended": "deny" } if {
+ some result in results
+ result.decision_extended == "deny"
+} else := { "decision_extended": "indeterminate" } if {
+ some result in results
+ result.decision_extended == "indeterminate_d"
+} else := { "decision_extended": "not_applicable" }
+
+evaluate_policyset_decision(policyset, child_results) := decision if {
+ evaluate_target(policyset.target).match_result.value == true
+ decision := evaluate_policy_combinator(policyset.combinator, child_results)
+} else := decision if {
+ is_indeterminate(evaluate_target(policyset.target))
+ decision := lift_decision_indeterminate(evaluate_policy_combinator(policyset.combinator, child_results))
+} else := { "decision_extended": "not_applicable" }
+
+evaluate_policyset_advices(policyset, child_results, child_advice) := { "advice" : advice } if {
+ decision := evaluate_policyset_decision(policyset, child_results)
+ policyset_advice := [expr | expr := policyset.advice[_]; expr.applies_to == decision ]
+ advice := array.concat(policyset_advice, child_advice)
+}
+
+evaluate_policyset_obligations(policyset, child_results, child_obligations) := { "obligations" : obligations } if {
+ decision := evaluate_policyset_decision(policyset, child_results)
+ policyset_obligations := [expr | expr := policyset.obligations[_]; expr.applies_to == decision ]
+ obligations := array.concat(policyset_obligations, child_obligations)
+}
+
+IIA1_policy := {
+ "combinator": "deny_overrides",
+ "target": [],
+ "obligations": [],
+ "advice": []
+}
+
+IIA1_rule := {
+ "target": [[[{ "function": "urn:oasis:names:tc:xacml:1.0:function:string-equal",
+ "designator": {
+ "identifier": "urn:oasis:names:tc:xacml:1.0:subject:subject-id",
+ "category": "urn:oasis:names:tc:xacml:1.0:subject-category:access-subject",
+ "type": "http://www.w3.org/2001/XMLSchema#string",
+ "must_be_present": false
+ },
+ "value": {
+ "kind": "primitive",
+ "type": "http://www.w3.org/2001/XMLSchema#string",
+ "value": "Julius Hibbert"
+ }}]],
+ [[{ "function": "urn:oasis:names:tc:xacml:1.0:function:anyURI-equal",
+ "designator": {
+ "identifier": "urn:oasis:names:tc:xacml:1.0:resource:resource-id",
+ "category": "urn:oasis:names:tc:xacml:3.0:attribute-category:resource",
+ "type": "http://www.w3.org/2001/XMLSchema#anyURI",
+ "must_be_present": false
+ },
+ "value": {
+ "kind": "primitive",
+ "type": "http://www.w3.org/2001/XMLSchema#anyURI",
+ "value": "http://medico.com/record/patient/BartSimpson"
+ }}]],
+ [[{ "function": "urn:oasis:names:tc:xacml:1.0:function:string-equal",
+ "designator": {
+ "identifier": "urn:oasis:names:tc:xacml:1.0:action:action-id",
+ "category": "urn:oasis:names:tc:xacml:3.0:attribute-category:action",
+ "type": "http://www.w3.org/2001/XMLSchema#string",
+ "must_be_present": false
+ },
+ "value": {
+ "kind": "primitive",
+ "type": "http://www.w3.org/2001/XMLSchema#string",
+ "value": "read"
+ }}],
+ [{ "function": "urn:oasis:names:tc:xacml:1.0:function:string-equal",
+ "designator": {
+ "identifier": "urn:oasis:names:tc:xacml:1.0:action:action-id",
+ "category": "urn:oasis:names:tc:xacml:3.0:attribute-category:action",
+ "type": "http://www.w3.org/2001/XMLSchema#string",
+ "must_be_present": false
+ },
+ "value": {
+ "kind": "primitive",
+ "type": "http://www.w3.org/2001/XMLSchema#string",
+ "value": "write"
+ }}]]],
+ "effect": "permit",
+ "obligations": [],
+ "advice": []
+}
+
+allow := evaluate_policyset_decision(IIA1_policy, [evaluate_rule_decision(IIA1_rule)])

© 2015 - 2026 Jakob L. Kreuze