Cfengine v2 reference


Next: , Previous: (dir), Up: (dir)

Cfengine-Reference

COMPLETE TABLE OF CONTENTS

This manual is for version 2.2.8 of cfengine and was last updated on the 30 July 2008.

Summary of contents


Next: , Previous: Top, Up: Top

1 Introduction to reference manual

The purpose of the cfengine reference manual is to collect together and document the raw facts about the different components of cfengine. Once you have become proficient in the use of cfengine, you will no longer have need of the tutorial. The reference manual, on the other hand, changes with each version of cfengine. You will be able to use it online, or in printed form to find out the details you require to implement configurations in practice.


Next: , Previous: Reference introduction, Up: Reference introduction

1.1 Installation

In order to install cfengine, you should first ensure that the following packages are installed.

OpenSSL
Open source Secure Sockets Layer for encryption.
URL: http://www.openssl.org
BerkeleyDB (version 3.2 or later)
Light-weight flat-file database system.
URL: http://www.oracle.com/technology/products/berkeley-db/index.html

The preferred method of installation is then

     tar zxf cfengine-x.x.x.tar.gz
     cd cfengine-x.x.x
     ./configure
     make
     make install

This results in binaries being installed in /usr/local/sbin. Since this is not necessarily a local file system on all hosts, users are encouraged to keep local copies of the binaries on each host, inside the cfengine trusted work directory.


Next: , Previous: Installation, Up: Reference introduction

1.2 Work directory

In order to achieve the desired simplifications, it was decided to reserve a private work area for the cfengine tool-set. In cfengine 1.x, the administrator could choose the locations of configuration files, locks, and logging data independently. In cfengine 2.x, this diversity has been simplified to a single directory which defaults to /var/cfengine (similar to /var/cron):

     /var/cfengine
     /var/cfengine/bin
     /var/cfengine/inputs
     /var/cfengine/outputs

The installation location /usr/local/sbin is not necessarily a local file system, and cannot therefore be trusted to a) be present, and b) be authentic on an arbitrary system.

Similarly, a trusted cache of the input files must now be maintained in the inputs subdirectory. When cfengine is invoked by the scheduler, it reads only from this directory. It is up to the user to keep this cache updated, on each host. This simplifies and consolidates the cfengine resources in a single place. The environment variable CFINPUTS still overrides this default location, as before, but in its absence or when called from the scheduler, this becomes the location of trusted files. A special configuration file update.conf is parsed and run before the main configuration is parsed, which is used to ensure that the currently caches policy is up-to-date. This has private classes and variables. If no value is set for CFINPUTS, then the default location is the trusted cfengine directory /var/cfengine/inputs.

The outputs directory is now a record of spooled run-reports. These are mailed to the administrator, as previously, or can be copied to another central location and viewed in an alternative browser..


Next: , Previous: Work directory, Up: Reference introduction

1.3 Cfengine hard classes

A single class can be one of several things:

To see all of the classes define on a particular host, run

     host# cfagent -p -v

as a privileged user. Note that some of the classes are set only if a trusted link can be established with cfenvd, i.e. if both are running with privilege, and the /var/cfengine/state/env_data file is secure. More information about classes can be found in connection with allclasses.


Next: , Previous: Hard classes, Up: Reference introduction

1.4 Filenames and paths

Filenames in Unix-like operating systems use for their directory separator the forward slash '/' character. All references to file locations must be absolute pathnames in cfengine, i.e. they must begin with a complete specification of which directory they are in. For example:

     /etc/passwd
     /usr/local/masterfiles/distfile

The only place where it makes sense to refer to a file without a complete directory specification is when searching through directories for different kinds of file, e.g.

     tidy:
     
       /home/user pattern=core age=0 recurse=inf
     

Here, one can write core without a path, because one is looking for any file of that name in a number of directories.

The Windows operating systems traditionally use a different filename convention. The following are all valid absolute file names under Windows:

      c:\winnt
      c:/winnt
      /var/cfengine/inputs
      //fileserver/share2/dir

The `drive' name “C:” in Windows refers to a partition or device. Unlike Unix, Windows does not integrate these seamlessly into a single file-tree. This is not a valid absolute filename:

     \var\cfengine\inputs

Paths beginning with a backslash are assumed to be win32 paths. They must begin with a drive letter or double-slash server name.


Previous: Filenames and paths, Up: Reference introduction

1.5 Debugging with signals

It is possible to turn debugging output on or off on a running cfagent. This is useful for troubleshooting the cause of hangups, or for getting debugging output from a cfagent launched from cfexecd.

A running cfagent process that receives a SIGUSR1 will immediately begin to behave as if it had been invoked with the '-d2' option. A SIGUSR2 will cause a running cfagent to run as if the '-d2' option had not been invoked.

Note that this output is often quite verbose.


Next: , Previous: Reference introduction, Up: Top

2 Cfkey reference

The very first thing you should do on every host is to establish a public-private key pair. To do this, you need to run the program

     everyhost# cfkey

on every host. This program needs to produce random numbers, and needs a source of randomness. A good strategy is to install and run the cfenvd program for a week or two in advance of deploying cfengine 2, since cfenvd collects random events, which are an excellent source of entropy for random number generation. If you get the error message “PRNG not seeded”, it means that insufficient data were found in order to make a random key. In that case, run cfenvd for a few days more and try again.


Next: , Previous: Cfkey, Up: Top

3 Cfshow reference

The cfshow command was introduced in cfengine 2.1.11 in order to provide a simple way to show some of the data stored by cfagent for operational purposes.

     everyhost# cfshow -a
     everyhost# cfshow -l
     everyhost# cfshow -c
     everyhost# cfshow -s
     everyhost# cfshow -p
     everyhost# cfshow -f cfagent.conf -r linux.*

The command line options are

`-a --active'
This prints a list of any currently active locks, i.e. tasks that cfengine believes it is currently enagaged in.
`-A --audit'
This prints a history of cfengine's behaviour collected if the Auditing variable is true, See Auditing. The audit data are best viewed in html or parsed with xml, using the --html and --xml options.
`-c --checksum'
This lists all of the files and their current checksum values in the current checksum database.
`-C --classes'
This lists all of the classes that have been used on the system over the past year, with frequency probabilities to show their relative occurrance rates and last observed times.
`-H --html'
Generate output in web browser-friendly html.
`-l --locks'
This prints a list of the locks and the last times an active lock was secured for each cfengine acivity. This list is potentially very long.
`-s --last-seen'
This lists the IP addresses of all known peers and the times they were last engaged in communication with the current host. The expected interval between communications is also printed. See FriendStatus. The output format is in a form that can easily be parsed by user scripts. e.g.
          IP + 192.168.1.101 192.168.1.101   [Tue Jan 23 16:13] not seen for (6.42) hrs, Av 0.02 +/- 0.01 hrs
          IP - 192.168.1.101 192.168.1.101   [Tue Jan 23 16:13] not seen for (6.42) hrs, Av 0.02 +/- 0.01 hrs
     

Lines marked with a + represent successful attempts made by cfagent on the current host to connect to another host. Lines with a - are connections attempted (but not necessarily succeeded) into cfservd from another host's cfagent or cfrun.

