Configuration 4 GNU (CFG)


CFG Middle Layer

Prev   Next

The middle layer manages the loading and saving of configuration XML documents. It is responsible for authorizing a user to perform reads and writes to a particular configuration object. It handles a large amount of the system's validation. Because it does the loading and saving, it may run as a separate, privilege process (one that has full access to the native configuration files). If it runs as a separate process, communication between the upper layer and this layer will use some sort of IPC. Preferably, this IPC would be flexible and extendible, like CORBA or SOAP. Whatever technology is chosen, however, security of the privileged process is absolutely and totally required.

Loading and Saving

The front-ends will have various mechanisms through which an XML representation of a configuration can be loaded or saved. To load a part of configuration, an "import" object would be created, containing properties such as "parser-module" and "configfile" that contain the name of the parser to run and the location of the exact configuration to load. Once this import object is created, the client will invoke its "expand" method. The "expand" method runs the requested parser and makes the object tree generated by the parser available as properties and children of the import object itself.

To save a part of configuration, one would use the "save" method of the import object. This save method again runs the appropriate parser, provides it the updated object tree, and has it rewrite the native configuration file.

As part of the load/save process, attention will be paid to access control, logging changes, etc. in the lower layers. In some cases, there may not actually be "native configuration files," in which the XML will simply be saved as-is to a file on disk.

File Access and Caching

All file access related to parsers will be handled by the section of the middle layer which interfaces with the bottom layer. This means that for cache hits, the parsers will not be consulted at all, and provides a point to track which files are read/written and make them available when needed.

Parser Access to Files

Parsers need access to various config file on multiple machines. To handle reading/writing to these files, the parsers must go through the middle layer's API. Initially, all parsers will be given access to a single main file, which the middle layer will be responsible for opening either at the start or end of the parser's execution (depending on whether loading or saving is taking place). Subsequent files must be requested by the parsers through the middle layer's API. For loading, the file will be given to the parser as an array containing each line of the file. For saving, the parser will give the middle layer a string to write out.

To help uniquely identify files, any file other than the main config file must be specified by its full path by the parser during loading/saving API calls. For the primary config file, the filename should be left blank in the API calls. The full path to the config file must be calculated by the parsers, as the way of determining the full path varies between config file formats. At this time there is no known config file format which specifies an included config file which is on a different host than the primary config file, so the host for included files will be assumed by the middle layer to be the same as the primary config file.

The following functions will be used for parser/middle layer interaction:

string[] load_primary_file();

Returns an array containing each line of the primary config file. The parser does not know the name of the primary config file, but the middle layer should be able to easily determine it. If the primary config file is a directory, the array should be a list of files in that directory. If there is no primary config file, returns null.

void save_primary_file($output); 
string  $output - The string to save;

Saves $output into the primary config file.

string[] load_secondary_file($fullpath); 
string  $fullpath - The file to load;

Returns an array containing each line of the specified config file. If $fullpath is a directory, the array should be a list of files in that directory. Returns null on failure. Note that the file may not really be located at $fullpath, $fullpath is just where the parser thinks the file should be. The middle layer may look on another host, add a prefix to the path, etc.

void save_secondary_file($output,  
 $fullpath); 
string  $output - The string to save;
string  $fullpath - The file to save to;

Saves $output into the secondary config file $fullpath. Note that the file may not realy be located at $fullpath, $fullpath is just where the parser thinks the file should go. The middle layer may store it on another host, add a prefix to the path, etc.

During loading, the middle layer is responsible for appending XML to the root node to track files which the XML document depends on and maintaining the most recently modified file's timestamp for inclusion into the XML.

Storage of Cached XML & Data

