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.
The Horde_Policy system should be able to replace all user preferences and most admin/file-level configuration. Policies should be nestable; it should be possible to load policies based on arbitrary criteria such as time of day, server load, user group, IP address, etc; administrators should be able to define at each level of the policy tree whether a value can be overridden. End users would only see the values that could be overridden, but should still be able to create multiple policies (probably not nested, though, for simplicity) that could be switched between, like "Locations" in some systems or separate "Home" and "Work" profiles (or probably more useful, Desktop and Mobile browser profiles).
From a system standpoint there should be three kinds of policies: PHP files on disk that can contain arbitrary logic (obviously admin only), YAML or JSON files on disk that contain a list of keys and values plus metadata (overridable or not, but no conditions), or policies stored in a SQL database or other backend storage, which would be functionally equivalent to on-disk JSON/YAML files.
When the policy system is fully implemented, the only classic configuration necessary should be enough information to point to the root policy. This could be as simple as the location of the root .php file that loads all other policies (though other policies might not be required), which would essentially eliminate ALL other configuration.
To avoid having a huge tree in memory, policies will be split out on a system level, such as main config, main preferences, mime driver configuration, etc. Applications will be able to either override system values or add their own keys, like they currently can, so that the Policy system will automatically reconcile IMP-specific MIME settings when in IMP's context.
From an end-user perspective, though, there should be one policy (or two, if they have Home and Work policies), with tabs/sub-sections for apps and section settings.
policy |-- name |-- targets | |-- target1 | `-- target2 |-- app1 (ie, imp) `-- app2 (ie, turba) |--attribute-group1 | |-- attribute-group2 | | `-- attribute1 | `-- attribute2 `-- attribute3
This structure should be easy to cache when a given app is loaded. something like if (!isset($policy[$app])) { load $policy[$app] from xml } .
Not something that we would really enforce in code, but we could have an organizational convention that we stick to in the xml files, so that each app has a common policy structure. Something like 'prefs', 'config', 'backends', 'servers', etc.
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:
horde_policy ------------ policy_id policy_name
horde_policy_attributes ----------------------- policy_id <-- what policy this attribute belongs to. attribute_name attribute_value attribute_scope <-- what app is this attribute defined in? attribute_overridable <-- can the value be overridden? attribute_type <-- what data type are we working with?
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'
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.
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.
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?
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?
Some thoughts about an API for Horde_Policy
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 addTarget() function removeTarget() function listTargets() function readXMLPolicy() function loadAttributes() function storeAttributes() function loadTargets() function storeTargets() function attribute($attribute, $property, $value) }
We should also have a Horde_Policy_Manager class for administration purposes
class Horde_Policy_Manager { }
Should we apply Policy values at login, or when an app is loaded?
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.
- 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.
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.