Access control in Phosphorus Five

I have just now significantly refactored authorisation or access control in Phosphorus Five, as you can see from its code. In addition, I’ve also removed a couple of “anomalies”, which arguably were bugs in its code – Some quite severe too may I add. Hence, I wanted to write up about how access to an object is granted or denied in Phosphorus Five, hopefully allowing you to more easily create your own access objects, granting or denying access to specific parts of your Phosphorus Five installation.

First things first, an access object in Phosphorus Five determines whether or not one or more roles have access to some part of your app. The role is the name of the access object’s root node, and whether or not it grants access or denies access to that role to the part in question, is determined according to its name, which can end with either “.deny” or “.allow”. Secondly access objects are “cascading”. What I mean by that, is that they obey to similar rules as a CSS selector. For instance, if I deny access to the path “/foo/” to some role, then unless explicitly overridden in another access object, that same role will be denied access to also “/foo/bar/”.

In addition you can create access objects that are referencing all non-root roles, by creating an access object with a role name of “*”. This implies that the access object is for all roles in the system, except the “root” role, which has access to everything always, and cannot be restricted in any ways. In addition each access object have a “type”. The type declaration of my access objects allows me (or you) to extend the access system, by creating your own types of access objects. By default though, there are the following access objects in Phosphorus Five.

  • p5.module – Determines if access to module is given or not
  • p5.io.read-file – Determines read access to files or folders on disc
  • p5.io.write-file – Determines write access to files or folders on disc
  • p5.hyper-core – Used in Hyper Core to determine access
  • p5.system.platform.execute-file – Used to determine if user has shell execute access to a file on disc

All of the above types are expected to have one of “.allow” or “.deny” after their names. If I wanted to grant access to the “foo” user to write to the files within the folder “/foo/bar/” for instance, I could create an access object resembling the following.

foo
  p5.io.write-file.allow:/foo/bar/

The above would allow all users belonging to the “foo” role to write to all files beneath “/foo/bar/”. Though it presents us with a dilemma, which is that it also allows the user delete the folder or rename it. This might not necessarily be what you want, so you can further restrict this operation, by adding another (parametrised) access object to your list of access objects.

foo
  p5.io.write-file.allow:/foo/bar/
foo
  p5.io.write-file.deny:/foo/bar/
    exact:true

Notice the [exact] parts above. Since a “deny” object always have precedence when two access objects have the same path and role name, if the user tries to rename or delete the “/foo/bar/” folder itself, the last access object from above will have precedence, and hence prevent the user from deleting or renaming the folder itself. However, since the last access object from above has an [exact] argument, it will only match the specified path, if it is exactly “/foo/bar/”. Hence, in our above example we first allows the user to write to everything inside of the folder “/foo/bar/”, for then to deny him to change the “/foo/bar/” folder itself. This gives the “foo” user complete control over everything inside of the “/foo/bar/” folder, but not the folder itself. An access object can be parametrised with the following arguments.

  • [exact] – Requires an exact match
  • [file-type] – A list of pipe separated file extensions, such as e.g. “hl|md|js”
  • [folder] – Requires the path to end with a “/” for the access object to be a match

This gives you an enormous flexibility, allowing you to for instance allow the user to only write to JavaScript and HTML files, restricting write access to all other files in the same folder. Or for instance allowing the user to write to all files inside a folder, but not to create, delete or rename folders. Etc, etc, etc. Below is an example of granting the “designer” role write, create and delete access to HTML, CSS and PNG files for instance inside your “/foo/bar/” folder.

designer
  p5.io.write-file.allow:/foo/bar/
    file-type:html|css|png

If you in addition want to allow the designer role to create folders too, you can accomplish that with the following.

designer
  p5.io.write-file.allow:/foo/bar/
    file-type:html|css|png
designer
  p5.io.write-file.allow:/foo/bar/
    folder:true
designer
  p5.io.write-file.deny:/foo/bar/
    exact:true

The above allows the “designer” role to create, delete, or rename JavaScript files, HTML files and PNG files inside of the “/foo/bar/” folder. It also allows him to create, delete, or rename existing folders inside of the “/foo/bar/” folder, but it prevents him from editing or deleting the actual “/foo/bar/” folder itself. By using the “*” role, you can also give all user access to write to files in some specific folder, and then afterwards restrict one or more roles. The following code allows everybody except the “guest” account to write to HTML files inside of your “/foo/bar/” folder.

*
  p5.io.write-file.allow:/foo/bar/
    file-type:html
guest
  p5.io.write-file.deny:/foo/bar/

The above logic will work since an explicitly named access object (our “guest” object from above), will always have precedence over an “*” object. Since all IO operations will check to see if the user has access to the file according to the access object list, this creates a fairly secure way to grant or deny users access to parts of your Phosphorus Five installation. You can also create your own types of access objects, extending the authorisation features of Phosphorus Five with your own logic – However, that is the subject of another article later …

Advertisements

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.