Balancing permissions

The Bukkit project now has a permissions system on the cusp of release. Since its method is heavily based off my proposal, I’m going to go over what my system (and Bukkit’s derivative) entails and the design decisions that went into choosing the final system. Now, authorization and permissions is a fairly major design decision. It’s not something that can be easily changed later, and the final system must strike a balance between ease of use and power. The system also has to be fast for components to repeatedly access and reduce the chances for errors made by the person configuring the permissions.

My suggestion involved a hierarchical system where child nodes would inherit the permissions of their parent. A child node could still override a parent’s permissions, however. For example (I am using periods to denote children):

  • Alex could have access to articles.manage
  • Sarah could have access to articles.manage.add and articles.manage.delete

In that case, Alex could add, edit, and delete articles because all three nodes would be children of articles.manage (which Alex has been given access to). Sarah, however, would only be able to add and delete articles. This alone makes for a lot of power when defining permissions as it removes a lot of redundancy. Components can also, especially if we stick with my dot notation, easily check for permissions by asking for the most specific child. The add page, for example, can simply check to see whether the user has access to articles.manage.add. As cool as that is, it starts getting even cooler when you start using dynamic permissions. Say you want to give Sarah the ability to edit some articles. How about only articles she owns and the articles of Jon? A component could simply check this on the fly:

  • Does Sarah have access to articles.manage.own?
  • Does Sarah have access to articles.manage.others.Alex?

Only one of those two conditions needs to be true and Sarah would be given access. In the case of Alex, who has the articles.manage permission, because own and others.Alex are children of articles.manage, Alex’s permissions would still continue to work. (Note: I later learned that some permissions systems have an “immunity” rank that somewhat simulates this. A hierarchical system gives more freedom.)

For all of the power that a simple hierarchy can provide, this system alone has some major limitations. What if you wanted to give Sarah access to everything in articles.manage but articles.manage.edit? You could list all the other children but edit, but this starts becoming unwieldy if articles.manage has a large number of children. This problem can be mitigated several different ways. My personal favorite, which I’ve used a number of times in the past, is to give each permission three or four different ranks:

  1. None (cannot be assigned to a permission)
  2. Allow
  3. Deny
  4. (optional: Strong allow)

NONE has the lowest precedence and the ranks grow in precedence down the list. So let’s reframe the problem of giving Sarah everything in articles.manage except for articles.manage.edit. Let’s first assume that all permissions start out, if undefined, as NONE, and that NONE means no access. Sarah would have:

  • ALLOW articles.manage
  • DENY articles.manage.edit

DENY overrides ALLOW, and so that would accomplish precisely what we would want. Setting access flags allows for a sufficiently powerful and yet fairly simple way of delineating the order in which permissions are to be applied. Most importantly, while I’ve only been discussing assigning permissions to users directly, if you were to apply this to groups, you could easily create groups with DENY or ALLOW permissions and reasonably know how the permissions for a user would turn out. Because you know DENY always overrides ALLOW, you could safely and carefully assign a (helpfully named) group to a user and have little question of the result. A cool use case would be:

  • You want to give Jon access to everything administrative but the power to restart.
  • You create the group “Administrators” with ALLOW for admin.* (wildcards!).
  • You create the group “No Restart” with DENY for admin.restart.
  • You give Jon membership for both groups. It works out.

There some deficiencies with using fixed access states though because you are essentially limited to two or three ranks, if you have complicated deeply hierarchical permissions, it becomes impossible to achieve what you want. I’ve implemented my system (with the tri-state or quad-state access flags) a few times and I haven’t run into too many cases where it was a major problem, but it’s something to consider as it does cripple the power of hierarchy a bit. Solving this deficiency unfortunately adds some complexity to the system, but it may be worthy to consider depending on the need. Two solutions I’ve considered are:

  • Rather than assign access ranks to individual permissions, use the order that the permissions are defined in to delineate the permission resolution order.
  • Instead of using a fixed number of access states for each permission, assign a number instead.

The first solution is not something I’ve ever seriously considered. I don’t like it because permissions can get very complicated when you have multiple groups per users and complicated inheritance trees (both of which I find essential to a powerful permissions system). If you have a few groups and a reasonable number of users, it won’t be to terrible, but once you start attaining tens of groups (with many inheriting each other) and eventually assign someone else that isn’t you to manage permissions, it may result in confusion. With permissions, that’s really bad. The last thing you want to do is to give that questionable user access to something that they shouldn’t have access to to begin with. However, it does solve the problem.

The latter solution is a bit more complicated than using a fixed number of access states because users have to remember differing levels of access. It solves the deficiency with using a fixed number of states though. If you need deep hierarchies of permissions, then I personally recommend this solution, but the other one has its strengths as well. To reduce the problem of requiring administrators to keep track of numeric access levels, a table of aliases (such as DENY = 10, ALLOW = 5, etc.) can be used.

Now, for all of this power, especially when you provide inheriting groups and multiple groups for users, makes for some complicated code. You have to cache resolved permissions to ensure that queries are fast, and when permissions change, you have to selectively invalidate the cache. Lastly, this is pretty damn complicated for your normal person, so GUIs greatly help.

Bukkit is using hierarchy just as I proposed. To handle ordering of permissions, it is using the order of permissions as defined in order to delineate resolution order. Permissions are actually not tied to groups; they are tied to “access profiles” and instead groups can be assigned an access profile. Users can be part of multiple groups at once and groups can inherit each other.

Note: There’s a plugin for Bukkit that something like this (but considerably simpler). I was discussing this system at the time and he picked it up.


9 Responses to Balancing permissions

  1. Thanks for the detailed post!

    So will this be directly tied into the core of craftbukkit or will it act as a 3rd party plugin but be sort of supported as the official permissions plugin?

    Also if it is planning to be in the core what else were you guys planning on adding at core level?

    Thanks,
    Kane


    • It will be a part of core. I can’t say what else will be added — whatever core components that needs to be added will be added.


  2. I don’t care as long as it works (unlike current Permissions) . Also, SQL support would make quite a lot of server owners really happy.


  3. Well thank god I switched from GroupUsers to Permissions. Looks very similar.

    At first it sucks, and for new users it’s a nightmare to look at….but once you understand it, it’s incredibly simple – and far better than hey0′s native permissions…


  4. “The Bukkit project now has a permissions system on the cusp of release”

    I notice that you wrote this in January. Do you know the current state of this project?


  5. Has it been released now and have i missed it :P . If not do you know when it will be ready and how do you edit it. Though commands in game?


  6. How do i make it so my Moderators have /jumpto, /thru all them etc.


  7. Um is the server down currently, the james one?


Leave a Reply

Your email address will not be published.

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>