14.5 Automating Complex Configuration Tasks with Cfengine

Cfengine is a wonderful tool for configuring and maintaining Unix computer systems. MarkBurgess, the author ofCfengine, describes it as follows:

Cfengine, or the configuration engine, is an autonomous agent and a middle to high level policy language for building expert systems which administrate and configure large computer networks. Cfengine uses the idea of classes and a primitive intelligence to define and automate the configuration and maintenance of system state, for small to huge configurations.

What'd he say? Using Cfengine means that you'll have to get used to some unfamiliar jargon, but it's worth it. Basically, what Mark is saying is that Cfengine is a standalone tool (set of tools) that administers and configures computers according to the instructions in its configuration files. The configuration files describe the desired characteristics of various system components using a high-level language which is easy to learn and use (and involves no programming). In this way, Cfengine can automatically bring one or a very large number of systems into line with each one's individually defined configuration specifications. It can also make sure they stay that way by monitoring them and correcting them as needed on an ongoing basis.

In more practical terms, the following list will give you some idea of the breadth of administration and configuration tasks thatCfengine can automate:

  • Configure the network interface.

  • Edit system configuration files and other text files.

  • Create symbolic links.

  • Check and correct the permissions and ownership of files.

  • Delete unwanted files.

  • Compress selected files.

  • Distribute files within a network in a correct and secure manner.

  • Automatically mount NFS filesystems.

  • Verify the presence and integrity of important files and filesystems.

  • Execute commands and scripts.

  • Manage processes.

  • Apply security-related patches and similar corrections.

Cfengine's home page is http://www.cfengine.org.

14.5.1 About Cfengine

Cfengine includes the following components:


The main utility that applies a configuration file to the local system.


A utility that applies a configuration file to remote systems


A server process that supports cfrun; it enables the Cfengine agent functionality to be invoked from a remote system


Another daemon that automates job scheduling and reporting


An anomaly-detection daemon


A security key-generation utility

Cfengine uses several configuration files (generally stored in /var/cfengine/inputs). The central configuration file is cfagent.conf, which specifies the characteristics of the system thatCfengine is to establish and maintain. Note that in genera,l cfagent.conf defines the final desired state of the system; it does not define the steps to take to achieve it.

The best way to introduce this file is with a simple example:

control:    domain = ( ahania.com )              Specify local domain.    access = ( chavez  root )            Who can run cfagent.    actionsequence = ( links tidy )      Actions to carry out, in this order.    maxage = ( 7 )                       Define a variable for later use.     groups:                                 Define a list of hosts.    HaveNoBin = ( blake yeats bogan toi robin ) tidy:                                   Action: remove unwanted files.     /tmp   pattern=*   age=$(maxage) recurse=inf     /home  pattern=*~  recurse=inf links:                                  Action: maintain symbolic links.    /logs -> /var/log                    Create this link if needed.        HaveNoBin::                          Create this link only on these hosts.       /bin -> /usr/bin

This file contains four sections, each headed by a keyword followed by a colon. The first section, control, is used to specify general settings for the file, to define variables, and for other similar purposes. In this case, it specifies a list of users who are allowed to run cfagent using this file as input, specifies the sequence of actions that should be carried out when the file is invoked, and defines a variable named maxage, setting its value to 7.

Assignment statements use the syntax illustrated in the example, using parentheses as delimiters:

name = ( value )

Actions are operations that Cfengine knows how to perform, and they are referred to by keywords. Here, we specify that the tidy action be performed first, followed by the links action. Each referenced action must have a section defining it somewhere in the configuration file.

The next section, groups, defines a list of groups which we've named HaveNoBin. This list will be used in the links section.

The next section in the file is the tidy section, which specifies unwanted files that Cfengine is to remove. These entries have the following general syntax:

start-dir [pattern=pattern] [recurse=n] options

start-dir is the directory in which to start searching, pattern is a pattern against which to match filenames (possibly containing wildcards), n indicates how many levels of recursion are wanted (inf means infinite), and options are additional options further specifying the files to be selected for removal.

In this case, files under /home ending with a tilde (and not starting with a period) are chosen (emacs backup files), as are files under /tmp last modified more than seven days ago. Note that the parameter to the age option is specified using the maxage variable.

The final section in the file is the links section, which specifies symbolic links that Cfengine is to maintain. In this case, two such links are listed, using the format:

link -> target

