/* GENI authorization. These statements are directly executable by a prolog simulation. Subsets of statements may be exchanged as signed logic credentials, e.g., in ABAC or MTL forms. Chase 3/17/13 Syntactic conventions for Minimalist Trust Logic (MTL) trust atoms: - Prolog terms: those starting with capital letters are variables, those starting with small letters are principals or objects. - The first parameter of every predicate is a principal who says/believes the trust atom. - If a predicate is a capability predicate, i.e., an atom with the predicate represents a role or capability held by a principal (the subject), then its second argument names the subject. - A capability predicate that terminates with _ is delegatable by the subject. Delegatable predicates have forms without the trailing underscore; these forms are not delegatable. - The capability predicate form with an appended Q (or Q_) has an additional string parameter that qualifies the predicate to some specific named privilege. A subject that holds the unqualified form of the predicate holds all of its associated named privileges. But these privileges may also be delegated individually. - Guard predicates are prefixed with guard_. The following syntactic conventions help represent events that occur as the prolog simulation runs. When an object is created: one atom is spoken by the requester to represent the request, and one atom is spoken by a server that accepts the request and creates the object and becomes its "root". These predicates are not legal MTL: they may have any number of arguments to capture the arguments of the request and the properties of the newly created object. The naming conventions help to identify these "artificial" predicates and their purpose, and also help yap avoid chasing its tail, which it just cannot seem to help doing if there is any way to do it. - In a ground fact that represents a delegation action, the predicate is prefixed with "delegate_". - In a ground fact that represents a request, the predicate is prefixed with "request_". - In a ground fact that represents an object being created (by an authority server for that object type), the predicate is prefixed with "root_". */ /* ---------------------------------------------------------------------------------------------- Coordinators and trust structure. Every principal must have local trust in the GENI root ("GOC"). The root endorses all coordinator roles. These roles are not delegatable, but they could be. */ identityProvider(X, I):- geniRoot(X, G), identityProvider(G, I). sliceAuthority(X, SA):- geniRoot(X, G), sliceAuthority(G, SA). projectAuthority(X, PA):- geniRoot(X, G), projectAuthority(G, PA). geniProxy(X, GP):- geniRoot(X, G), geniProxy(G, GP). aggregate(X, A):- geniRoot(X, G), aggregate(G, A). gmoc(X, GM):- geniRoot(X, G), gmoc(G, GM). /* ---------------------------------------------------------------------------------------------- User attributes asserted by duly authorized identity providers. We distinguish only registered GENI users and PIs. There can be any number of attributes. They can be used arbitrarily as goals in guard rules, to limit access to users possessing specific attributes. */ geniUser(X, Y):- identityProvider(X, I), geniUser(I, Y). geniPI(X, Y):- identityProvider(X, I), geniPI(I, Y). /* ---------------------------------------------------------------------------------------------- X accepts an object of type T if X trusts the object's self-proclaimed root as an authority for objects of type T. Note: for each object, the prolog simulation must search for an authority that proclaims itself to be the object's root. This implies that any principal may proclaim itself the root, and X accepts it iff X trusts it as an authority. In a "real" system object names are self-certifying: no search, no forgery. */ qualifiedProject(X, PA, P):- root(PA, PA, P), projectAuthority(X, PA), project(PA, P). qualifiedSlice(X, SA, S):- root(SA, SA, S), sliceAuthority(X, SA), slice(SA, S, P). /* ---------------------------------------------------------------------------------------------- PA policy rules for operations on "standard" projects. PAs may choose to issue different rules for other (non-standard) projects. Note: these rules empower delegation of membership to anyone. The SA guard rules below limit the exercise of some privileges to GENI users only. Optionally we could limit them to members of the associated project. */ member_(PA, M, P):- standard(PA, P), owner(PA, M, P). member_(PA, M, P):- standard(PA, P), delegate_member_(M2, M, P), member_(PA, M2, P). member(PA, M, P):- standard(PA, P), member_(PA, M, P). member(PA, M, P):- standard(PA, P), delegate_member(M2, M, P), member_(PA, M2, P). memberQ(PA, M, P, PRIV):- standard(PA, P), member(PA, M, P). memberQ_(PA, M, P, PRIV):- standard(PA, P), member_(PA, M, P). memberQ(PA, M, P, PRIV):- standard(PA, P), delegate_memberQ(M2, M, P, PRIV), memberQ_(PA, M2, P, PRIV). memberQ_(PA, M, P, PRIV):- standard(PA, P), delegate_memberQ_(M2, M, P, PRIV), memberQ_(PA, M2, P, PRIV). /* ---------------------------------------------------------------------------------------------- SA policy rules for operations on "standard" slices. SAs may choose to issue different rules for other (non-standard) slices. Note: these rules empower delegation of control to anyone. The aggregate guard rules below limit the exercise of some privileges to GENI users only. Optionally we could limit them to members of the associated project. */ controls_(SA, C, S):- standard(SA, S), owner(SA, C, S). controls_(SA, C, S):- standard(SA, S), delegate_controls_(C2, C, S), controls_(SA, C2, S). controls(SA, C, S):- standard(SA, S), controls_(SA, C, S). controls(SA, C, S):- standard(SA, S), delegate_controls(C2, C, S), controls_(SA, C2, S). controlsQ(SA, C, S, PRIV):- standard(SA, S), controls(SA, C, S). controlsQ_(SA, C, S, PRIV):- standard(SA, S), controls_(SA, C, S). controlsQ(SA, C, S, PRIV):- standard(SA, S), delegate_controlsQ(C2, C, S, PRIV), controlsQ_(SA, C2, S, PRIV). controlsQ_(SA, C, S, PRIV):- standard(SA, S), delegate_controlsQ_(C2, C, S, PRIV), controlsQ_(SA, C2, S, PRIV). /* Additional SA policy rules for standard slices: Any project member can get info about any slice associated with the project. The PI of a project may query or stop any slice associated with the project. The member cannot delegate that privilege, and delegators may restrict it on a per-member basis. GMOC may query or stop any GENI slice. */ controlsQ(SA, C, S, "info"):- standard(SA, S), root_slice(SA, S, P, C2), qualifiedProject(SA, PA, P), memberQ(PA, C, P, "info"). controlsQ(SA, C, S, "stop"):- standard(SA, S), root_slice(SA, S, P, C2), qualifiedProject(SA, PA, P), owner(PA, C, P). controlsQ(SA, C, S, "info"):- standard(SA, S), root_slice(SA, S, P, C2), gmoc(SA, C). controlsQ(SA, C, S, "stop"):- standard(SA, S), root_slice(SA, S, P, C2), gmoc(SA, C). /* ---------------------------------------------------------------------------------------------- PA guard policy to create (root) a project. All projects are "standard". root_project is a "temporary" holder for the new project's properties. Note: in simulation the guard is re-evaluated whenever the project is queried. An optional add-on rule set supports a hierarchy of subprojects. */ root_project(PA, P, C):- request_project(C, PA, P), projectAuthority(PA, PA), geniPI(PA, C). root(PA, PA, P):- root_project(PA, P, C). owner(PA, C, P):- root_project(PA, P, C). project(PA, P):- root_project(PA, P, C). standard(PA, P):- root_project(PA, P, C). /* ---------------------------------------------------------------------------------------------- SA guard policy to create (root) a slice. All slices are standard. Requests to create a slice may be proxied through a duly authorized GENI proxy. root_slice is a "temporary" holder for the new slice's properties. Note: in simulation the guard is re-evaluated whenever the slice is queried. */ root_slice(SA, S, P, C):- request_slice(C, SA, S, P), sliceAuthority(SA, SA), qualifiedProject(X, PA, P), memberQ(PA, C, P, "instantiate"), geniUser(X, C). root_slice(SA, S, P, C):- proxied_request_slice(PXY, C, SA, S, P), sliceAuthority(SA, SA), geniProxy(SA, PXY), speaksFor(C, PXY, C), qualifiedProject(X, PA, P), memberQ(PA, C, P, "instantiate"), geniUser(X, C). root_slice(SA, S, P, C):- proxied_request_slice(PXY, C, SA, S, P), sliceAuthority(SA, SA), geniProxy(SA, PXY), speaksForOn(C, PXY, C, P), qualifiedProject(X, PA, P), memberQ(PA, C, P, "instantiate"), geniUser(X, C). root(SA, SA, S):- root_slice(SA, S, P, C). owner(SA, C, S):- root_slice(SA, S, P, C). slice(SA, S, P):- root_slice(SA, S, P, C). standard(SA, S):- root_slice(SA, S, P, C). /* ---------------------------------------------------------------------------------------------- Aggregate guards Aggregate guard policy to create a sliver in a slice. Note: in simulation the guard is re-evaluated whenever the sliver is queried. */ root_sliver(A, SV, SL):- request_sliver(C, A, SV, SL), qualifiedSlice(A, SA, SL), controlsQ(SA, C, SL, "instantiate"), geniUser(A, C). /* Aggregate guard policy for client C to get info about a slice SL on this aggregate. */ guard_slice_info(A, C, SL):- qualifiedSlice(A, SA, SL), controlsQ(SA, C, SL, "info"). /* Aggregate guard policy for client C to stop a slice SL on this aggregate. Note: does not require GENI user. */ guard_slice_stop(A, C, SL):- qualifiedSlice(A, SA, SL), controlsQ(SA, C, SL, "stop"). /* Aggregate operator can query or stop any slice on this aggregate. */ guard_slice_stop(A, C, SL):- operator(A, C). guard_slice_info(A, C, SL):- operator(A, C). /* ---------------------------------------------------------------------------------------------- Sample aggregate guards for proxied requests to change the state of a slice. Requests to operate on a slice may be proxied through a duly authorized GENI proxy. This is easier in the real system because the guard can check speaksFor authorization first and then use the standard guards. Aggregate guard policy to create a sliver in a slice. Note: in simulation the guard is re-evaluated whenever the sliver is queried. */ proxied_root_sliver(A, SV, SL, C, PXY):- proxied_request_sliver(PXY, C, A, SV, SL), qualifiedSlice(A, SA, SL), geniProxy(A, PXY), controlsQ(SA, C, SL, "instantiate"), geniUser(A, C). root_sliver(A, SV, SL):- proxied_root_sliver(A, SV, SL, C, PXY), speaksFor(C, PXY, C). root_sliver(A, SV, SL):- proxied_root_sliver(A, SV, SL, C, PXY), speaksForOn(C, PXY, C, SL). root_sliver(A, SV, SL):- proxied_request_sliver(PXY, C, A, SV, SL), qualifiedSlice(A, SA, SL), geniProxy(A, PXY), controlsQ(SA, C, SL, "instantiate"), geniUser(A, C), slice(SA, SL, P), speaksForOn(C, PXY, C, P). /* ---------------------------------------------------------------------------------------------- Here are some facts for a scenario */ sliceAuthority(g, sa). identityProvider(g, idp). projectAuthority(g, pa). aggregate(g, exo). geniRoot(sa, g). geniRoot(pa, g). geniRoot(exo, g). geniUser(idp, alice). geniUser(idp, bob). geniUser(idp, cary). geniUser(idp, drd). geniUser(idp, earl). geniUser(idp, frank). geniPI(idp, drd). request_project(drd, pa, p). delegate_member(drd, alice, p). request_slice(alice, sa, s, p). request_sliver(alice, exo, sv1, s). delegate_controls_(alice, bob, s). request_sliver(bob, exo, sv2, s). delegate_controls(bob, cary, s). request_sliver(cary, exo, sv3, s). delegate_controlsQ(bob, earl, s, "instantiate"). request_sliver(earl, exo, sv4, s). delegate_member(drd, bob, p). delegate_member_(drd, cary, p). delegate_member(cary, frank, p). geniProxy(g, pxy). speaksFor(bob, pxy, bob). proxied_request_sliver(pxy, bob, exo, sv5, s). speaksForOn(alice, pxy, alice, p). proxied_request_slice(pxy, alice, sa, s2, p). proxied_request_sliver(pxy, alice, exo, sv6, s2). delegate_controlsQ(bob, frank, s, "instantiate"). speaksForOn(frank, pxy, frank, s). request_sliver(frank, exo, sv7, s).