|
Cookbook /
SecLayerSummary: Provide a ready-made security layer for controlling page access
Version: 2008-08-21
Prerequisites: 2.2.x beta
Status: Alpha
Maintainer: Peter Bowers
Categories: DevelopmentTool
Download: Attach:SecLayer.phpΔ
Questions answered by this recipe
DescriptionA tool for recipe developers to aid in adding a security layer.
NotesSecurity is determined by a combination of 4 elements: (1) page pattern, (2) authorization level, (3) (optional) priority, and (4) (optional) user ID. To facilitate administration users can be combined into @groups and you can set up aliases for one or more authorization levels. Note that SecLayer does not require a certain set of authorization levels - the recipe using SecLayer defines which authorization levels are valid. As a reference, here is a definition of what is contained in each of these 4 elements:
These elements can all be set up on an auth-config page as colon-delineated fields. This auth-config page is then parsed via a call to slParsePage() (usually in config.php) prior to any calls to slAuthorized(). If an administrator prefers to set things up in config.php rather than on an auth-config page then he/she may do so via calls to slAddAuth(). A typical config.php making use of SecLayer might look like this:
include_once("cookbook/RecipeX.php");
include_once("cookbook/SecLayer.php");
slParsePage($pagename, "SiteAdmin.RecipeXAuth", $AuthRecipeX);
slAddAuth($AuthRecipeX, "SiteAdmin.SecretPage", "edit", 1, "joe,sally");
(The specifics of a particular recipe's use of SecLayer will have to be defined by that recipe -- that example config.php is purely hypothetical.) Here is what a simple auth-config page might look like (accepting the defaults for user IDs and priority): Test.*:read,edit Group.*:read,edit Group.VitalPage:-edit (:if ! auth admin:) Group.Secret:-read,-edit (:endif:) What this mean is that any file in the Test group can be read or edited by the calling recipe. And any page in the Group group can be read and edited EXCEPT that Group.VitalPage does NOT allow editing and the page Group.Secret allows neither reading nor editing unless you ar. The entire page (or section) will be processed using the "if", "comment", and "include" rules before slParsePage() starts to see what authorizations are actually contained there. This allows you to do conditionals based on If an administrator prefers to use a syntax which approaches page-specification in Test.*:read,edit Group.*:read,edit -Group.VitalPage:edit (:if ! auth admin:) -Group.Secret:read,edit (:endif:) As you can see the negation (exclusion) can be applied either on the page patterns or on the authorization levels. One says "for this page (pattern) you are not allowed to do this action" while the other says "when authorizing this action exclude this page pattern". (It is possible to negate both the page pattern and the authorization level resulting in a POSITIVE INCLUSION (2 negatives equals a positive), but that's just plain confusing and not recommended unless it's really neeeded.) Aliases and groups can be defined by use of the "=" operator. What this means is that any given token will be expanded to another set of tokens. So this definition: @admins = jack,sally,sam means that every time the token @admins occurs (for instance, in a user list) it will be replaced by those users. You are not limited to user groups -- an alias can also be defined for a set of authorization privileges or a set of page patterns: all = read,edit,attr none = -read,-edit,-attr adminfiles = SiteAdmin.*,Site.Myprivatepage Aliases and groups are synonyms. By convention the "@" character is used as a prefix for groups of users. Be aware that this is up to the administrator - it is not something enforced by SecLayer. (In other words, you are free to put the @ before groups or not and you can also put the @ in front of other aliases - you'll just confuse anybody else that tries to administer your site...) Aliases and groups can be defined recursively, with one alias containing another alias. They will all be expanded as expected. If a given definition would become an infinite loop then the situation will be prevented, but the name of the alias will end up as a token. For instance, in these definitions: most = read,edit all = most,attr @groupA = sam, @groupB @groupB = jack, @groupA The token "all" will now become "read, edit, attr" after "more" is expanded. The token "@groupA" will contain "sam, jack, @groupA" and the token "@groupB" will contain "jack, sam, @groupB". Leaving the group is necessary in a case like this to prevent an infinite loop. Let's define another auth-config page, this time including a @group and a couple aliases as well as introducing the user field: @admins = jack,sally,sam all = read,edit,attr none = -read,-edit,-attr Test.*:all::@admins Group.*:read,edit::@admins,-sam Group.VitalPage:-edit Group.Secret:none As you can see, the fact that we specify users on one line doesn't mean we need to do so on all lines. The rule is simple -- whenever the user field is not included it will default to a user '*' which means all users. Note that negation is handled differently between users and other fields. A negated user removes that user entirely from that authorization - not that he is negatively authorized (proscribed) but that that user is simply removed from that context of authorization. Negation in a page or authorization context, on the other hand, actively negates the authorization being provided. This is an important consideration when the priority field is in use or when all of a given group except one or two will be given a certain authorization. In this example: @powerusers = sam, jack, sally SiteAdmin.PageX:edit::@powerusers, -jack GroupA.*:-edit::jack -GroupB.*:edit::jack Jack has specifically been denied authorization from any pages in GroupA or GroupB. (In one the authorization was negated and in the other the page was negated.) However, for SiteAdmin.PageX his authorization was simply not defined. This means that a lower priority authorization could still authorize him. (If no other line authorizes him he will still not be authorized because there has been no explicit authorization for SiteAdmin.PageX.) In general, SecLayer operates on this rule:
This means that an auth-config page like this will not allow writing to any page in the SiteAdmin group, even to the MyRecipe page: SiteAdmin.*:-read,-edit,-attr SiteAdmin.MyRecipe:read,edit This is because the presence of the matching exclusion always over-rides any possible inclusion. Because of this problem there SecLayer also has a concept of priorities: SiteAdmin.*:-read,-edit,-attr:2 SiteAdmin.MyRecipe:read,edit:1 This means that the inclusive pattern for MyRecipe is at a higher priority than the exclusive pattern for SiteAdmin.* and so we will not get to the lower priority pattern at all. The generalized rule above becomes a bit more complicated when priorities are introduced.
slParsePage() takes 3 arguments:
slAddAuth() takes 5 arguments:
Once the array containing the authorization table has been initialized using either/both of slParsePage() and slAddAuth() then the recipe can make use of slAuthorized() function prior to reads/writes of pages to make sure that the security layer is enforced. slAuthorized() takes 3 arguments:
3 other functions are provided as wrapper functions for the basic PmWiki functions UpdatePage() and RetrieveAuthPage(). These wrappers will enforce SecLayer security prior to calling the basic functions. These functions follow: slUpdatePage()
slUpdateAuthPage()
slRetrieveAuthPage()
Note that for some of these wrapper functions you will need to specify arguments which were previously default (in the base function) in order to specify arguments which follow. There could still be some movement in the order of these arguments to minimize this type of difficulty. Release Notes
See AlsoContributorsThe basic approach to the auth-config page is borrowed from fox. Comments |