Here, we specify that the /var/log directory should be linked to /logs and also that /bin should be a link to /usr/bin. When run, Cfengine checks whether these links exist, creating them if necessary. However, the latter link applies only to hosts in the list HaveNoBin. This is specified by preceding the link specification with a class designation (indicated by the double colons). In this case, the class is defined by the host group name, but much more complex classes are possible (as we'll see).

Actions are performed in the order specified in actionsequence; the ordering of their sections within the configuration file has no effect on their execution order. Thus, in this case, tidy will still be carried out after links even though its section precedes the links section in the configuration file.

Table 14-2 lists the most importantCfengine actions. We'll look at examples of several of them in the next subsection.

Table 14-2. Useful Cfengine actions




Create/maintain symbolic and hard links.


Remove unwanted files.


Set file ownership and protection, and/or check for modification.


Set directory ownership, protection.


Verify that filesystems are available and contain sufficient free space.


Rename undesirable files to name.cfengine.


Copy local or remote files to the local system.


Edit ASCII text files.


Specify servers for automatic NFS filesystem mounting by Cfengine.


Specify local filesystems available for NFS mounting by Cfengine.


Specify filesystems to mount or unmount by Cfengine.


Verify the existence of and control processes.


Specify characteristics of network interfaces.


Maintain /etc/resolv.conf.


Specify the static default gateway.


Execute arbitrary shell commands from within Cfengine.


Use an add-on module.

14.5.2 Actions

We'll begin with a slightly more complicated tidy example:

control:    split = ( " " )    dirlist = ( "tmp var/tmp 1/scratch 2/scratch" ) tidy:    /$(dirlist) pattern=* age=3 recurse=inf

The control section specifies the list separator character and then defines the variable dirlist as a list of four directories. This variable is then used in the tidy specification, and the three options apply to each directory in turn.

The files action is used to specify various desired characteristics and corrective actions for files. Here is an example section:

files:    /etc/security mode=600 owner=root group=0 recurse=inf action=fixall    /home recurse=inf include=*.dat action=compress    /var/log/messages owner=root mode=644 action=create

The first entry specifies the required ownership and protection of the directory /etc/security and everything under it. By default, Cfengine checks whether the current settings conform to these specifications. Here, however, action=fixall tells Cfengine to modify the current settings if necessary to match the specified ones.

The second entry causes all files with an extension of .dat under /home to be compressed. The third entry creates the file /var/log/messages if it does not exist.

The files action can also be used to verify the integrity of system executables in /usr/bin:

control:    ChecksumDatabase = ( /usr/local/admin/cfengine/cksums ) files:    /usr/bin checksum=md5 exclude=*.sav action=warnall

The database file used to store the correct checksums for files is specified in the control section, and the checksum option in the files entry specifies that the comparison be made. A warning will be issued for each incorrect checksum.

On Solaris systems, Cfengine can also specify ACLs for files:

acl:                                    Define an ACL.    { secure1         method:overwrite                Replace current ACL (default is "append").         fstype:posix         default_user:*:=rwx         default_group:chem:=rwx         default_other:*:=         user:chavez:=rwx         user:mark:+rx         user:toreo:=r         mask:*:rwx    } files:    /private acl=secure1 action=fixall

The acl section defines one or more named ACLs, which can then be specified for files (see Section 7.4 for more information about access control lists).

The disable action causes Cfengine to rename files which ought not to be present on this system:

disable:    /etc/hosts.equiv     home/.rhosts  inform=true    /var/log/messages rotate=6

The first two entries cause Cfengine to rename the indicated files if they exist, adding the extension .cfengine. In the second case, the special directory keyword home is used to refer to all user home directories. In this case, Cfengine also issues a warning message when such files are found.

The third entry illustrates another use for the disable section: log file rotation. The entry tells Cfengine to maintain six old copies of the /var/log/messages file. As with other log rotation facilities, the saved files are given the extensions .1 through .6.

The following actions specify the default gateway and name server list for the system:

defaultroute:                           Specify default gateway. resolve:                                Name server list.

Cfengine adds a static route for the specified default gateway if one does not already exist. Similarly, the servers listed in the resolve section are added to /etc/resolv.conf if necessary, and the resulting server list are ordered as indicated in the resolve section of cfagent.conf.

The processes action may be used to tell Cfengine to verify that important processes are running, restarting them if necessary, as well as to have Cfengine signal processes:

processes:    "sendmail" restart "/usr/sbin/sendmail" useshell=false inform=true    "inetd" signal=hup    "kudzu" signal=kill    "g02" matches<=2 signal=suspend action=bymatch inform=true

The first field in each entry is a pattern that is matched against the output of the ps command.[9] In general, Cfengine will apply the entry's specifications to each matching process.

[9] More specifically, ps aux on BSD-like systems, and ps -ef on System V-based systems.

The first entry causes Cfengine to determine if there is a sendmail daemon running. If not, one is started using the specified command. The useshell options says not to use a subshell when restarting the daemon (see the Cfengine documentation for the rationale and implementation details).

The next two entries specify signals to be sent to the inetd and kudzu processes if they are present.

The final entry causes Cfengine to search for processes matching the string "g02", and it will count the number of such processes. The entry specifies that the desired system state include no more than two such processes. The action=bymatch option tells Cfengine to correct the situation when this condition is not met, according to the directives of the other options. In this case, if there are more than two such processes i.e., if the desired condition specified by matches=<2 is not met it suspends all of them (signal=suspend) and outputs a message indicating this.

The editfiles action can be used to make changes to ASCII text files. It is very useful for maintaining certain system configuration files. For example, the following section tells Cfengine to disable some inetd-based unwanted services:

editfiles:    { /etc/inetd.conf        HashCommentLinesContaining "rlogin"        HashCommentLinesContaining "rexec"        HashCommentLinesContaining "finger"        HashCommentLinesContaining "tftp"    }

Similarly, the following section tells Cfengine to add a line to existing user .login scripts if it is not already present:

editfiles:    { home/.login       AppendIfNoSuchLine  "/usr/local/bin/motd.pl"    }

See the Cfengine documentation for full details on the capabilities of this action.

The copy action is used to tell Cfengine to copy local or remote files to the local system, as in these simple examples:

copy:    /aux/save/etc/ntp.drift dest=/etc/ntp.drift mode=644    /aux/save/etc/shells dest=/etc/shells mode=644    /masterfiles/etc/hosts.deny serverfilemaster        dest=/etc/hosts.deny owner=root group=0 mode=644

The first two entries specify local files to be copied from the source the first field to the destination location (dest= option). The third entry causes a file to be copied from filemaster:/masterfiles/etc/hosts.deny to /etc/hosts.deny on the local system. The copied file will be assigned the specified ownership and file protection mode.

14.5.3 Classes

Here is a more complex copy section, which also reintroducesCfengine classes:

copy:    linux::          $(masteretc)/rc.config dest=/etc/rc.config o=root mode=644    ShadowHosts::       $(masteretc)/passwd server=$(pwdmaster) dest=/etc/passwd           owner=0 group=0 mode=644 trustkey=true       $(masteretc)/shadow server=$(pwdmaster) dest=/etc/shadow           owner=0 group=0 mode=600 trustkey=true encrypt=true

The first copy operation will occur only on Linux systems, and it consists of copying the file rc.config from the location specified in the masteretc variable (defined elsewhere in the configuration file) to /etc and assigning the specified ownership and protection.

The second subsection applies only to the host group ShadowHosts, and it contains two copy specifications. They tell Cfengine to update /etc/passwd and /etc/shadow from master copies located on a remote host, specifying the required ownership and permissions. In both cases, the copy operation must use the Cfengine trusted key security mechanism (to ensure that the data is really coming from the source it purports to), and the shadow password file is transmitted in encrypted form.

The cfkey utility is used to set up trusted keys on systems using Cfengine. It must be run before these features can be used.

cfkey requires a large amount of random data to function properly. If your system does not provide /dev/random (or it does not work effectively), you must run the cfenvd daemon for a week before you install Cfengine to give it enough time to collect the required random data. cfkey will fail with the error message "error: PRNG not seeded" unless a sufficient amount of random data is available.

Cfengine classes are made up of one or more of the following components:

  • An operating system keyword. These include: hpux, aix, solaris, freebsd, linux, osf, and NT. The cfagent -p -v command shows keywords defined for the current system.

  • A host name.

  • A host group name (as defined in the groups section)

  • A name of a day of the week.

  • An hour of the day, in the format Hrnn: Hr14 for 2:00 P.M.

  • A minute of the hour, in the format Minnn: Min33 for 33 past the hour.

  • A 5-minute interval, in the format Minn_n+5: Min00_05 for the first five minutes of the hour. Note that n must be divisible by 5.

  • A quarter hour, in the format Qn: Q2 for the second quarter hour. This construct can also be combined with an hour: e.g., Hr02_Q3 for 2:30-2:44 P.M.

  • A day of the month, in the format Dayn: Day1 for the first.

  • A month name.

  • A year, in the format Yrnnnn: Yr2001 for 2001.

  • A locally defined class name:

    control:          addclasses = ( myclass )

    The default class is any, which matches any host at any time. Unspecified time and date classes default to all. Multiple classes are joined by periods (AND logic) or vertical bars (OR logic).

Here are some examples:

Class specification                          Matches ... solaris.Monday.Hr01::                   Solaris systems on Mondays at 1:00 A.M. aix|hp-ux::                             AIX and HP-UX systems. aix.!vader::                            AIX systems except host vader. December.Day31.Friday::                 December 31 if it is a Friday. Monday.$(fourtimes)::                   Four specified each hour times on Monday.

The final example uses a list of times defined earlier:

control:    fourtimes = ( Min03 Min18 Min34 Min49 )

If both AND and OR joins are used, ANDs are evaluated first:

Class specificationMatches ... solaris|aix.Monday.Hr01::               Solaris systems always;                                         AIX systems on Mondays at 1:00 A.M. (solaris|aix).Monday.Hr01::             Solaris and  AIX systems on Mondays at 1:00 A.M.

Classes can be used in any context within the configuration file. In this example, they are used to define a variable differently for different operating systems:

control:    linux::   swaptest = ( /usr/bin/free -m -o )    aix::     swaptest = ( /usr/sbin/lsps -a ) ... shellcommands:    $(swaptest) > $(reportdir)/swap_report.out

Cfengine interprets unknown class names as hostnames. If no such host exists, the class is ignored. This fact can be used to temporarily disable a section's classes by altering the associated class name (or adding one):

Xlinux:: Xany::

Real cfagent.conf files can become very large, so you may want to use the include file mechanism, the import action. For example, the following configuration file consists entirely of included files whose divisions are used to make each individual file more manageable:

import:    cf.groupdefs                         Always include these files.    cf.common    hpux: cf.hpux                        Operating system specific includes.    aix: cf.aix    linux: cf.linux    and so on

14.5.4 Configuring cfservd

TheCfengine server has its own configuration file. Here is a simple example:

# cfservd.conf control:    domain = ahania.com    cfrunCommand = ( "/var/cfengine/bin/cfagent" )    IfElapsed = ( 1 )    ExpireAfter = ( 15 )    MaxConnections = ( 50 )    MultipleConnections = ( true )    LogAllConnections = ( true )    TrustKeysFrom = ( 192.168.10/24 )    DynamicAddresses = ( )    topdir = ( /aux/crengine/masterfiles ) grant:                                  Grant access to files.    $(topdir)/outgoing    *.ahania.com deny:                                   Deny access to files.    $(topdir)/outgoing    maverick.ahania.com

The daemon also requires an addition to /etc/services:

cfengine    5308/tcp

Finally, you must start the daemon at boot time by adding it to one of the system boot scripts.

14.5.5 Running Cfengine

Once set up, Cfengine may be run manually on the local system with the cfagent command. It has the following useful options:

-f file

Specify an alternate configuration file (the default configuration file is /var/cfengine/inputs/cfagent.conf).


Verbose output mode.


Preview a Cfengine run: indicate what would be done, but don't actually perform any actions.

-N class

Disable the specified user-defined class.

The cfrun utility is used to initiate Cfengine runs on remote systems. It has the following syntax:

cfrun [host-list] [local-options] [-- remote-options] [-- classes]

For example, the following command runs Cfengine on hosts smiley, toby, and percy and provides verbose output on the local system:

# cfrun smiley toby percy 

The following command runs Cfengine on all hosts listed in the cfrun.conf configuration file (see the documentation for details), although execution will occur only on remote Linux and Solaris systems:

# cfrun -v -- -- linux solaris 

To automate Cfengine runs, use the cfexecd daemon (which you must also add to the system startup scripts). Once it is running, you can configure when Cfengine runs via a cfagent.conf entry like this one:

control:    schedule = ( Min00_05 Min15_20 Min30_35 Min45_50 )

This example will cause Cfengine to run four times an hour.

Essential System Administration
Essential System Administration, Third Edition
ISBN: 0596003439
EAN: 2147483647
Year: 2002
Pages: 162

Similar book on Amazon

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net