`-r --regex regex'
Search the cfengine policy file (e.g. cfagent.conf) for rules that belong to classes matching the named regular expression. Note that the class "any" is not automatically matched and the search is based on the class text from the file. The output is not related to which classes are currently defined.
`-s --performance'
Shows the time in seconds required to complete copies and shell executions.
          (0.00 mins  Tue Feb 13 19:05) Av 0.00 +/- 0.00 for Copy(localhost:/usr/local/sbin/cfagent > /var/cfengine/bin/cfagent)
          (0.00 mins  Tue Feb 13 19:05) Av 0.00 +/- 0.00 for Copy(localhost:/usr/local/sbin/cfenvd > /var/cfengine/bin/cfenvd)
          (0.02 mins  Tue Feb 13 19:05) Av 0.02 +/- 0.00 for Copy(localhost:/usr/local/sbin/cfexecd > /var/cfengine/bin/cfexecd)
          (0.00 mins  Tue Feb 13 19:05) Av 0.00 +/- 0.00 for Copy(localhost:/usr/local/sbin/cfservd > /var/cfengine/bin/cfservd)
          (6.41 mins  Tue Feb 13 18:50) Av 0.00 +/- 0.00 for Exec(/usr/bin/updatedb --prunepaths=/media)
          (0.00 mins  Tue Feb 13 19:05) Av 0.00 +/- 0.00 for Exec(/usr/sbin/ntpdate 128.39.74.16 > /dev/null)
     

`-X --xml'
Generate output in xml for parsing by scripts etc.


Next: , Previous: Cfshow, Up: Top

4 Cfagent reference


Next: , Previous: Cfagent reference, Up: Cfagent reference

4.1 Cfagent intro

Cfagent is the workhorse of cfengine. It interprets and computes the necessary strategies for implementing convergent maintenance. In order to carry out work efficiently, the agent groups similar actions together. The order of these actions is goverened by a list called the actionsequence.

In many cases, cfagent will be able to complete all its work in a single pass of the actionsequence. However, in complex configurations, it is hard to resolve all of the ordering dependencies automatically in a single pass. Cfagent keeps track both of all actions that have been performed and of those that might still need to be performed (given that some actions depend on the later outcomes of others). If there is a possibility that an action ordering dilemma might occur, it runs a second pass of the actionsequence to more quickly resolve the dependency (avoiding the wait for next scheduled run). No actions are performed twice however, since the agent checks off actions that have already been performed to avoid unnecessary duplication.


Next: , Previous: Cfagent intro, Up: Cfagent reference

4.2 The file cfagent.conf

     
      control:
     
        classes::
     
            domain = ( DNS-domain-name )
     
      classes:
     
        Class/Group definitions
     
      import:
     
        Files to import
     
      # other items
     


Next: , Previous: The file cfagent.conf, Up: Cfagent reference

4.3 Cfagent runtime options

Note that GNU long options are available with the syntax --longoption. The long names are given in brackets.

`-a'
(--sysadm) Print only the name of the system administrator then quit.
`-A'
(--auto) Can be used to signify an automatic run of cfengine, as opposed to a manual run. The distinction is not predetermined. Use of this option currently causes cfengine to ignore locks. This option is reserved for future development.
`-b'
(--force-net-copy) Normally cfengine detects attempts to copy from a server via the network that will loop back to the localhost. It then avoids using the network to make the copy. This option forces cfengine to copy using the network. Yes, someone thinks this is useful!
`-c'
(--no-check-files) Do not check file systems for ownership / permissions etc.
`-C'
(--no-check-mounts) Check mount points for consistency. If this option is specified then directories which lie in the “mount point” area are checked to see whether there is anything mounted on them. Normally this is off since not all machines use mounted file systems in the same way. e.g. HPUX does not generally operate with partitions, but nevertheless one might wish to mimick a partition-like environment there, but it would be irritating to be informed that nothing was mounted on the mount point.
`-d'
(--debug) Enable debugging output. Normally you will want to send this to a file using the shell script command or a pipe. -d1 shows only parsing output. -d2 shows only runtime action output. -d0 shows both levels. Debugging ouput is intended mainly for the author's convenience and is not a supported feature. The details of this output may change at any time.
`-D'
(--define) Define a compound class symbol of the form alpha.beta.gamma.
`-e'
(--no-edits) Suppress file editing.
`-E'
(--enforce-links) Globally force links to be created where plain files or links already exist. Since this option is a big hammer, you have to use it in interactive mode and answer a yes/no query before cfengine will run like this.
`-f'
(--file) Parse filename after this switch. By default cfengine looks for a file called cfengine.conf in the current directory.
`-h'
(--help) Help information. Display version banner and options summary.
`-H'
(--no-hard-classes). Prevents cfengine from generating any built-in class name information. Can be used for emulation purposes.
`-i'
(--no-ifconfig) Do not attempt to configure the local area network interface.
`-I'
(--inform) Switches on the inform output level, whereby cfengine reports everything it changes..
`-k'
(--no-copy) Do not copy/image any files.
`-K'
(--no-lock) Ignore locks when running.
`-l'
(--traverse-links) Normally cfengine does not follow symbolic links when recursively parsing directories. This option will force it to do so.
`-L'
(--delete-stale-links) Delete links which do not point to existing files (except in user home directories, which are not touched).
`-m'
(--no-mount) Do not attempt to mount file systems or edit the filesystem table.
`-M'
(--no-modules) Ignore modules in actionsequence.
`-n'
(--recon,--dry-run,--just-print) No action. Only print what has to be done without actually doing it.
`-N'
(--negate,--undefine) Cancel a set of classes, or undefine (set value to false) a compound class of the form alpha.beta.gamma.
`-p'
(--parse-only) Parse file and then stop. Used for checking the syntax of a program. You do not have to be superuser to use this option.
`-P'
(--no-processes) Do not execute the processes action.
`-q'
(--no-splay) Switch off host splaying (sleeping).
`-Q'
(--quert) Query the values of the comma separated list of variable names.
`-s'
(--no-commands) Do not execute scripts or shell commands.
`-S'
(--silent) Silence run time warnings.
`-t'
(--no-tidy) Do not tidy file systems.
`-u'
(--use-env) Causes cfengine to generate an environment variable `CFALLCLASSES' which can be read by child processes (scripts). This variable contains a summary of all the currently defined classes at any given time. This option causes some System V systems to generate a Bus Error or segmentation fault. The same information is available from the cfengine built-in variable $(allclasses) and can be passed as a parameter to scripts. When this variable grows too large for embedding one can also access a complete list of current classes in /var/cfengine/state/allclasses.
`-U'
(--underscore-classes). When this option is set, cfengine adds an underscore to the beginning of the hard system classes (like _sun4, _linux etc. The longer compound classes are not underscored, since these are already complex and would unlikely result in collisions.) This can be used to avoid naming conflicts if you are so unjudicious as to name a host by the name of a hard class. Other classes are not affected.
`-v'
(--verbose) Verbose mode. Prints detailed information about actions and state.
`-V'
(--version) Print only the version string and then quit.
`-x'
(--no-preconf) Do not execute the cf.preconf net configuration file.
`-X'
(--no-links) Do not execute the links section of a program.
`-w'
(--no-warn,--quiet) Do not print warning messages.
`-z'
(--schedule) Print the exec schedule for the LAN (used by cfexecd).

In version 2.0.4, an abbreviation for actionsequence exclusions was added:

     $ cfagent --avoid resolve,copy
     $ cfagent --just tidy --just shellcommands


Next: , Previous: Cfagent Runtime Options, Up: Cfagent reference

4.4 Variable expansion and contexts

Variables in cfengine 2 are defined in contexts. Variables in a given context refer to the different phases of execution of cfengine: global, update and main. In the "current" context, variables have the form

     $(variable) ${variable}

and are expanded either on parsing or at execution. Variables that cannot be expanded remain as dollar strings. Variables belonging to a context that is not the current one may be referred to as

     $(context.variable)  or  ${context.variable}

There is no difference between these forms as far as cfengine is concered. Some authors like to use the () form for cfengine variables, to distinguish them with shell variables in command strings. When using the () form in function arguments, they should be quoted to avoid parsing errors.

Consider the example:

     $(global.env_time)

Some variables in cfengine are associative arrays (as made famous by Perl). Such arrays are referred to by square brackets:

     
     $(array[key])  $(array[$(key)])
     

and so on. Note carefully that cfengine requires parentheses or braces around variable names. Unlike in the shell, they cannot be omitted.


Next: , Previous: Variable expansion and contexts, Up: Variable expansion and contexts

4.4.1 Setting variables with functions

A number of special functions can be used to set variables in cfengine. You can import values from the execution of a shell command by prefixing a command with the word exec. This method is deprecated as of cfengine version 2; use the ExecResult function instead.

     
       control:
     
        # old method
     
        listing = ( "exec /bin/ls -l" )
     
        # new method
     
        listing = ( ExecResult(/bin/ls -l) )
     

This sets the variable `listing' to the output of the command in the quotes. Some other built-in functions are

