section‹Secure Service Specification› theory
Service imports
UPF begin text‹
In this section, we model a simple Web service and its access control model
that allows the staff in a hospital to access health care records of patients. ›
subsection‹Datatypes for Modelling Users and Roles› subsubsection‹Users› text‹
First, we introduce a type for users that we use to model that each
staff member has a unique id: › type_synonym user = int (* Each NHS employee has a unique NHS_ID. *)
text‹
Similarly, each patient has a unique id: › type_synonym patient = int (* Each patient gets a unique id *)
subsubsection‹Roles and Relationships› text‹In our example, we assume three different roles for members of the clinical staff:›
datatype role = ClinicalPractitioner | Nurse | Clerical
text‹
We model treatment relationships (legitimate relationships) between staff and patients
(respectively, their health records. This access control model is inspired by our detailed
NHS model. › type_synonym lr_id = int type_synonym LR = "lr_id ⇀ (user set)"
text‹The security context stores all the existing LRs.› type_synonym Σ = "patient ⇀ LR"
text‹The user context stores the roles the users are in.› type_synonym υ = "user ⇀ role"
subsection‹Modelling Health Records and the Web Service API› subsubsection‹Health Records› text‹The content and the status of the entries of a health record› datatype data = dummyContent datatype status = Open | Closed type_synonym entry_id = int type_synonym entry = "status × user × data" type_synonym SCR = "(entry_id ⇀ entry)" type_synonym DB = "patient ⇀ SCR"
subsubsection‹The Web Service API› text‹The operations provided by the service:› datatype Operation = createSCR user role patient
| appendEntry user role patient entry_id entry
| deleteEntry user role patient entry_id
| readEntry user role patient entry_id
| readSCR user role patient
| addLR user role patient lr_id "(user set)"
| removeLR user role patient lr_id
| changeStatus user role patient entry_id status
| deleteSCR user role patient
| editEntry user role patient entry_id entry
fun is_createSCR where "is_createSCR (createSCR u r p) = True"
|"is_createSCR x = False"
fun is_appendEntry where "is_appendEntry (appendEntry u r p e ei) = True"
|"is_appendEntry x = False"
fun is_deleteEntry where "is_deleteEntry (deleteEntry u r p e_id) = True"
|"is_deleteEntry x = False"
fun is_readEntry where "is_readEntry (readEntry u r p e) = True"
|"is_readEntry x = False"
fun is_readSCR where "is_readSCR (readSCR u r p) = True"
|"is_readSCR x = False"
fun is_changeStatus where "is_changeStatus (changeStatus u r p s ei) = True"
|"is_changeStatus x = False"
fun is_deleteSCR where "is_deleteSCR (deleteSCR u r p) = True"
|"is_deleteSCR x = False"
fun is_addLR where "is_addLR (addLR u r lrid lr us) = True"
|"is_addLR x = False"
fun is_removeLR where "is_removeLR (removeLR u r p lr) = True"
|"is_removeLR x = False"
fun is_editEntry where "is_editEntry (editEntry u r p e_id s) = True"
|"is_editEntry x = False"
fun SCROp :: "(Operation × DB) ⇀ SCR"where "SCROp ((createSCR u r p), S) = S p"
|"SCROp ((appendEntry u r p ei e), S) = S p"
|"SCROp ((deleteEntry u r p e_id), S) = S p"
|"SCROp ((readEntry u r p e), S) = S p"
|"SCROp ((readSCR u r p), S) = S p"
|"SCROp ((changeStatus u r p s ei),S) = S p"
|"SCROp ((deleteSCR u r p),S) = S p"
|"SCROp ((editEntry u r p e_id s),S) = S p"
|"SCROp x = ⊥"
fun patientOfOp :: "Operation ==> patient"where "patientOfOp (createSCR u r p) = p"
|"patientOfOp (appendEntry u r p e ei) = p"
|"patientOfOp (deleteEntry u r p e_id) = p"
|"patientOfOp (readEntry u r p e) = p"
|"patientOfOp (readSCR u r p) = p"
|"patientOfOp (changeStatus u r p s ei) = p"
|"patientOfOp (deleteSCR u r p) = p"
|"patientOfOp (addLR u r p lr ei) = p"
|"patientOfOp (removeLR u r p lr) = p"
|"patientOfOp (editEntry u r p e_id s) = p"
fun userOfOp :: "Operation ==> user"where "userOfOp (createSCR u r p) = u"
|"userOfOp (appendEntry u r p e ei) = u"
|"userOfOp (deleteEntry u r p e_id) = u"
|"userOfOp (readEntry u r p e) = u"
|"userOfOp (readSCR u r p) = u"
|"userOfOp (changeStatus u r p s ei) = u"
|"userOfOp (deleteSCR u r p) = u"
|"userOfOp (editEntry u r p e_id s) = u"
|"userOfOp (addLR u r p lr ei) = u"
|"userOfOp (removeLR u r p lr) = u"
fun roleOfOp :: "Operation ==> role"where "roleOfOp (createSCR u r p) = r"
|"roleOfOp (appendEntry u r p e ei) = r"
|"roleOfOp (deleteEntry u r p e_id) = r"
|"roleOfOp (readEntry u r p e) = r"
|"roleOfOp (readSCR u r p) = r"
|"roleOfOp (changeStatus u r p s ei) = r"
|"roleOfOp (deleteSCR u r p) = r"
|"roleOfOp (editEntry u r p e_id s) = r"
|"roleOfOp (addLR u r p lr ei) = r"
|"roleOfOp (removeLR u r p lr) = r"
fun contentOfOp :: "Operation ==> data"where "contentOfOp (appendEntry u r p ei e) = (snd (snd e))"
|"contentOfOp (editEntry u r p ei e) = (snd (snd e))"
fun contentStatic :: "Operation ==> bool"where "contentStatic (appendEntry u r p ei e) = ((snd (snd e)) = dummyContent)"
|"contentStatic (editEntry u r p ei e) = ((snd (snd e)) = dummyContent)"
|"contentStatic x = True"
fun allContentStatic where "allContentStatic (x#xs) = (contentStatic x ∧ allContentStatic xs)"
|"allContentStatic [] = True"
subsection‹Modelling Access Control› text‹
In the following, we define a rather complex access control model for our
scenario that extends traditional role-based access control
(RBAC)~cite‹"sandhu.ea:role-based:1996"› with treatment relationships and sealed
envelopes. Sealed envelopes (see~cite‹"bruegger:generation:2012"› for details)
are a variant of break-the-glass access control (see~cite‹"brucker.ea:extending:2009"›
for a general motivation and explanation of break-the-glass access control). ›
subsubsection‹Sealed Envelopes›
type_synonym SEPolicy = "(Operation × DB ↦ unit) "
definition get_entry:: "DB ==> patient ==> entry_id ==> entry option"where "get_entry S p e_id = (case S p of ⊥==>⊥ | ⌊Scr⌋==> Scr e_id)"
definition userHasAccess:: "user ==> entry ==> bool"where "userHasAccess u e = ((fst e) = Open ∨ (fst (snd e) = u))"
definition readEntrySE :: SEPolicy where "readEntrySE x = (case x of (readEntry u r p e_id,S) ==> (case get_entry S p e_id of ⊥==>⊥ | ⌊e⌋==> (if (userHasAccess u e) then ⌊allow ()⌋ else ⌊deny ()⌋ )) | x ==>⊥)"
definition deleteEntrySE :: SEPolicy where "deleteEntrySE x = (case x of (deleteEntry u r p e_id,S) ==> (case get_entry S p e_id of ⊥==>⊥ | ⌊e⌋==> (if (userHasAccess u e) then ⌊allow ()⌋ else ⌊deny ()⌋)) | x ==>⊥)"
definition editEntrySE :: SEPolicy where "editEntrySE x = (case x of (editEntry u r p e_id s,S) ==> (case get_entry S p e_id of ⊥==>⊥ | ⌊e⌋==> (if (userHasAccess u e) then ⌊allow ()⌋ else ⌊deny ()⌋)) | x ==>⊥)"
type_synonym FunPolicy = "(Operation × DB × Σ,unit) policy"
fun createFunPolicy :: FunPolicy where "createFunPolicy ((createSCR u r p),(D,S)) = (if p ∈ dom D then ⌊deny ()⌋ else ⌊allow ()⌋)"
|"createFunPolicy x = ⊥"
fun addLRFunPolicy :: FunPolicy where "addLRFunPolicy ((addLR u r p l us),(D,S)) = (if l ∈ dom S then ⌊deny ()⌋ else ⌊allow ()⌋)"
|"addLRFunPolicy x = ⊥"
fun removeLRFunPolicy :: FunPolicy where "removeLRFunPolicy ((removeLR u r p l),(D,S)) = (if l ∈ dom S then ⌊allow ()⌋ else ⌊deny ()⌋)"
|"removeLRFunPolicy x = ⊥"
fun readSCRFunPolicy :: FunPolicy where "readSCRFunPolicy ((readSCR u r p),(D,S)) = (if p ∈ dom D then ⌊allow ()⌋ else ⌊deny ()⌋)"
|"readSCRFunPolicy x = ⊥"
fun deleteSCRFunPolicy :: FunPolicy where "deleteSCRFunPolicy ((deleteSCR u r p),(D,S)) = (if p ∈ dom D then ⌊allow ()⌋ else ⌊deny ()⌋)"
|"deleteSCRFunPolicy x = ⊥"
fun changeStatusFunPolicy :: FunPolicy where "changeStatusFunPolicy (changeStatus u r p e s,(d,S)) = (case d p of ⌊x⌋==> (if e ∈ dom x then ⌊allow ()⌋ else ⌊deny ()⌋) | _ ==>⌊deny ()⌋)"
|"changeStatusFunPolicy x = ⊥"
fun deleteEntryFunPolicy :: FunPolicy where "deleteEntryFunPolicy (deleteEntry u r p e,(d,S)) = (case d p of ⌊x⌋==> (if e ∈ dom x then ⌊allow ()⌋ else ⌊deny ()⌋) | _ ==>⌊deny ()⌋)"
|"deleteEntryFunPolicy x = ⊥"
fun readEntryFunPolicy :: FunPolicy where "readEntryFunPolicy (readEntry u r p e,(d,S)) = (case d p of ⌊x⌋==> (if e ∈ dom x then ⌊allow ()⌋ else ⌊deny ()⌋) | _ ==>⌊deny ()⌋)"
|"readEntryFunPolicy x = ⊥"
fun appendEntryFunPolicy :: FunPolicy where "appendEntryFunPolicy (appendEntry u r p e ed,(d,S)) = (case d p of ⌊x⌋==> (if e ∈ dom x then ⌊deny ()⌋ else ⌊allow ()⌋) | _ ==>⌊deny ()⌋)"
|"appendEntryFunPolicy x = ⊥"
fun editEntryFunPolicy :: FunPolicy where "editEntryFunPolicy (editEntry u r p ei e,(d,S)) = (case d p of ⌊x⌋==> (if ei ∈ dom x then ⌊allow ()⌋ else ⌊deny ()⌋) | _ ==>⌊deny ()⌋)"
|"editEntryFunPolicy x = ⊥"
definition RBAC :: "(role × Operation) set"where "RBAC = {(r,f). r = Nurse ∧ is_readEntry f} ∪ {(r,f). r = Nurse ∧ is_readSCR f} ∪ {(r,f). r = ClinicalPractitioner ∧ is_appendEntry f} ∪ {(r,f). r = ClinicalPractitioner ∧ is_deleteEntry f} ∪ {(r,f). r = ClinicalPractitioner ∧ is_readEntry f} ∪ {(r,f). r = ClinicalPractitioner ∧ is_readSCR f} ∪ {(r,f). r = ClinicalPractitioner ∧ is_changeStatus f} ∪ {(r,f). r = ClinicalPractitioner ∧ is_editEntry f} ∪ {(r,f). r = Clerical ∧ is_createSCR f} ∪ {(r,f). r = Clerical ∧ is_deleteSCR f} ∪ {(r,f). r = Clerical ∧ is_addLR f} ∪ {(r,f). r = Clerical ∧ is_removeLR f}"
definition RBACPolicy :: RBACPolicy where "RBACPolicy = (λ (f,uc). if ((roleOfOp f,f) ∈ RBAC ∧⌊roleOfOp f⌋ = uc (userOfOp f)) then ⌊allow ()⌋ else ⌊deny ()⌋)"
subsection‹The State Transitions and Output Function›
subsubsection‹State Transition›
fun OpSuccessDB :: "(Operation × DB) ⇀ DB"where "OpSuccessDB (createSCR u r p,S) = (case S p of ⊥==>⌊S(p↦∅)⌋ | ⌊x⌋==>⌊S⌋)"
|"OpSuccessDB ((appendEntry u r p ei e),S) = (case S p of ⊥==>⌊S⌋ | ⌊x⌋==> ((if ei ∈ (dom x) then ⌊S⌋ else ⌊S(p ↦ x(ei↦e))⌋)))"
|"OpSuccessDB ((deleteSCR u r p),S) = (Some (S(p:=⊥)))"
|"OpSuccessDB ((deleteEntry u r p ei),S) = (case S p of ⊥==>⌊S⌋ | ⌊x⌋==> Some (S(p↦(x(ei:=⊥)))))"
|"OpSuccessDB ((changeStatus u r p ei s),S) = (case S p of ⊥==>⌊S⌋ | ⌊x⌋==> (case x ei of ⌊e⌋==>⌊S(p ↦ x(ei↦(s,snd e)))⌋ | ⊥==>⌊S⌋))"
|"OpSuccessDB ((editEntry u r p ei e),S) = (case S p of ⊥==>⌊S⌋ | ⌊x⌋==> (case x ei of ⌊e⌋==>⌊S(p↦(x(ei↦(e))))⌋ | ⊥==>⌊S⌋))"
|"OpSuccessDB (x,S) = ⌊S⌋"
fun OpSuccessSigma :: "(Operation × Σ) ⇀ Σ"where "OpSuccessSigma (addLR u r p lr_id us,S) = (case S p of ⌊lrs⌋==> (case (lrs lr_id) of ⊥==>⌊S(p↦(lrs(lr_id↦us)))⌋ | ⌊x⌋==>⌊S⌋) | ⊥==>⌊S(p↦(Map.empty(lr_id↦us)))⌋)"
|"OpSuccessSigma (removeLR u r p lr_id,S) = (case S p of Some lrs ==>⌊S(p↦(lrs(lr_id:=⊥)))⌋ | ⊥==>⌊S⌋)"
|"OpSuccessSigma (x,S) = ⌊S⌋"
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.