CFG Middle Layer | |
---|
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.
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.
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.
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.
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.
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.
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.
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.
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 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.
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.
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
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.
| |
|
|