A(X,Y)
Makes an associative array entry, associating X and Y. For instance:
          control:
          
           assoc_array = ( A(B,"is for bird") A(C,"is for cat") )
          
     

results in:

          
          OBJECT: main
             4569 : assoc_array[B]=is for bird
             4630 : assoc_array[C]=is for cat
          
     

Another example:

          control:
          
           binhost = ( A(linux,machine1) A(solaris,machine2) )
          
          copy:
          
           # Contact machine 1 for linux
           # Contact machine 2 for solaris
          
           /etc/source dest=/etc/receve server=$(binhost[$(class)])
          
     

ExecResult(command)
Executes the named command without a shell-wrapper and inserts the output into the variable. Note that, when this is used in cfengine built-in list variables, any spaces are interpreted as list separators. In other lists, normal rules for iteration apply.
ExecShellResult(command)
Executes the named command with a shell-wrapper and inserts the output into the variable. Note that, when this is used in cfengine built-in list variables, any spaces are interpreted as list separators. In other lists, normal rules for iteration apply.
RandomInt(a,b)
Generate a random integer between a and b.
ReadArray(filename,fileformat,separator,comment,Max number of bytes)
Reads up to a maximum number of bytes from a properly formatted file into a one-dimensional associated array. File formats are:
autokey
If this format is specified, ReadArray tries to interpret the file as a table of items separated with the separator character. Blank lines and comments (to end of line) are ignored. Items are keyed numerically starting from 1 to the maximum number in the file. The newline $(n) is always considered to be a separator, no matter what the current separator is.
textkey
If this format is specified, ReadArray tries to interpret the file as a list of lines of the form:
                 key,value
          

ReadFile(filename,Max number of bytes)
Read a maximum number of bytes from a file.
ReadTable(filename,fileformat,separator,comment,Max number of bytes)
Reads up to a maximum number of bytes from a properly formatted file into a two-dimensional associated array.
autokey
If this format is specified, ReadArray tries to interpret the file as a table of items separated with the separator character. Blank lines and comments (to end of line) are ignored. Items are keyed numerically starting from 1 to the maximum number in the file. Any lines that do not contain the correct number of separators cause the function to fail without making any assignment.
textkey
If this format is specified, ReadArray tries to interpret the file as a list of lines of the form:
                 key1,key2,value1
                 key3,key4,value2
          

This variable would then be references as $(table[key1][key2]).


