section‹The Core of the Unified Policy Framework (UPF)› theory
UPFCore imports
Monads begin
subsection‹Foundation› text‹
The purpose of this theory is to formalize a somewhat non-standard view
on the fundamental concept of a security policy which is worth outlining.
This view has arisen from prior experience in the modelling of network
(firewall) policies. Instead of regarding policies as relations on resources,
sets of permissions, etc., we emphasise the view that a policy is a policy
decision function that grants or denies access to resources, permissions, etc.
In other words, we model the concrete function that implements the policy
decision point in a system, and which represents a "wrapper" around the
business logic. An advantage of this view is that it is compatible
with many different policy models, enabling a uniform modelling framework to be
defined. Furthermore, this function is typically a large cascade of nested
conditionals, using conditions referring to an internal state and security
contexts of the system or a user. This cascade of conditionals can easily be
decomposed into a set of test cases similar to transformations used for binary
decision diagrams (BDD), and motivate equivalence class testing for unit test and
sequence test scenarios. From the modelling perspective, using \HOL as
its input language, we will consequently use the expressive power of its
underlying functional programming language, including the possibility to
define higher-order combinators.
In more detail, we model policies as partial functions based on input
data $\alpha$ (arguments, system state, security context, ...) to output
data $\beta$: ›
text‹... allowing the notation @{typ "'α ↦ 'β"} for the policy type and the
notations for @{term None} and @{term Some} of the \HOL library
{typ "'α option"} type:›
notation"None" (‹⊥›) notation"Some" (‹⌊_⌋›80)
text‹Thus, the range of a policy may consist of @{term "⌊accept x⌋"} data,
of @{term "⌊deny x⌋"} data, as well as @{term "⊥"} modeling the undefinedness
of a policy, i.e. a policy is considered as a partial function. Partial
functions are used since we describe elementary policies by partial system
behaviour, which are glued together by operators such as function override and
functional composition. ›
text‹We define the two fundamental sets, the allow-set $Allow$ and the
deny-set $Deny$ (written $A$ and $D$ set for short), to characterize these
two main sets of the range of a policy. › definition Allow :: "('α decision) set" where"Allow = range allow"
definition Deny :: "('α decision) set" where"Deny = range deny"
subsection‹Policy Constructors› text‹
Most elementary policy constructors are based on the
update operation @{thm [source] "Fun.fun_upd_def"} @{thm Fun.fun_upd_def}
and the maplet-notation @{term "a(x ↦ y)"} used for @{term "a(x:=⌊y⌋)"}.
Furthermore, we add notation adopted to our problem domain:›
syntax_consts "_policylet1"⇌ allow and "_policylet2"⇌ deny and "_Maplets""_MapUpd"⇌ fun_upd and "_emptypolicy"⇌ Map.empty translations "_MapUpd m (_Maplets xy ms)"⇌"_MapUpd (_MapUpd m xy) ms" "_MapUpd m (_policylet1 x y)"⇌"m(x := CONST Some (CONST allow y))" "_MapUpd m (_policylet2 x y)"⇌"m(x := CONST Some (CONST deny y))" "∅"⇌"CONST Map.empty"
text‹Here are some lemmas essentially showing syntactic equivalences:› lemma test: "∅(x↦+a, y↦-b) = ∅(x ↦+ a, y ↦- b)"by simp
lemma test2: "p(x↦+a,x↦-b) = p(x↦-b)"by simp
text‹
We inherit a fairly rich theory on policy updates from Map here. Some examples are: ›
lemma pol_upd_triv1: "t k = ⌊allow x⌋==> t(k↦+x) = t" by (rule ext) simp
lemma pol_upd_triv2: "t k = ⌊deny x⌋==> t(k↦-x) = t" by (rule ext) simp
lemma pol_upd_allow_nonempty: "t(k↦+x) ≠∅" by simp
subsection‹Override Operators› text‹
Key operators for constructing policies are the override operators. There are four different
versions of them, with one of them being the override operator from the Map theory. As it is
common to compose policy rules in a ``left-to-right-first-fit''-manner, that one is taken as
default, defined by a syntax translation from the provided override operator from the Map
theory (which does it in reverse order). ›
text‹
The following two operators are variants of the standard override. For override\_A,
an allow of wins over a deny. For override\_D, the situation is dual. ›
definition override_A :: "['α↦'β, 'α↦'β] ==> 'α↦'β" (infixl‹++'_A›100) where"m2 ++_A m1 = (λx. (case m1 x of ⌊allow a⌋==>⌊allow a⌋ | ⌊deny a⌋==> (case m2 x of ⌊allow b⌋==>⌊allow b⌋ | _ ==>⌊deny a⌋) | ⊥==> m2 x) )"
lemma empty_override_D[simp]: "∅⨁D p = p" apply (rule ext) apply (simp add:override_D_def)
subgoal for x apply (case_tac "p x", simp_all)
subgoal for a apply (case_tac a, simp_all) done done done
subsection‹Coercion Operators› text‹
Often, especially when combining policies of different type, it is necessary to
adapt the input or output domain of a policy to a more refined context. ›
text‹
An analogous for the range of a policy is defined as follows: ›
definition policy_range_comp :: "['β==>'γ, 'α↦'β] ==> 'α ↦'γ" (infixl‹o'_f›55) where "f o_f p = (λx. case p x of ⌊allow y⌋==>⌊allow (f y)⌋ | ⌊deny y⌋==>⌊deny (f y)⌋ | ⊥==>⊥)"
lemma range_split_charn: "(f,g) ∇ p = (λx. case p x of ⌊allow x⌋==>⌊allow (f x)⌋ | ⌊deny x⌋==>⌊deny (g x)⌋ | ⊥==>⊥)" apply (simp add: range_split_def) apply (rule ext)
subgoal for x apply (case_tac "p x") apply (simp_all)
subgoal for a apply (case_tac "a") apply (simp_all) done done done
text‹
The connection between these two becomes apparent if considering the following lemma: ›
lemma range_split_vs_range_compose: "(f,f) ∇ p = f of p" by(simp add: range_split_charn policy_range_comp_def)
lemma range_split_id [simp]: "(id,id) ∇ p = p" apply (rule ext) apply (simp add: range_split_charn id_def)
subgoal for x apply (case_tac "p x") apply (simp_all)
subgoal for a apply (case_tac "a") apply (simp_all) done done done
lemma range_split_bi_compose [simp]: "(f1,f2) ∇ (g1,g2) ∇ p = (f1 o g1,f2 o g2) ∇ p" apply (rule ext) apply (simp add: range_split_charn comp_def)
subgoal for x apply (case_tac "p x") apply (simp_all)
subgoal for a apply (case_tac "a") apply (simp_all) done done done
text‹
The next three operators are rather exotic and in most cases not used. ›
text‹
The following is a variant of range\_split, where the change in the decision depends
on the input instead of the output. ›
definition dom_split2a :: "[('α ⇀ 'γ) × ('α ⇀'γ),'α ↦ 'β] ==> 'α ↦ 'γ" (infixr‹Δa›100) where"P Δa p = (λx. case p x of ⌊allow y⌋==>⌊allow (the ((fst P) x))⌋ | ⌊deny y⌋==>⌊deny (the ((snd P) x))⌋ | ⊥==>⊥)"
definition dom_split2 :: "[('α ==> 'γ) × ('α ==>'γ),'α ↦ 'β] ==> 'α ↦ 'γ" (infixr‹Δ›100) where"P Δ p = (λx. case p x of ⌊allow y⌋==>⌊allow ((fst P) x)⌋ | ⌊deny y⌋==>⌊deny ((snd P) x)⌋ | ⊥==>⊥)"
definition range_split2 :: "[('α ==> 'γ) × ('α ==>'γ),'α ↦ 'β] ==> 'α ↦ ('β ×'γ)" (infixr‹∇2›100) where"P ∇2 p = (λx. case p x of ⌊allow y⌋==>⌊allow (y,(fst P) x)⌋ | ⌊deny y⌋==>⌊deny (y,(snd P) x)⌋ | ⊥==>⊥)"
text‹
The following operator is used for transition policies only: a transition policy is transformed
into a state-exception monad. Such a monad can for example be used for test case generation using
HOL-Testgen~cite‹"brucker.ea:theorem-prover:2012"›. ›
definition policy2MON :: "('ι×'σ ↦ 'o×'σ) ==> ('ι ==>('o decision,'σ) MONSE)" where"policy2MON p = (λ ι σ. case p (ι,σ) of ⌊(allow (outs,σ'))⌋==>⌊(allow outs, σ')⌋ | ⌊(deny (outs,σ'))⌋==>⌊(deny outs, σ')⌋ | ⊥==>⊥)"
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.