CS 290C: Formal Models for Web Software Lecture 10: WebAlloy: Website Modeling, Analysis and Synthesis with Alloy Instructor: Tevfik Bultan Access Control for Web Applications • Access control in web applications is a crucial problem • Web applications handle a wide variety of critical data – Ecommerce sites store customer account information and purchase history – Online applications for taxes, permits, visas – Google Health, Microsoft HealthVault allow patients to upload their medicate data online and share it with doctors and hospitals Access Control • Access control in web applications is difficult – Access control mechanisms provided by file systems, databases or web servers are too coarse grain – Manual coding of the access control mechanisms in scripting languages is error prone – Web application frameworks do not provide many options for customized access control • There have been high profile information leaks: – Harvard Business School website was leaking admission status from a URL before the official notification – Website for payroll processing let 25K customers to access each others’ W2 forms • Both of these leaks were due to improper enforcement of the access control policy Observation • In a typical web application, any operation has to be specified in multiple contexts: – The application logic implementing the action – The security layer enforcing the access control policy – The user interface that initiates the action • The idea in WebAlloy is to specify the operations and related access control rules once as part of the data model and then automatically generate the implementation Website Modeling with Weballoy • Recall that in Alloy signatures denote as set of objects (atoms) • For example, a data model for an online grades management can be specified with the following signatures: abstract sig User { } sig Teacher, Student extends User { } sig Course { } • In addition to user defined signatures, Weballoy supports the following signatures: – Int, Bool, String, Date, DateTime, Email, and Password Fields • Relationships among objects are specified as fields of signatures abstract sig User { name: String, } sig Teacher extends User { teaches: set Course } sig Student extends User { assists, attends: set Course } sig Course { name: String, teachers: set Teacher, assistants, students: set Student, grades: students -> lone Int } Alloy Metamodel • Every Alloy model corresponds to an instance of the Alloy metamodel – each signature s in the original model corresponds to a meta atom denoted as s$ – each field f in the signature s corresponds to a meta atom denoted s$f • Given a meta atom m for a signature – m.fields denotes the set of meta atoms that correspond to the fields of that signature – m.value denotes the elements in that signature • Given a meta atom m for a field – m.value denotes the tuples in that field Alloy metamodel • Behaviors of a model can be specified reflectively using the metamodel pred equal [c1, c2: Course] { c1.name = c2.name c1.teachers = c2.teachers c1.assistants = c2.assistants c1.students = c2.students c1.grades = c2.grades } pred equal [c1, c2: Course] { all f: Course$.fields | c1.(f.value) = c2.(f.value) } • The expression Course$.fields denotes the set of meta atoms corresponding to fields in the Course signature Facts • The allowed behavior of the data model can be restricted using facts fact { teachers = ~teaches } • This fact denotes that the teachers and teaches relations are exactly the inverse of each other Transactions • Weballoy supports transactions for modifying the data model • Transactions allow adding atoms to a signature, destroying atoms, adding tuples to a field and removing tuples from a field. • Modifications to the data model are grouped into transactions – Each transaction is either executed as a whole or rejected as a whole • Each transaction consists of – a set of atoms and tuples to be added and – a set of atoms and tuples to be deleted Transactions • Each transaction is defined as a pair of sets (AS, DS): – AS is the set of atoms and tuples to be added – DS is the set of atoms and tuples to be deleted • For each (m, x) pair in AS – Either m is a meta atom denoting a signature and x is a fresh atom to be added to that signature – Or m is a meta atom denoting a field and x is a new tuple to be added to that field • Each (m, x) pair in DS is also either a signature or a field Transactions • Example transaction – the first set is the AS, and the second set is the DS ({ // AS (Course$, c2), (Course$name, c2->"Software Engineering"), (Course$teachers, c2->t1) }, { // DS (Course$, c1) } ) Queries • Each query RS is a set of pairs (x, f) where – x is an atom and – f is a meta atom corresponding to a field of x that the user wants to retrieve • The following queries retrieve – The set of courses taught by t1 – The set of teachers teaching c1 { (t1, Teacher$teaches), (c1, Course$teachers) } Preconditions • Preconditions specify conditions that must be evaluated before an atom is created or destroyed or before a tuple is inserted or removed. • Precondition on creating an atom for a given signature s can be specified by declaring a predicate: s.preAdd • Precondition on adding a tuple to a given field f can be specified by declaring a predicate: f.preAdd Preconditions • In a predicate f.preAdd, the default parameter is this • The parameter this corresponds to the tuple (v1->v2) being added to the f field. – It contains two values v1 and v2, one for the domain of the relation and one for the range of the relation – this.first returns v1 – this.second returns v2 Preconditions • In a precondition, it is also possible to refer to a singleton set called me – me corresponds to the current logged-in user’s atom – If the user is not logged in, me evaluates to empty set Preconditions • Examples – A user cannot add teaching assistants to a course if the user is not teaching that course – A user cannot remove a teaching assistant from a course if the user is not the teacher nor the teaching assistant being removed pred assistants.preAdd { (one me) and (me in this.first.teachers) } pred assistants.preDel { (one me) and (me in this.first.teachers + this.second) } Postconditions • Postcondition on creating an atom for a given signature s can be specified be declaring a predicate: s.postAdd • Postcondition on adding a tuple to field f can be specified by declaring a predicate: f.postAdd Postconditions • Examples: – A newly created course has exactly one teacher and no assistants nor students. – Last teacher of a course cannot be removes pred Course.postAdd { this.teachers = me one this.teachers no this.assistants + this.students } pred teachers.postDel { some this.first.teachers } Expansion Triggers • A mechanism for automatically propagating changes in one field to other fields • Given field f and g the user can declare “f.onAdd: g” to denote that set of tuples should be automatically added to g when f grows fun fun fun fun teachers.onAdd: teaches teachers.onDel: teaches teaches.onAdd: teachers teaches.onDel: teachers { { { { this.second this.second this.second this.second -> -> -> -> this.first this.first this.first this.first } } } } Expansion triggers • Expansion triggers can also propagate changes between a field and a signature or between a two signatures: – A.onAdd:f : denotes the set of tuples to add to f whenever A grows – A.onDel:f : denotes the set of tuples to remove from f when A shrinks – f.onDel:A : denotes the set of atoms to delete from A whenever f shrinks – A.onDel:B : denotes the set of atoms to delete from B whenever A shrinks Capabilities • Each capability is a triple: Action->univ->univ • Actions are: R (retrieval), A (addition), D (deletion) • There are five types of capabilities: – Atom creation – Atom deletion – Tuple insertion – Tuple deletion – Tuple retrieval Capabilities • Creating a new atom in signature s requires the capability tuple (A, A, s$) • Destroying an existing atom x requires the capability triple (D, D, x) • Inserting the tuple (x1, x2, …, xn) into field f in signature s requires the capability triple (A, x1, s$f) • Deleting the tuple (x1, x2, …, xn) from field f in signature s requires the capability triple (D, x1, s$f) • Reading the tuple (x1, x2, …, xn) from field f in signature s requires the capability triple (R, x1, s$f) – Reading capabilities are ignore when processing a transaction Capabilities • Weballoy defines the following default functions for convinience: – ADD = A-> A – DELETE = D->D – W = A+D – RW = R+W enum Action { R, A, D } fun W: Action { A + D } fun RW: Action { R + W } fun ADD: Action->Action { A -> A } fun DELETE: Action->Action { D -> D } Access control policies using Capabilities • Access control policies can be specified using capabilities • Instead of writing capabilities for each field separately, meta model can be used to write concise access control policies: fun policy: Action -> univ -> univ { W -> me.teaches -> Course$.fields } Example • Given the policy: fun policy: Action -> univ -> univ { W -> me.teaches -> Course$.fields } • Suppose teacher t1 wishes to remove s1 from c1.assistants where the current database is as follows: Teacher = t1 + t2 + t3. Student = s1 + s2 + s3. Course = c1 + c2 + c3. c1.assistants = s3. c2.assistants = s1. c3.assistants = s2. t1.teaches = c1 + c2. t2.teaches = c3. t3.teaches = c1. Example • The capabilities possessed by t1 are determined by evaluating the policy function with me = t1. • The expression me.teaches evaluates to {c1, c2}, so t1 currently has 20 capability triples resulting from the cross product {A, D} → {c1, c2} → {Course$name, Course$teachers, Course$assistants, Course$students, Course$grades}. • The required capability D → c1 → Course$assistants is one of the 20 capabilities currently possessed by t1, so the request is approved if it does not violate another constraint such as a pre- or post-condition. Processing a Transaction • When a transaction is received, the server does the following: – Check the capability rules and make sure that the user has the required capability – Check the preconditions for the atom creation and tuple insertion requests and applies the onAdd triggers, performs creations & insertions and then checks the postconditions – If any pre or post conditions are violated, then the entire transaction is rejected – If a fact is violated all changes are rolled back and the transaction is rejected. Processing a Query • When a query is received, it is not necessary to evaluate pre or postconditions since the data model is not being modified • When a query is received, the website associates the singleton set me with the atom corresponding to the user making the query (or empty set if the user is not logged in) and then evaluates the capability function policy to determine the capabilities possessed by the user. Validation • Using Alloy as a specification language has the significant benefit: – The model can be automatically validated • The Alloy run command can be used to generate instances of the data model • Alloy check command can be used to do bounded verification Validation Example • Check whether the pre-condition for adding an assistant to a course is true if and only if the current user possesses the corresponding capability triple for adding assitants: check { all c:Course, s:Student | preAdd[c->s] iff A->c->Course$assistants in policy } module Weballoy sig Date = Int {} sig DateTime = Int {} sig Email = String {} sig Password = String {} sig LongString = String { } lone sig me in univ { } abstract sig Entity { name: lone String, owners: set Entity, created: DateTime, modified: DateTime, } abstract sig NamedEntity extends Entity { } { some name } abstract sig LoginUser extends NamedEntity { suspended: Bool, email: disjoint Email, password: Password } enum Action { R, A, D } fun W: fun RW: fun ADD: fun DELETE: Action->Action { D -> D } Action{A+D} Action{R+W} Action->Action { A -> A } fun first [x: univ->univ] : univ { x.univ } fun second [x: univ->univ] : univ { univ.x } Weballoy library specifications Web Application Synthesis • Weballoy automatically generates web application implementations from Alloy specifications written based on the approach we discussed in the previous slides • The synthesized application consists of – JavaScript client code – Java servlets running on the server – A custom-made relational tuple store is used as the database Web Application Synthesis • The automatically generated code consists of – Database schema automatically generated from the Alloy data model using Weballoy schema compiler – JavaScript +HTML code automatically generated from the Alloy data model using the Weballoy AJAX compiler – Servlets automatically generated from the Alloy access control specification using the Weballoy policy compiler Web application synthesis • The front-end JavaScript and the back-end server code are decoupled and communication by sending RPC messages via HTTP POST – There are five message types supported for communication between the client and the server • When the user makes changes, the JavaScript code combines the set of additions and deletions by the user to a transaction and sends it to the server – The transaction request is checked by the write capability checker, the insertion checker, the deletion checker and the consistency checker before the changes are committed to the data store Message Types • There are five RPC message types used for client and server side communication – Login: Returns an authentication cookie – Logout: Invalidates an existing cookie – Get: Returns a set of tuples – Suggest: Returns a set of atoms whose field values start with a given substring – Submit: Submits a transaction Front-End Customization Using Templates • Weballoy generates a default user interface • This default user interface can be customized by the user • Weballoy has a template system that allows embedding of Alloy expressions in HTML • <F:FieldName> denotes a field element which is displayed using the built-in widget designed for that field’s type – <F:FieldName view=“v”> means use the view labeled v • <F:S:SigName> displays each atom of the signature – <F:FieldName view=“v”> Templates sig Message { author: String, subject: String, text: LongString, replies: set Reply } sig Reply { author: String, text: String } <html> <view sig="Message" label="showMessage" public="yes"> <b>Author:</b> <F:author/> <b>Subject:</b> <F:subject/> <b>Text:</b> <F:text/> <b>Replies:</b> <F:replies/> </view> <view sig="Reply" label="showReply" public="yes"> <b>Author:</b> <F:author/> <b>Text:</b> <F:text/> </view Templates <html> <view sig="Message" label="showMessage" public="yes"> <b>Author:</b> <F:author/> <b>Subject:</b> <F:subject/> <b>Text:</b> <F:text/> <F:replies view="inlineReply"/> </view> <view sig="Reply" label="inlineReply"> <F:author/> wrote "<F:text/>" </view> </html>