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.
In order to install cfengine, you should first ensure that the following
packages are installed.
OpenSSL http://www.openssl.org
Berkeley DB 3.2 or later http://www.sleepycat.com
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.
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 rationalized
to a single directory which defaults to /var/cfengine (by analogy with
/var/cron):
The installation location
/usr/local/sbin is not necessarily a local file system, and cannot
therefore be trusted i) to be present, and ii) to be authentic on an
arbitrary system.
Similarly, a trusted cache of the input files must now be maintained
in the inputs sub-directory. 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 cf.update is
parsed and run before the main configuration is parsed, which is
used to ensure that the currently caches policy is up-to-date.
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..
The name of an operating system architecture e.g. ultrix, sun4 etc.
This is referred to henceforth as a hard class.
The (unqualified) name of a particular host. If your system returns a fully
qualified domain name for your host, cfagent truncates it so as to unqualify
the name.
The name of a user-defined group of hosts.
A day of the week (in the form Monday Tuesday Wednesday..).
An hour of the day (in the form Hr00, Hr01 ... Hr23).
Minutes in the hour (in the form Min00, Min17 ... Min45).
A five minute interval in the hour (in the form Min00_05, Min05_10 ... Min55_00)
A day of the month (in the form Day1 ... Day31).
A month (in the form January, February, ... December).
A year (in the form Yr1997, Yr2001).
An arbitrary user-defined string. (see the reference manual).
The ip-address octets of any active interface, in the form (ipv4_192_0_0_1,
ipv4_192_0_0,ipv4_192_0,ipv4_192).
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/env_data
file is secure.
Node:Evaluated classes,
Next:Filenames and paths,
Previous:Hard classes,
Up:Reference introduction
Evaluated classes
Cfengine provides a number of in-built functions for evaluating classes,
based on file tests. Using these internal functions is quicker than
calling the shell test function. The time functions place their
arguments in chronological order.
IsNewerThan(f1,f2)
True if file 2 is modified more recently than file 1. (mtime)
AccessedBefore(f1,f2)
True if file 1 had its last access earlier than file 2 (atime)
ChangedBefore(f1,f2)
True if file 1's attributes were changed in any way before file 2's (ctime).
FileExists(file)
True if the named file object exists.
IPRange(address-range)
True if the current host lies within the specified range
IsDir(f)
True if the named file object is a directory.
IsLink(f)
True if the named file object is a symbolic link.
IsPlain(f)
True if the named file object is a plain file.
ReturnsZero(command)
True if the named shell command returns with exit code zero (okay).
The directory separator is the forward slash '/' character. All references
to file locations must be absolute names 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.
Cfengine was implemented primarily on Unix-like operating systems, but
has since been ported to Windows operating systems and MacOS X. The Windows
operating systems traditionally use a different filename convention.
The following are all valid absolute file names under Windows:
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.
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.
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, if they 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 internal
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.
-q
(--no-splay) Switch off host splaying (sleeping).
-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 5 systems to generate a Bus
Error or segmentation fault. The same information is available from the
cfengine internal variable $(allclasses) and can be passed as a
parameter to scripts.
-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
(--smtp) Print the SMTP server for the LAN (used by cfexecd).
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 internal 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. Non-definable.
binserver
The default server for binary data.
Non definable.
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.
ChecksumUpdates
If set to `on', security information is automatically updated, See ChecksumUpdates.
class
The currently defined system hard-class (e.g. sun4, hpux).
Non-definable.
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.
faculty
The faculty or site as defined in control (see site).
fqhost
The fully qualified (DNS/BIND) hostname of the system, which
includes the domain name as well.
host
The hostname of the machine running the program.
ipaddress
The numerical form of the internet address of the host currently running
cfengine.
MaxCfengines
The maximum number of cfengines which should be allowed to
co-exist 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:'
prefix on output lines to something else. You might wish to shorten
the string, or have a different prefix for different hosts. The value
in this variable is appended with the name of the host. 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 / (see the reference manual).
site
This variable is identical to $(faculty) and may be used interchangeably.
split
The character on which list variables are split (see the reference manual).
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, so as to avoid name collisions. See also Runtime Options in the
Reference manual.
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.
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.
The name of an operating system architecture e.g. ultrix, sun4 etc.
This is referred to henceforth as a hard class.
The (unqualified) name of a particular host. If your system returns a fully
qualified domain name for your host, cfagent truncates it so as to unqualify
the name.
The name of a user-defined group of hosts.
A day of the week (in the form Monday Tuesday Wednesday..).
An hour of the day (in the form Hr00, Hr01 ... Hr23).
Minutes in the hour (in the form Min00, Min17 ... Min45).
A five minute interval in the hour (in the form Min00_05, Min05_10 ... Min55_00)
A quart hour (in the form Q1, Q2, Q3, Q4)
An abbreviated time with quarter hour specified (in the form Hr00_Q1, Hr23_Q4 etc.)
A day of the month (in the form Day1 ... Day31).
A month (in the form January, February, ... December).
A year (in the form Yr1997, Yr2001).
An arbitrary user-defined string. (see the reference manual).
The ip-address octets of any active interface, in the form (ipv4_192_0_0_1,
ipv4_192_0_0,ipv4_192_0,ipv4_192).
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 sun4orultrixorosf.
In other words, compound classes support two operators: AND and OR,
written . and | respectively. 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:
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:
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.
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.
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:
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').
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.
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.
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.
ACL Example
Here is an example of a configuration file for an NT ACL:
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.
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).
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.
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 )
The control section is a sequence of declarations which looks something
like the following example:
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 = ( user1user2 ... )
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.
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
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
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. Note might actually be preferable to define classes
returned by modules under AddInstallables which is equivalent. 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.
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.
means that cfengine first executes links with the classes
firstpass and includedefined. 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.
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:
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.
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.
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.
Node:ChecksumDatabase,
Next:ChecksumUpdates,
Previous:BinaryPaddingChar,
Up:control
ChecksumDatabase
ChecksumDatabase = ( /var/cfengine/cfdb )
If this filename is defined, cfengine will use it to store
message digests (i.e. cryptographic checksums) of files
for security purposes, See files, checksum=.
This variable defaults to `off'. If set to true, cfagent will
automatically update the checksum of a file, if it changes on the disk.
This means that a security warning will be issued only once
about files which have changed, and the changed version will be re-registered
as the correct version. This option could be switched on after a
system upgrade, for instance, in order to update the database, and then
switched to `off' again to reduce the risk of missing a security
alert. Alternatively, if you are confident that the first message is
sufficient, it can be left as `on' so that only one message is
given.
Note that the variables LD_LIBRARY_PATH is special. This
library path is needed to run processes as children of cfengine.
Often, if the agent is started from cron (which is started by init),
there is no suitable library path set, and shellcommands will
fail with strange errors about not being able to load shared
objects. Setting a library path here is a useful way of
correcting this problem.
Node:copylinks,
Next:defaultcopytype,
Previous:childlibpath,
Up:control
CopyLinks
This list is used to define a global list of names or patterns
which are to be copied rather than linked symbolically. For example
CopyLinks = ( *.config )
The same facility can be specified for each individual
link operation using the copy option See links.
Copying is performed using a file age comparison.
Note that all entries defined under a specified class
are valid only as long as that class is defined. For instance
class::
CopyLinks = ( pattern )
would define a pattern which was only valid when
class is defined.
This parameter determines the default form of copying for all copy operations
parsed after this variable. The legal values are
ctime (intial default), mtime, checksum and binary.
e.g.
If this parameter is set to true, cfengine will delete files on mailservers
whose names do not correspond to a known user name, but might be owned by a
known user.
If this parameter is set to true, cfengine will delete mail files on mailservers
which do not have a name belonging to a known user id. This does not
include lock files.
If this parameter is set to true, cfengine will delete files on mailservers
whose names do not correspond to a known user name, but might be owned by a
known user.
This variable defines the domainname for your site. You must define it
here, because your system might not know its domainname when you run
cfengine for the first time. The domainname can be used as a cfengine
variable subsequently by referring to $(domain). The domainname
variable is used by the action resolve. The domain is also used
implicitly by other matching routines. You should define the domain as
early as possible in your configuration file so as to avoid problems,
especially if you have the strange practice of naming hosts with their
fully qualified host names since groups which use fully qualified names
can fail to be defined if cfengine is not able to figure out the domain name.
This variable has the same effect as the command line options
--dry-run or -n. It tells cfengine to only report
what it should do without actually doing it.
Cfengine will refuse to edit a file which is larger than the value of
editbinaryfilesize in bytes. This is to prevent possible
accidents from occurring. The default value for this variable is 10000000
bytes. If you don't like this feature, simply set the value to be a
very large number or to zero. If the value is zero, cfengine will
ignore it.
This variable is used by cfengine every time it becomes necessary to
edit a file. Since file editing applies only to text files, the files
are probably going to be relatively small in most cases. Asking to edit
a very large (perhaps binary) file could therefore be the result of an
error.
A check is therefore made as a security feature. Cfengine will refuse
to edit a file which is larger than the value of editfilesize in
bytes. This is to prevent possible accidents from occurring. The
default value for this variable is 10000 bytes. If you don't like this
feature, simply set the value to be a very large number or to zero.
If the value is zero, cfengine will ignore it.
This parameter controls the global value of the ExpireAfter parameter.
See Spamming and security. This parameter controls the maximum time in
minutes which a cfengine action is allowed to live. After this time
cfengine will try to kill the cfengine which seems to have hung and
attempt to restart the action.
ExpireAfter = ( time-in-minutes )
This parameter may also be set per action in the action
sequence by appending a pseudo-class called ExpireAftertime.
For instance,
actionsequence = ( copy.ExpireAfter15 )
sets the expiry time parameter to 15 minutes for this copy command.
The homepattern variable is used by the cfengine model for
mounting nfs filesystems. See NFS resources. It is also used in the evaluation of the
pseudo variable home, See files, tidy.
homepattern is in fact a list and is used like a wildcard or
pattern to determine which filesystems in the list of mountables
are home directories. See mountables. This relies on your sticking
to a rigid naming convention as described in the first reference above.
For example, you might wish to mount (or locate directly if you are not
using a separate partition for home directories) your home directories
under mountpattern in directories u1, u2 and so on.
In this case you would define homepattern to match these numbers:
homepattern = ( u? )
Cfengine now regards any directory matching
$(mountpattern)/u? as being a user login directory.
Suppose you want to create mount home directories under
$(mountpattern)/home and make subdirectories for staff and
students. Then you would be tempted to write:
HomePattern = ( home/staff home/students )
Unfortunately this is not presently possible. (This is, in principle,
a bug which should be fixed in the future.) What you can do instead is
to achieve the same this as follows:
This parameter controls the global value of the IfElapsed
parameter, See Spamming and security. This parameter
controls the minimum time which must have elapsed for
an action in the action sequence before which it will be
executed again.
IfElapsed = ( time-in-minutes )
This parameter may also be set per action in the action
sequence by appending a pseudo-class called IfElapsedtime.
For instance,
ActionSequence = ( copy.IfElapsed15 )
sets the elapsed time parameter to 15 minutes for this copy command.
This variable switches on the output level whereby cfengine
reports changes it makes during a run. Normally only
urgent messages or clear errors are printed. Setting
Inform to on makes cfengine report on
all actions not explicitly cancelled with a `silent' option.
To set this output level one writes:
If you have an operating system which is installed on some
non-standard hardware, you might have to specifically set the
name of the network interface. For example:
It is only necessary to set the interface name in this fashion
if you have an operating system which is running on special
hardware. Most users will not need this.
The choice set here overrides the system defaults and the
choices made in the cfrc file, See cfrc resource file.
This list may be used to define a number of extensions
which are regarded as being plain files by the system.
As part of the general security checking cfengine will
warn about any directories which have names using
these extensions. They may be used to conceal directories.
moduledirectory = ( directory for plugin modules )
This is the directory where cfengine will look for plug-in modules
for the actionsequence, See actionsequence. Plugin modules
may be used to activate classes using special algorithms.
See Writing plugin modules.
The mountpattern list is used by the cfengine model for mounting
nfs filesystems. See NFS resources. It is also used in the evaluation of the
pseudo variable home, See files, tidy.
It is used together with the value of homepattern to locate and
identify what filesystems are local to a given host and which are
mounted over the network. For this list to make sense you need to
stick to a rigid convention for mounting your filesystems under a single
naming scheme as described in the section mentioned above. If you
follow the recommended naming scheme then you will want to set the value
of mountpattern to
mountpattern = ( /$(site)/$(host) )
which implies that cfengine will look for local disk partitions under a
unique directory given by the name of the host and site. Any
filesystems which are physically located on the current host lie in this
directory. All mounted filesystems should lie elsewhere. If you
insist on keeping mounted file systems in more than one location, you
can make a list like this:
The netmask variable defines the partitioning of the subnet addresses on
your network. Its value is defined by your network administrator. On
most systems it is likely to be 255.255.255.0. This is used to
configure the network interface in netconfig.
See actionsequence.
Every host on the internet has its own unique address. The addresses
are assigned hierarchically. Each network gets a domain name and
can attach something like 65,000 hosts to that network. Since this is
usually too many to handle in one go, every such network may be divided
up into subnets. The administrator of the network can decide how the
division into subnets is made. The decision is a trade-off between
having many subnets with few hosts, or many hosts on few subnets. This
choice is made by setting the value of a variable called netmask.
The netmask looks like an internet address. It takes the form:
aaa.bbb.ccc.mmm
The first two numbers aaa.bbb are the address of the domain. The
remainder ccc.mmm specifies both the subnet and the hostname.
The value of netmask tells all hosts on the network: how many of
the bits in the second half label different subnets and how many label
different hosts on each of the subnets?
The most common value for the netmask is 255.255.255.0. It is
most helpful to think of the netmask in terms of bits. Each base-10
number between 0-255 represents 8 bits which are either set or not set.
Every bit which is set is a network address and every bit which is zero
is part of a host address. The first two parts of the address
255.255 always takes these values. If the third number is
255, it means that the domain is divided up into 256 sub networks
and then the remaining bits which are zero can be used to give 255
different host addresses on each of the subnets.
If the value had been 255.255.255.254, the network would be
divided up into 2^15 subnets, since fifteen of the sixteen bits
are one. The remaining bit leaves enough room for two addresses 0 and
1. One of those is reserved for broadcasts to all hosts, the
other can be an actual host -- there would only be room for one host
per subnet. This is a stupid example of course, the main point with the
subnet mask is that it can be used to trade subnets for hosts per
subnet. A value of 255.255.254.0 would allow 128 different
subnets with 2*256-1 = 511 hosts on each.
We needn't be concerned with the details of the netmask here. Suffice
it to say that its value is determined for your entire domain by the
network administrator and each host has to be told what the value is.
Each host must also know what convention is used for the broadcast
address. This is an address which hosts can send to if they wish to
send a message to every other host on their subnet simultaneously. It is
used a lot by services like NIS to ask if any hosts are willing to
perform a particular service. There are two main conventions for the
broadcast address: address zero (all host bits are zero) and the highest
address on the subnet (all host bits are ones). The convention can be
different on every subnet and it is decided by the network
administrator. When you write a cfengine program you just specify the
convention used on your subnet and cfengine works out the value of the
broadcast address from the netmask and the host address
See broadcast. Cfengine works out the value of the broadcast address
using the value of the netmask.
If enabled, this option causes cfengine to detect and
disable files which have purely non-alphanumeric
filenames, i.e. files which might be accidental or
deliberately concealed. The files are then marked
with a suffix .cf-nonalpha and are rendered
visible.
NonAlphaNumFiles = ( on )
These files can then be tidied by searching for
the suffix. Note that alphanumeric means
ascii codes less than 32 and greater than 126.
This variable is included only for future expansion. If you do not
define this variable, its value defaults to "nfs".
At present cfengine operates only with NFS (the network file system).
When cfengine looks for network file systems to mount, it adds lines in
the filesystem table (/etc/fstab,/etc/checklist etc.) to
try to mount filesystems of type "nfs". In principle you might want
to use a completely different system for mounting filesystems over the
network, in which case the `mount type' would not be "nfs" but
something else.
At the time of writing certain institutions are replacing NFS with AFS
(the Andrew filesystem) and DFS (from the distributed computing
environment). The use of these filesystems really excludes the need to
use the mount protocol at all. In other words if you are using AFS or
DFS, you don't need to use cfengine's mounting commands at all.
The value of this variable determines the characters which is used by
cfengine in creating the unique filenames in the file
repository. Normally, its value is set to _ and each / in
the path name of the file is changed to _ and stored in the
repository. If you prefer a different character, define it here. Note
that the character can be quoted with either single or double quotes in
order to encompass spaces etc.
Defines a special directory where all backup and junk
files are collected. Files are assigned a unique filename
which identifies the path from which they originate.
This affects files saved using disable, copy,
links and editfiles See Disabling and the file repository.
When cfexecd is used in daemon mode, it defaults to running
once an hour, on the hour, i.e..
schedule = ( Min00_05 )
This can be extended to make the agent run more often. The time
specifiers are cfengine classes, and are written as intervals of time
rather the precise times. Cfengine's time resolution is purposely
limited to five minutes because the auto-correlation time of user
resources is generally greater than this. Thus, it is assumed that
precision timing is not required and the start time of cfengine, when
scheduled in daemon mode, is not better than a few minutes. The daemon
does not require precision, but offers many other strategic
features for load balancing and security.
Other time classes can be used in the schedule list, but note
that cfexecd will not run the agent more than once every five minutes.
This is treated as a fundamental granularity.
This variable is used by the action required. It defines for
cfengine what you consider to be the minimum number of files in a
`required' directory. If you declare a directory as being required,
cfengine will check to see if it exists. Then, if the directory
contains fewer than the value of sensiblecount files, a warning
is issued. The default value for this variable is 2.
This variable is used by the action required. It defines for
cfengine what you consider to be the minimum size for a `required' file.
If you declare a file as being required, cfengine will check to see if
the file exists. Of course, the file may exist but be empty, so the
size of the file is also checked against this constant. If the file is
smaller than the value of sensiblesize a warning is issued. The
default value for this variable is 1000 bytes.
This causes cfengine to produce detailed output of what action is
being carried out as part of the prefix information during output.
This is intended only for third party tools which collect and parse
the cfengine output. It will be of little interest to humans.
This variable defines a convenient name for your site configuration. It
is useful for making generic rules later on, because it means for
instance that you can define the name of a directory to be
/$(site)/$(host)/local
without having to redefine the rule for a specific site. This is a
handy trick for making generic rules in your files which can be imported
into a configuration for any site.
faculty is a synonym for site. The two names
may be used interchangeably.
The value of this variable is used to define the list separator in
variables which are expected to be treated as lists. The default value
of this variable is the colon :. Cfengine treats variables
containing this character as lists to be broken up and iterated over in
the following cases:
in the `to' field of a multiple link action,
in the `from' field of a copy action,
in the directory field of a tidy action,
in the directory field of the files action,
in the ignore action.
This typically allows communication with PATH-like
environment variables in the shell.
A list of additional spool directories for cfengine to police. In these
directories, filenames should correspond to existing users of the
system. When users lost their accounts, this list plus the mail spool
directory will be checked for files owned by deprecated users.
See also: DeleteNonOwnerFiles, DeleteNonUserFiles.
Filenames in this list are treated as suspicious and generate a warning
as cfengine scans directories. This might be used to detect hacked systems
or concealed programs. Checks are only made in directories which cfengine
scans in connection with a command such as files, tidy or copy.
The mail address of your system administrator should be placed here.
This is used in two instances. If cfengine is invoked with the option
-a, then it simply prints out this value. This is a handy
feature for making scripts.
The administrators mail address is also written into the personal log
files which cfengine creates for each user after tidying files, so you
should make this an address which users can mail if they have troubles.
The timezone variable is a list of character strings which define your local
timezone. Normally you will only need a single timezone, but sometimes
there are several aliases for a given timezone e.g. MET and CET are synonymous.
Currently only the first three characters of this string are
checked against the timezone which cfengine manages to glean from the
system. If a mismatch is detected a warning message is printed.
cfengine does not attempt to configure the timezone. This feature works
only as a reminder, since the timezone should really be set once and for
all at the time the system is installed. On some systems you can set
the timezone by editing a file, a procedure which you can automate with
cfengine See editfiles.
The value of the timezone can be accessed by variable substitution
in the usual way. It expands to the first item in your list.
shellcommands:
"echo ${timezone} | mail ${sysadm}"
The default timeout for network connections is 10 seconds. This
is too short on some routed networks. It is not permitted to set
this variable smaller than 3 seconds or larger than 60 seconds.
This variable switches on the output level whereby cfengine
reports everything it does during a run in great detail. Normally only
urgent messages or clear errors are printed, See Inform.
This option is almost equivalent to using the --verbose of -v
command-line options. The only difference is that system environment reporting
information, which is printed prior to parsing, is not shown.
To set this output level on selected hosts one writes:
This variable switches on the parser-output level whereby cfengine
reports non-fatal warnings. This is equivalent to setting the command
line switch --no-warn, or -w. To set this output level on
selected hosts one writes:
If this parameter is set to true, cfengine will warn about files on
mailservers whose names do not correspond to a known user name, but
might be owned by a known user.
If this parameter is set to true, cfengine will warn about mail files on
mailservers which do not have a name belonging to a known user id. This
does not include lock files.
If this parameter is set to true, cfengine will warn about files on
mailservers whose names do not correspond to a known user name, but
might be owned by a known user.
Cfengine copies files between locally mounted filesystems and via the
network from registered servers. The copy algorithm avoids
race-conditions which can occur due to network and system latencies by
copying first to a file called file.cfnew on the local
filesystem, and then renaming this quickly into place. The aim of this
roundabout procedure is to avoid situations where the direct rewriting
of a file is interrupted midway, leaving a partially written file to be
read by other processes. Cfengine attempts to preserve hard links to
non-directory file-objects, but see the caution below.
Caution should be exercised in copying files which change rapidly in size.
This can lead to file corruption, if the size changes during copying. Cfengine
attempts to prevent this during remote copies.
The destination file is the only obligatory item. This must be the name
of an object which matches the type of the master object i.e. if the
master is a plain file, the destination must also be the explicit name
of a plain file. An implicit `copy file to directory' syntax is not
allowed. Symbolic links are copied as symbolic links, plain files are
copied as plain files and special files are copied as special files.
The recurse option is required to copy the contents of subdirectories.
mode, owner, group
The file mode, owner
and group of the images are specified as in the files function
See files.
action
The action may take the values warn or
silent. The default action is fix, i.e. copy files. If warn
is specified, only a warning is issued about files which require
updating. If silent is given, then cfengine will copy the files
but not report the fact.
force
If set to `true', this option causes cfengine to copy files regardless
of whether it is up to date.
forceipv4
If you are working on an ipv6 enabled pair of hosts, cfengine will
normally select ipv6 for communication between them. If you wish
to force the use of ipv4 for some reason, set this option to true.
forcedirs
If set to `true', this option causes files or links which block the
creation of directories, during recursive copying, to be moved
aside forcably. A single non-supressable warning is given when this
occurs; the file is moved to filename.cf-moved.
backup
If the backup option is set to "false", cfengine
will not make a backup copy of the file before copying.
repository
This allows a local override of the Repository variable, on an item
by item basis. If set to "off" or "none" it cancels the value of a global repository.
Copy makes a literal image of the master file at the destination,
checking whether the master is newer than the image. If the image needs
updating it is copied. Existing files are saved by appending
.cfsaved to the filename.
stealth
If set to `on' causes cfengine to preserve atime and mtime
on source files during local
file copies. File times cannot be preserved on
remote copies. This option should normally only be used
together with a checksum copy, since preserving atime and mtime
implies changing ctime which will force continual copying.
This is a weakness in the Unix file system. Ctime cannot be
preserved. Before version 1.5.0, there was a typo which
made this option active on many file copies.
timestamps
If this is set to `preserve' or `keep', the times of the source
files are kept by the destination files during copying. This is
like the `p' option of the tar command.
recurse
Specifies the depth of recursion when copying whole file-trees
recursively. The value may be a number or the keyword inf.
Cfengine crosses device boundaries or mounted filesystems when
descending recursively through file trees. To prevent
this it is simplest to specify a maximum level of recursion.
symlink
This option may be repeated a number of times to specify the
names of files, or wildcards which match files which are to
be symbolically linked instead of copied. A global list of
patterns can also be defined in the control section of the program
See linkcopies.
ignore
This works like the global ignore directive but here you may
provide a private list of ignorable directories and files.
Unlike include, exclude this affects the way cfengine parses
directory trees.
include
This option may be repeated a number of times to specify the names of
files, or wildcards which match files which are to be included in a copy
operation. Specifying one of these automatically excludes everything
else except further include patterns. A global list of patterns can
also be defined in the control section of the program.
exclude
This option may be repeated a number of times to specify the
names of files, or wildcards which match files which are to
be excluded from a copy operation. A global list of
patterns can also be defined in the control section of the program
`excludes' override `includes'.
See excludelinks.
type
Normally cfengine uses the ctime date-stamps on files to determine
whether a file needs to be copied: a file is only copied if the master
is newer than the copy or if the copy doesn't exist. If the type is set
to checksum or sum, then a secure MD5 checksum is used to
determine whether the source and destination files are identical. If
byte or binary is specified, a byte by byte comparison is
initiated. An mtime comparison does not take into account
changes of file permissions, only modifications to the contents of the
files.
server
If you want to copy a file remotely from a server, you specify the
name of the server here. This must be the name of a host which is
running the cfservd daemon, and you must make sure that you
have defined the variable domain in the control section
of the cfagent.conf file. If you don't define a domain
you will probably receive an error of the form `cfengine: Hey! cannot
stat file'.
oldserver
If this is true, cfengine uses the old protocol specification for
temporary compatibility with early version 2 alphas.
trustkey
This option defaults to 'no' or 'false'. If set to true, cfagent will
accept a public key from a server whose public key is presently unknown
to the agent, on trust. This option should be used to bootstrap public
key transfer between hosts. Once a public key has been accepted, it will
not be replaced automatically. Dated public keys must be removed
by hand.
encrypt
Has an effect only when used in conjuction with copy from a remote file
server. This causes cfengine to use encryption and one-time keys on
transferred data. (This requires RSA keys to be installed on both client
and server hosts, and provides strong authentication and encryption,
using random session keys.) The preferred algorithm is Blowfish, with a
128 bit key. Generally speaking the only case in which this function
makes sense is in transferring shadow password files. Encrypting the
transfer of system binaries makes little sense. Note: the
encryption keys required to get files from cfservd are those for the
user under which cfservd is running (normally root).
verify
If verify is true, cfagent attempts to verify the integrity of a remote
file transfer before the new file is installed. This takes time, since
an MD5 computation and transaction must take place.
size
With this option you can specify that a file is only to be copied if the
source file meets a size critereon. This could be used to avoid
installing a corrupted file (the copying of an empty password file, for
instance). Sizes are in bytes by default, but may also be quoted in
kilobytes or megabytes using the notation:
numberbytes
numberkbytes
numbermbytes
Only the first characters of these strings are significant, so they may
be written however is convenient: e.g. 14kB, 14k,
14kilobytes etc.
Examples are:
size=<400 # copy if file size is < 400 bytes
size=400 # copy if file size is equal to 400 bytes
size=>400 # copy if file size > 400 bytes
linktype
This option determines the type of link used to make links. This only
applies if the file is linked rather than copied because it matches
a pattern set by symlink. The default type is a direct symbolic
link. The values relative or absolute may be used, but
hard links may not be created in place of copied files, since hard links
must normally reside on the same filesystem as their files, and it
is assumed that most links will be between filesystems. If this value
is set to copy or none, symbolic links will be replaced
by actual copies of the files they point to. Note that for directories,
this option is ignored.
typecheck
Controls whether cfengine allows files of one type to overwrite files of
another type, i.e. switches on/off errors if source and existing
destination files do not match in type, e.g. if a file would overwrite a
directory or link. The default is on for safety reasons.
define
This option is followed by a list of classes which are to be `switched on'
if and only if the named file was copied. In multiple (recursive) copy
operations the classes become defined if any of the files in the file
tree were copied. This feature is useful for switching on other actions
which are to be performed after the installation of key files (e.g.
package installation scripts etc).
purge
If this option is set to true, cfengine will remove files in the
destination directory which are not also in the source directory. This
allows exact images of filesystems to be mantained. Note that if the
copy command has includes or excludes or ignored files, cfengine will
purge only those files on the client machine which are also on the
server. Included files are not purged.
This means that some files (such as system specific work files)
can be excluded from copies without them being destroyed.
Note that purging is disallowed if contant with a remote server fails.
This means that local files will not be destroyed by a denial of service
attack. You should not use this option to synchronize NFS mounted
file systems. If the NFS server goes down, cfengine cannot then tell the
difference between a valid empty directory and a missing NFS file system.
If you use purge, use a remote copy also.
If we specify purge, then the following options will also be set and
cannot be altered: forcedirs=true, typecheck=false, since
other defaults could be very destructive.
In the first example, a global aliases file is copied from the master
site file /local/etc/aliases to /etc/aliases, setting the
owner and protection as specified. The file gets installed if
/etc/aliases doesn't exist and updated if /local/etc/aliases
is newer than /etc/aliases. In the second example, backup-etc
is a directory containing master configuration files (for instance, services,
aliases, passwd...). Each of the files in backup-etc
is installed or updated under /etc. Finally, a global
nsswitch.conf file is kept up to date for solaris systems.
The home directive can be used as a destination, in which
case cfengine will copy files to every user on the system. This is
handy for distributing setup files and keeping them updated:
You can force the copying of files, regardless of the date stamps
by setting the option force=true or force=on. The default
is force=false or force=off.
Hard links are not like symbolic links, they are not merely pointers to
other files, but alternative names for the same file. The name of every
file is a hard link, the first so to speak. You can add additional names
which really are the file, they are not just pointers. For the
technically minded, they are not separate inodes, they are additional
directory references to the same inode. When you perform a copy
operation on multiple files, cfengine attempts to preserve hard links
but this is a difficult task.
Because a hard link just looks like an ordinary file (it cannot be
distingiushed from the original, the way a symbolic link can)
there is a danger that any copy operation will copy two hard links to
the same file as two separate copies of the same file. The difference
is that changes a hard-linked file propagate to the links, whereas
two copies of a file are completely independent thereafter.
In order to faithfully reproduce all hardlinks to all files, cfengine
needs to examine every file on the same filesystem and check whether
they have the same inode-number. This would be an enourmous overhead, so it
is not done. Instead what happens is that cfengine keeps track of only
the files which it is asked to examine, for each atomic copy-command,
and makes a note of any repeated inodes within this restricted set.
It does not try to go off, wandering around file systems looking to
other files which might be hardlinks.
To summarize, cfengine preserves hardlinks during copying, only
within the scope of the present search. No backups are made of
hard links, only of the first link or name of the file is backed
up. This is a necessary precaution to avoid dangling references
in the inode table. As a general rule, hard links are to be avoided
because they are difficult to keep track of.
In long recursive copies, where you descend into many levels of diretories,
you can quickly run out of file descriptors. The number of file descriptors
is a resource which you can often set in the shell. It is a good idea
to set this limit to a large number on a host which will be copying
a lot of files. For instance, in the C shell you would write,
limit descriptors 1024
Most systems should have adequate defaults for this parameter, but
on some systems it appears to be set to a low value such as 64, which is
not sufficient for large recursive tree searches.
Dynamical routing is not configurable in cfengine, but for machines with
static routing tables it is useful to check that a default route is
configured to point to the nearest gateway or router. The syntax for
this statement is simply:
defaultroute:
class::
my_gateway
For example:
defaultroute:
most::
129.240.22.1
rest::
small_gw
Gateways and routers usually have internet address aaa.bbb.ccc.1
-- i.e. the first address on the subnet. You may use the numerical
form or a hostname for the gateway.
This is a synonyn for required, See required.
This action tests for the existence of a file or filesystem. It should
be called after all NFS filesystems have been mounted. You may use the
special variable $(binserver) here.
Files or filesystems which you consider to be essential to the operation
of the system can be declared as `required'. Cfengine will warn
if such files are not found, or if they look funny.
Suppose you mount your filesystem /usr/local via NFS from some
binary server. You might want to check that this filesystem is not
empty! This might occur if the filesystem was actually not
mounted as expected, but failed for some reason. It is therefore not
enough to check whether the directory /usr/local exists, one must
also check whether it contains anything sensible.
Cfengine uses two variables: sensiblesize and
sensiblecount to figure out whether a file or filesystem is
sensible or not. You can change the default values of these variables
(which are 1000 and 2 respectively) in the control section.
See control.
If a file is smaller than sensiblesize or does not exist, it
fails the `required' test. If a directory does not exist, or contains
fewer than sensiblecount files, then it also fails the test and a
warning is issued.
disks:
any::
/$(site)/$(binserver)/local
If you set the freespace variable to a value and set inform=true,
cfagent issues warnings when free disk space falls below this threshold.
Any define-classes also become defined in this instance.
(the default units are kilobytes,
but you may specify bytes or megabytes), e.g.
If the option force=true is used, cfengine will parse filesystems
even on NFS mounted filesystems. Normally it does not make sense to
check filesystems that are not native to the local host, but occasionally
ne would like to force such a check in order to set a class, based on the
result, for instance.
Directories declarations consist of a number of directories to be
created. Directories and files may also be checked and created using
the touch option in the files actions. See files.
The form of the command is similar to that of files but this
command is only used to create new directories. Valid options are
mode, owner, group and are described under
files See files. This interface is only for convenience.
It is strictly a part of the `files' functionality and is performed
together with other `files' actions at run time.
The creation of a path will fail if one of the links in the path is a
plain file or device node. A list of classes may optionally be defined
here if a directory is created.
Disabling a file means renaming it so that it becomes harmless. This
feature is useful if you want to prevent certain dangerous files from
being around, but you don't want to delete them-- a deleted file cannot
be examined later. The syntax is
Cfengine renames a given file by appending the name of the file with the
suffix .cfdisabled. A typical example of a file you would
probably want to disable would be the /etc/hosts.equiv file which
is often found with the + symbol written in it, opening the
system concerned to the entire NIS universe without password protection!
Here is an example:
Hint: The last example disables a file which restricts access to the
at utility. Such a command could be followed by a file action,
See files,
files:
some::
/var/spool/cron/at.allow =0644 N [root] [wheel] touch
which would create an empty security file at.allow.
See also your system manual pages for the at command if you don't
understand why this could be useful.
Disabling a link deletes the link. If you wish you may use the
optional syntax
disable:
/directory/name type=file
to specify that a file object should only be disabled if it is a plain
file. The optional element type= can take the values
plain, file, link or links. If one of
these is specified, cfengine checks the type and only disables
the object if there is a match. This allows you to disable a file
and replace it by a link to another file for instance.
NOTE that if you regularly disable a file which then gets recreated by
some process, the disabled file filename.cfdisabled will
be overwritten each time cfengine disables the file and therefore the
contents of the original are lost each time. The rotate facility
was created for just this contingency.
The disable feature can be used to control the size of system log files,
such as /var/adm/messages using a further option rotate.
If the value rotate is set to 4, say,
disable:
filename rotate=4
then cfengine renames
the file concerned by appending `.1' to it and a new, empty file is
created in its place with the same owner and permissions. The next time
disable is executed `.1' is renamed to `.2' and the file
is renamed `.1' and a new empty file is created with the same
permissions. Cfengine continues to rotate the files like this
keeping a maximum of four files. This is similar to the behaviour
of syslog.
If you simply want to empty the contents of a log file, without
retaining a copy then you can use rotate=empty or
rotate=truncate. For instance,
to keep control of your World Wide Web server logs:
This keeps a running log which is emptied each Sunday and Wednesday.
The size= option in disable allows you to carry out a disable
operation only if the size of the file is less than, equal to or greater
than some specified size. Sizes are in bytes by default, but
may also be quoted in kilobytes or megabytes using the notation:
numberbytes
numberkbytes
numbermbytes
Only the first characters of these strings are significant, so they may
be written however is convenient: e.g. 14kB, 14k,
14kilobytes etc.
Examples are:
size=<400 # disable if file size is < 400 bytes
size=400 # disable if file size is equal to 400 bytes
size=>400 # disable if file size > 400 bytes
This options works with rotate or normal disabling; it is just
an extra condition which must be satisfied.
If a disable command results in action being taken by cfengine, an optional
list of classes becomes can be switched on with the aid of a statement
define=classlist in order to trigger knock-on actions.
The repository declaration allows a local override of the
Repository variable, on an item by item basis. If set to "off" or
"none" it cancels the value of a global repository and leaves the disabled
file in the same directory.
Performs ascii (line-based) editing on text-files or limited binary
editing of files.
If editing a file which has hard links to it, be aware that
editing the file will destroy the hard link references. This is also the
case with shell commands. You should avoid hard links whenever possible.
The form of an editing command is
editfiles can also search directories recursively through directories
and edit all files matching a pattern, using Include, Exclude, and
Ignore (see Recursive File Sweeps in the tutorial).
The first of these affects the file /etc/netmasks on all SunOS 4
systems, deleting any lines containing the string "255.255.254.0" and
Appending a single line to the file containing "128.39 255.255.255.0"
if none exists already. The second affects only hosts in the class
`PrintServers' and adds the names of three hosts: tor, odin and borg to
the file /etc/hosts.lpd which specifies that they are allowed to
connect to the printer services on any host in the class `PrintServers'.
Note that single or double quotes may be used to enclose strings
in cfengine. If you use single quotes, your strings may contain
double quotes and vice-versa. Otherwise a double quoted string
may not currently contain double quotes and likewise for
single quoted strings.
As of version 1.3.0, you can use the home directive in
edit filenames, enabling you to edit files for every user
on the system, provided they exist. For example, to edit
every user's login files, you would write
If a user does not possess the named file, cfengine just skips
that user. A new file is not created.
The meanings of the file-editing actions should be self-explanatory.
Commands containing the word 'comment' are used to `comment out' certain
lines in a file rather than deleting them. Hash implies a shell
comment of the type
# comment
Slash implies a comment of the C++ type:
// comment
Percent implies a comment of the type:
% comment
More general comment types may be defined using the
SetCommentStart, SetCommentEnd and
CommentLinesMatching, CommentLinesStarting
functions.
A special group of editing commands is based on the GNU Regular
Expression package. These use GNU regular expressions to search line by
line through text and perform various editing functions. Some of these
commands are based on the concept of a file pointer. The pointer starts
at line one of the file and can be reset by 'locating' a certain line,
or by using the reset-pointer commands. The current position of the
pointer is used by commands such as InsertLine to allow a
flexible way of editing the middle of files.
A simple decision mechanism is incorporated to allow certain editing
actions to be excluded. For instance, to insert a number of lines
in a file once only, you could write:
Since the first inserted line matches the predicate on subsequent calls,
the grouped lines will only be carried out once.
The full list of editing actions is given below in alphabetical order.
Note that some commands refer to regular expressions and some refer to
'literal strings' (i.e. any string which is not a regular
expression). Variable substitution is performed on all strings. Be
aware that symbols such as ., * and so on are
meta-characters in regular expressions and a backslash must be used to
make them literal. The regular expression matching functions are
POSIX extended regular expressions.
See Regular expressions.
AbortAtLineMatching quoted-regex
This command sets the value of a regular expression. In all editing
operations (except FixEndOfLine and GotoLastLine) which involve multiple
replacements and searches, this expression marks a boundary
beyond which cfengine will cease to look any further. In other
words, if cfengine encounters a line matching this regular
expression, it aborts the current action. BE CAREFUL with this
feature: once set, the string remains set for the remainder of
the current file. It might therefore interact in unsuspected ways
with other search parameters. Editing actions are always aborted
as soon as the abort expression is matched.
Use UnsetAbort to unset the feature.
Append quoted-string
Add a line containing the quoted string to the end of the file.
This should be used in conjunction with the
decision structures BeginGroupIfNoLineMatching and
BreakIfLineMatches.
AppendIfNoSuchLine quoted-string
Add a line containing the quoted string to the end of the file
if the file doesn't contain the exact line already.
AppendIfNoLineMatching quoted-regex
A new version of the older AppendIfNoSuchLine
which uses a regular expression instead of a literal
string. The line which gets appended must be set
previously using SetLine.
AppendToLineIfNotContains quoted-string
This commands looks for an exact match of the quoted string
in the current line. If the quoted string is not contained
in the line, it is appended. This may be used for adding
entries to a list.
AutoCreate
If this command is listed anywhere in the file action list, cfengine
will create the named file if it doesn't exist. Normally cfengine issues
an error if the named file does not exist, but if this is set,
notification of the file's absence is only in verbose output. New files
are created with mode 644 (see also Umask), read access for everyone and write access for
the cfengine user (normally root). Note that if you set this,
BeginGroupIfFileIsNewer will always be true.
AutomountDirectResources quoted-string
This command is designed to assist with automounter configuration for
users wishing to use the automounter for NFS filesystems, but still use
the cfengine mount model.
Applied to the current file, it is equivalent to saying: for each of the
mountable resources in the list See mountables, append if not found a
line for a direct automount map command, to the current file. The
string which follows can be used to specify any special mount options
e.g. "-nosuid" for non setuid mounting (of all the
mountables). Note that this is added to the current file and not to a
file named /etc/auto_direct.
Backup quoted-string
Set to true or false, on or off to set inform level for this file.
Default is on.
BeginGroupIfDefined quoted-string
The lines following, up to the first EndGroup
are executed if the quoted class is defined.
BeginGroupIfNotDefined quoted-string
The lines following, up to the first EndGroup
are executed if the quoted class is not defined.
BeginGroupIfFileExists quoted-string
The lines following, up to the first EndGroup
are executed if the quoted filename exists (can be statted).
Files which are not readable by the running process are
for all intents and purposes non-existent.
BeginGroupIfFileIsNewer quoted-string
The lines following, up to the first EndGroup
are executed if the quoted filename is newer than the file being
edited.
BeginGroupIfNoLineContaining quoted-string
The lines following, up to the first EndGroup
are executed if the quoted string does not appear in
any line in the file.
BeginGroupIfNoLineMatching quoted-regex
The lines following, up to the first EndGroup
are executed if the quoted regular expression
does not match any line in the file.
BeginGroupIfNoMatch quoted-regex
The lines following, up to the first EndGroup
are executed if the quoted regular expression does
not match the current line.
BeginGroupIfNoSuchLine quoted-string
The lines following, up to the first EndGroup
are executed if the quoted literal string
does not match any line in the file.
BreakIfLineMatches quoted-regex
Terminates further editing of the current
file if the current line matches the quoted
regular expression.
CatchAbort
Edit actions which abort on failure (such as LocateLineMatching)
will jump to the first instance of this marker instead of completely
aborting an edit if this keyword occurs in an editing script.
You can catch the exceptions thrown by the following commands:
CommentNLines,CommentToLineMatching,DeleteNLines,DeleteToLineMatching,
HashCommentToLineMatching,IncrementPointer,
LocateLineMatching,PercentCommentToLineMatching,
RunScriptIf(No)LineMatching,UnCommentNLines.
CommentLinesMatching quoted-regex
Use the current value of the comment delimiters
set using SetCommentStart and SetCommentEnd to comment
out lines matching the given regular expression in quotes.
CommentLinesStarting quoted-string
Use the current value of the comment delimiters
set using SetCommentStart and SetCommentEnd to comment
out lines starting with the quoted literal string.
CommentNLines quoted-string
Comments up to N lines from the current file, starting from the
location of the current line pointer. If the end of the file is reached
and less than N lines are deleted, a warning is issued, but
editing continues. The current value of the comment delimiters is
used to determine the method of commenting, (see SetCommentStart).
After the operation the pointer points to the line after the
commented lines.
CommentToLineMatching quoted-regex
Use the current value of the comment delimiters set using
SetCommentStart and SetCommentEnd to comment out lines
from the current position in a file to a line matching the given regular
expression in quotes.
DefineClasses "class1:class2:..."
Activate the following colon, comma or dot-separated list of classes if
and only if the file is edited.
DeleteLinesAfterThisMatching quoted-regex
Delete lines after the current position which match the quoted expression.
DeleteLinesContaining quoted-string
Delete all lines containing the exact string quoted.
DeleteLinesMatching quoted-regex
Delete all lines matching the quoted regular expression.
DeleteLinesStarting quoted-string
Delete all lines beginning with the exact string quoted.
DeleteNLines quoted-string
Deletes up to N lines from the current file, starting from the
location of the current line pointer. If the end of the file is reached
and less than N lines are deleted, a warning is issued, but
editing continues.
DeleteToLineMatching quoted-regex
Delete lines from the current position, up to
but not including a line matching the regular expression
in the quoted string. If no line matches the
given expression, a warning is only printed in
verbose mode, but all edits are immediately
abandoned.
EditMode "Binary"
If set to binary, the file will be edited as if it were a non-ASCII file.
See discussion below.
EditMode "Binary"
EmptyEntireFilePlease
Deletes all lines from the current file.
ElseDefineClasses
See DefineClasses
EndGroup
Terminates a begin-end conditional structure.
EndLoop
Terminates a loop. See ForEachLineIn
Filter filteralias
Name a fiter for pruning file searches.
FixEndOfLine
The quoted string which follows may be either dos
or Unix to fix the end of line character conventions
to match these systems. This command should be executed
last of all, since cfengine appends new lines with the conventions
of the system on which is was complied during edit operations.
ForEachLineIn quoted-filename
This marks the beginning of a for-loop which reads successive
lines from a named file. The result is like using SetLine
for each line in the file. Nested loops are not permitted.
GotoLastLine
Moves the file pointer to the last line in
the current file.
HashCommentLinesContaining quoted-string
Add a # to the start of any line containing the quoted string.
HashCommentLinesMatching quoted-regex
Add a # to the start of any line exactly matching the quoted regular expression.
HashCommentLinesStarting quoted-string
Add a # to the start of any line starting with the quoted string.
IncrementPointer quoted-number
Increments the value (in lines) of the file pointer
by the number of lines specified in the quoted
string (as a denary number). e.g. "4".
Negative values are equivalent to decrementing the
pointer. If a request is made to increment/decrement
outside of the file boundaries the pointer `bumps'
into the boundary and remains there, i.e. either at
start of file or end of file.
Inform quoted-string
Set to true or false, on or off to set inform level for this file.
Default is off.
InsertFile quoted-string
Inserts the named file after the current line position
in the file. This should be used in conjunction
with a begin-end construction in order to avoid
including the file every time cfengine is run.
If the file does not exist, or cannot be opened,
there is only a warning issued in verbose mode.
Note if the file is empty, or if the current line
pointer is not set, the file is inserted at the start
of the file.
InsertLine quoted-string
Inserts the quoted string as a line at the current
position in the file. After the insert, the file
pointer is incremented by one so that subsequent
inserted lines are placed after the first.
This should probably be used in conjunction with the
conditional begin-end tests to avoid lines being
inserted on every run.
LocateLineMatching quoted-regex
Moves the current-position pointer to the start
of the line matching the quoted regular expression.
If there is no match, a warning is only issued in
verbose mode, but all editing is immediately
aborted. See also WarnIfNoLineMatching
so that you can get an explicit warning, even
out of verbose mode.
PercentCommentLinesContaining quoted-string
Add a % to the start of any line containing the quoted string.
PercentCommentLinesMatching quoted-regex
Add a % to the start of any line exactly matching the quoted regular.
PercentCommentLinesStarting quoted-string
Add a % to the start of any line starting with the quoted string.
Prepend quoted-string
Add a line containing the quoted string to the start of the file.
This should be used in conjunction with the
decision structures BeginGroupIfNoLineMatching and
BreakIfLineMatches.
PrependIfNoLineMatching quoted-regex
A new version of the older PrependIfNoSuchLine
with uses a regular expression instead of a literal string.
The string prepended is the one set using SetLine.
PrependIfNoSuchLine quoted-string
Add a line containing the quoted string to the start of the file
if the file doesn't contain the exact line already.
Recurse digit/inf
For recursive descents when editing whole file trees.
ReplaceLineWith quoted-string
Replace the line at the current position with the
text in the quoted string. The file pointer remains
pointing to this line after the change.
ReplaceAll quoted-regex With quoted-string
Replace all instances of strings matching the regular expression in the
first quotes with the exact string in the second set of quotes,
throughout the current file. Note that cfengine matches on a left to
right basis, with the first match taking precedence, so if your regular
expression matches text ambiguously it is the first occurrence which is
replaced. For example, if you replace cf.* with CFENGINE
and cfengine encounters a line hello cfengine cfengine, then this
will be replaced with hello CFENGINE even though two possible
strings match the regular expression. On the other hand if the
expression is not ambiguous, say replacing cfengine with
CFENGINE, then the result would be hello CFENGINE CFENGINE.
ReplaceLinesMatchingField quoted-number
This command replaces any lines in the current file with the current line
set by SetLine or ForEachLineIn, if the lines
are split into fields (e.g. the password file) separated by the
SplitOn character (':' by default), and the corresponding
fields match.
The idea behind this command was to be able to override global
passwords (from a file which gets distributed) by new passwords
in a local file. Rather than maintaining the files separately,
this simply overrides the entries with the new ones.
Repository quoted string
This allows a local override of the Repository variable, on an item
by item basis. If set to "off" or "none" it cancels the value of a global repository.
ResetSearch quoted-string
Sets the current-position pointer to the line number
in the quoted string. EOF indicates the end of
the file.
RunScript quoted-string
Executes the named script command. Before executing the script any edits
are saved to disk. After the script has executed,
cfengine reloads the file for any further editing
operations. The script (which may be any executable
program) is appended with two arguments: the name of the
file which is being edited and the system hard class
(e.g. sun4, ultrix etc.) of the system executing
the script.
CAUTION: cfengine knows nothing about
the success or failure of anything that is done during the
execution of user scripts. This feature is to be
used at the users own peril!
RunScriptIfLineMatching quoted-string
Executes the script named with the SetScript
command only if the current file contains a line matching
the quoted regular expression.
CAUTION: cfengine knows nothing about
the success or failure of anything that is done during the
execution of user scripts. This feature is to be
used at the users own peril!
RunScriptIfNoLineMatching quoted-regex
Executes the script named with the SetScript
command if the current file contains no line matching
the quoted regular expression.
CAUTION: cfengine knows nothing about
the success or failure of anything that is done during the
execution of user scripts. This feature is to be
used at the users own peril!
SetCommentStart quoted-string
Specify which string should be used for starting
a comment using the commands CommentLineMatching
and CommentLineStarting. The default is the hash
symbol # followed by a single space.
SetCommentEnd quoted-string
Specify which string should be used for ending
a comment using the commands CommentLineMatching
and CommentLineStarting. The default is the empty
string. For example, you could make C style comments
by setting CommentStart to /* and comment
end to */.
SetLine quoted-string
Sets a current line value which can be appended using
AppendIfNoLineMatching using a regular expression.
SetScript quoted-string
Sets the name of a user-supplied script
for editing the current file.
SlashCommentLinesContaining quoted-string
Add a // to the start of any line containing the quoted string.
SlashCommentLinesMatching quoted-regex
Add a // to the start of any line exactly matching the quoted regular expression.
SlashCommentLinesStarting quoted-string
Add a // to the start of any line starting with the quoted string.
SplitOn quoted-string
This defines a single character which is to be interpreted as a
field separator for editing files with columns. The default value
for this is :, as is used in the password and group files.
It is used in conjunction with ReplaceLinesMatchingField.
Syslog quoted-string
Set to true or false, on or off to set inform level for this file.
Default is off.
Umask quote mode
Set local umask for file creation and script execution.
UnCommentLinesContaining quoted-string
Uncomment all lines in file containing the quoted string as a
substring. The comment delimiters are assumed to be those
set using SetCommentStart and SetCommentEnd.
UnCommentLinesMatching quoted-regex
Uncomment all lines in file matching the quoted regular expression. The
comment delimiters are assumed to be those set using SetCommentStart and
SetCommentEnd.
UnCommentNLines quoted-string
Uncomments N lines starting from the current position, using
the currently defined method for commenting. Note that the
comment start and end symbols are removed independently, i.e.
they are not matched, so that a comment may be spread over
several lines. e.g. If using C style /* and */
comments, the command UnCommentNLines "3" would
uncomment
/* 1 */
/* 2 */
/* 3 */
and also
/* 1
2
3 */
UnsetAbort quoted-string
Switches off the feature AbortAtLineMatching.
UseShell "false"
Normally cfengine uses a shell based exec function to run
scripts during editing. This involves the inheritance of
environment variables and path, which carries with it an
inherent security risk. Setting this value to false
causes execution to execute without an encapsulating shell.
WarnIfLineContaining quoted-string
Issue a warning if the quoted string is found as a
substring of one or more lines in the file.
WarnIfLineMatching quoted-regex
Issue a warning if the quoted regular expression
matches one or more lines in the file.
WarnIfLineStarting quoted-string
Issue a warning if the quoted string matches the start
of one or more lines in the file.
WarnIfNoLineContaining quoted-string
Issue a warning if the quoted string is not contained
in one or more lines in the file.
WarnIfNoLineMatching reg-ex
Issue a warning if the quoted regular expression does not match
one or more lines in the file.
WarnIfNoLineStarting quoted-string
Issue a warning if the quoted string is not found
at the start of one or more lines in the file.
WarnIfNoSuchLine quoted-regex
Issue a warning if the quoted regular expression does not
match one or more lines in the file.
A limited number of operations can also be performed on purely binary files, e.g.
compiled programs, in order to search for strings or viral code, or to modify
strings within a program. Binary mode is a mutually exclusive, separate mode to normal
editing. The limit on the size of binary files is set by editbinaryfilesize
in control.
ReplaceAll regex With literal
Replaces occurrences of the matched regular expression with\
the provided literal text, only if the length of the literal substitute
is less than or equal to the length of the located string. If the
replacement string is shorter, it is padded with ascii spaces (character 32) by default.
The padding character can be changed by setting BinaryPaddingChar in control.
Padding with a null byte would lead to corruption of text within a program.
WarnIfContainsString regex/literal
Yields a warning if the literal string or regular expression matches.
Cfengine first attempts a literal match and then a regular expression
match.
WarnIfContainsFile filename
Yields a warning if the contents of the named file exactly match
part of the file which is being edited. This can be used to search for
binary data which cannot be typed directly into the cfengine program,
e.g. virus signatures.
It is suggested that you use these editing functions with
caution. Although all possible safeguards have been incorporated into
them, it is still possible through carelessness to do damage to
important files on your system. Always test editing programs carefully
before committing them to your global site configuration.
The files facility allows you to touch (create), check for the
existence, owner and permissions of files, change the permissions and
test for setuid root programs.
The meaning of these item is sketched out below and becomes clearer on
looking at a number of examples. Note that, each of the options below
can be written in either upper or lower case and abbreviated by any
unique abbreviation.
A file object is interpreted as a directory if you write it in the
following form: /directory-path/.. i.e. a trailing dot signifies
a directory. This then becomes the same as the directory command.
/directory
This is the only obligatory part of a file action. This is a directory
at which a file search should begin. This may be a single file or a
directory. The recursion specifier may be used to force cfengine to
descend into subdirectories in a controlled fashion, starting from this
point, checking files there also. The wildcard home may also be
used. See home directive.
mode=modestring
Specifies what the allowed permissions for files are. If cfengine finds
that a file's mode is incorrect, the value of the action
option determines what will be done about it. The modestring should
consist of either a three digit octal numbers with +, - or
= symbols, or a text string like that used by the command
chmod. For instance: mode=u=rwx,og+rx would mean set the
read/write and execute flags for the user (file owner) and add the
read/execute flags for others and group bits. An example of the
numerical form might be -002 which would mean that the
read-for-others flag should either not be set or should be unset,
depending on the action you choose. +2000 would mean that the
setuid flag should be present or set, depending on the action.
+2000,-002 would be a combination of these. The = sign
sets to an absolute value, so =755 would set the file mode to
mode 755.
flags=BSD flags
The free BSD Unices have additional filesystem flags which can be seton
files. Refer to the BSD chflags documentation for this. For
example,
This specifier tells cfengine whether or not to recurse into
subdirectories. If the value is zero, only the named file or directory
is affected. If the value is 1, it will open at most one level of
subdirectory and affect the files within this scope. If the value is
inf then cfengine opens all subdirectories and files beginning
from the specified filename.See Recursion.
owner=owner list
This is a list of allowed owners, or uids by number, separated by
commas. For example root,2,3,sysadm. In cases where you ask
cfengine to fix the ownership automatically, the owner will be set to
the first recogized owner in the list if and only if it is not one of the named
uids in the list.
group=group list
This is a list of allowed groups, or gids by number, separated by
commas. For example wheel,2,3,sysadm. In cases where you ask
cfengine to fix the ownership automatically, the group will be set to
the first recognized group in the list if and only if it is not one of the named
gids in the list.
The upper line results only in warnings being issued. The actions
beginning `fix' prompt cfengine to fix encountered problems without
bothering the user. No message is issued unless in verbose mode. The
special features on the third line will be explained separately. Alert
is like -print in the find command, it triggers on the existence
of files which have not been ignored, excluded or filtered. This should
normally be used together filter, in order to locate files of particular types.
include=wildcard/pattern
You can include this option several times to specify specific patterns
which are to be included in the search. Once you specify one
pattern you exclude all files not matching at least one of the
patterns. The case be useful for restricting a search, or for
modifying the permissions of only certain files.
exclude=wildcard/pattern
You can include this option several times to specify specific patterns
which are to be excluded from the search. This overrides any patterns
given in the include= list.
ignore
This works like the global ignore directive but here you may
provide a private list of ignorable directories and files.
Unlike include, exclude this affects the way cfengine parses
directory trees.
links=stop/traverse/tidy
Normally cfengine does not descend into subdirectories which are pointed
to by symbolic links. If you wish to force it to do so (without using
the -l command line option) you may give this option the value
true, or traverse, or follow. To specify no
recursion you set the value false or stop.
Note that the value set here in the cfengine program always
overrides the value set by the -l command line option, so you
can protect certain actions from this command line option by specifying
a negative value here. If you specify no value here, the behaviour is
determined by what you specify on the command line.
The value links=tidy has the same effect as the -L command
line option except that here it may be specified per item rather than
globally. Setting this value causes links which point to non-existent
files to be deleted.
If the warn directive is used (for directories, plain files or both)
then only a warning message is issued if the file being tested does not
match the specification given. If the fix directives are used then
cfengine does not issue a warning, it simply fixes the value silently.
Non-existent files are created by the touch command. A
directory may be touched (created) by writing the filename
/a/b/c/. with a dot as the last character. (This may also be
achieved with the directories directive, See directories.)
define=classlist
If a file operation results in action being taken to fix a file,
the colon, comma or dot separated list of classes becomes defined.
Warnings do not activate the classes.
checksum=md5/sha
If set this option causes cfengine to add a checksum for the named file
to a database. Changes in the value of this checksum are then warned as
a security issue. This should normally only be used to monitor binary
files which one would not expect to change often. Note also that the use
of this option can mean a significant performance penalty. The variable
ChecksumDatabase should be set in control: to the filename
of a database file which is used to cache checksum values. Note that it
is also possible to use a database file for cfservd's remote copying by
checksum. If you use the same file for both purposes you risk losing
warnings. Security warning messages are issued only once and the value
in the database is then changed to the new value of the file
automatically i.e. the behaviour is similar to that of setuid root
program detection, See ChecksumDatabase.
The default values are mode=+000, recurse=0,
action=warnall and any owner or group is acceptable. The default
for links is to not traverse links unless the -l option is
set on the command line.
The recursion specifier tells cfengine what to do, starting from
/directory name. A value of r=0 means `no recursion' and
any checking is limited only to the named file or directory. A value of
r=inf implies unlimited recursion. Cfengine then descends into
all subdirectories checking or setting the permissions of files until it
`bottoms out' at a plain file. A value such as R=4 means descend
recursively into subdirectories, but no more than four levels. This is
a useful safety net in preventing unforeseen accidents. A recursive
search also bottoms out on device boundaries and symbolic links
(provided the -l option is not used).
When you specify the permissions for a whole file tree, using the
recursion specifier it is awkward to have to remember that directories
must be executable. cfengine will do this for you automatically. If
you specify that a file tree is to have a read flag set, cfengine will
ensure that the corresponding execute flag is also set for directories
which live in the tree. So the command
files:
myclass::
/dir mode=a+rw r=inf fixall
would set all plain files to mode 644 and all directories to 755, that
is read/write for everyone on plain files and read/write/execute for
everyone on directories.
If you want to check the files of all the users who have their login
areas on the current host, you can use a wildcard directive home
instead of a directory name. In this case the file action iterates over
all home directories physically on the current host. The home
directories are, of course, located by searching for files which match
$(mountpattern)/$(homepattern)
i.e. the values which are specified in the control part of the
program. For example the following line is a very useful service to
ignorant users.
files:
any::
home mode=o-w r=inf act=fixall
It ensures automatically that no user has files which can be written to
by other arbitrary users.
As a corollary to this, you may write something like
any::
home/www mode=a+r fixall
to specify a special subdirectory of every users' home directory. This
statement would check that all of the files in users' world wide web
directories were readable for everyone.
The linkchildren facility is almost identical to that already
described under links. See Link Children. The only
difference here is that the ownership and permissions on the links are
set all in one operation. For example:
The touch facility creates a new file with the
specified permissions and ownership, or corrects the
permissions and ownership of an existing file, in addition
to updating the time stamps.
This is like touch except that an existing
file's time stamps, permissions and ownership will not be modified
if the file already exists. If the file does not exist, the
attributes are set to the values specified, or to the default
values of 0644.
A filter is a way of selecting or pruning during a search over
files or processes. Since filter rules could apply to several objects, cfengine
allows you to define filter conditions as separate objects to be
applied in different contexts.
Filter objects can be used in copy, editfiles,
files, tidy and processes. In most cases one
writes
.. filter=<i>filteralias</i>
in the appropriate command. The exception is editfiles, where the syntax
is
Filters are defined in a separate section. Filters for files
and processes are defined together. They differ only in the
criteria they contain. Here is are examples of file filters:
Filters:
{ filteralias1
Owner: "mark|cell|motd"
Group: "ecg|mark"
Mode: "700"
FromCtime: "date(2000,1,1,0,0,0)" # absolute date
ToCtime: "now"
FromMtime: "tminus(1,0,0,2,30,0)" # relative "ago" from now
ToMtime: "inf" # end of time
FromAtime: "date(1997,2,22,0,0,0)"
ToAtime: "inf"
FromSize: "10000" # File size interval
ToSize: "10mb"
ExecRegex: "/usr/bin/file(.*ascii.*)"# Result from "files" command
Type: "dir|link" # reg|link|dir|socket|fifo|door|char|block
NameRegex: ".*.asc" # regex matching file name
IsSymLinkTo: "/dev/null" # True if file is a link to object name regex
Result: "Type" # Result which shouldbe returned
}
#########################################
{ testfilteralias2
ExecProgram: "/bin/ls $(this)" # True if the program returns true. $(this) is the current object
}
#########################################
{ testfilteralias3
Owner: "mark"
}
Filters are evaluated like classes. In fact, the filtering works by evaluating
the class attributes for each file.
File filters:
Owner:
and Group can use numerical id's or
names, or "none" for users or groups which are undefined in
the system passwd/group file.
Mode: applies only to file objects. It shares syntax with
the mode= strings in the files command. This test returns
true if the bits which are specified as `should be set' are indeed
set, and those which are specified as `should not be set' are not set.
Atime:,Ctime:,Mtime:
apply only to file objects.
These specify ranges From and To. If the file's time stamps
lie in the specified range, this returns true. Times are
specfied by a six component vector
(year,month,day,hour,minutes,seconds)
This may be evaluated as two functions: date() or tminus()
which give absolute times and times relative to the current time respectively.
In addition, the words now and inf may be used.
e.g.
FromCtime: "date(2000,1,1,0,0,0)" # absolute date
ToCtime: "now"
FromMtime: "tminus(1,0,0,2,30,0)" # relative "ago" from now
ToMtime: "inf" # end of time
Type:
applies only to file objects may be a list of file types
which are to be matched. The list should be separated by the OR symbol
`|', since these types are mutually exclusive. The possible values are
currently
reg|link|dir|socket|fifo|door|char|block
ExecRegex:
matches the test string against the output of the specified command.
NameRegex:
matches the name of the file with a regular expression.
IsSymLinkTo:
applies only when the file object $(this) is a symbolic link. It is true
if the regular expression matches the contents of the link.
ExecProgram:
matches if the command returns successfully (with return code 0).
Note that this feature introduces an implicit dependency on the command being
called. This might be exploitable as a security weakness by advanced intruders.
Result:
specifies the way in which the above elements are combined
into a single filter.
Process filters:
Owner
process owner UID (quoted regex)
PID:
process ID (quoted regex)
PPID:
parent process ID (quoted regex)
PGID:
process group ID (quoted regex)
RSize:
resident size (quoted regex)
VSize:
virtual memory size (quoted regex)
Status:
status (quoted regex)
Command:
CMD or COMMAND fields (quoted regex)
(From/To)TTime:
Total elasped time in TIME field (accumulated time)
(From/To)STime:
Starting time for process in STIME or START field (accumulated time)
TTY:
terminal type, or none (quoted regex)
Priority:
PRI or NI field (quoted regex)
Threads:
NLWP field for SVR4 (quoted regex)
Result:
logical combination of above returned by filter (quoted regex)
Examples: processes started between 18th Nov 2000 and now.
The groups action (equivalently referred to as classes as
of version 1.4.0) is used to define classes which stand for groups of
hosts. If you use the NIS (network information service) facility for
defining netgroups then this idea will already be familiar to you
and you can probably use your already-defined netgroups in cfengine.
To define a group, you simply make a list and assign it a name. Here is
an example of the syntax:
groups:
science = ( saga tor odin )
packages = ( saga )
AllHomeServers = ( saga )
AllBinaryServers = ( saga )
OIH_servers = ( saga )
OIH_clients = ( tor odin )
notthis = ( !this )
ip_in_range = ( IPRange(129.0.0.1-15) ) # host is in ip address range
ip_in_range = ( IPRange(129.0.0.1/24) ) # host is in ip address range (CIDR notation)
To include a list of hosts from a NIS netgroup, you use the + symbol, or
the +@ construction. For example:
Using an enormous netgroup does not use up any space. A group
declaration results in the storage of only the class name regardless of
how many hosts are in the list. The rule is that the left hand side of
the assignment becomes defined (true) if the list on the right hand side
includes the host which is parsing the file -- i.e. $(host).
In some cases your netgroups will not correspond exactly to the list you
want, but it might be more convenient to use a netgroup except
for certain hosts. You can `undefine' or remove hosts from the netgroup
list by using the minus `-' symbol. For example:
group = ( +mynetgroup -specialhost -otherhost )
which means, of course, all hosts in netgroup mynetgroup except
for specialhost and otherhost. Finally, you may also
subtract two netgroups in the following manner.
group = ( +bignetgroup -smallnetgroup )
The `minus' command effectively eliminates its members from
bignetgroup if they exist within that group. If none of the
hosts in smallnetgroup exist in bignetgroup then the
command has no effect.
Groups may now contain previously defined cfengine groups too. This
allows one class to inherit the attributes of another class, for instance:
The classes on the right hand side are effectively ORed together into
the left hand side. This enables complex classes to be constructed from
several other basic classes, e.g.
SpecialTimes = ( Hr00 Monday Day1 )
which evaluates to true every day when it between 00:00 hours and 00:59,
all day Monday and all day on the first day of every month.
Finally, you can define groups (strictly classes) by the result of a shell
command. A shell command or program is deemed to be `true' if it
exits with a status of zero, i.e. it calls exit(0). Any other
value is taken to be false. You can include shell commands as the members
of groups in order to define classes based on the outcomes of your
own scripts by enclosing the script in single or double quotes:
have_cc = ( '/bin/test -f /usr/ucb/cc' )
The class have_cc will then be defined if the shell command returns
true. Of course, you can put any script or program in the single quotes as
long as they adhere to the convention that zero exit status means true.
If you have several members which are shell commands, then the effect is
to make the class the logical OR of the scripts' results.
As of version 1.4.0, you may use the synonym classes for groups.
The homeservers 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
home directories (login areas) which client hosts should mount.
A sample homeserver declaration looks like this:
homeservers:
Physics:: einstein
Math:: riemann euler
The meaning of this declaration is the following. Any host which finds
itself to be a member of the classes on the left hand side of the
assignment need to mount all home directory resources from the hosts on
the right hand side of the assignment. The pattern variable
homepattern is used to determine which resources are home
directories in the list of mountables. See mountables.
Let us consider an example in which homepattern is set to the
wildcard value home? and the mountables list is given by
Any host in the group Physics would now want to mount all home
directories from the host einstein. There are two of these.
Both the filesystems listed for einstein match the
homepattern variable since they end in home?. cfengine
would therefore take this to mean that all hosts in Physics
should mount both of these filesystems.
Hosts in Math, on the other hand, should mount only
homedirectories from the hosts riemann and euler. There
is only a single filesystem on riemann and it does not match
homepattern, so it is not mounted. On euler there is a
match, so this filesystem will be added to the appropriate hosts.
Cfengine picks out home directory resources from the
mountables list by trying to match the homepattern
variable, starting from the end of the directory name. You do not
therefore have to use the designation /site/host/home? but this
is a simple choice and is highly recommended.
When you specify a recursive search as part of a files,
tidy or copy action, you would sometimes like to exclude
certain directories from the list of sub directories. In most cases you
will want to do this on a per-command basis (see the pages for these
actions separately), but you can also make a global ignore list. This
can be accomplished by adding the directory to the ignore-list. The syntax
is
None of the above directories will be checked or entered during
recursive descents unless a specific command is initiated to search
those directories with their names as the top of the search tree.
A handy tip if you are tidying /tmp recursively is to include the
directory .X11 here. This directory is used by the X-windows
system and deleting it while a window manager has an open session can
cause the user some trouble.
Ignore refers to all recursive searches in tidy, files, copy and links.
To break up a large configuration file into smaller files you can use
the include directive. This conditionally reads in files if the class
on the left hand side of the assignment matches the host parsing the
file. This enables also a variety of cfengine configuration scripts to
read in a standard set of default settings. The syntax of the statement
is:
Note that, if you define variables in an imported file they will not be
defined for operations in their parent files. This because cfengine reads in all the
import files after the main file has been parsed--not at the place where you
call import in your script. This means that variables or macros defined in
imported files are only defined after the main program. Variables from earlier
files are inherited by later includes, but not vice-versa.
If you have more than one network interface, or you do not wish to use the
default interface name, this section may be used to define further
interfaces to be checked. This feature can replace the older method
of setting netmask and broadcast address in control:. If the netmask
variable is not set, cfengine ignores the default interface configuration.
Example:
The symbolic links function is one of the greatest plusses in cfengine
as a system administration tool. It allows you to do two things: check
single links for correctness and consistency (or make them if they do
not exist), and check or make links to every file in a designated
directory. This latter feature is called multiple linking or linking
children. The linkchildren feature is also available from the
files action See files. The syntax of a link item is:
If links exists and point to their intended destinations then no
action is taken. If a link exists but points incorrectly then a
warning is issued, unless the pling operator ! is given, in
which case the correct value is forced.
If the link exists and points to a file which does
not exist a warning is issued unless the command line option -L
is used, in which case the link is deleted.
cfengine makes any directories which are required leading up to the link
name on the left hand side of the arrow automatically. In the last
example the `pling' forces cfengine to make the link even if a file for
link exists previously. Plain files are saved by appending
.cfsaved to the filename, or by moving to a repository, whereas
old links are removed. The same effect can be enforced globally using
the -E option, but only if the program is run interactively. (In
this case a prompt is issued to make sure that you wish to use such a
big hammer on your system!)
The link operation accepts a number of parameters
type=hard/relative/absolute
If the link type is hard, a hard link is created See Hard links.
Symbolic links may specify two special types. If relative
is selected, and the `to' object is an absolute path name,
the link name will be rewritten as a pathname relative
to the source file, using . and .. to move relative
to the current directory. For instance, a link from /usr/local/file
to /usr/file would be linked as ./../file.
If the `to' object is already relative,
this has no effect.
If absolute is specified, cfengine
will try to resolve the true path location of the `to' object,
expanding any symbolic links or dots in the path name, up to
a maximum of four levels of symbolic links.
copy=pattern
This option can be repeated any number of times to build up a list of
filenames or wildcards which are to be copied rather than linked
symbolically. The copy is made on an age-comparison basis. A global
variable may also be set to invoke this feature See copylinks.
Directories cannot be copied in this way.
copytype=checksum/ctime
This specifies the basis for deciding whether to update a file
which is to be copied instead of linked See copy.
nofile=kill/force
This decides what happens to links which point to non-existent
files. The default action is to remove such links, or refuse to
create them. By setting the force option you can force
cfengine to make symbolic links to files which do not exist.
This is useful for setting up links to filesystems which
are not permanently mounted.
exclude=pattern
This option can be repeated any number of times to build up a list of
filenames or wildcards which are to be excluded from the linking
process. A global variable may also be set to invoke this feature
See excludelinks.
ignore
This works like the global ignore directive but here you may
provide a private list of ignorable directories and files.
Unlike include, exclude this affects the way cfengine parses
directory trees.
recurse=number/inf
This option can only be used with multiple link operations See Multiple Links.
If this option is specified, cfengine links only non-directory
objects. Directories are instead created and links within those
directories are also created. The value of this option specifies the
maximum number of levels to which cfengine should recursively descend a
link tree. inf means infinite recursion. Cfengine also ignores
files and directories in the ignore list See ignore.
define=classlist
If a link is created or replaced, the colon, comma or dot separated
list of classes becomes defined.
The final feature of the links facility is connected to the use of the
cfengine model for mounting NFS filesystems. In particular it concerns
the variable $(binserver). The easiest way to understand this
feature is to illustrate a couple of examples. Consider the following:
The result of this command is quite different depending on which host is
executing it. The variable $(site) clearly has a fixed value,
but the variable $(binserver) might expand to any valid binary
server for the host executing the program. See binservers. The
procedure cfengine adopts is to go through its list of mountables,
keeping only those mountable resources which belong to defined binary
servers for the current host. It then attempts to match a filesystem by
substituting $(binserver) with each of its valid binservers in
turn and it matches the first one binary server which yields an existing
file.
Note that every host is a binary server for itself, so that the value of
$(binserver) which has absolute priority is alway the same as the
value of $(host). This ensures that the link will always be made
to a local filesystem if the rules of the model are upheld.
With the link symbol +>, you opt to link all of the files in a
directory to corresponding files in another directory. This procedure is
sometimes useful for installing software. In the example
every file in the directory /usr/local/lib/perl/bin is linked
symbolically to a corresponding file in /usr/local/bin. The
`pling' character forces cfengine to replace old links or plain files
already existing. Old links are removed, whereas old files are saved
by appending .cfsaved to the filename See repository.
Each time cfengine runs it goes through all of the files in the
directory concerned and checks the appropriate link accordingly. If new
files appear, new links will be added. If a file disappears but the
link to it remains, a warning will be issued, unless the -L
command line option is used, in which case the link is deleted.
The linkchildren directive is a closely related to the cfengine model
for NFS filesystems. It is a way of making links which embodies a
rudimentary kind of `intelligence'.
Consider the following:
links:
any::
/usr/local/lib/emacs +> linkchildren
The word linkchildren automatically tells cfengine that it should
look for an appropriate file to link to on a binary server for the
current host. The exact meaning of the above statement is as follows.
cfengine begins searching though the list of mountable resources,
discarding any filesystems which do not belong to valid binary servers.
It looks for a filesystem ending in `emacs' (the last link of the left
hand side). If all is well, these file systems are already mounted and
they can be searched. If no resource is found ending in `emacs', we go
to the next link lib and look for a filesystem ending in `lib'.
If this is not found we go to local and so on. When a match is
made, cfengine then tries to locate the file by checking whether it
exists relative to the matched filesystem. For example, suppose `local'
matched with host:/site/host/local. It would then try to locate
host:/site/host/local/lib/emacs and link all of the children
therein to the local file directory /usr/local/lib/emacs.
Here is another example which makes reference to the cfengine model for
mounting NFS filesystems. Suppose you have a host with some spare disk
space. You want to mount /usr/local from the binary architecture
server, but you also want to use the disk you have locally. The
following lines
have the effect of creating a directory /$(site)/electron/local
and filling it with links to all of the files and directories on the
binary server's mounted filesystem. It results in an exact copy (by
linkage) on the local disk, but does not use up your local disk space.
The space you have remaining could, for example, be used for software
with a special license for that host. The second link links
/usr/local to the `nearest' binary server. But the nearest
binary server is always $(host) which means this evaluates to a
file which now exists because of the first command, so on the host
`electron' the directory /usr/local ends up being a link to
/$(site)/electron/local which is full of links to the binary
server.
If you've caught your breath after that mouthful you probably have mixed
feelings about creating a bunch of links in this way. What happens if
the files they point to are removed? Then you are left with a lot of
useless links. Actually this is no problem for cfengine, since you can
ask cfengine to simply remove links which point to non-existent files
See files. Nevertheless, this feature clearly requires some caution
and is mainly a spice for advanced users of the cfengine model.
When specifying symbolic linking, you can ask cfengine
to change the link type to be either relative to the
source or to be an absolute path. What this means is the
following. Consider the following link:
/var/tmp/cfengine -> /local/cfengine
If we add the option type=relative, then instead
of creating a link which points to /local/cfengine,
the link is created pointing to the location
./../../local/cfengine
In other words, the link is relative to the calling
directory /var/tmp.
If a link is specified as being absolute with the option
type=absolute, then cfengine attempts to resolve
to value of the link so as to be the true path of the
target. If the target name contains a symbolic link, then
this is expanded as far as possible to give the true
path to the file. For example, if /local is
really a link to /site/myhost/local then the link
would point to /site/myhost/local/cfengine.
Cfengine will also allow you to create hard links to regular files. A
hard link is in every way identical to the original file, it merely has
a different name (technically, it is a duplicate inode). To create a
hard link you use the link-option type=hard. For example:
Cfengine will not create hard links to directories or other special files.
This is always a slightly dubious practice and is best avoided anyway.
POSIX says that the hard link can be on a different device to the file
it points to, but both BSD and System 5 restrict hard links to be on
the same device as their predecessors. Cfengine has no policy on this,
but--in the theoretical case in which the hard link and the predecessor
were on different file systems--it becomes near impossible to determine
with certainly between a hard link and a very similar regular file, and thus
cfengine issues a warning in verbose mode about this eventuality.
Provided both link and predecessor are on the same filesystem cfengine
determines the status of hard links by comparing the device and inode
numbers of the file pointed to.
The mailserver declaration need only be used if you are using
cfengine's model for mounting NFS filesystems. This declaration informs
hosts of which NFS filesystem contains mail for its users. All hosts
apart from the mail-host itself must then mount the mail spool directory
across the network. The declaration looks like this:
mailserver:
class:: mailhost:/var/spool/mail
The result of the mailcheck command in the action-sequence is now
to mount the filesystem /var/spool/mail on the host
mailhost. This action is carried out on any machine which does
not already have that filesystem mounted.
The mail spool directory is mounted, by default, onto the official mail
spool directory for the system which is parsing the program. In other
words, on an HPUX system, the spool directory is mounted on
/usr/mail by default, whereas on a Sun system it would be mounted
on /var/spool/mail. The default location can be changed by using
the resource file. See cfrc resource file.
If you do not use the cfengine model for statically mounting NFS
filesystems (or if there are filesystems which do not naturally fall
into the bounds of that model) then you can still statically mount
miscellaneous filesystems using a statement of the form:
This statement would mount the directory
/$(site)/libraryserver/data physically attached to host
libraryserver onto a directory of the same name on all hosts in the
group physics. The modes ro and rw signify
read-only and read-write respectively.
If no mode is given, read-write is assumed.
The mountables declaration need only be used if you are using
cfengine's model for mounting NFS filesystems. This declaration informs
hosts of what filesystem resources are available for mounting. This
list is used in conjunction with binservers and
homeservers to determine which filesystems a given host should
mount, according to the cfengine model.
The syntax of the list is:
mountables:
class::
"filesystem to mount"
readonly=false/off/true/on
mountoptions=nfs-options
Notice that binary and home-directory filesystems are mixed freely here.
Cfengine determines which of the entries are homedirectories using the
homepattern variable.
Every time you add a disk or a mountable partition to your network, you
should add the partition to the list of mountables.
NOTE: This list is read in order, top down. Cfengine looks for
the first filesystem matching a given binary server when expanding the
variable $(binserver), so sometimes the ordering of filesystems
matters.
This list can be accessed in editfiles, to allow straightforward
configuration of the automounter, using the command AutomountDirectResources.
Using the processes facility, you can test for the existence of
processes, signal (kill) processes and optionally restart them
again. Cfengine opens a pipe from the system ps command and searches
through the output from this command using regular expressions to match
the lines of output from ps. The regular expression does not
have to be an exact match, only a substring of the process line. The
form of a process command is
By default, the options sent to ps are "-aux" for BSD systems and "-ef"
for system 5. You can use the SetOptionString command to redefine
the option string. Cfengine assumes only that the first identifiable number
on each line is the process identifier for the processes, so you must not
choose options for ps which change this basic requirement (this is not a
problem in practice). Cfengine reads the output of the ps-command normally only
once, and searches through it in memory. The process table is only
re-consulted if SetOptionString is called. The options have the
following meanings:
signal=signal name
This option defines the name of a signal which is to be sent to all processes
matching the quoted regular expression. If this option is omitted, no signal
is sent. The signal names have the usual
meanings. The full list, with largely standardized meanings, is
hup 1 hang-up
int 2 interrupt
quit 3 quit
ill 4 illegal instruction
trap 5 trace trap
iot 6 iot instruction
emt 7 emt instruction
fpe 8 floating point exception
kill 9 kill signal
bus 10 bus error
segv 11 segmentation fault
sys 12 bad argument to system call
pipe 13 write to non existent pipe
alrm 14 alarm clock
term 15 software termination signal
urg 16 urgent condition on I/O channel
stop 17 stop signal (not from tty)
tstp 18 stop from tty
cont 19 continue
chld 20 to parent on child exit/stop
gttin 21 to readers pgrp upon background tty read
gttou 22 like TTIN for output if (tp->t_local<OSTOP)
io 23 input/output possible signal
xcpu 24 exceeded CPU time limit
xfsz 25 exceeded file size limit
vtalrm 26 virtual time alarm
prof 27 profiling time alarm
winch 28 window changed
lost 29 resource lost (eg, record-lock lost)
usr1 30 user defined signal 1
usr2 31 user defined signal 2
Note that cfengine will not attempt to signal or restart processes 0 to 3
on any system since such an attempt could bring down the system. The only
exception is that the hangup (hup) signal may be sent to process 1
(init) which normally forces init to reread its terminal configuration
files.
restart "shell command"
Note the syntax: there is no equals sign here. If the keyword `restart'
appears, then the next quoted string is interpreted as a shell command
which is to be executed after any signals have been sent. This command
is only issued if the number of processes matching the specified regular
expression is zero, or if the signal sent was signal 9 (sigkill) or 15
(sigterm) , i.e. the normal termination signals. This could be used to
restart a daemon for instance. Cfengine executes this command and
waits for its completion so you should normally only use this
feature to execute non-blocking commands, such as daemons which
dissociate themselves from the I/O stream and place themselves in the
background. Some unices leave a hanging pipe on restart (they never
manage to detect the end of file condition). This occurs on POSIX.1 and
SVR4 popen calls which use wait4. For some reason they fail to find and
end-of-file for an exiting child process and go into a deadlock trying
to read from an already dead process. This leaves a zombie behind (the
parent daemon process which forked and was supposed to exit) though the
child continues. A way around this is to use a wrapper script which
prints the line "cfengine-die" to STDOUT after restarting the
process. This causes cfengine to close the pipe forcibly and continue.
Cfengine places a timeout on the restart process and attempts to
clean up zombies, but you should be aware of this possibility.
owner=,group=
Sets the process uid and gid (setuid,gid) for processes which are
restarted. This applies only to cfengine run by root.
chroot
Changes the process root directory of the restarted process, creating
a `sandbox' which the process cannot escape from. Best used together with
a change of owner, since a root process can break out of such a confinement
in principle.
chdir
Change the current working directory of the restarted process.
useshell=true/false/dumb
When restarting processes, cfengine normally uses a shell to
interpret and execute the restart command. This has inherent
security problems associated with it. If you set this option to
false, cfengine executes restart commands without using a shell.
This is recommended, but it does mean that you cannot use any
shell operators or features in the restart command-line.
Some programs (like cron) do not handle I/O properly when they fork
their daemon parts, this causes a zombie process and normally
hangs cfengine. By choosing the value `dumb' for this, cfengine
ignores all output from a program and does not use a startup shell.
This prevents programs like cron from hanging cfengine.
matches=number
This option may be used to set a maximum, minimum or exact number of
matches. If cfengine doesn't find a number of matches to the regular
expression which is in accordance with this value it signals a warning.
The <, > symbols are used to specify upper and lower
limits. For example,
matches=<6 # warn number of matches is greater than or equal to 6
matches=1 # warn if not exactly 1 matching process
matches=>2 # warn if there are less than or equal to 2 matching processes
include=literal
Items listed as includes provide an extra level of selection after the
regular expression matches have been expanded. If you include one
include option, then only lines containing one or more of the literal
strings or wildcards will be matched.
exclude=literal
Process lines containing literal strings or wildcards in exclude
statements are not matched. Excludes are processed after regular
expression matching and after includes.
define=classlist
The colon, command or dot separated list of classes becomes activated if the
number of regular expression matches is non zero.
action=signal/do/warn
The default value of this option is to silently send a signal
(if one was defined using the signal option) to matching
processes. This is equivalent to setting the value of this
parameter to signal or do. If you set this option
to warn, cfengine sends no signal, but prints a message
detailing the processes which match the regular expression.
If the option is set to bymatch, then signals are only sent
to the processes if the matches criteria fail.
Here is an example script which sends the hang-up signal to cron,
forcing it to reread its crontab files:
processes:
"cron" signal=hup
Here is a second example which may be used to restart the nameservice
on a solaris system:
A more complex match could be used to look for processes belonging to
a particular user. Here is a script which kills ftp related processes
belonging to a particular user who is known to spend the whole day
FTP-ing files:
control:
actionsequence = ( processes )
#
# Set a kill signal here for convenience
#
sig = ( kill )
#
# Better not find that dumpster here!
#
matches = ( 1 )
processes:
#
# Look for Johnny Mnemonic trying to dump his head, user = jmnemon
#
".*jmnemon.*ftp.*" signal=$(sig) matches=<$(matches) action=$(do)
# No mercy!
The regular expression .* matches any number of characters, so this
command searches for a line containing both the username and something to
do with ftp and sends these processes the kill signal.
You can arrange for signals to be sent, only if the number of matches
fails the test. The action=bymatch option is used for this.
For instance, to kill process `XXX' only if the number
of matches is greater than 20, one would write:
This is a synonym for disks, See disks.
This action tests for the existence of a file or filesystem. It should
be called after all NFS filesystems have been mounted. You may use the
special variable $(binserver) here.
Files or filesystems which you consider to be essential to the operation
of the system can be declared as `required'. Cfengine will warn
if such files are not found, or if they look funny.
Suppose you mount your filesystem /usr/local via NFS from some
binary server. You might want to check that this filesystem is not
empty! This might occur if the filesystem was actually not
mounted as expected, but failed for some reason. It is therefore not
enough to check whether the directory /usr/local exists, one must
also check whether it contains anything sensible.
Cfengine uses two variables: sensiblesize and
sensiblecount to figure out whether a file or filesystem is
sensible or not. You can change the default values of these variables
(which are 1000 and 2 respectively) in the control section.
See control.
If a file is smaller than sensiblesize or does not exist, it
fails the `required' test. If a directory does not exist, or contains
fewer than sensiblecount files, then it also fails the test and a
warning is issued.
required:
any::
/$(site)/$(binserver)/local
If you set the freespace variable to a value (the default units are kilobytes,
but you may specify bytes or megabytes), e.g.
then cfengine will warn when the filesystem concerned has less than this
amount of free space. By adding a define tag, you can switch on
any number of classes if this happens. This allows you to activate special
measures for dealing with a filesystem which is in danger of becoming
full.
The file /etc/resolv.conf specifies the default nameserver for
each host, as well as the local domain name. This file can also contain
other information, but these are the only two things cfengine currently
cares about. In specifying nameservers you should use the dotted
numerical form of the IP addresses since your system may not understand
the text form if it is not correctly configured. You may list as many
nameservers as you wish, with the default server at the top of the list.
The resolver normally ignores entries if you add more than three. The
statement:
declares a list of nameservers for hosts in the group or class
mygroup. When you add the resolve command to the
actionsequence, this declaration together with the domain
variable (set here to uio.no) results in a
/etc/resolv.conf file of the form:
Note that the resolve action does not delete anything from the
file /etc/resolv.conf. It adds nameservers which do not
previously exist and reorders the lines of servers which do exist.
As of version 1.3.11, you may use a quoted string to add non-nameserver
lines to this file. For example:
Cfengine focuses on fairly simple minded tasks in order to be as general
as possible. In many cases you will therefore want to write a script to
do something special on your system. You can still take advantage of
the classes you have defined by executing these scripts or shell
commands from this section.
The syntax is simply to quote the command you wish to be executed.
The user and group ID's of the process can be set to restrict the
permissions of the shellcommand to another user only if cfengine is
executed by root. If you set the optional timeout string, then cfengine
will abort the shellcommand if it exceeds the specified time-limit in
seconds. This can be useful for avoiding situations caused by hung
network connections etc.
Variable substitution works within the strings. Here are some examples.
If you need to write more advanced scripts, which make detailed use of the
classes defined by cfengine, use the $(allclasses) variable to send
a complete list of classes to your script in the format
CFALLCLASSES=class1:class2:class3...
This variable is kept up-to-date at any given time with only the classes
which are defined. The command line option -u or
--use-env can be used to define an environment variable which
will be inherited by all scripts and contains the same information.
This is not the standard approach, since some systems cannot
cope with this rapid change of environment and generate a Bus Error.
Commands can be iterated over variable lists, provided there is
at least one space between each variable. For example:
This iterates over all values of the list variables. See Iterating over lists.
If you are iterating over a list, the timeout applies to each separate
iteration, not to the sum of all the iterations.
The chroot option changes the process root directory of the
command, creating a `sandbox' which the process cannot escape from. Best
used together with a change of owner, since a root process can break out
of such a confinement in principle. The chdir option changes the
current working directory of the restarted process.
The preview option means that the shellcommand will also be executed during
the --dry-run (-n) options. This allows cfengine to be more aware
of the results of scripts which define classes. This option should be used
with care.
Scripts should conform to the protocol of not executing unnecessary commands
when the classes opt_dry_run is defined.
The tidy function is used to delete (remove permanently) unwanted files
from a system. It is useful for tidying up in /tmp or cleaning
out core files from users' home directories. The form of an
entry is:
Note that, each of the options below
can be written in either upper or lower case and abbreviated by any
unique abbreviation.
/directory
This is the directory name to directories which mark the start of a
search for files matching certain wildcards. The wildcard home
may be used instead of an explicit directory, in which case cfengine
iterates over all home directories. It is compulsory to specify a
directory.
pattern=wildcard or include=wildcard
A wildcard or filename to match the files you wish to be deleted. The
pattern may contain the special symbols ? which matches a single
character and * which matches any number of characters as in the
shell. These two options are synonymous, as of version 2.0.x.
exclude=wildcard
This does not work for the home directive; use the global ignore list for this.
ignore=wildcard
This does not work for the home directive; use the global ignore list for this.
recurse=number/inf
This specifier tells cfengine whether or not to recurse into
subdirectories. If the value is zero, only the named file or directory
is affected. If the value is 1, it will open at most one level of
subdirectory and affect the files within this scope. If the value is
inf then cfengine opens all subdirectories and files beginning
from the specified filename. See Recursion.
age=days
The age of a file in days represents a minimum access time
elapsed before the file will be deleted. In other word a file will be
deleted if it has not been accessed for days days.
links=stop/traverse/tidy
Normally cfengine does not descend into subdirectories which are pointed
to by symbolic links. If you wish to force it to do so (without using
the -l command line option) you may give this option the value
true, or traverse, or follow. To specify no
recursion you set the value false or stop.
Note that the value set here in the cfengine program always
overrides the value set by the -l command line option, so you
can protect certain actions from this command line option by specifying
a negative value here. If you specify no value here, the behaviour is
determined by what you specify on the command line.
The value links=tidy has the same effect as the -L command
line option except that here it may be specified per item rather than
globally. Setting this value causes links which point to non-existent
files to be deleted. This feature will not work on commands with the
home wildcard feature. If you want to clean up old links you
should either user a files command or the command line option
which sets the tidy feature globally.
size=>number/empty
Old syntax size=number/empty.
The value of this parameter decides the size of files to be deleted.
Files larger than this value will be deleted if they also are older than
the time specified in age. The default size is zero so that any
file which gets matched by another critereon is deleted. However, if you
want to single out only totally empty files, the empty may be used.
With this option only empty files, nevery files with anything in them,
will be deleted, if older than age. By default, the filesizes
are in kilobytes, but kilobytes and megabytes may also be specified by
appending b,k,m to the numbers. Only the first character after the
number is significant so you may write the numbers however it might be
convenient, e.g. 14k, 14kB, 14kilobytes, the same as
for disable.
type=ctime/mtime/atime
This value is used to set the type of time comparison made using
age. The default is to compare access times (atime) or
the last time the file was read. A comparison by modification
time (mtime) uses the last time the contents of the file was
changed. The ctime parameter is the last time the contents, owner
or permissions of the file were changed.
dirlinks=keep/tidy/delete
This value is used to decide whether cfengine will delete
links which point to directories. The default value is to keep
the links. Note that, if the travlinks option is switched on,
cfengine will not tidy or delete links which point to directories,
instead it follows them into the subdirectory. This is a supplement
to the rmdirs option. You need both to make links
to directories disappear. Note that, even if travlinks
is set to true, cfagent will not follow symbolic links that are
not owned by the agent user ID; this is to prevent link race attacks,
in which users with write access could divert the agent to another part
of the filesystem,
rmdirs=true/false/all/sub
Normally cfengine will not delete directories. If this option is
set to `true' then cfengine will delete any directories which
are empty. Non-empty directories will not be touched and no
message will be given unless in verbose mode. Note that this
option overrides the above option dirlinks, so that even
links which point to empty directories will be removed.
If this is set to `sub' then the topmost directory will not
be removed, only sub-directories.
define=classlist
The colon, comma or dot separated list of classes becomes defined
if any file matching the specified pattern is deleted.
Take a look at the following example:
tidy:
AllHomeServers::
home pattern=core R=inf age=0
home pattern=*~ R=inf age=7
home pattern=#* R=inf age=30
any::
/tmp/ pat=* R=inf age=1
/ pat=core R=2 age=0
/etc pat=hosts.equiv r=0 age=0
In the first example, all hosts in the group AllHomeServers
iterate a search over all user home directories looking for `core' files
(older than zero days) and emacs backup files *~,
#* older than seven days.
The default values for these options are the empty string for the
wildcard pattern, zero for the recursion and a specification of the age
is compulsory.
When cfengine tidies users' home directories, it keeps a log of all the
files it deletes each time it is run. This means that, in case of
accidents, the user can see that the file has been deleted and restore
it from backup. The log file is called .cfengine.rm and it is
placed in the home directory of each user. The file is owned by root,
but is readable to the user concerned.
The unmount function unmounts non-required filesystems and removes the
appropriate entry from the filesystem table (/etc/fstab or
equivalent). The syntax is simply
The options allow you to temporarily unmount a directory without actually
removing it from the filesystem table. The option force is not currently
implemented and will likely have to be system dependent.
For example:
If the device is busy then the actual unmount will not take place until
it becomes free, or the machine is rebooted. This feature should work
on AIX systems, in spite of these machines inherent peculiarities in the
form of the filesystem table.
Some users do not mount filesystems on a directory of the same name as the
source directory. This can lead to confusion.
Note, if you have problems removing a mounted filesystem, try using
the mountpoint of the filesystem, rather than the name of the filesystem itself,
in the unmount command.
The server daemon is controlled by a file called
cfservd.conf.
The syntax of this configuration file is deliberately modelled on
cfengine's own configuration file, but despite the similarities, they are separate.
You can use groups and import in both files
to break up files into convenient modules and to import
common resources, such as lists of groups.
Note that the classes in the cfservd.conf file do not tell you the
classes of host which have access to files and directories, but rather
which classes of host pay attention to the access and deny commands when
the file is parsed.
Authentication is not by class or group but by hostname, like
the /etc/exports file on most Unix systems. The syntax for the
file is as follows:
control:
classes::
domain = ( DNS-domain-name )
cfrunCommand = ( "script/filename" ) # Quoted
MaxConnections = ( maximum number of forked daemons )
ChecksumDatabase = ( filename )
IfElapsed = ( time-in-minutes )
DenyBadClocks = ( false )
AllowConnectionsFrom = ( IP numbers )
DenyConnectionsFrom = ( IP numbers )
AllMultipleConnectionsFrom = ( IP numbers )
TrustKeysFrom = ( IP numbers )
AllowUsers = ( mark systemuser )
LogAllConnections = ( false/true )
SkipVerify = ( IP numbers )
DynamicAddresses = ( IP numbers )
groups:
Group definitions
import:
Files to import
admit: | grant:
classes::
/file-or-directorywildcards/hostnames
deny:
classes::
/file-or-directorywildcards/hostnames root=hostlist encrypt=true/on
The file consists of a control section and access information.
In the access control lists below, host ranges can be specified in a
number of ways i) as substrings, ii) as address ranges denoted by the
"-" hyphen, or iii) as CIDR (Classless Inter Domain Routing) notation.
For example
In the CIDR notation, the slash followed by a number indicates the
netmask, or the number of bits which are common to a group of hosts.
Normally, this is connected to a specific subnet, but here it simply
represents the number of bits from the left which are fixed for matching;
all remaining bits are wildcards.
The following forms are equivalent:
This variable allows a list
of numerical IP masks to be specified, which cfservd will allow connections from.
If the list is not empty and a host whose IP address is not specified
attempts to connect to the daemon, its connection will be closed
immediately.
This can be used to prevent hanging connection attacks from malicous
hosts and other denial of service attacks which would bind thread
resources.
This variable should contain a list of IP wildcards to hosts which are
allowed simultaneous sessions on the server. Hosts which are not in this
list are allowed to connect only once, i.e. they must terminate and
reconnect in order to establish a new session. This is to prevent a
possible attacker from opening multiple sockets and never closing them,
resulting in a denial of service attack. Hosts IP's can be placed here
if they could have overlapping copy sessions (e.g. long backup transfers
which can run over time). This prevents the error message "Multiple
connections denied/spam shield".
This list determines which users are to be allowed to connect to the daemon.
Note that there is no way of identifying users except by their public keys.
If a malicious asserts their identity, when no public key for the named
user is known to the server, then they could spoof the identity of that
user. All users who should be allowed to connect need to be here.
This applies to use of cfrun.
AllowUsers = ( mark root )
In other words, this is a "security by obscurity" first defence against
picking up bad keys, when the server is in trust mode, with respect to a
host. The attacker must know a valid user name in order to even try
their luck entering into a key dialogue.
This reduces the probability that spoofing can be successful. The only
real defence against spoofing is to make sure that all required public keys
are installed in advance, and to switch off trust.
This is the path and filename to a database which will cache
MD5 checksum values server-side. This optimization is only available
if you have the Berkeley database library libdb on your
system. If this variable is not defined, no database caching
will be used and checksum values will be computed directly on
request. The utility of this solution is a trade-off between
the time it takes to compute the checksum versus the time
for a disk-based lookup.
If this is set to off, cfservd will not deny access to clients whose
clocks are off by more than one hour. The default is to deny access to
systems whose clocks differ by more than one hour. This can prevent
messages of the form `Can't stat' file when remote copying.
The IfElapsed anti-spamming filter is also built into
cfservd so that a remote user cannot even get as far as
causing cfengine to parse its input files (which could
be used for spamming in itself). The time is in minutes,
the default is one hour.
If set to true, every successful connection will be logged to syslog.
This could be useful for identifying abuses of the service, if the server
should come under attack, e.g. a denial of service attack. The IP address
can then be excluded from the allowed connections list.
This integer value sets a limit on the maximum number of
child daemon threads which cfservd will `fork' in order
to handle remote requests. The default value is ten.
Hosts which are included in this list are automatically
trusted, if cfservd does not know their public key. This
allows public keys to be exchanged. Cfservd will not automatically
accept a public key from a host it does not know, since the
key will be used to assert strong authentication later.
Once a pubic key has been associated with an IP address, it
will never be updated, unless the existing key is deleted by hand.
Hosts which are included in this list are assumed to have IP addresses which
can change with time, e.g. hosts which are given IP addresses by DHCP
or a BOOTP like protocol.
control:
DynamicAddresses = ( 128.39.74.100-200 ) # DHCP range
If cfservd receives a connection from an IP address that is in this list,
and trustkey is true, the existing key for that IP address can be
replaced with a new key, and the old key is recorded in a "used keys"
list, access is granted. If trust is switched off, the server looks
in the "used key list" to see if the key has been seen before. If not
access is refused. If it has been seen before - it uses this earlier
trust to accept the connection and replace the IP-key binding.
Note that used keys are kept in a database for easy lookup, whereas
fixed keys are kept in files for easy administration. If host keys
change or are reinstalled on the dynamically allocated hosts, then
this database should probably be deleted to purge keys that become
illegal.
This list specificies the names of hosts which are to have read
access to files, regardless of the owner of the file. This effectively
gives root users on connecting hosts privileges to non-root owned
files on the server, but not vice-versa, similar to the NFS root mapping,
except that there is no question of a client being able to modify files
on the server. Caution: cfservd trusts the DNS service, so be aware that
cache poisoning attacks are a possible way of bypassing access controls.
If this option is set, cfservd will only serve the named files
if the copy access type is secure, i.e. on an encrypted
link. This presupposes that cfengine has been compiled with
a working OpenSSL library.
If connecting hosts use a Network Address Translator in order to share an IP address,
reverse lookup will fail to give a correct verification of host identity.
You can switch off cfservd's verification of IP host identity for specific IP addresses
or patterns using this command. E.g.
SkipVerify = ( 192.0.0.10 192.0.2. )
This does not affect key verification.
NOTE!! This is a security risk because it means that cfservd implicitly
trusts the connecting hosts! You should be very careful in using
Network Address Translators in a secure environment. It is not recommended
for sites which require a high level of security.
The general syntactic form of the cfrun command is
cfrun -option --longoptionclass1class2 ...
Since cfrun addresses remote hosts, there is an ambiguity in
whether options are intended for the cfrun command itself, on the local
host, or whether they are to be passed on to the agent on the remote hosts.
To clarify this distinction, the arguments are organized as follows:
Local options are processed by cfrun on the local host; remote options
are passed on as options to the remote cfagent (actually to the
command defined in cfrunCommand in the file cfservd.conf;
remote classes are processed by the remote cfservd service, and specifiy
classes which must be satisfied by the remote host in order to invoke the
remote command.
The -q and -I options are
always assumed when executing cfengine remotely, so that SplayTime is
effectively zero when polling hosts serially, and the output always
shows what is happening on the remote hosts.
Each host evaluates the classes sent by cfrun
and decides whether cfengine should be invoked.
Only hosts which belong to the classes defined on the cfrun
command line are executed. This allows you to single out groups of hosts
which should execute cfengine, based on the very classes which you have
defined for your configuration. If no classes are sent on the command
line, then all hosts are run.
cfrun uses a configuration file which is located under the
CFINPUTS directory in order to determine which hosts and in
which order it should try to connect. Because cfengine always uses a
reliable TCP protocol for connections, it verifies each connection
rather than simply broadcasting openly. Using this file you can even
simulate broadcasting to hosts outside your subnet.
This file should contain every host name you ever want to
configure remotely, because you can still select subsets of
the file by specifying classes which the remote host will understand.
If the remote host is not in one of the classes you specify when you
run cfrun, then it will simply ignore the request. Conversely,
if you do not place a host in this file, it will never be contacted
when you use the cfrun command. The format of the file
is as follows
If the option outputdir is present, cfrun forks a separate
process for each host and passes the output to files in a named directory.
The maxchild line limits the number of forked processes.
It is important to add the domain-name to this file.
The options you specifiy in this file, per host, are added to those
you might specify on the command line when invoking cfengine remotely.
For instance, you might know of a bug on one host and decide not to
perform interface configuration on that one machine. You would write
a line like this:
funny.domain -- -i # problem host
You could use cfrun inside one of your cfengine configuration
files in order to remotely execute cfengine on all of the other network
machines, by setting up a host list. The disadvantage however is that
cfengine has to poll the systems on the network, which means that
cfengine cannot be working in parallel on all hosts.
Some other examples:
e.g. cfrun -- -- linux Run on all linux machines
cfrun -- -p Ping and parse on all hosts
cfrun -v -- -p Ping all, local verbose
cfrun -v -- -k -- solaris Local verbose, all solaris, but no copy
Amongst the local options, one may specify a subset of the hosts which are to
be contacted by cfrun, i.e. to avoid processing the entire list of hosts. For
example, to contact only host1 and host2, given that they are already in
the list of hosts.
Firewalls and Network Address Translators (NAT) can be a problem for
addressing. Suppose you have a firewall and with a private IP-range
behind the firewall. You want to update the nodes from a central
host. You can do a two stage configuration: first update the firewall and
then update from the firewall to the nodes.
But suppose you already use SNAT (Source Network Address Translation) and DNAT
(Destination ...) for the nodes. With DNAT you can say that socket 22000
on the firewall is routed to host-name:5308. DNAT gives us the
possibilty to update the nodes from a central server in one step instead
of two.
If the port command is given cfrun uses this to connect to the client
instead of the default (5308) one.
Here is an example (cfrun.hosts):
In wrapper mode (non-forking, non-daemon mode), cfagent is run by adding a
line to the root crontab file of each system:
0,30 * * * * /usr/local/sbin/cfexecd -F
This is enough to ensure that cfengine will get run. Any output generated
by this job, will be stored in /var/cfengine/outputs.
In addition, if you add the following to the file cfagent.conf,
the system administrator will be emailed a summary of any output:
control:
smtpserver = ( mailhub.example.org ) # site MTA which can talk smtp
sysadm = ( mark@example.org ) # mail address of sysadm
Fill in suitable values for these variables.
An alternative, or additional way to run cfengine, is to run the cfexecd
program is daemon mode (without the -F) option. In this mode, the daemon
lives in the background and sleeps, activating only in accordance with
a scheduling policy. The default policy is to run once every hour (equivalent
to Min00_05). Here is how you would modify cfagent.conf in
order to make the daemon execute cfagent every half-hour:
control:
# When should cfexecd in daemon mode wake up the agent?
schedule = ( Min00_05 Min30_35 )
Note that the time specifications are the basic cfengine time classes.
Although one of these methods should suffice,
no harm will arise from running both cron and the cfexecd side-by-side.
Cfagents locking mechanisms ensure that no contention will occur.
Note, that if problems with library path for compiled in libraries occur, an
explicit library path can be specified with the -L option.
In some cases you will want to run cfengine on a system to configure it
from scratch. If the system is in a very bad way, it might not even be
able to parse the cfengine configuration file, perhaps because the
network was not properly configured or the DNS (Domain Name Service) was
out of action. To help prevent this situation, cfengine looks for a
script called cf.preconf which gets executed prior to parsing and
can be used to perform any emergency tests. This file needs only
contain enough to get the system to parse the configuration files.
cf.preconf may be any script in any language. It need not exist
at all! It is fed one argument by cfengine, namely the system hard-class
for the current system (e.g. ultrix). Here is an example:
#!/bin/sh
#
# cf.preconf is an emergency/bootstrap file to get things going
# in case cfengine is unable to parse its config file
#
backupdir=/iu/nexus/local/iu/etc
#
# If these files don't exist, you might not be able to parse cfagent.conf
#
if [ ! -s /etc/resolv.conf ]; then
echo Patching basics resolv.conf file
cat > /etc/resolv.conf << XX
domain iu.hioslo.no
nameserver 128.39.89.10
XX
fi
#
# SVR4
#
if [ "$1" = "solaris" ]; then
if [ ! -s "/etc/passwd" ]; then
echo Patching missing passwd file
/bin/cp $backupdir/passwd /etc/passwd
fi
if [ ! -s "/etc/shadow" ]; then
echo Patching missing passwd file
/bin/cp $backupdir/shadow /etc/shadow
fi
fi
#
# BSD 4.3
#
if [ "$1" = "linux" ]; then
if [ ! -s "/etc/passwd" ]
then
echo Patching missing passwd file
/bin/cp $backupdir/passwd.linux /etc/passwd
fi
fi
If, for some reason you are not satisfied with the defaults which
cfengine uses, then you can change them by making an entry in the
resource file. The default values are defined in the source code file
classes.c in the distribution. The format of the resource file
is:
hardclass.variable: value
For example, you might want to forget about where your HPUX system
mounts its mail directory and mount it under /usr/spool/mail. In
this case you would add the line:
hpux.maildir: /usr/spool/mail
To redefine the filesystem table for GNU/linux, you would write:
linux.fstab: /etc/linuxfstab
The full list of re-definable resources is:
mountcomm # command used to mount filesystems
unmountcomm # command used to unmount filesystems
ethernet # name of the ethernet device
mountopts # options to above mount command
fstab # the name of the filesystemtable
maildir # the location of the mail directory
netstat # the full path to netstat and options
pscomm # the path to the system's ps command
psopts # the options used by ps (default aux/ef)
You should never need to redefine resources unless you decide to do something
non-standard. Interested readers are referred to the values in classes.c.
Cfengine is easily extensible so as to support a variety of
architectures. You can even add your own. To do so you need, first of
all, to define a new class for the operating system concerned. The file
classes.c has been separated off from the remainder of the source
code so that you can easily see which data structures need to be
extended.
To make life as straightforward as possible, three unused classes have
been defined. They are called (unremarkably) unused1,
unused2 and unused3. If you add any further classes, it
will be necessary to increase the constant clssattr defined in
cf.defs.h by one for every new addition. You do not need to
change clssattr if you simple replace one of the unused classes
by a real class.
To see fully the impact of what you need to do, you should make a search
for the strings unused? in all of the source files. Certain
special cases need to be handled for each operating system. For
example, the form of the filesystem table is quite radically different
on some systems such as AIX. One thing you must do is to fill in the
default values for the new operating system in the file
classes.c.
If you fill in the details for a new operating system before it finds
its way into a new release, you might consider sending the details to
the bug list in the next paragraph.
#####################################################################
#
# CFENGINE CONFIGURATION FOR site = iu.hioslo.no
#
# This file is for root only.
#
######################################################################
###
#
# BEGIN cfagent.conf
#
###
import:
#
# Split things up to keep things tidy
#
any::
cf.groups
cf.main
cf.site
cf.motd
hpux:: cf.hpux
linux:: cf.linux
solaris:: cf.solaris
sun4:: cf.sun4
ultrix:: cf.ultrix
freebsd:: cf.freebsd
#
# Do you want to do this ?
#
AllHomeServers:: cf.users
###
#
# END cfengine.conf
#
###
##################################################################
#
# cf.motd
#
# This file is used to set the message of the day file on
# each host
#
##################################################################
#####
#
# BEGIN cf.motd
#
#####
control:
#
# This points to the file containing general text
#
masterfile = ( /iu/nexus/local/iu/etc/motd-master )
local_message = ( /etc/motd.local )
editfiles:
{ /etc/motd
BeginGroupIfFileIsNewer "$(masterfile)"
EmptyEntireFilePlease
InsertFile "$(masterfile)"
InsertFile "$(local_message)"
PrependIfNoSuchLine "This system is running $(class):$(arch)"
EndGroup
}
#####
#
# BEGIN cf.motd
#
#####
Whether or not you perform any special services for users, with or
without their consent is entirely a matter of local policy. In a school
or college situation, users are often uncooperative and some are even
irresponsible. This file shows you what you could do in an environment
with inexperienced users, but please don't feel as though you have to be
this totalitarian.
#################################################################
#
# cf.users - for iu.hioslo.no
#
# This file contains user specific actions
#
#################################################################
###
#
# BEGIN cf.users
#
###
ignore:
robot
tidy:
longjob::
#
# Some users just don't understand what they are doing
# and this is safest, allbeit totalitarian
#
home pat=.rhosts age=0
#
# Tidy up users' home dirs
#
home pat=core r=inf age=0
home pat=a.out r=inf age=1
home p=*% r=inf age=2
home p=*~ r=inf age=2
home p=#* r=inf age=1
home p=*.dvi r=inf age=14 type=ctime
home p=*.log r=inf age=2
home p=Log.* r=inf age=3
home p=CKP r=inf age=1
home p=BAK r=inf age=1
home p=log r=inf age=0
home p=*.o r=inf age=0
home p=*.aux r=inf age=3
home p=*.zip r=inf age=7
home/.deleted p=* r=inf age=0
home/.wastebacket p=* r=inf age=14
home/www p=*~ r=inf age=1
#
# Clear the big cache files netscape creates
#
home/.netscape-cache p=cache????* r=inf age=0
home/.MCOM-cache p=cache????* r=inf age=0
home/.netscape/cache p=* r=inf age=0
#################################################################
files:
AllHomeServers.longjob.rest::
#
# Check users files are not writable to the world
# and there are no stale links (pointing nowhere)
#
home mode=o-w recurse=inf action=fixall # links=tidy
home/.xsession mode=755 action=fixall
home/.cshrc mode=755 action=fixall
#################################################################
copy:
Hr00.longjob::
#
# Make sure each user has an up to date standard
# setup. Cshrc just sources in a big standard file
# which is kept in ~user/../.setupfiles/cshrc
# to reduce disk wastage
#
$(masterfiles)/lib/Cshrc dest=home/.cshrc
$(masterfiles)/lib/tkgrc dest=home/.tkgrc
$(masterfiles)/lib/fvwm2rc dest=home/.fvwm2rc
###
#
# END cf.users
#
###
#################################################################
#
# cf.solaris - for iu.hioslo.no
#
# This file contains solaris specific patches
#
#################################################################
###
#
# BEGIN cf.solaris
#
###
directories:
#
# httpd/netscape want this to exist for some bizarre reason
#
/usr/lib/X11/nls
################################################################
tidy:
/var/log pattern=syslog.* age=0
MailHub::
/var/mail pattern=lp age=0
#################################################################
files:
#
# If this doesn't exist fork will not work and the
# system will not even be able to run the /etc/rc
# scripts at boottime
#
/etc/system o=root g=root m=644 action=touch
/var/log/syslog o=root m=666 action=touch
#############################################################
copy:
#
# Some standard setup files, can't link because
# machine won't boot if their not on / partition.
#
/local/bin/tcsh dest=/bin/tcsh mode=755
/local/iu/etc/nsswitch.standalone dest=/etc/nsswitch.conf
#
# Our named server uses a newer BIND
# Put this here so that it will be preserved under
# solaris reinstallation
#
NameServers::
/local/iu/sbin/in.named dest=/usr/sbin/in.named mode=555
/local/iu/sbin/in.named.reload dest=/usr/sbin/in.named.reload mode=555
/local/iu/sbin/in.named.restart dest=/usr/sbin/in.named.restart mode=555
/local/iu/sbin/in.ndc dest=/usr/sbin/in.ndc mode=555
/local/iu/sbin/named-xfer dest=/usr/sbin/named-xfer mode=555
/local/iu/lib/nslookup.help dest=/usr/lib/nslookup.help mode=444
any::
/local/iu/lib/libresolv.a dest=/usr/lib/libresolv.a mode=444
/local/iu/lib/libresolv.so.2 dest=/usr/lib/libresolv.so.2 mode=444
/local/bin/nslookup dest=/usr/sbin/nslookup mode=444
##############################################################
editfiles:
{ /etc/netmasks
AppendIfNoSuchLine "128.39 255.255.255.0"
}
{ /etc/defaultrouter
AppendIfNoSuchLine "128.39.89.1"
}
{ /usr/openwin/lib/app-defaults/XConsole
AppendIfNoSuchLine "XConsole.autoRaise: on"
}
#
# CERT security patch for vold vulnerability
#
{ /etc/rmmount.conf
HashCommentLinesContaining "action cdrom"
HashCommentLinesContaining "action floppy"
}
##############################################################
disable:
/etc/.login type=file
/etc/aliases
#
# These files are ENORMOUS, don't let them fill the disk
#
Wednesday::
/var/lp/logs/lpsched rotate=empty
/var/adm/wtmpx rotate=empty
/var/adm/wtmp rotate=empty
##############################################################
files:
/etc/passwd m=0644 o=root g=other action=fixplain
/etc/shadow m=0600 o=root g=other action=fixplain
/etc/defaultrouter m=0644 o=root g=other action=touch
/var/adm/wtmpx m=0664 o=adm g=adm action=touch
/var/adm/wtmp m=0644 o=root g=adm action=touch
/var/adm/utmp m=0644 o=root g=adm action=fixplain
/var/adm/utmpx m=0664 o=adm g=adm action=fixplain
/tmp m=1777 action=fixdirs
##############################################################
disable:
#
# CERT security patch
#
/usr/openwin/bin/kcms_calibrate
/usr/openwin/bin/kcms_configure
/usr/bin/admintool
################################################################
shellcommands:
AllBinaryServers.Saturday.longjob.Hr00::
#
# Make sure the man -k / apropos data are up to date
#
"/usr/bin/catman -M /local/man"
"/usr/bin/catman -M /local/X11R5/man"
"/usr/bin/catman -M /usr/man"
"/usr/bin/catman -M /local/gnu/man"
"/usr/bin/catman -M /usr/openwin/share/man"
"/usr/bin/catman -M /local/X11R5/man"
"/usr/bin/catman -M /usr/share/man"
################################################################
editfiles:
#
# A painless way to add an rc.local script to the rc files
# under solaris without having to fight though inittab
#
{ /etc/rc3.d/S15nfs.server
AppendIfNoSuchLine "sh /local/iu/etc/rc.local"
}
#
# umask defined when inetd starts is inherited by all subprocesses
# including ftpd which saves with mode 666 (!) unless we do this
#
{ /etc/rc2.d/S72inetsvc
PrependIfNoSuchLine "umask 022"
}
###
#
# END cf.solaris
#
###