|
|||||||
New to SitePoint Forums? Register here for free!
|
![]() |
|
|
Thread Tools | Display Modes |
|
|
|
|
#1 |
|
SitePoint Evangelist
![]() ![]() ![]() ![]() Join Date: Dec 2003
Location: Arizona
Posts: 418
|
Patterns Tutorial Series (part 1): RBAC Domain Model
For our first collaborative effort it has been suggested by several users that we implement a Role-Based Access Control system using Design Patterns and Best Practices. There is an official ANSI spec for Role-Based Access Control here:
http://csrc.nist.gov/rbac/rbac-std-ncits.pdf Approach: I think we should start with the domain model and then move onto the data model (database design) which will include a mapping between the two. Once we have a solid Domain Model and Data Model we can start talking about whether we want a service layer, what the application layer would look like, and finally the presentation layer. I think that making a service layer would be nice enhancement because then we could have a Web-based presentation layer and build some Web services on top as well. I think we could purposefully start out simple and go through some refactoring to illustrate how that process fits into the picture. So, let's start with the domain model. JT ---------------------------------------------------------------------- Update: Here is the progress that has been made so far: We started off by looking at the NIST RBAC specification. Realizing that the spec was way too large for our purposes, we decided to focus on the core RBAC. We removed the concept of sessions and concentrated on the relationship between Users, Roles, and Permissions. It was proposed that we have a User class but ultimately we decided that the scope of a user class would be too large. Instead, we would have a Authorizer class which returned a set of permissions. The set of permissions would be inspected to determine whether or not a user had permission to do a particular operation. An interface and some test cases were created and we are now at the point where we will begin to flesh out the classes and indentify patterns that will be used in the implementation. ---------------------------------------------------------------------- Last edited by seratonin; Apr 10, 2004 at 13:51. |
|
|
|
|
|
#2 |
|
SitePoint Evangelist
![]() ![]() ![]() ![]() Join Date: Dec 2003
Location: Arizona
Posts: 418
|
The core spec identifies the following entities:
User Role Object Operation Permission Session There is a many-to-many relationship between Users and Roles There is a many-to-many relationship between Roles and Permissions. There is a one-to-many relationship between Users and Sessions. There is a many-to-many relationship between Sessions and Roles. There is a many-to-many relationship between Objects and Operations. There is a containment relationship between Permissions and (Objects and Operations). A session is really just a set of active roles for a particular user. Does anybody want to whip up a quick UML diagram to illustrate this or is the drawing in the spec sufficient? This is a nice spec BTW. Thanks, JT Last edited by seratonin; Apr 4, 2004 at 19:59. |
|
|
|
|
|
#3 |
|
SitePoint Zealot
![]() ![]() Join Date: Apr 2003
Location: Mexico
Posts: 138
|
I think maybe is not that necessary as you commented the spec is very good (y) but maybe including a diagram from the spec for example
![]() could do ? |
|
|
|
|
|
#4 |
|
SitePoint Evangelist
![]() ![]() ![]() ![]() Join Date: Dec 2003
Location: Arizona
Posts: 418
|
The application will need to do the user assignments and permission assignments as well as CRUD for each entity identified above.
JT |
|
|
|
|
|
#5 |
|
SitePoint Evangelist
![]() ![]() ![]() ![]() Join Date: Dec 2003
Location: Arizona
Posts: 418
|
A permission is really just a container of objects and operations on those objects. So we want to be able ask the system questions like:
Does this user have permission to do this operation on this object? PHP Code:
|
|
|
|
|
|
#6 | |
|
SitePoint Zealot
![]() ![]() Join Date: Apr 2003
Location: Mexico
Posts: 138
|
Quote:
.Now what about using the proposed function/method names and prototypes by the spec ? ... I believe that the only tricky part of this, considering that there is already an evolved spec, is to come up with a solution or implementation that is flexible, highly reusable and adapted to target the web development environtment. more later.... Last edited by oivaf; Apr 4, 2004 at 23:49. Reason: Removed db schema to avoid confusion/loss of focus |
|
|
|
|
|
|
#7 |
|
SitePoint Evangelist
![]() ![]() ![]() ![]() Join Date: Dec 2003
Location: Arizona
Posts: 418
|
Your preliminary schema looks good. I was hoping that we could tackle the object model first and then proceed to the database design, but it appears that you have captured the core relationships in your data model.
JT |
|
|
|
|
|
#8 |
|
SitePoint Evangelist
![]() ![]() ![]() ![]() Join Date: Dec 2003
Location: Arizona
Posts: 418
|
So we have the following entities for core RBAC:
User Role Permission Operation Object Session The spec also defines the following "functions": Administrative commands: AddUser DeleteUser AddRole DeleteRole AssignUser DeassignUser GrantPermission RevokePermission Supporting system functions: CreateSession DeleteSession AddActiveRole DropActiveRole CheckAccess Review functions: AssignedUsers AssignedRoles Advanced review functions: RolePermissions UserPermissions SessionRoles SessionPermissions RoleOperationsOnObject UserOperationsOnObject So now we have the task of determining the classes, attributes, and methods from this information. JT |
|
|
|
|
|
#9 | |
|
SitePoint Victim
![]() ![]() ![]() ![]() ![]() ![]() Join Date: Apr 2003
Location: London
Posts: 2,273
|
Hi...
Quote:
![]() You've started off with a huge spec, but no goal or context. You will end up with a design that is overkill and then takes ages to code. Modern development is iterative, not waterfall, and this could turn into a worst practices thread rather than a best practices one. Already it's too complicated for just about any web app. I've ever seen. Here are some places where things have gone overboard... The spec includes methods for setting up roles and permissions for a continually running system. With PHP you can do that by editing a file. It looks very much to me like a spec. for a centralised authentication and authorisation server, rather than a single application. Is that what you want? If not then just edit a single web page and so doing ditch over half the methods. What do you want the client code to look like? The only operation an authorisation system ultimately has to accomplish is this... PHP Code:
You are jumping straight into a model. Who says the essential entities are those listed above? They may exist as something (being conceptual they probably will), but that something could just be the act of one referencing the other. You have started with a relational DB schema. Who says we need a relational database? Authorisation data is read often, but written rarely. This opens up lot's of possibilities. It is probable that an RDBMS system will still be used, but it is still an implementation decision that can be put off. Just suppose that we do indeed want an authentication system that could be remoted. Here is one facade and one memento that will do the trick just following the spec. given... PHP Code:
Code:
<?xml?>
<rbac version="214">
<role name="superuser">
<operation name="edit"/>
</role>
</rbac>
PHP Code:
This is all worst case of course. No one has said that we will ever need remote access. yours, Marcus |
|
|
|
|
|
|
#10 |
|
SitePoint Evangelist
![]() ![]() ![]() ![]() Join Date: Dec 2003
Location: Arizona
Posts: 418
|
I believe the goal here should be to implement the Core RBAC spec. The spec is huge, we only need the core for now. The core is pretty simple as I have outlined above. What I think we need to do is define what classes we are going to have and how the operations fit into those classes. I already have a DomainModel in my head that should accommodate the core RBAC using the entities above. If we find that the entities are insufficient, we can always create different one's. My idea was to start with the spec and diverge if necessary.
JT Last edited by seratonin; Apr 5, 2004 at 00:28. |
|
|
|
|
|
#11 |
|
SitePoint Evangelist
![]() ![]() ![]() ![]() Join Date: Dec 2003
Location: Arizona
Posts: 418
|
Edit.
Last edited by seratonin; Apr 5, 2004 at 12:15. |
|
|
|
|
|
#12 |
|
SitePoint Evangelist
![]() ![]() ![]() ![]() Join Date: Dec 2003
Location: Arizona
Posts: 418
|
Here is a set of simple interfaces and some ideas of where I think the various functions belong.
PHP Code:
JT Last edited by seratonin; Apr 5, 2004 at 00:22. |
|
|
|
|
|
#13 |
|
SitePoint Zealot
![]() ![]() Join Date: Apr 2003
Location: Mexico
Posts: 138
|
Hi,
first of all I don't have much experience so pardon my (future) mistakes , as lastcraf says maybe we should state what is going to be the goal or context for this project or tutorial or whatever I never thought to implement all the entire spec but instead adapt it to web applications. I believe the client code will be very similar to the one seratonin and lastcraft posted. By skimming the spec you can realize that there are at least 2 sets of functions for core rbac: one for the end user and one for the rbac system administration and yes you could say it is very basic and easy to implement because it is. The complexity increases with the other levels of rbac like Hierarchical RBAC, SSD relation and DSD relation for which I still haven't seen a use in web development. I really find it very easy to code an rbac system the wrong way so this thread is a great oportunity to do the oposite ![]() So where should we start ? maybe a list of requirements ? ......mm I'll remove the db schema ![]() |
|
|
|
|
|
#14 |
|
SitePoint Zealot
![]() ![]() Join Date: Apr 2003
Location: Mexico
Posts: 138
|
First I think we should divide the functions/classes on
1) client side - the programmer who wants to implement rbac on a new or existing application 2) administration side - this is the interface that interacts with the objects and users of our new or existing application, creating, editing, assigning roles, creating and assigning permissions, etc. To clarify an object could be for example: the authoring suite of Serendipity then the possible operations would be create, edit or delete entries. Now about the interfaces ... on the client side ideally IMO our rbac implementation shouldn't have to know anything about authentication nor sessions. You could authenticate to an LDAP server or via SOAP, or you could have file or db sessions with you own Session class. I know you can have wrappers to integrate everything but I think that that task should be left to the end user. So for example using the proposed functions we just need: PHP Code:
seratonin : in your Session interface regarding your methods addActiveRole and dropActiveRole, I don't think we're going to need those because usually a user is authenticated only once and at that moment all the roles corresponding to the user are loaded (is this a good or bad thing ?). Also I believe that this methods are part of the higher levels of RBAC ![]() about your user and session interfaces see my comments above and tell me what you think ![]() |
|
|
|
|
|
#15 | |
|
Non-Member
![]() ![]() ![]() ![]() ![]() ![]() Join Date: Jan 2004
Location: Planet Earth
Posts: 1,807
|
Quote:
![]() As Marcus has said - my interpretation - to implement the whole specification would be way over the top ? Also, I think the original purpose of this thread, we should remain OO all the way, to design with OO and Proc Prog would proberly do more harm than good for those who are interested in learning OO Design, Design Patterns and Refactoring, et al. ![]() |
|
|
|
|
|
|
#16 |
|
Non-Member
![]() ![]() ![]() ![]() ![]() ![]() Join Date: Jan 2004
Location: Planet Earth
Posts: 1,807
|
PHP Code:
This requirement could change from application to application is what I'm saying I suppose ![]() |
|
|
|
|
|
#17 |
|
SitePoint Evangelist
![]() ![]() ![]() ![]() Join Date: Dec 2003
Location: Arizona
Posts: 418
|
Let's say we started off with a more course-grained, "service-oriented" approach and we treated the core RBAC functional specification as a set of "use cases".
We would have: PHP Code:
PHP Code:
Thanks, JT |
|
|
|
|
|
#18 |
|
SitePoint Evangelist
![]() ![]() ![]() ![]() Join Date: Dec 2003
Location: Arizona
Posts: 418
|
After reviewing the original specification and the various posts, I think we should refine/descope the spec a little bit. As Marcus stated in his post, ultimately the client needs to be able to ask the system the following question:
"Does this user have permission to do this operation on this object?" The original spec calls for "sessions" but I don't think that is necessary for our treatment. I think we should focus on User, Role, and Permission (where a permission contains an operation and an object). Now, typically there are two stages, authentication and authorization. Authentication usually happens once and Authorization will happen many times once the user has been authenticated. So if we want to include authentication, our system must also ask: "Is the user authethenticated?" and also provide some mechanism to authenticate the user. We could have two stateless classes that are responsible for these two activities: Authenticator Authorizer Or we could somehow integrate the behavior directly into our Domain Model. I think that we can expose the functionality with Authenticator and Authorizer interfaces but have then directing calls to the Domain model (User, Role, Permission) which behind those interfaces. Now keep in mind I have not even begun to think about the admin functions (create user, create role etc). JT |
|
|
|
|
|
#19 | |
|
Non-Member
![]() ![]() ![]() ![]() ![]() ![]() Join Date: Jan 2004
Location: Planet Earth
Posts: 1,807
|
Quote:
PHP Code:
![]() Just my thoughts. |
|
|
|
|
|
|
#20 |
|
SitePoint Evangelist
![]() ![]() ![]() ![]() Join Date: Dec 2003
Location: Arizona
Posts: 418
|
I like the idea of breaking things up a bit so that we don't have any "god" classes but those classes (at least by the names) sound more like they should be a group of related domain logic in some domain model. Okay. So we have these administrative functions. Who or what would normally take care of these functions? Most likely it would be a system administrator. If we put the functionality in the User Domain Model, then you will have a bunch of functionality that is not used by 99% of the users. Where to put the administrative functions... Well, we could have an Administrator class which has the functions addUser, deleteUser, addRole, deleteRole, assignUser, deassignUser, grantPermission, revokePermission. So we would have three classes:
PHP Code:
JT Last edited by seratonin; Apr 5, 2004 at 13:24. |
|
|
|
|
|
#21 |
|
Non-Member
![]() ![]() ![]() ![]() ![]() ![]() Join Date: Jan 2004
Location: Planet Earth
Posts: 1,807
|
Indeed
![]() Looks well thought out and clean. |
|
|
|
|
|
#22 | |
|
SitePoint Evangelist
![]() ![]() ![]() ![]() Join Date: Dec 2003
Location: Arizona
Posts: 418
|
Quote:
JT |
|
|
|
|
|
|
#23 |
|
SitePoint Victim
![]() ![]() ![]() ![]() ![]() ![]() Join Date: Apr 2003
Location: London
Posts: 2,273
|
Hi...
I am still trying to reduce the scope so that something can be demonstrated working. I favour use cases over structural specs. for this. We have two use cases... 1) We ask the authenticator to turn an identity into a set of permissions. These permissions can be queried (they are read only in this context) and return simple boolean values. 2) An administrator/script can add and remove people and permissions. To save effort, permissions are grouped into roles. A user can have multiple roles in RBAC. I have already spotted some potential pitfalls in the discussions above... 1) I don't think it is a good idea to have object IDs mixed in. This will entangle the permissions system with application specific stuff. You probably have an idea of ownership and this can be expressed within the application code by adding more permissions. E.g. Have edit_own_documents (author) as well as edit_documents (editor in chief). How these are handled is up to the application - as it should be. Ownership of objects within the application is likely to be complex and highly variable. 2) Don't involve sessions as the core problem has nothing to do with session management. Basically once you have a set of permissions you can place that set into the session. You no longer need the user's identity because the sesssion system takes care of that for you. You also involve synchronisation issues this way. Because permissions are constant after the login (invariant) they can be cached into the session easily. A user on the other hand may change and you will likely have to fetch it from deep storage on every request. I am going to shamelessly plug my own tool here and turn the use cases into a test case... PHP Code:
Other use cases and test cases can probably be fleshed out. My only thought on persistence is that the queries will be quite involved, but it is otherwise data centric. A PermissionsFinder makes sense in each type of storage. e.g... PHP Code:
I am avoiding classes for roles and operations as these objects are purely passive data. They would be represented in the storage schema only. This is one of the ways that thinking in data terms rather than in jobs can throw you off track and make things seem more complicated than they really are. yours, Marcus |
|
|
|
|
|
#24 |
|
SitePoint Evangelist
![]() ![]() ![]() ![]() Join Date: Dec 2003
Location: Arizona
Posts: 418
|
The one thing I want to keep from the original spec is the fact that a permission is an operation/object pair. Your permission system mixes the two. edit_own_document is actually a permission to do an 'edit' on a 'document'. I think allowing for mixing an matching operations/objects keeps the system flexible and doesn't add too much overhead.
Another thing that is important is the many-to-many relationship between users and roles and the many-to-many relationship between roles and permissions. This makes the system really flexible and avoids redundant data storage. Unfortunately, without using id's, it is difficult to model a many-to-many relationship in say an XML document. You would have something like this: Code:
<?xml version="1.0"?>
<rbac>
<users>
<user id="1" name="John" username="user" password="pass"/>
<user id="2" name="Jane" username="user" password="pass"/>
</users>
<roles>
<role id="1" name="Sales Person"/>
<role id="2" name="Sales Manager"/>
</roles>
<!-- a permission is a mapping between an operation and an object -->
<permissions>
<permission id="1" operation="1" object="1"/>
<permission id="2" operation="2" object="1"/>
<permission id="3" operation="3" object="1"/>
</permissions>
<operations>
<operation id="1" name="add"/>
<operation id="2" name="update"/>
<operation id="3" name="delete"/>
</operations>
<objects>
<object id="1" name="article"/>
</objects>
<!-- User Assignment -->
<user_roles>
<user_role user="1" role="1"/>
<user_role user="2" role="1"/>
</user_roles>
<!-- Permission Assignment -->
<role_permissions>
<role_permission role="1" permission="1"/>
<role_permission role="2" permission="1"/>
<role_permission role="2" permission="2"/>
<role_permission role="2" permission="3"/>
</role_permissions>
</rbac>
JT Last edited by seratonin; Apr 5, 2004 at 17:52. |
|
|
|
|
|
#25 | ||
|
SitePoint Victim
![]() ![]() ![]() ![]() ![]() ![]() Join Date: Apr 2003
Location: London
Posts: 2,273
|
Hi...
Quote:
It's not the end of the world however. Just a change of character. How about we add object IDs later on, perhaps as an extension? Quote:
How closely do you want to stick to the spec? yours, Marcus |
||
|
|
|
![]() |
| Bookmarks |
«
Previous Thread
|
Next Thread
»
| Thread Tools | |
| Display Modes | |
|
|
|
All times are GMT -7. The time now is 14:31.






.

, as lastcraf says maybe we should state what is going to be the goal or context for this project or tutorial or whatever 





Hybrid Mode
