1. We have moved to a new forum! There may be a few things not working properly so please let us know if you find a bug. Remember to use the bbCode [ sql ] tag for SQL statements.

Fine Grained Role Based Access Control (RBAC) system

Discussion in 'Database Design' started by ben, May 29, 2006.

  1. ben Administrator

    --------------------------------
    Edit: 2012/02/16 A port for CodeIgniter can now be found #here#. Thanks Peter!

    --------------------------------
    Here is a the database design for a "fine grained" Role Based Access Control (RBAC) system I am currently working on.

    [IMG]

    The general concept is that a user can have one or more roles.
    • Each role is defined in the in "rabac_roles_has_domain_privileges" table.
    • A role is defined as the right (or denial) to exert a privilege on a domain.
    • A role is given an 'importance', i.e. an integer value between 0 and 100. The higher the number the greater the importance.
    • A domain is a collection of objects a user may want to access (or perform an action on), such as a 'member page' or 'forum topic'.
    • A privilege is a collection of actions a user may want to perform on an object, such as 'view', 'add', 'delete', 'edit'.
    Briefly (and I will be adding more information with time)
    • A domain can either be singular or plural.
    • A domain is "plural" if it is a collection of more than one object.
    • A domain is "singular" if it corresponds to only one object (so the object and domain name will be the same)
    The same can be said about actions. (At this stage it is worth noting that plural domains will always finish with a 's'. Domains and objects are named by 'nouns' whereas, privileges and actions are named by 'verbs'.).

    A role is defined by several domain-privilege pairs.
    • Domains that are singular have precedence over their corresponding object defined in a plural domain. This is important to define "fine-grained" role permissions.
    For example, a singular domain defined by the action 'view' will have precedence over a plural domain defined by the actions 'add', 'edit', 'view'. (The plural domain also contains the action 'view' but will yield to the singular domain.)
    The same can be said for privileges.

    Here are somemore pictures that should hopefully clarify things:

    Users has roles
    [IMG]
    This picture shows that the user 'ben' has the 'administrator' and the 'member' role. This is just an example since the 'administrator' role automatically has access to all objects and can perform all actions.

    Roles definition
    [IMG]
    The administrator role is the most important, followed by moderator, then member and finally the last is public.
    NOTE: Two different roles can have the same importance. This is allowed.

    Roles as permissions
    [IMG]
    Take a look at the moderator role definition. You will see that the moderator can perform all_actions on all_objects, except for the 'admin_page', which he is only allowed to view.

    Privileges has actions
    [IMG]
    This picture clarifies the idea of 'singular' and 'plural'. Hopefully it is self explanatory.

    Domains has objects
    [IMG]

    This project (including the admin panel) is 95% complete. It is already useable and written in PHP, so if you would like to try it out send me an email at ben at sqlrecipes dot com (If you do try it out, I would appreciate your feedback and suggestions.)

    The system is distributed under the BSD license and requires the ADODB database connection layer (ADOdb Database Abstraction Library for PHP (and Python) for MySQL, PostgreSQL, Microsoft SQL Server, Oracle, Firebird, Interbase, LDAP, Access, VFP, DB2 and many other databases) as well as a MySQL database server.

    If you have any suggestions concerning this article please post your comment below.

    You can now download these files by going to the end of this thread (page 10) to find the download location

    Attached Files:

  2. ben Administrator

    Update

    The project is now 95% complete, I still need to add a few more API methods and tidy things up. The admin Control Panel is completely finished though, so you can administer roles, privileges and domains using a GUI.
  3. ben Administrator

    Somemore info

    You may be wondering whether it is possible to find out all the privileges a user is allowed to perform with just one query. The answer is YES.
    This means you could find out all the privileges a user has when they login, store the information in $_SESSION and you won't have to query the database again. Doing it this way, checking a users right to perform a certain action is extremely fast.


    You will also be able to find out all the users that are able to perform a certain action on a given object with just one query as well.
  4. ben Administrator

    It is all in the design

    The critical part of the RBAC implementation is the database design. Everything flows from there. (So take the time to study the design. Once you get it, everything else falls into place). Once your design is right you should be able to obtain all the infromation you need with just one query (and perhaps a little post processing to find out which privilege has priority over another.).

    So there are really no secrets... all the information is on this page, which means you should be able to implement an RBAC system in any programming language. If you want to see how I did it in PHP send me an email. I would be interested to hear from people who want to port it to other languages.
  5. ben Administrator

    Interesting email with answers

    > I followed most of the article that you wrote on your site and the
    > document that you published about Authorize_bv, but there is a couple of
    > things that I do not get.
    >
    > Firstly, the data model that you provided with the article does not seem
    > to allow/disallow certain permissions directly to the user. What I mean
    > is that lets say the user belongs to a "moderator" role, that has "read"
    > access to "all_pages", how would you take read access away from this
    > user without making modifications to the role "moderator"? I see you use
    > something similar to this in the PDF document of Authorize_bv, but I
    > fail to see how it will fit in the current data model.
    >
    Yes, Authorize_bv did this on the 'user' level, which means each user would have personal privileges assigned to them. Even though it seems at first more flexible it is not efficient and requires more database entries. That is when I moved to the role based approach. Rather than assign privileges to each user, you now assign the privileges to a 'role' and then each user is assigned a role. This makes it a lot more flexible to modify and administer. (i.e. instead of changing each users priviliges, which could run in the thousands..., you now only need to change one role definition.)

    The way to achieve your aim using the role based approach is to create a new role called 'moderator_read_disabled' and give it an importance greater than the 'moderator' role. You could then define the new role as 'read'action 'disabled' on 'all_pages'.
    You then assign this new role to the users (i.e. moderators) you want. Since it has a higher importance than the standard 'moderator' it will take precedence, but only for the 'read' action that affects the 'all_pages' domain. The other moderator privileges will work as normal.

    > How would you handle groups of users? Lets say we have 10 users in a
    > department, and these 10 must have access to "moderator". Is there some
    > functionality to allow me to put these 10 in a group and then assign the
    > "moderator" role only to the group?
    >
    This would be easy to implement. All you would need to do is instead of assigning roles to individual users you would assign roles to 'groups'. If you look at the first image on this thread you will see the second table from the top is called 'rbac_users_has_roles'. Instead of storing user_ids you would store group_ids and just change the field and table names accordingly.

    You would also need 2 more tables to define your groups and another to keep the many-to-many relationship between the users and the groups. However if these tables already exist in your system the rbac_bv class can easily be integrated into it.

    This would only require minor changes to the API, namely changing a few field names and table names in the SQL queiries.

    > I would like to see what your final product looks like as I am also
    > doing some research in this area. I also went through LiveUser, but to
    > be quite honest, it looks a bit dodgy and heavy. I like your version
    > more, but I am just curious about the above questions.
    >
    I hope these explanations help. Please feel free to ask more questions.
    In reality there isn't much to a role based access control system. Once the database design is done all you are really doing is querying the database to find out if a user can peform a certain action on a given object.
  6. ben Administrator

    Intersting questions concerning articles

    I received an email the other day asking whether the RBAC system can be used to manage numerous articles, and whether it is possible to find out which articles a person is allowed to read the moment they log into a system.


    The answer to both these questions is 'yes'.

    An article is just an 'object'. You can group articles that belong to a certain category into a 'domain'.

    Let say there are two types of articles. Ones that are for the public and others that are private (or sensitive.)
    We can then create two domains named 'public articles' and 'private articles' and assign the various articles to them.

    We then create a role called 'view public articles' that defines the privilige to 'view' 'public articles'.
    Let's say we want to play it safe and make sure that the 'view public articles' role is not allowed to view 'private articles', so we add this requirement to the 'view public article' role. (We would only do this if there is a chance of making a mistake and assigning an already marked private article to the public domain.)

    We then need to assign users to roles so that we can determine which users are allowed to read what.

    Once this is done we can then find out which articles a person can read the moment they login with just one query.
  7. ben Administrator

    Some Help?

    If any of yo would like to contribute some documentation, or perhaps some notes that would help others get up to speed with the system please post them here.
  8. ben Administrator

    RE: RBAC for Typo3, eZ Components and eGroupWare

    Hi Thomas,

    You can download the files from at the bottom of the first post

    If you want to discuss the implementation in more detail feel free to send me a PM.
  9. Unregistered Guest

    Ben,
    I'd love to have a look at this system you've built.
    Unfortunately it seems the zip file is corrupt. Could you please have a look at it for me?

    Cheers.
  10. ben Administrator

    There was a similar problem a few weeks ago. It should now be fixed. Please let me know if you still have a problem opening up the file.
  11. eDave New Member

    Just a quick note regarding the schema.
    On mysql 5.0.37 the last constraint could not be created. You get this error:
    Code:
    mysql> ALTER TABLE rbac_users_has_roles ADD CONSTRAINT fk_users_has_roles_roles FOREIGN KEY (roles_id) REFERENCES rbac_roles (id); 
    ERROR 1005 (HY000): Can't create table './irie/#sql-4d0_86.frm' (errno: 150)
    
    Which through a strange series of translations thanks to bad error messages equals:

    Code:
    mysql> SHOW INNODB STATUS;
    ------------------------
    LATEST FOREIGN KEY ERROR
    ------------------------
    070513 11:51:55 Error in foreign key constraint of table irie/#sql-4d0_86:
     FOREIGN KEY (roles_id) REFERENCES rbac_roles (id):
    Cannot find an index in the referenced table where the
    referenced columns appear as the first columns, or column types
    in the table and the referenced table do not match for constraint.
    Note that the internal storage type of ENUM and SET changed in
    tables created with >= InnoDB-4.1.12, and such columns in old tables
    cannot be referenced by such columns in new tables.
    See http://dev.mysql.com/doc/refman/5.0/en/innodb-foreign-key-constraints.html
    for correct foreign key definition.
    In short, rbac_users_has_roles(roles_id) has a different type to rbac_roles (id).
    To fix this I removed the unsigned from rbac_users_has_roles(roles_id)
    Code:
    mysql> alter table rbac_users_has_roles change roles_id roles_id int(11) NOT NULL;
    I guess this will only impact if you get beyond 2147483647 rows in rbac_users_has_roles? (a scary thought).
  12. caphrim007 New Member

    Thanks for that Dave. I receive the same error on MySQL 4.1.20 but your change fixes it there as well.
  13. ben Administrator

    I have just uploaded the RBAC admin files to the server. You should be able to download the files from the 1st post on this thread. If there are any issues please send me a PM.

    Cheers,

    Ben
  14. ben Administrator

  15. mjlecomte New Member

    Re: thanks & best regards...

    Just curious if Cem or anyone else has ported this to CodeIgniter. I went looking at CodeIgniter to no avail.

    Is the admin panel now in the zip?
  16. ben Administrator

    Re: thanks & best regards...

    Yes. There are two zip files. One just contains the RBAC classes the other contains the RBAC classes + all the admin panel files. (You can tell by looking at the sizes.)
  17. mjlecomte New Member

    Thanks, that's great.

    I'm new to access control, and "RBAC" seems to be what I am looking for. I was wondering if you could briefly state pros or cons or limitations or recommendations of 3 designs:

    1. this one
    2. phpGACL (PHP Generic Access Control Lists)
    3. radicore (A Role-Based Access Control (RBAC) system for PHP)

    #3 has a RBAC wrapped up inside a framework, and there is a licensing issue. So I may not be able to use that one, despite any merits of the logic (although Tony appears to have a sizeable background designing these things so I hate to dismiss it outright).

    Whichever one I end up with I plan to port to CodeIgniter.

    Thanks for any thoughts you may have.
  18. ben Administrator

    I am aware of both these systems, but cannot give a detailed analysis of them since I only looked at them briefly about 2 years ago .... so some things may have changed.
    At the time I was looking for a RBAC framework and downloaded/installed phpGACL. I played around with it, read the documentation but (call me slow if you like ;-) I just couldn't see how to make it work for my situation. It was actually after spending some time trying to understand the intricacies of phpGACL that I decided to make RBAC_bv.

    Concerning Radicore, I remember reading Tony's pages and found them interesting. A lot of his work is worth reading, even if it is just to get a different perspective on tackling a problem.

    The main aim I had when making RBAC_bv was that it had to be conceptually easy to understand and still flexible.

    It had to be fast and efficient and cater to simple as well as complex situations alike.

    90% of web apps only need simple role based access control mechanisms to deal with a user who has just logged in, such as 'is the user a member?' or 'is the user an administrator?'
    Basically we just want to determine the role of a user. (i.e. member, admin, moderator etc...). RBAC_bv can do that very quickly.

    If you look at the picture of the database design on the first post of this thread you will see that the whole design follows a pyramid structure with the roles defined at the top and the finer details defined at the bottom. So in essence you can drill down the pyramid to get finer and finer permission classification for the user.

    RBAC_bv allows you to query the database at any point and retrieve all the information you need with just one query.
    For example, you can find out with just one query:
    - all the roles assigned to a user
    - all the privileges assigned to a role
    - all the domains assigned to a role
    - all the actions assigned to a privilege
    - all the objects assidned to a domain

    which means you can also determine with just one query:
    - all the actions a user can perform or not perform on any object.

    conversely you can also find out quickly which users have a certain role and therefore which users can perform a certain action on a given object.

    The key however to all this working nicely is taking time to think through the actions and objects you will be dealing with and grouping them appropriately together.


    So in summary the advantages would be:
    - Easy to understand (I hope ;-)!
    - Easy to extend
    - Can be used as a fine grained or coarse grained RBAC framework depending on your requirements
    - Efficient and fast (However I have never run tests to see how it compares in speed to the other systems... any takers?)
    - BSD license


    Disadvantages:
    - Not polished. The main purpose of this thread is really to share an idea, a concept that others can take and improve upon. That is why all the code is released under the BSD license. So don't consider RBAC_bv unless you are willing to get your hands durty ;-)

    For anyone wanting to integrate RBAC_bv into their own framework, I would be glad to help in any way I can.
  19. mjlecomte New Member

    Hi Ben,

    Just curious if you ever happened across LiveUser (http://www.gvngroup.be/doc/LiveUser/permission_complex.php)?

    phpGACL seems to have been around the longest and allegedly has had numerous users. I'm a little surprised that none of these ACLs (phpGACL, LiveUser, this one) aren't more "organized" for lack of a better word. This is not in reference to the quality or merits of the class itself, but moreso the documentation. So like you mentioned in one of your earlier posts, I guess I'm a bit too slow as well and am not sure how to use the class, that's where your concept shines to me, it is easier to grasp looking at the ERD.

    Do you have an idea how to implement user management in your system? That is, how to handle controlling administration rights of users? I have a situation where I might want to ability to have "admins" or "department managers" create users or assign rights to other users. The scenario comes to mind where you want to limit what rights could be assigned, for instance you would'nt want a "department manager" to be able to create a "super administrator" etc.
  20. ben Administrator

    Yes, I came across LiveUser when I did my original research. I just quickly read through the docs and looked at their diagrams, but didn't do too much with it since it 'looked' complicated.
    Admittedly, anything new looks complicated, but for some reason it just didn't click. That is why I like 'choice' in the open source world. There are more than one ways to achieve the same end result, it is just a matter of finding the one that works for you.

    True. I can't comment on the other systems but as for RBAC_bv, the key, (as I have already mentioned before) is in the database design. If you take the time to study the design and play around with it you will see that you can retrieve any piece of information you want with just one query.
    All the methods I have written are mainly SQL queries with a little post processing. If you looks at the code I have written you will see what I mean.

    We must think the same ;-) However I am sure to many people the ERD would be more confusing.


    Yes. In actually fact you already solved the problem without realising it. (Which reminds me I should upload a pdf document that explains what I am about to say.)
    The privileges defined in RBAC_bv follow the rules of the english language. I won't go into this in detail because they are discussed in the docs. But to answer your question, you would create a role called 'department manager' you would then create an action 'create' and an object 'user'. You then link the action to the object in the 'rbac_roles_has_domain_privileges'. (i.e. it is just a record that states that the role 'department manager' is allowed to 'create' a 'user' object. (As opposed to not being allowed to perform a certain action))


    This is precisely what RBAC_bv is designed to do. i.e. clearly define the privileges of each user group, so they don't conflict with one another.
    In your case the object 'user' would be associated with the role 'simple_user', so that once a new user was created you could assign to them the role of 'simple_user' which would be defined as the right to 'view' the 'public_pages' object. (or whatever you want really.)

    I hope this helps a little.

Share This Page