[[toc]] + Horde Policies The idea of Horde Policy is to implement a replacement for the current prefs system, modeled after how Group Policy Objects work in a Microsoft Active Directory. Including a nice administrative GUI, meaning no more editing prefs.php files, and happier admins. ---- ++ Visualization of a Horde Policy <code> policy |-- name |-- targets | |-- target1 | `-- target2 |-- app1 (ie, imp) `-- app2 (ie, turba) |--attribute-group1 | |-- attribute-group2 | | `-- attribute1 | `-- attribute2 `-- attribute3 </code> * each app would have a policy.xml file defining what policy attributes are available. * A target can consist of one or more: * entire installation * horde application * horde group * individual user * guest user * build a Horde Policy manager to list, create, edit, delete, etc. policies. * Store Horde Policies in DB table(s) * horde_policy table(s)? * extend the datatree? The data structure fits perfectly with a few performance tweaks ---- ++ Storage In order to make Horde Policies as generic as possible, it's probably best to specify a new backend for them. Then we can write policy drivers for the various parts of Horde that might use them, such as Prefs. I'm a big fan of the Datatree structure, slightly simplified, to hold the Policy information. The !DataTree itself has proved not to scale very well, but I think by removing a few unneeded fields (for this application, at least), we can reduce the number of JOIN statements, and it should scale just fine. Another thing to think about is how many Horde Policies is a given site going to have? Probably no more than a handful on average. Anyway, here's a new table structure idea: <code> horde_policy ------------ policy_id policy_name </code> <code> horde_policy_attributes ----------------------- policy_id <-- what policy this attribute belongs to. attribute_nameattribute_scope attribute_state <-- mask for things like enabled, disabled, overridable, etc. attribute_type <-- what data type are we working with?attribute_value</code> <code> horde_policy_targets -------------------- policy_id target_idattribute_scope <--uid, gid, app-name, or global/default target_typewhat app is this attribute defined in? attribute_overridable <--'uid', 'gid', 'app', or 'global'/'default' </code> Wecanget the attribute group structure from the XML file. No need to worry about storing it, just need to enforce that all attributes for a given app have unique names. If therethe value be overridden? attribute_type <-- what data type aretwo attributes with the same name,weshould use the last one found in the XML file. ---- ++ Cascading Heirarchyworking with? </code>Listed<code> horde_policy_targets -------------------- policy_id <-- what policy this target belongs to. target_id <-- uid, gid, app, site, or guest target_type <-- 'uid', 'gid', 'app', 'site', or 'guest' </code> We can get the attribute group structure from the XML file. No need to worry about storing it, just need to enforce that all attributes for a given app have unique names. If there are two attributes with the same name, we should use the last one found in the XML file. ---- ++ Cascading Heirarchy Listed by priority, highest-priority first. All levels would need to be checked, though, as some lower level might have the overridable bit set to false. * **user-defined** - value defined by the user. * **uid** - policy applied directly to the current user. * **gid** - policy applied to a group that the current user is a member of. * **app** - policy applied to currentappapp. * **site** - policy applied to entire site. * **default** - default value pulled from XML file. When loading a policy, we should go bottom-to-top in this list. Any new values in higher levels can just overwrite the values found in lower levels, unless a lower level has specified that the value is not overridable. We need to work out a way to resolve collisions at a given level. For example, a user might be a member of various groups, and each group might have a different value set for a given attribute. If there is not a value set at a higher level, how do we decide which takes priority? Sort alphabetically? Give a priority to overridable? Add documentation saying that this behaviour is undefined and leave it up to admins to avoid collisions? ---- ++ Cache At login, all applicable Policies should be loaded and cached. We should also try to do something to cache Policies for guest sessions. Could we use Horde_Cache for this? ---- ++ Other Thoughts * all $pref->getValue() calls could be handled on the backend by writing a Policy driver for the Prefs system, giving us a drop-in replacement. * we'd need a way to clearly define what happens if two Horde Policies have overlapping, conflicting settings. * Keep a history of who created or edited a policy, and when (maybe even track what changed). Can we use the history classes for this? * Do we need a Policy "manager" object like we have with the !DataTree? Or should we include static functions to Horde_Policy? do static functions get copied for each instance of an object? If so, the "manager" object might be the way to go. ++ API Some thoughts about an API for Horde_Policy <code type=php"> class Horde_Policy { var $name // policy name var $targets // array of targets var $attributes // array of attributes var $_params // storage parameters function name($name) {} // get/set policy name function attribute($attribute, $params) // set given attribute function addTarget() function removeTarget() function listTargets() static function getPolicyAttribute($attribute) // go through the cascading heirarchy, and return the value with priority (see Cascading Heirarchy above) } </code> Still need to be able to read from XML, not sure if that should be put in the constructor, or in the public API. Also need to be able to save to backend somehow. ---- ++What happensSteps involved when applying a Horde Policy * read XML file(s) to set up internal attribute tree with default values. * see if any policies target the current user, if so... * go through target cascade (see above), pulling values from SQL * overwrite default values with values pulled from SQL * cache Should we apply Policy values at login, or when an app is loaded? ---- ++ Links http://www.microsoft.com/technet/itsolutions/msit/security/grppolobjectmgmt.mspx - gives a good overview on how MS GPO's work, and a nice graphic that really helped me visualize the internal workings. ---- ++Cut & PasteLong term goals from mailing listuntil I can better organize my thoughts> - with something like this in place I think it would make more and > more sense to move everything that's at all user-related in conf.php > files to this system. Things like "user capabilities" in both Horde > and IMP - they can even be locked (overridable = false?) by default, > but letting people easily manage them on a per-group basis, or > whatever, sounds very good to me. Just brainstorming here, but we could even go a step further and use this type of system for all of the configs (except for maybe the very basic stuff, like authentication). Doing so would let different groups have different configs, which might be helpful for sites hosting for various groups. > If there were a way to manage, say, IMAP server configs, or other > backend configurations (sieve servers, etc.) using this system, that > would be even better. Yes! We could put IMAP server configs, etc. in a GPO and assign to targets as necessary. Same way that printers can be assigned in an active directory. "group A uses this IMAP server, group B uses this other IMAP server, group C gets to specify their own IMAP server." The possibilities are endless! I love it!