ReadList(filename,fileformat,comment,Max number of bytes)
Reads up to a maximum number of bytes from a properly formatted file into a listvariable. File formats are:
lines
If this format is specified, ReadList tries to interpret the file as a list of items on separate lines. The value returned is a list formatted by the Split character.
          
          hosts = ( ReadList(/var/cfengine/inputs/datafile,lines,#,1000) )
          
     

ReadTCP(host/IP,portnumber,send string,Max number of bytes)
Reads up to a maximum number of bytes from a TCP service. Can be used to test whether certain services are responding to queries. It is recommended that this be used primarily to check services running on localhost. Bear in mind that this clause, executed on 100 hosts will produce the effect of a distributed denial of service attack, so the probe should be restricted to a single representative tester-host. For example:
          
          one_host_only::
          
           # USE WITH CAUTION !
          
           probewww = ( ReadTCP(localhost,80,'GET index.html',1000) )
          
     

Or testing a network service:

          control:
          
           checkhost::
          
           probesmtp = ( ReadTCP(localhost,25,"",1024) )
           probewww  = ( ReadTCP(project.iu.hio.no,80,"GET /viewcvs HTTP/1.0 ${n}${n}",1024) )
          
          classes:
          
            viewcvs_error = ( RegCmp(".*Python Traceback.*","${probewww}") )
          
          alerts:
          
            viewcvs_error::
          
               "Received viewcvs error from web server"
     

SelectPartitionNeighbours(filename,comment,Policy,group size)
This function is for use in peer to peer monitoring applications. It allows individual hosts to identify themselves as part of a group and find their peers. The function returns a list variable, delimited by the list separation character, for use with Split.
          
           control:
          
             allpeers = ( SelectPartitionNeighbours(/var/cfengine/inputs/cfrun.hosts,#,random,4) )
          
           copy:
          
             /data/file dest=/p2prepository/file server=$(allpeers)
          
     

SelectPartitionLeader(filename,comment,Policy,group size)
This function is for use in peer to peer monitoring applications. It allows individual hosts to identify themselves as part of a group and select a leader. This function reads a text file of hostnames or IP addresses, one host per line, with blank lines and comments and partitions it into groups of a fixed size. It then returns picks a leader for the the group and returns its name as the value of the function.
          
           control:
          
             leader = ( SelectPartitionLeader(/var/cfengine/inputs/cfrun.hosts,#,random,4) )
          
           copy:
          
             /data/file dest=/p2prepository/file server=$(leader)
          
     
Note that functions should have no spaces between the function name and the leading parenthesis, but should themselves be surrounded by white space. For example:
     
     control:
     
      variable2 = ( RandomInt(0,23) )
     
      variable3 = ( ExecResult(/bin/ls -a /opt) )
     
      myexcerpt  = ( ReadFile("/etc/services",220) )
     
      listvar = ( ReadArray(/tmp/array,textkey,",","#",100) )
     

In the latter case, the file could look like this:

     host$ more /tmp/array
     one,String to tbe read
     two,Nothing string
     three,Everything comes in threes

and results in the definition of (verify with cfagent -p -d3):

     OBJECT: main
        960 : listvar[one]=String to tbe read
        259 : listvar[two]=Nothing string
        224 : listvar[three]=Everything comes in threes


Next: , Previous: Setting variables with functions, Up: Variable expansion and contexts

4.4.2 Special variables

Variables are referred to in either of two different ways, depending on your taste. You can use the forms $(variable) or ${variable}. The variable in braces or parentheses can be the name of any user defined macro, environment variable or one of the following special built-in variables.

AllClasses
A long string in the form `CFALLCLASSES=class1:class2...'. This variable is a summary of all the defined classes at any given time. It is always kept up to date so that scripts can make use of cfengine's class data.
arch
The current detailed architecture string—an amalgamation of the information from uname. A constant.
binserver
The default server for binary data. A constant.
cfinputs_version
The version string of the current configuration, used for version control and auditing.
ChecksumDatabase
If set to the name of a file, cfagent will use this to store checksums of important files, and give `tripwire functionality', See ChecksumDatabase. This option was deprecated in 2.1.22.
ChecksumUpdates
If set to `on', security information is automatically updated.
class
The currently defined system hard-class (e.g. sun4, hpux). A constant.
date
The current date string. Note that if you use this in a shell command it might be interpreted as a list variable, since it contains the default separator `:'.
domain
The currently defined domain.
EmailFrom
The email address from whom email from cfexecd should appear to originate.
EmailMaxLines
Most lines of output to email from a single cfexecd-induced run of cfagent. If undefined, defaults to 100. If set to 0, no email is sent by cfexecd. If set to inf, no maximum is enforced.
EmailTo
The E-mail address to whom mail should be sent (overrides sysadm variable).
faculty
The faculty or site as defined in control (see site).
fqhost
The fully qualified hostname of the system.
host
The hostname of the machine running the program.
ipaddress
The numerical form of the Internet address of the host currently running cfengine found by a reverse lookup in DNS.
ipv4[interface]
The IPv4 address of the named interface as determined from a probe of the interfaces. This variable belongs in the global context and refers to as in the following examples:
          
          ${global.ipv4[hme0]}
          ${global.ipv4[eth0]}
          
     

MaxCfengines
The maximum number of cfengines which should be allowed to run concurrently on the system. This can prevent excessive load due to unintentional spamming in situations where several cfengines are started independently. The default value is unlimited.
ostype
A short for of $(arch).
OutputPrefix
This quoted string can be used to change the default `cfengine:${hostname}' prefix on output lines to something else. You might wish to shorten the string, or have a different prefix for different hosts. The default is equivalent to,
            OutputPrefix = ( "cfengine:$(host):")
     


RepChar
The character value of the string used by the file repository in constructing unique filenames from path names. This is the character which replaces `/'.
site
This variable is identical to $(faculty) and may be used interchangeably.
smtpserver
The name of the host to which mail output should be sent.
split
The character on which list variables are split.
sysadm
The name or mail address of the system administrator.
timezone
The current timezone as defined in control.
UnderscoreClasses
If this is set to `on' cfengine uses hard classes which begin with an underscore to avoid name collisions, See Cfagent Runtime Options.
version
The current cfengine version string as defined in the code.
year
The current year.

These variables are kept special because they play a special role in setting up a system configuration. You are encouraged to use them to define fully generalized rules in your programs. Variables can be used to advantage in defining filenames, directory names and in passing arguments to shell commands. The judicious use of variables can reduce many definitions to a single one if you plan carefully.

NOTE: the above control variables are not case sensitive, unlike user macros, so you should not define your own macros with these names.

The following variables are also reserved and may be used to produce troublesome special characters in strings.

cr
Expands to the carriage return character.
colon
Expands to the colon `:' character.
dblquote
Expands to a double quote "
dollar
Expands to `$'.
lf
Expands to a line-feed character (Unix end of line).
n
Expands to a newline character.
quote
Expands to a single quote '.
spc
Expands simply to a single space. This can be used to place spaces in filenames etc.
tab
Expands to a single tab character.


Previous: Special variables, Up: Variable expansion and contexts

4.4.3 Iteration over lists

Variables can be used as iterators in some situations. Iteration over lists is currently rather limited in cfengine and is something to be improved on in a future version. When a variable is used as an iterator, a character is chosen to represent a list separator, as in the shell `IFS' variable. The default separator is the colon `:' character:

     control:
     
      listvar = ( one:two:three:four )
     

The action that contains a variable to be interpreted as a list appears as separate actions, one for each case:

     shellcommand:
     
       "/bin/echo $(listvar)"

is equivalent to

     shellcommand:
     
       "/bin/echo one"
       "/bin/echo two"
       "/bin/echo three"
       "/bin/echo four"

If multiple iterators are used, these are handled as nested loops:

     cfengine::/bin/echo one 1:     one 1
     cfengine::/bin/echo one 2:     one 2
     cfengine::/bin/echo one 3:     one 3
     cfengine::/bin/echo one 4:     one 4
     cfengine::/bin/echo two 1:     two 1
     cfengine::/bin/echo two 2:     two 2
     cfengine::/bin/echo two 3:     two 3
     cfengine::/bin/echo two 4:     two 4
     cfengine::/bin/echo three:     three 1
     cfengine::/bin/echo three:     three 2
     cfengine::/bin/echo three:     three 3
     cfengine::/bin/echo three:     three 4
     cfengine::/bin/echo four :     four 1
     cfengine::/bin/echo four :     four 2
     cfengine::/bin/echo four :     four 3
     cfengine::/bin/echo four :     four 4

Where iterators are not allowed, the implied lists are treated as scalars:

     
     alerts:
     
      amnexus::
     
       "do $(list1) $(list2)"

e.g.

     
     cfengine:: do one:two:three:four 1:2:3:4

Iterative expansion is currently restricted to:


Next: , Previous: Variable expansion and contexts, Up: Cfagent reference

4.5 Cfengine classes

A cfengine action looks like this:

     
     action-type:
     
        compound-class::
     
            declaration

A single class is an identifier that may consist of any alphanumeric character or the underscore, just like identifiers in ordinary programming languages. Classes that are derived from data like IP addresses or host names convert any other characters (like `.' or `-') into underscores. A single class can be one of several things:

A compound class is a sequence of simple classes connected by dots or `pipe' symbols (vertical bars). For example:

     
     myclass.sun4.Monday::
     
     sun4|ultrix|osf::
     

A compound class evaluates to `true' if all of the individual classes are separately true, thus in the above example the actions which follow compound_class:: are only carried out if the host concerned is in myclass, is of type sun4 and the day is Monday! In the second example, the host parsing the file must be either of type sun4 or ultrix or osf. In other words, compound classes support two operators: AND and OR, written `.' and `|' respectively. From cfengine version 2.1.1, I bit the bullet and added `&' as a synonym for the AND operator. Cfengine doesn't care how many of these operators you use (since it skips over blank class names), so you could write either

     
     solaris|irix::
     

or

     
     solaris||irix::
     

depending on your taste. On the other hand, the order in which cfengine evaluates AND and OR operations does matter, and the rule is that AND takes priority over OR, so that `.' binds classes together tightly and all AND operations are evaluated before ORing the final results together. This is the usual behaviour in programming languages. You can use round parentheses in cfengine classes to override these preferences.

Cfengine allows you to define switch on and off dummy classes so that you can use them to select certain subsets of action. In particular, note that by defining your own classes, using them to make compound rules of this type, and then switching them on and off, you can also switch on and off the corresponding actions in a controlled way. The command line options -D and -N can be used for this purpose. See also addclasses in the Reference manual. A logical NOT operator has been added to allow you to exclude certain specific hosts in a more flexible way. The logical NOT operator is (as in C and C++) `!'. For instance, the following example would allow all hosts except for myhost:

        action:
     
         !myhost::
     
             command

and similarly, so allow all hosts in a user-defined group mygroup, except for myhost, you would write

        action:
     
         mygroup.!myhost::
     
             command

which reads `mygroup AND NOT myhost'. The NOT operator can also be combined with OR. For instance

     
        class1|!class2

would select hosts which were either in class 1, or those which were not in class 2.

Finally, there is a number of reserved classes. The following are hard classes for various operating system architectures. They do not need to be defined because each host knows what operating system it is running. Thus the appropriate one of these will always be defined on each host. Similarly the day of the week is clearly not open to definition, unless you are running cfengine from outer space. The reserved classes are:

     ultrix, sun4, sun3, hpux, hpux10, aix, solaris, osf, irix4, irix, irix64
        sco, freebsd, netbsd, openbsd, bsd4_3, newsos, solarisx86, aos,
               nextstep, bsdos, linux, debian, cray, unix_sv, GnU, NT

If these classes are not sufficient to distinguish the hosts on your network, cfengine provides more specific classes which contain the name and release of the operating system. To find out what these look like for your systems you can run cfengine in `parse-only-verbose' mode:

     
       cfagent -p -v
     

and these will be displayed. For example, Solaris 2.4 systems generate the additional classes sunos_5_4 and sunos_sun4m, sunos_sun4m_5_4.

Cfengine uses both the unqualified and fully host names as classes. Some sites and operating systems use fully qualified names for their hosts. i.e. uname -n returns to full domain qualified hostname. This spoils the class matching algorithms for cfengine, so cfengine automatically truncates names which contain a dot `.' at the first `.' it encounters. If your hostnames contain dots (which do not refer to a domain name, then cfengine will be confused. The moral is: don't have dots in your host names! NOTE: in order to ensure that the fully qualified name of the host becomes a class you must define the domain variable. The dots in this string will be replaced by underscores. In summary, the operator ordering in cfengine classes is as follows:

`()'
Parentheses override everything.
`!'
The NOT operator binds tightest.
`. &'
The AND operator binds more tightly than OR.
`|'
OR is the weakest operator.


Previous: Cfengine classes, Up: Cfengine classes

4.5.1 Setting classes with special functions

Cfengine provides a number of built-in functions for evaluating classes, based on file tests. Using these built-in functions is quicker than calling the shell test function. The time functions place their arguments in chronological order.

AccessedBefore(f1,f2)
True if file 1 was accessed more recently than file 2 (UNIX atime)
ChangedBefore(f1,f2)
True if file 1's attributes were changed in any way more recently than file 2's (UNIX ctime)
ClassMatch(regexp)
True if the quoted regular expression matches one of the currently defined classes. It is wise to place ClassMatch at the end of your parsing in order to capture as many of the user-defined classes as possible.
          classes:
          
             userdef = ( ClassMatch(.*linux.*) )
     

FileExists(file)
True if the named file object (file/directory or link) exists.
GroupExists(groupname|gid)
True if the groupname or group id is registered on the system.
HostRange(basename,start-stop)
True if the current relative domain name begins with basename and ends with an integer between start and stop. Note well: matching is case insensitive (both hostname and basename are converted to all lower case for comparison.)
IsDefined(variable-id)
True if the named variable is defined. Note well: use the variable name, not its contents (that is, IsDefined(var), and not IsDefined(${var}))
IsDir(f)
True if the file f is a directory
IsLink(f)
True if the file f is a symbolic link
IsPlain(f)
True if the file f is a plain file
IsNewerThan(f1,f2)
True if file 2 was modified more recently than file 1 (UNIX mtime)
IPRange(address-range)
True if the current host lies within the specified IP range
PrepModule(module,arg1 arg2...)
True if the named module exists and can be executed. The module is assumed to follow the standard programming interface for modules (see Writing plugin modules in tutorial). Unlike actionsequence modules, these modules are evaluated immediately on parsing. Note that the module should be specified relative to the authorized module directory.
Regcmp(regexp,string or list separated string)
True if the string matched the regular expression regexp.
ReturnsZero(command)
True if the named shell command returns with exit code zero (success). The command is executed without a shell wrapper.
ReturnsZeroShell(command)
True if the named shell command returns with exit code zero (success) when executed in the environment of a shell wrapper.
Strcmp(s1,s2)
True if the string s1 exactly matches s2
UserExists(username|uid)
True if the username or user id is registered on the system (this does not imply that the user can log in or has a home directory).


IsGreaterThan(s1,s2)
Returns true if the value of s1 is greater than the value of s2. Note that, if the strings have numerical values, a numerical comparison is performed, otherwise a string comparison is used.
IsLessThan(s1,s2)
Returns true if the value of s1 is less than the value of s2. Note that, if the strings have numerical values, a numerical comparison is performed, otherwise a string comparison is used.
          
          	control:
          
            	 actionsequence = ( files )
          
          	 a = ( 2.12 )
           	 b = ( 2.11 )
          
          	classes:
          
          	lt = ( IsLessThan(${a},${b}) )
             	gt = ( IsGreaterThan(${a},${b}) )
          
          	alerts:
          
          	  lt:: "$(a) LESS THAN $(b)"
          	  gt:: "$(a) GREATER THAN $(b)"
     

For example:

     
     classes:
     
      access_to_dir = ( ReturnsZero(/bin/cd /mydir) )
      compare       = ( ChangedBefore(/etc/passwd_master,/etc/passwd) )
      isplain       = ( IsPlain(/tmp/import) )
      inrange       = ( IPRange(128.39.89.10-15) )
      CIDR          = ( IPRange(128.39.89.10/24) )
      compute_nodes = ( HostRange(cpu-,01-32)
      gotinit       = ( PrepModule(startup2,"arg1 arg2") )
     


Next: , Previous: Cfengine classes, Up: Cfagent reference

4.6 acl

     
        acl:
     
           class::
     
              { acl-alias
     
              action
              }
     

Cfengine's ACL feature is a common interface for managing filesystem access control lists (ACLs). An access control list is an extended file permission. It allows you to open or close a file to a named list of users (without having to create a group for those users); similarly, it allows you to open or close a file for a list of groups. Several operating systems have access control lists, but each typically has a different syntax and different user interface to this facility, making it very awkward to use. This part of a cfengine configuration simplifies the management of ACLs by providing a more convenient user interface for controlling them and—as far as possible—a common syntax.

An ACL may, by its very nature, contain a lot of information. Normally you would set ACLs in a files command, See files, or a copy command, See copy. It would be too cumbersome to repeat all of the information in every command in your configuration, so cfengine simplifies this by first associating an alias together with a complex list of ACL information. This alias is then used to represent the whole bundle of ACL entries in a files or copy command. The form of an ACL is similar to the form of an editfiles command. It is a bundle of information concerning a file's permissions.

     
      { acl-alias
     
       method:overwrite/append
       fstype:posix/solaris/dfs/afs/hpux/nt
     
       acl_type:user/group:permissions
       acl_type:user/group:permissions
       ...
      }
     

The name acl-alias can be any identifier containing alphanumeric characters and underscores. This is what you will use to refer to the ACL entries in practice. The method entry tells cfengine how to interpret the entries: should a file's ACLs be overwritten or only adjusted? Since the filesystems from different developers all use different models for ACLs, you must also tell cfengine what kind of filesystem the file resides on. Currently only Solaris and DCE/DFS ACLs are implemented.

NOTE: if you set both file permissions and ACLs the file permissions override the ACLs.


Next: , Previous: acl, Up: acl

4.6.1 Access control entries

An access control list is build of any number of individual access control entries (ACEs). The ACEs has the following general syntax:

         acl_type:user/group:permissions

The user or group is sometimes referred to as a key. For an explanation of ACL types and their use, refer to your local manual page. However, note that for each type of filesystem, there are certain entries which must exist in an ACL. If you are creating a new ACL from scratch, you must specify these. For example, in Solaris ACLs you must have entries for user, group and other. Under DFS you need what DFS calls a user_obj, group_obj and an other_obj, and in some cases mask_obj. In cfengine syntax these are called user:*:, other:*: and mask:*:, as described below. If you are appending to an existing entry, you do not have to re-specify these unless you want to change them.

Cfengine can overwrite (replace) or append to one or more ACL entries.

overwrite
method:overwrite is the default. This sets the ACL according to the specified entries which follow. The existing ACL will be overwritten completely.
append
method:append adds or modifies one or more specified ACL entries. If an entry already exists for the specified type and user/group, the specified permission bits will be added to the old permissions. If there is no ACL entry for the given type and user/group, a new entry will be appended.
If the new ACL exactly matches the existing ACL, the ACL is not replaced.

The individual bits in an ACE may be either added subtracted or set equal to a specified mask. The `+' symbol means add, the `-' symbol subtract and `=' means set equal to. Here are some examples:

     
       acltype:id/*:mask
     
       user:mark:+rx,-w
       user:ds:=r
       user:jacobs:noaccess
       user:forgiven:default
     
       user:*:rw
       group:*:r
       other:*:r
     

The keyword noaccess means set all access bits to zero for that user, i.e. remove all permissions. The keyword default means remove the named user from the access crontrol list altogether, so that the default permissions apply. A star/asterisk in the centre field indicates that the user or group ID is implicitly specified as of the owner of the file, or that no ID is applicable at all (as is the case for `other').


Next: , Previous: ACEs, Up: acl

4.6.2 Solaris ACLs

Under Solaris, the ACL type can be one of the following:

             user
             group
             mask
             other
             default_user
             default_group
             default_mask
             default_other

A user or group can be specified to the user, group, default_user and default_group types. Solaris ACL permissions are the normal UNIX permissions bits `rwx', where:

         
             r - Grants read privileges.
             w - Grants write privileges.
             x - Grants execute privileges.


Next: , Previous: Solaris ACLs, Up: acl

4.6.3 DFS ACLs

In DCE, the ACL type can be one of the following:

             other
             mask
             any
             unauthenticated
             user
             group
             foreign_other
             foreign_user
             foreign_group

The user, group, foreign_user and foreign_group types require that you specify a user or group. The DCE documentation refers to types user_obj, group_obj and so on. In the cfengine implementation, the ugly `_obj' suffix has been dropped to make these more in keeping with the POSIX names. user_obj::, is equivalent to user:*: is cfengine. The star/asterisk implies that the ACL applies to the owner of the file object.

DFS permissions are comprised of the bits `crwxid', where:

             c - Grants control privileges, to modify an acl.
             r - Grants read  privileges.
             w - Grants write privileges.
             x - Grants execute privileges.
             i - Grants insert privileges.
             d - Grants delete privileges.

See the DCE/DFS documentation for more information about this.

It is not possible to set ACLs in foreign cells currently using cfengine, but you can still have all of your ACL definitions in the same file. You must however arrange for the file to be executed on the server for the cell concerned. Note also that you must perform a DCE login (normally as user `cell_admin') in order to set ACLs on files which are not owned by the owner of the cfengine-process. This is because you must have a valid security ticket.


Next: , Previous: DFS ACLs, Up: acl

4.6.4 NT ACLs

NT ACEs are written as follows:

            acl_type:user/group:permissions:accesstype

The actual change consists of the extra field containing the access type. A star/asterisk in the field for user/group would normally imply that the ACL applies to the owner of the file object. However this functionality is as of today not yet implemented.

In NT, the ACL type can be one of the following:

                user
                group

Both types require that you specify the name of a user or a group.

NT permissions are comprised of the bits `rwxdpo', where:

         r - Read privileges
         w - Write privileges
         x - Execute privileges
         d - Delete privileges
         p - Privileges to change the permissions on the file
         o - Privileges to take ownership of the file

In addition to any combination of these bits, the word noaccess or default can be used as explained in the previous section. NT comes with some standard, predefined permissions. The standards are only a predefined combination of the different bits specified above and are provided with cfengine as well. You can use the standards by setting the permission to read, change or all. The bit implementation of each standard is as on NT:

                read   - rx
                change - rwxd
                all    - rwxdpo

where the bits follow the earlier definition. The keywords mentioned above can only be used alone, and not in combination with `+', `-', `=' and/or other permission bits.

NT defines several different access types, of which only two are used in connection with the ACL type that is implemented in cfengine for NT. The access type can be one of the following:

                allowed
                denied

Intuitively, allowed access grants the specified permissions to the user, whilst denied denies the user the specified permissions. If no access type is specified, the default is allowed. This enables cfengine's behaviour as on UNIX systems without any changes to the configuration file. If the permissions noaccess or default is used, the access type will be irrelevant.

4.7 ACL Example

Here is an example of a configuration file for an NT ACL:

     control:
             actionsequence = ( files )
             domain = ( iu.hioslo.no )
     
     files:
             $(HOME)/tt    acl=acl_alias1    action=fixall
     
     acl:
             { acl_alias1
     
             method:overwrite
             fstype:nt
     
             user:gustafb:rwx:allowed
             user:mark:all:allowed
             user:toreo:read:allowed
             user:torej:default:allowed
             user:ds2:+rwx:allowed
     
             group:dummy:all:denied
             group:iu:read:allowed
             group:root:all:allowed
             group:guest:dpo:denied
             }


Previous: NT ACLs, Up: acl

4.7.1 ACL Example

Here is an example of a configuration file for one Solaris ACL and one DCE/DFS ACL:

     control:
             actionsequence = ( files )
             domain = ( iu.hioslo.no )
     
     files:
             $(HOME)/tt    acl=acl_alias1    action=fixall
             /:/bigfile    acl=acl_alias2    action=fixall
     
     acl:
             { acl_alias1
     
             method:overwrite
             fstype:posix
     
             user:*:rwx
             user:mark:=rwx
             user:sowille:=rx
             user:toreo:=rx
             user:torej:default
             user:ds2:+rwx
             group:*:rx
             group:iu:r
             group:root:x
             mask:*:rx
             other:*:rx
     
             default_user:*:=rw
             default_user:mark:+rwx
             default_user:ds:=rwx
             default_group::=r
             default_group:iu:+r
             default_mask::w
             default_other::rwx
             }
     
             { acl_alias2
     
             method:overwrite
             fstype:dfs
     
             user:*:rwxcid
             group:*:rxd
             other:*:wxir
             mask:*:rxw
             user:/.../iu.hioslo.no/cell_admin:rc
             group:/.../iu.hioslo.no/acct-admin:rwxcid
             user:/.../iu.hioslo.no/root:rx
             }


Next: , Previous: acl, Up: Cfagent reference

4.8 alerts

Alerts are normally just messages that are printed when classes become activated in order to alert the system administrator to some condition that has arisen. Alerts can also be special functions, like ShowState() that generate system output.

Alerts cannot belong to the class any, that would generate a message from every host. In a huge network this could result in vast amounts of Email. This behaviour can be forced, however, by creating an alias for the class `any' that is defined on the affected hosts.

     
     alerts:
     
        class::
     
           quoted message
     
             ifelapsed=time
             audit=true/false
     
           ShowState(parameter)
           SysLog(priority,message)
           SetState(name,ttl,policy)
           UnSetState(name)
           FriendStatus(hours)
           PrintFile(filename,lines)
     

For example:

     
     alerts:
     
       myclass::
     
       "Reminder: say hello every hour" ifelapsed=60
     
       nfsd_in_high_dev2::
     
       "High NFS server access rate 2dev at $(host) value $(value_nfsd_in) av $(average_nfsd_in) pm $(stddev_nfsd_in)"
       ShowState(incoming.nfs)
     
      # ROOT PROCS
     
       anomaly_hosts.RootProcs_high_dev2::
     
        "RootProc anomaly high 2 dev on $(host) value $(value_rootprocs) av $(average_rootprocs) pm $(stddev_rootprocs)"
       ShowState(rootprocs)
     

The ShowState() function reports on state gathered by the cfenvd daemon.

     ShowState(incoming.tcpsyn)
     ShowState(outgoing.smtp)
     ShowState(incoming.www)
     ShowState(outgoing.www)
     ShowState(procs)
     ShowState(rootprocs)
     ShowState(otherprocs)
     ShowState(users)

To limit the frequency of alerts, you can set locking times:

      # ROOT PROCS
     
       anomaly_hosts.RootProcs_high_dev2::
     
        "RootProc anomaly high 2 dev on $(host) value $(value_rootprocs) av $(average_rootprocs) pm $(stddev_rootprocs)"
     
        ShowState(rootprocs)  ifelapsed=10 expireafter=20
     

Alerts can also be channeled directly to syslog, to avoid extraneous console messages or email.

     
       SysLog(LOG_ERR,"Test syslog message")
     

One application for alerts is to pass signals from one cfengine to another by persistent, shared memory. For example, suppose a short-lived anomaly event triggers a class that relates to a security alert. The event class might be too short-lived to be followed up by cfagent in full. One could thus set a long term class that would trigger up several follow-up checks. A persistent class could also be used to exclude an operation for an interval of time.

Persistent class memory can be added through a system alert functions to give timer behaviour. For example, consider setting a class that acts like a non-resettable timer. It is defined for exactly 10 minutes before expiring.

     
       SetState("preserved_class",10,Preserve)
     

Or to set a class that acts as a resettable timer. It is defined for 60 minutes unless the SetState call is called again to extend its lifetime.

     
       SetState(non_preserved_class,60,Reset)
     

Existing persistent classes can be deleted with:

     
               UnsetState(myclass)
     

The FriendStatus function is available from version 2.1.4 and displays a message if hosts that normally have a cfengine protocol connection with the current host have not connected for more than than specified number of hours. If the number of hours is set to zero, cfengine uses a machine-learned expectation value for the time and uses this to report. The friend status of a host is thus the expectation that there is a problem with a remote peer. Expected contact rates of more than the variable LastSeenExpireAfter are ignored as spurious, See lastseenexpireafter.

The PrintFile function can be used to display short excerpts from text files. The arguments are the filename and a maximum number of lines to be printed.


Next: , Previous: alerts, Up: Cfagent reference

4.9 binservers

The binservers declaration need only be used if you are using cfengine's model for mounting NFS filesystems. This declaration informs hosts of which other hosts on the network possess filesystems containing software (binary files) which client hosts should mount. This includes resources like programs in /usr/local and so on. A host may have several binary servers, since there may be several machines to which disks are physically attached. In most cases, on a well organized network, there will be only one architecture server per UNIX platform type, for instance a SunOS server, an ULTRIX server and so on.

Binary servers are defined as follows:

     
     binservers:
     
        physics.sun4::   sunserver sunserver2
        physics.linux::  linuxserver
     

The meaning of this declaration is the following. All hosts of type sun4 which are members of the group physics should mount any binaries declared in the mountables resource list which belong to hosts sunserver or sunserver2. Similarly all linux machines should mount binary filesystems in the mountables list from linuxserver.

Cfengine knows the difference between binaries and home directories in the mountables list, because home directories match the pattern given by homepattern. See homepattern. See homeservers.

Note that every host is a binary server for itself, so that the first binary server (and that with highest priority) is always the current host. This ensures that local filesystems are always used in preference to NFS mounted filesystems. This is only relevant in connection with the variable $(binserver).


Next: , Previous: binservers, Up: Cfagent reference

4.10 broadcast

This information is used to configure the network interface for each host.

Every local area network has a convention for determining which internet address is used for broadcast requests. Normally this is an address of the form aaa.bbb.ccc.255 or aaa.bbb.ccc.0. The difference between these two forms is whether all of the bits in the last number are ones or zeroes respectively. You must find out which convention is used at your establishment and tell cfengine using a declaration of the form:

     broadcast:
     
       any::
     
          ones     # or zeros, or zeroes
     

In most cases you can use the generic class any, since all of the hosts on the same subnet have to use the same convention. If your configuration file encompasses several different subnets with different conventions then you will need to use a more specific.

Cfengine computes the actual value of the broadcast address using the value specified above and the netmask See netmask.


Next: , Previous: broadcast, Up: Cfagent reference

4.11 control

The fundamental piece of any cfengine script or configuration file is the control section. If you omit this part of a cfengine script, it will not do anything! The control section is used to define certain variables, set default values and define the order in which the various actions you have defined will be carried out. Because cfengine is a declarative or descriptive language, the order in which actions appear in the file does not necessarily reflect the order in which they are executed. The syntax of declarations here is:

       control:
     
          classes::
     
             variable = ( list or value function(args) )
     

The control section is a sequence of declarations which looks something like the following example:

     
     control:
     
       site     = ( univ )
       domain   = ( univ.edu )
       sysadm   = ( admin@computing.univ.edu )
       netmask  = ( 255.255.252.0 )
       timezone = ( EDT )
       nfstype  = ( nfs )
     
       childlibpath = ( /usr/local:/mylibs )
     
       sensiblesize  = ( 1000 )
       sensiblecount = ( 2 )
       editfilesize  = ( 4000 )
     
       actionsequence =
          (
          links.some
          mountall
          links.others
          files
          )
     
       myvariable = ( something )
       mymacro    = ( somethingelse )
       myrandom   = ( RandomInt(3,6) )
       myexcerpt  = ( ReadFile("/etc/services",220))
     

Parentheses are required when making a declaring information in cfengine. Note that a limited number of built-in functions exists:

For more functions, See Setting variables with functions.

The meaning of each of these lines is described below.


Next: , Previous: control, Up: control

4.11.1 AbortClasses

The AbortClasses list is a list of class identifiers that will result in the abortion of the current cfagent instanitation with an error message containing the name of the offending class.

     
      AbortClasses = ( emergency nologin_exists )
     

This mechanism allows one to make controlled exceptions at the agent level. For example

     control:
     
      actionsequence = ( shellcommands )
     
      AbortClasses = ( danger_will_robinson )
     
     shellcommands:
     
       "shellcom 1"
       "shellcom 2" define=ok elsedefine=danger_will_robinson
     


Next: , Previous: AbortClasses, Up: control

4.11.2 access

The access list is a list of users who are to be allowed to execute a cfengine program. If the list does not exist then all users are allowed to run a program.

        access = ( user1 user2 ...  )

The list may consist of either numerical user identifiers or valid usernames from the password database. For example:

        access = ( mark aurora 22 456 )

would restrict a script to users mark, aurora and user id 22 and 456.


Next: , Previous: access, Up: control

4.11.3 actionsequence

The action sequence determines the order in which collective actions are carried out. Here is an example containing the full list of possibilities:

        actionsequence =
           (
           mountall               # mount filesystems in fstab
           mountinfo              # scan mounted filesystems
           checktimezone          # check timezone
           netconfig              # check net interface config
           resolve                # check resolver setup
           unmount                # unmount any filesystems
           packages               # install/upgrade/remove packages
           shellcommands          # execute shell commands
           editfiles              # edit files
           addmounts              # add new filesystems to system
           directories            # make any directories
           links                  # check and maintain links (single and child)
           mailcheck              # check mailserver
           mountall               # (again)
           required               # check required filesystems
           tidy                   # tidy files
           disable                # disable files
           files                  # check file permissions
           copy                   # make a copy/image of a master file
           processes              # signal / check processes
           module:name            # execute a user-defined module
           )
     

Here is a more complete description of the meaning of these keywords.

addmounts
causes cfengine to compute which NFS filesystems are missing from the current host and add them. This includes editing the filesystem table, creating the mount-directory, if required. This command relies on information provided by mountinfo, so it should normally only be called after mountinfo. If the filesystem already appears to be in the filesystem table, a warning is issued.
checktimezone
runs a check on the timezone defined for the shell running cfengine.
directories
executes all the commands defined under the directories section of the program. It builds new directories.
disable
executes all the commands defined under the disable section of the program.
editfiles
executes all the commands defined under the editfiles section of the program.
files
executes all the commands defined under the files section of the program.
links
executes all the commands defined under the links section of the program.
mailcheck
tests for the presence of the NFS-mounted mail spooling directory on the current host. The name of the mail spool directory is defined in the mailserver section of the cfengine program. If the current host is the same as the mailserver (the host which has the physical spool directory disk) nothing is done. Otherwise the filesystem table is edited so as to include the mail directory.
module
Normally cfengine's ability to detect the systems condition is limited to what it is able to determine while excuting predefined actions. Classes may be switched on as a result of actions cfengine takes to correct a problem. To increase the flexibility of cfengine, a mechanism has been introduced in version 1.5 which allows you to include a module of your own making in order to define or undefine a number of classes. The syntax
            module:mytests
          
            "module:mytests arg1 arg2 .."
     

declares a user defined module which can potentially set the classes class1 etc. Classes returned by the module must be declared so that cfengine knows to pay attention to rules which use these classes when parsing; this is done using AddInstallable. If arguments are passed to the module, the whole string must be quoted like a shellcommand. See Writing plugin modules. Whether or not these classes become set or not depends on the behaviour of your module. The classes continue to apply for all actions which occur after the module's execution. The module must be owned by the user executing cfengine or root (for security reasons), it must be named module:module-name and must lie in a special directory, See moduledirectory.

mountall
mounts all filesystems defined in the hosts filesystem table. This causes new NFS filesystems added by addmounts and mailcheck to be actually mounted. This should probably be called both before mountinfo and after addmounts etc. A short timeout is placed on this operation to avoid hanging RPC connections when parsing NFS mounted file systems.
mountinfo
builds internal information about which filesystems are presently mounted on the current host. Cfengine assumes that required-filesystems which are not found need to be mounted. A short timeout is placed on this operation to avoid hanging RPC connections when parsing NFS mounted file systems. If this times out, no further mount operations are considered reliable and are summarily cancelled.
netconfig
checks the netmask, hostname, IP address and broadcast address for the current host. The correct values for the netmask and broadcast address are set if there is an error. The defaultroute is matched against the static routing table and added if no default route exists. This does not apply to DHCP clients, which set a default route automatically.
required
executes all the commands defined under the required section of the program. It checks for the absence of important NFS resources.
resolve
checks and corrects the DNS domain name and the order of nameservers in the file /etc/resolv.conf.
packages
executes commands defined under the packages section of the program. This will query the system's package database for the specified packages, at the specified versions, set classes based on whether or not those packages exist, and optionally install, upgrade or remove those packages using a pre-defined package manager command.
shellcommands
executes all the commands defined under the shellcommands section of the program.
tidy
executes all the commands defined under the tidy section of the program.
unmount
executes all the commands defined under the unmount section of the program. The filesystem table is edited so as to remove the unwanted filesystems and the unmount operation is executed.
processes
executes commands defined under the processes section of the program.

Under normal circumstances this coarse ordering is enough to suit most purposes. In some cases you might want to, say, only perform half the link operations before mounting filesystems and then, say, perform the remainder. You can do this (and similar things) by using the idea of defining and undefining classes. See Defining classes.

The syntax

     
     actionsequence =
        (
        links.firstpass.include
        ...
        links.secondpass
        )

means that cfengine first executes links with the classes firstpass and include defined. Later it executes links with secondpass defined. You can use this method of adding classes to distinguish more finely the flow of control in programs.

A note about style: if you define and undefine lots of classes to do what you want to do, you might stop and ask yourself if your groups are defined as well as they should be. See groups. Programming in cfengine is about doing a lot for only a little writing. If you find yourself writing a lot, you are probably not going about things in the right way.


Next: , Previous: actionsequence, Up: control

4.11.4 AddClasses

        AddClasses  = ( list of identifiers )

The AddClasses directive is used to define a list of class attributes for the current host. Normally only the hard classes defined by the system are `true' for a given host. It is convenient though to be able to define classes of your own to label certain actions, mainly so that they can later be excluded so as to cut short or filter out certain actions. This can be done in two ways. See actionsequence.

To define a list of classes for the current session, you write:

     AddClasses = ( exclude shortversion )

This is equivalent to (though more permanent than) defining classes on the command line with the -D option. You can now use these to qualify actions. For example

     
       any.exclude::
           ...

Under normal circumstances exclude is always true — because you have defined it to be so, but you can undefine it in two ways so as to prevent the action from being carried out. One way is to undefine a class on the command line when you invoke cfengine:

     

host# cfengine -N exclude

or

     

host# cfengine -N exclude.shortversion host# cfengine -N a.b.c.d

These commands run cfengine with the named classes undefined. That means that actions labelled with these classes are excluded during that run.

Another way to restrict classes is to add a list of classes to be undefined in the actionsequence. See next section.


Next: , Previous: addclasses, Up: control

4.11.5 AddInstallable

        AddInstallable  = ( list of identifiers )

Some actions in your cfengine program will be labelled by classes which only become defined at run time using a define= option. Cfengine is not always able to see these classes until it meets them and tries to save space by only loading actions for classes which is believes will become defined at some point in the program. This can lead to some actions being missed if the action is parsed before the place where the class gets switched on, since cfengine is a one-pass interpreter,. To help cfengine determine classes which might become defined during a run, you can declare them in this list. It does no harm to declare classes here anyway. Here is an example where you need to declare a class because of the ordering of the actions.

     
     control:
     
         AddInstallable  = ( myclass )
     
     files:
     
        myclass::
     
          /tmp/test mode=644 action=fixall
     
     copy:
     
          /tmp/foo dest=/tmp/test define=myclass
     

If we remove the declaration, then when cfengine meets the files command, it skips it because it knows nothing about the class `myclass'—when the copy command follows, it is too late. Remember that imported files are always parsed after the main program so definitions made in imported files always come later than things in the main program.


Next: , Previous: addinstallable, Up: control

4.11.6 AllowRedefinitionOf

Normally cfagent warns about redefinitions of variables during parsing. This is presumed to be a mistake. To avoid this behaviour, add the name of the variable to this list, and the warning disappears.

     control:
     
     actionsequence = ( copy )
     
     AllowRedefinitionOf = ( cfrep )
     
     cfrep = ( bla )
     
     cfrep = ( blo )
     


Next: , Previous: AllowRedefinitionOf, Up: control

4.11.7 Auditing

If this variable is set to true then cfengine conducts extensive auditing of its actions to a database in the work directory. When rules are applied, their locations and policy version are recorded also so that it is possible to see exactly which rule was applied and when. It is assumed that the version is recorded as below:

     
     control:
     
       cfinputs_version = ( 1.2.1 )
       Auditing = true
     

This variable acts as the global default behaviour and may be overriden locally by audit=true/false attributes, where applicable.


Next: , Previous: Auditing, Up: control

4.11.8 AutoDefine

     
     control:
     
        hup_syslogd::
     
          autodefine = ( /etc/syslog.c* )
     

Referring to the class that prefixes the command, autodefine is a list of file patterns that will define the said class, if a named file is copied in any statement. This helps to avoid having to write a large number of file-specific copy: lines with define=class configured. In the example above, the class hup_syslogd would be defined if /etc/syslog.conf is copied at any time.


Next: , Previous: AutoDefine, Up: control

4.11.9 BinaryPaddingChar

     BinaryPaddingChar = ( \0 )

This specifies the type of character used to pad strings of unequal length in editfiles during binary editing. The default value is the space character, since this is normally used to edit filenames or text messages within program code.


Next: , Previous: BinaryPaddingChar, Up: control

4.11.10 BindToInterface

If this is set to a specific IP address of an IP configured interface, cfagent will use that address for outgoing connections. On Multi-homed hosts this allows one to restrict the traffic to a known interface. An interface must be configured with an IP address in order to be bound.

This feature is not available for old operating systems.