The XML will be stored in a directory to be determined (probably .cfg in the user's home directory until privilege escalation code is added to CFG) with the same permissions as the original primary config file. Ideally, a single system-wide location would be used. A subdirectory will be created and named after each host for which XML data is cached. The domain name will be used if available, otherwise "localhost" or the primary IP of the machine will be used. Slashes (forward or backward) in the full path of the file will be replaced with underscores (double slashes will be replaced by a single underscore), and any underscores already in the path will be replaced with double underscores. Additionally, the unix timestamp of the modification time of the primary file will be appended to the filename. So that the file /etc/weird_app/main.conf for localhost modified at timestamp 500000000 will be stored in CACHEDIR/localhost/etc_weird__app_main.conf.500000000. Note that if main.conf were to include a file with a later modification time, the latest modification time of all the relevant files would be appended instead.

The file will be owned by the user running CFG, or by root when system-wide caching is implemented, and only be readable or writable by the owner (600).

Inside the actual XML, included config files will be listed directly under the root XML node. For example, if a main Samba configuration file /etc/samba/smb.conf includes the files /etc/samba/smb.extra.conf and /etc/samba/smb.more.conf, then the following XML would be stored in the cache, assuming the most recently modified time of the 3 files is 5000000.

Example 7. XML cache file etc_samba_smb.conf.5000000
<samba-config>
  <dependfile primary="true" host="localhost" owner="root"
        group="root" mode="0644">
    /etc/samba/smb.conf
  </dependfile>
  <dependfile owner="root" group="root" mode="0644">
    /etc/samba/smb.extra.conf
  <dependfile>
  <dependfile owner="bob" group="users" mode="0600">
    /etc/samba/smb.more.conf
  </dependfile>
  <dependstamp>5000000</dependstamp>
  <samba-global>
    ...
  </samba-global>
  ...
</samba-config>

Only 1 version of each config file is kept in the main directory for each host. Before a new cache file is written, older versions must be moved to an attic subdirectory for each host. This ensures that when checking the cache, the library will not have to waste time locating the most recent file. If a crash occurs, the worst case will be that the cache file will be prematurely moved to the attic subdirectory.

Caching

When an XML document load is requested, the cache is checked to see if a matching cache file for the given host and full path exists. Only one version of each config file for a specific host will ever be present in the main subdirectory for the host. If such a file is found, the timestamp appended to it must be equal to or greater than the timestamp of the primary config file. If so, each non-primary dependfile's timestamp must not be higher than the dependstamp. If so, the cache file is used.

If one or more of those conditions are not met (a cache miss), then the parser is run to generate the XML document being requested. The library appends dependfile and dependstamp tags to the XML as described above, and the file is stored in the cache. Any previous versions of the config file are moved into an attic subdirectory specific to the appropriate host.

During saving, the XML document is saved to the cache immediately after the config files are finished being written by the parser and middle layer. Any previous versions of the config file are moved into an attic subdirectory specific to the appropriate host.

Translations

Several types of translations will be done. In some cases, two XML documents it requested from two different parsers will need to be merged. For example, it may request an XML representation of a config file from the parser for that config file format, and then request an XML representation of the relevent man page from a man page parser. To make displaying context-sensitive help easier for the UI, it will then merge the data from the man page into the relevant nodes in the XML for the actual config data.

In some cases, default values will need to be added to the XML on its way to the UI, or be stripped from the XML on its way back to the unparsers. What cannot be done in a compatible way by the Schema files (default value adding) will be done here.

Plugins

Plugin capability will be available for the middle layer. Extended features such as more advanced authentication, remote configuration editing, logging and rollback, etc. will be available through plugins. These plugins will be non-specific to the application being configured or data in the XML. It will simply perform an advanced task with the XML.

Access Control

There are two aspects of access control. First, there is the process of authenticating the caller as who it says it is. Second, there is the process of authorizing the caller with given abilities.

Authentication

Users may select with what identities they will connect to the Config4GNU system. The identity will be some node that exists in the Config4GNU object model. Initially, the only identity possible to connect as will be the current user. Since users and groups will exist in the Config4GNU object model for each machine, the authenticated identity will be the user object for the current user.

Authorization

Authorization is done on the target objects. That is, to grant a user access to change a certain configuration, I will go to that certain configuration and add the user to the list of things allowed to make changes. This list is called an access control list (ACL) because it is a list of access control items.

Since the Config4GNU object model is XML-based, the following elements will be defined to represent access-control information.

Access Control Elements

access-control

specifies an inline access control list

access-class

references one or more external access control list definitions

The access-control allows an ACL to be specified directly with the relevant node that it covers (the context node). The ACL will be a list of users and groups and their associated privileges. The order is important, for the first access control item where the subject (i.e. user or group) matches will be the one that determines access.

Examples

Example 8. Use of the access-control element
<access-control>
  <aci>
    <match>user[name=root]</match>
    <privilege>readwrite</privilege>
  </aci>
  <aci>
    <match>user[name=jdoe]</match>
    <privilege>readonly</privilege>
  </aci>
  <aci>
    <match>group[name=admins]</match>
    <privilege>readwrite</privilege>
  </aci>
  <default>
    <privilege>none</privilege>
  </default>
</access-control>

In the above example, assume that jdoe is a member of the admins group. In this case, jdoe will have read-only access, despite the fact that the admins group has readwrite access. This is because jdoe occurs first and therefore will be matched.

Example 9. Use of the access-class element
<access-class>admin</access-class>

This effectively "includes" all the access control items that are defined in the access control class named "admin". The location where these external access control classes are defined is not yet determined.

Definitions

Access Control Definitions

access control list

zero or more access control items that have the same context node

access control item

defines a subject and a privilege for an context node

context node

the XML node on which an access control list is attached and for which it defines access

privilege

one of none, readonly, or readwrite

subject

any Config4GNU object, typically a user or a user group. If a "container" object is specified, then all objects that exist within the container will implicitly be given the same privilege

Query Subsystem

This subsystem will be responsible for all queries to the system. It should incorporate any optimizations that it can, including for instance, heavy caching of results.

An example of a query would be: "list all user accounts on all servers where the name of the user is jdoe." Obviously this kind of query might take some time if the computer this is executed on doesn't already have some idea of what users already exist.

Prev Up Next
CFG Upper Layer Home CFG Bottom Layer

SourceForge Logo