aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakob L. Kreuze2023-09-07 16:37:58 -0400
committerJakob L. Kreuze2023-09-12 18:45:54 -0400
commitcf431b44c044afa568aa7da6cebd39d83e63a805 (patch)
tree204c490a159f27dd5992c2254e6c8a1891a1c40f
parent558e85458b6825129aee68b51894937a55cfcc03 (diff)
Troll through syntax once more
-rw-r--r--xacml-proofs/lean/Xacml.lean233
-rw-r--r--xacml-proofs/modeling-choices.org34
2 files changed, 216 insertions, 51 deletions
diff --git a/xacml-proofs/lean/Xacml.lean b/xacml-proofs/lean/Xacml.lean
index 2801567..387b9a2 100644
--- a/xacml-proofs/lean/Xacml.lean
+++ b/xacml-proofs/lean/Xacml.lean
@@ -18,12 +18,47 @@ inductive Decision where
| permit : Decision
| deny : Decision
| indeterminate : Decision
- | indeterminate_d : Decision
- | indeterminate_p : Decision
- | indeterminate_dp : Decision
| not_applicable : Decision
deriving BEq, Repr
+inductive Decision' where
+ | permit : Decision'
+ | deny : Decision'
+ | indeterminate : Decision'
+ | indeterminate_d : Decision'
+ | indeterminate_p : Decision'
+ | indeterminate_dp : Decision'
+ | not_applicable : Decision'
+deriving BEq, Repr
+
+instance : Coe Decision' Decision where
+ coe b :=
+ match b with
+ | 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
+
+inductive EffectType where
+ | permit : EffectType
+ | deny : EffectType
+deriving 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 ------------------------------------------------------------
------------------------------------------------------------------------
@@ -128,6 +163,12 @@ deriving BEq, Repr
def FunctionID : Type := String
deriving 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."
+
inductive Expression where
| apply (function : FunctionID) (args: List Expression) : Expression
| attribute_designator (inner : AttributeDesignator) : Expression
@@ -147,40 +188,46 @@ deriving BEq, Repr
def Target : Type := List AnyOf
deriving BEq, Repr
-structure AttributeAssignmentExpression where
+structure AttributeAssignment where
category : String
identifier : String
issuer : Option String
- expression : Expression
deriving BEq, Repr
-structure ObligationExpression where
- assignments : List AttributeAssignmentExpression
+structure Obligation where
+ assignments : List AttributeAssignment
identifier : String
- fulfill_on : Decision
deriving BEq, Repr
-structure Obligation where
- assignments : List AttributeAssignmentExpression
+structure Advice where
+ assignments : List AttributeAssignment
identifier : String
deriving BEq, Repr
-structure AdviceExpression where
+structure AttributeAssignmentExpression where
+ category : String
+ identifier : String
+ issuer : Option String
+ expression : Expression
+deriving BEq, Repr
+
+structure ObligationExpression where
assignments : List AttributeAssignmentExpression
identifier : String
- applies_to : Decision
+ fulfill_on : Decision
deriving BEq, Repr
-structure Advice where
+structure AdviceExpression where
assignments : List AttributeAssignmentExpression
identifier : String
+ applies_to : Decision
deriving BEq, Repr
-- n.b. "The <Condition> contains one <Expression> element"
structure Rule where
target : Target
condition : Expression
- effect : Decision
+ effect : EffectType
obligations : List ObligationExpression
advice : List AdviceExpression
@@ -202,13 +249,79 @@ structure Policy where
obligations : List ObligationExpression
advice : List AdviceExpression
-structure ResponseAuxiliary where
- status : Option String
+inductive StatusCode
+ | ok : StatusCode
+ | missing_attribute : StatusCode
+ | syntax_error : StatusCode
+ | processing_error : StatusCode
+deriving BEq, Repr
+
+structure ResultAuxiliary where
+ status : Option (List StatusCode)
obligations : List Obligation
advice : List Advice
deriving BEq, Repr
-def Choice : Type := List (Decision × ResponseAuxiliary)
+structure MissingAttributeDetail where
+ category : String
+ identifier : String
+ issuer : Option String
+ value : Option Value
+ type : XmlType
+deriving BEq, Repr
+
+def Result : Type := Decision × (Option ResultAuxiliary)
+
+def is_indeterminate (x : Expression) : Bool :=
+ match x with
+ | Expression.attribute_value (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 status₂ obligations₂ advice₂) =>
+ ResultAuxiliary.mk
+ status₁
+ (obligations₁ ++ obligations₂)
+ (advice₁ ++ advice₂)
+
+def Choice : Type := List (Decision × ResultAuxiliary)
deriving BEq, Repr
---
@@ -234,7 +347,7 @@ def example_4_1_policy :=
] -- </AnyOf>
]
(Expression.attribute_value (#<XmlType.boolean, "True">))
- Decision.permit
+ EffectType.permit
[] []]
[] []
@@ -308,7 +421,7 @@ def example_4_2_policy_rule_1 :=
XmlType.string
Option.none
false)]])
- Decision.permit
+ EffectType.permit
[] []]
[] []
@@ -366,7 +479,7 @@ def example_4_2_policy_rule_2 :=
XmlType.string
Option.none
false)]])
- Decision.permit
+ EffectType.permit
[] []]
[] []
@@ -430,7 +543,7 @@ def example_4_2_policy_rule_3 :=
XmlType.string
Option.none
false)]])
- Decision.permit
+ EffectType.permit
[] []]
[] []
@@ -476,7 +589,7 @@ def example_4_2_policy_rule_4 :=
false)
(#<XmlType.string, "read">)]]]
(Expression.attribute_value (#<XmlType.boolean, "True">))
- Decision.deny
+ EffectType.deny
[] []]
[] []
@@ -624,29 +737,39 @@ def evaluate_target (target : Target) (context : Request) : MatchResult :=
let rest := evaluate_target xs context
if rest == MatchResult.no_match then rest else MatchResult.indeterminate
-def evaluate_rule (rule : Rule) (context : Request) : Decision × ResponseAuxiliary :=
+def evaluate_assignments (assignments : List AttributeAssignmentExpression) : List AttributeAssignment :=
+ assignments.map (fun assignment =>
+ match assignment with
+ | AttributeAssignmentExpression.mk category identifier issuer _ =>
+ AttributeAssignment.mk category identifier issuer)
+
+
+def evaluate_rule (rule : Rule) (context : Request) : Decision' × ResultAuxiliary :=
let decision :=
- if rule.target == [] then rule.effect
+ if rule.target == [] then (rule.effect).to_decision'
else match evaluate_target rule.target context with
| MatchResult.is_match =>
match (evaluate_expression rule.condition : Value) with
- | (XmlType.string, "True") => rule.effect
- | (XmlType.string, "False") => Decision.not_applicable
+ | (XmlType.string, "True") => (rule.effect).to_decision'
+ | (XmlType.string, "False") => Decision'.not_applicable
| (_, _) =>
- if rule.effect == Decision.permit then
- Decision.indeterminate_p else
- Decision.indeterminate_d
- | MatchResult.no_match => Decision.not_applicable
- | MatchResult.indeterminate => Decision.not_applicable
- let obligations := rule.obligations.filter (fun obl => obl.fulfill_on == decision)
- let advice := rule.advice.filter (fun obl => obl.applies_to == decision)
+ if (rule.effect).to_decision' == Decision'.permit then
+ Decision'.indeterminate_p else
+ Decision'.indeterminate_d
+ | MatchResult.no_match => Decision'.not_applicable
+ | MatchResult.indeterminate => Decision'.not_applicable
+ let obligations := rule.obligations.filter (fun obl => obl.fulfill_on == (decision : Decision))
+ let advice := rule.advice.filter (fun obl => obl.applies_to == (decision : Decision))
(
decision,
- ResponseAuxiliary.mk
+ ResultAuxiliary.mk
Option.none
- (obligations.map (fun expr => Obligation.mk expr.assignments expr.identifier))
- (advice.map (fun expr => Advice.mk expr.assignments expr.identifier))
- )
+ (obligations.map (fun expr => Obligation.mk
+ (evaluate_assignments expr.assignments)
+ expr.identifier))
+ (advice.map (fun expr => Advice.mk
+ (evaluate_assignments expr.assignments)
+ expr.identifier)))
-- theorem test :
-- ∀ (r : Rule) (c : Request),
@@ -665,18 +788,32 @@ def evaluate_rule (rule : Rule) (context : Request) : Decision × ResponseAuxili
-- simp [h_condition_eval] }
-- { simp }
+def evaluate_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 evaluate_policy (policy : Policy) (context : Request) : Choice :=
- match policy.rules with
- | [rule₁] => [evaluate_rule rule₁ context]
- | _ => []
+ let results := policy.rules.map (fun x => evaluate_rule x context)
+ let decision := evaluate_deny_overrides (results.map Prod.fst)
+ let obligations := policy.obligations.filter (fun obl => obl.fulfill_on == (decision : Decision))
+ let advice := policy.advice.filter (fun obl => obl.applies_to == (decision : Decision))
+ -- TODO: How do we combine advice/obligations?
+ [(
+ decision,
+ ResultAuxiliary.mk
+ Option.none
+ (obligations.map (fun expr => Obligation.mk
+ (evaluate_assignments expr.assignments)
+ expr.identifier))
+ (advice.map (fun expr => Advice.mk
+ (evaluate_assignments expr.assignments)
+ expr.identifier))
+ )]
-def evaluate_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
#eval evaluate_policy example_4_1_policy example_4_1_request
diff --git a/xacml-proofs/modeling-choices.org b/xacml-proofs/modeling-choices.org
index 80c2968..8d88c61 100644
--- a/xacml-proofs/modeling-choices.org
+++ b/xacml-proofs/modeling-choices.org
@@ -1,4 +1,17 @@
-* Not Relevant
+XACML makes use of URIs and strings as identifiers. When such identifiers are compared for equality, the comparison MUST be done so that the identifiers are equal if they have the same length and the characters in the two identifiers are equal codepoint by codepoint.
+
+(This is equivalent to string equality in Lean.)
+
+* Modeling Exceptions
+
+7.19 Exception handling specifies that an indeterminate decision is returned and a statuscode is set.
+ StatusCode is, however, optional.
+
+* In Scope vs Out of Scope
+
+"We would like to be as complete as possible, so as to ensure that this can be leveraged to prove a refinement of a policy down to the status codes, obligations, and advice it returns."
+
+** Not Relevant
- [ ] Element <Description> (no semantic meaning)
- [ ] Element <PolicyIssuer> (XMLAdmin)
@@ -26,7 +39,7 @@
- [ ] Element <VariableReference> (dissolved by compiler translation)
- [ ] Element <Content> (dissolved by compiler translation)
-* Modeled
+** Modeled
- [X] Element <PolicySet>
- [X] Element <Target>
@@ -65,7 +78,7 @@
- [ ] Element <StatusCode>
- [ ] Element <MissingAttributeDetail>
-* Doesn't Line Up with ACES
+** Doesn't Line Up with ACES
- Does use PolicySetDefaults and XPathVersion but it's just XPath 1.0. Probably safe to ignore and have our XPath implementation follow 1.0.
@@ -88,3 +101,18 @@ Same assumption about PolicySelector as logic paper.
- Assume Attribute->Issuer has no effect on access control decision
- TODO What about Attribute->IncludeInResult?
+
+* 7.3.3 Multivalued attributes
+
+If a single <Attribute> element in a request context contains multiple <AttributeValue> child elements, then the bag of values resulting from evaluation of the <Attribute> element MUST be identical to the bag of values that results from evaluating a context in which each <AttributeValue> element appears in a separate <Attribute> element, each carrying identical meta-data.
+
+This is handled by the compiler.
+
+* Variable Substitution
+
+Functions SHALL NOT have side effects, as evaluation order cannot be guaranteed in a standard way.
+
+* Compiler Versus Embedding Decisions
+
+Example: =<AllOf>= and =<AnyOf>= are specified to be nonempty.
+We could encode this in Lean's type system but it's more convenient to assume that an empty =AllOf= or =AnyOf= will never be constructed by the trusted compiler base.

© 2015 - 2026 Jakob L. Kreuze