CFEngine Part 1

What is CFEngine

CFEngine is an open source tool for system configuration management and is used in large scale environments with hundreds of servers. This has continued to be an important part of system administration. With the advent of virtualization, the number of servers now have the ability to scale well beyond the physical limitations of the data center and the concept of manually administering more than 100+ servers quickly becomes unfeasible for a single admin. The list of capabilities for CFEngine is nearly limitless but some of the main tasks include basic operating system configuration and maintenance, management of system users, customizable control of security and software/patching installation.

Due to the complexity of CFEngine, this will be a multi-posting topic. I have decided to go with CFEngine as opposed to Chef or Puppet due to its maturity and scalability. It was first written in 1993 and is very fast since it is written in C and does not rely on Ruby like the other two configuration management programs. There is also a large community user base from which to draw upon since the automation of tasks in the sysadmin work is generally not unique.

Installation

As root, we are going to install the free community version from one of the repos using Fedora 19,

# yum install cfengine

The default directory structure will be in /var/cfengine although some of the files from the yum install will need to be moved/linked into the correct directory.

# cd /var/cfengine
# ls
bin  inputs  masterfiles  modules  outputs  ppkeys

Configuration

The main cf files should be in the masterfiles subdirectory and will need to be copied from where the package manager placed them,

# ls /usr/share/cfengine/CoreBase/
cfengine_stdlib.cf  failsafe.cf  promises.cf
# cp -Rp /usr/share/cfengine/CoreBase/*.cf /var/cfengine/masterfiles/
# ls masterfiles/
cfengine_stdlib.cf  failsafe.cf  promises.cf

You may only have 2 binaries linked in the bin subdirectory but there are actually several more that we need to link,

# cd /var/cfengine/bin
# ls -l
lrwxrwxrwx. 1 root root 18 Mar 15 17:09 cf-agent -> /usr/sbin/cf-agent
lrwxrwxrwx. 1 root root 21 Mar 15 17:09 cf-promises -> /usr/sbin/cf-promises

# for i in $(cd /usr/sbin/ && ls -1 cf-*); do ln -s /usr/sbin/$i ./$i; done

# ls -l
lrwxrwxrwx. 1 root root 18 Mar 15 17:09 cf-agent -> /usr/sbin/cf-agent
lrwxrwxrwx. 1 root root 18 Mar 15 17:32 cf-execd -> /usr/sbin/cf-execd
lrwxrwxrwx. 1 root root 16 Mar 15 17:32 cf-key -> /usr/sbin/cf-key
lrwxrwxrwx. 1 root root 17 Mar 15 17:32 cf-know -> /usr/sbin/cf-know
lrwxrwxrwx. 1 root root 21 Mar 15 17:32 cf-monitord -> /usr/sbin/cf-monitord
lrwxrwxrwx. 1 root root 21 Mar 15 17:09 cf-promises -> /usr/sbin/cf-promises
lrwxrwxrwx. 1 root root 19 Mar 15 17:32 cf-report -> /usr/sbin/cf-report
lrwxrwxrwx. 1 root root 21 Mar 15 17:32 cf-runagent -> /usr/sbin/cf-runagent
lrwxrwxrwx. 1 root root 20 Mar 15 17:32 cf-serverd -> /usr/sbin/cf-serverd

Next we need to generate a pair of public/private keys that will be stored in the ppkeys subdirectory. If by chance the package install came with a set of keys, it is best to delete them and create new ones,

# /var/cfengine/bin/cf-key
# ls /var/cfengine/ppkeys/
localhost.priv  localhost.pub

Now to bootstrap the policy server. In our case, we are going to make the server and client the same machine. This is going to move master files into the inputs subdirectory and should properly start the cf-execd process. The ip address for my server is 192.168.100.50,

# /var/cfengine/bin/cf-agent --bootstrap --policy-server 192.168.100.50
** CFEngine BOOTSTRAP probe initiated
 -> This host is: localhost.localdomain
 -> Operating System Type is linux
 -> Operating System Release is 3.9.5-301.fc19.x86_64
 -> Architecture = x86_64
 -> Internal soft-class is linux
 -> No policy failsafe discovered, assume temporary bootstrap vector
 -> No previous policy has been cached on this host
 -> Assuming the policy distribution point at: 192.168.100.50:/var/cfengine/masterfiles
 -> Attempting to initiate promised autonomous services...

 ** This host recognizes itself as a CFEngine Policy Hub, with policy distribution and knowledge base.
 -> The system is now converging. Full initialisation and self-analysis could take up to 30 minutes

 R: This host assumes the role of policy distribution host
 R:  -> Updated local policy from policy server
 R:  -> Started the server
 R:  -> Started the scheduler
 -> Bootstrap to 192.168.100.50 completed successfully

# ls /var/cfengine/inputs/
cfengine_stdlib.cf  failsafe.cf  failsafe.cf.cfsaved  promises.cf

Verify the CFEngine processes are running,

# ps -elf | grep cf

If for some reason the cf-execd process is not running, you can manually start it from the command line. The other system daemons and setup of a remote client will be explaining in follow-up posts. For now, we are going learn the basics by creating a simple policy to change the /etc/issue file to contain a pre-login message. Change to the /var/cfengine/masterfiles directory,

# cd /var/cfengine/masterfiles

vi the file issue.cf and add the following lines,

bundle agent issue
{
  vars:
      "issue" string => "/etc/issue";

  files:
      "$(issue)"
        create => "true",
        edit_line => message;
}

bundle edit_line message
{
  insert_lines:
      "Welcome to my CFEngine server";
}

This will setup the agent issue to be executed using the defined key words. The edit_line parameter controls insert_lines and will write the message to the file if it doesn’t already exist. Now, this policy has to be added into the main promises.cf file to be executed. Edit the promises.cf file and add issue and issue.cf into the bundlesequence and inputs section as follows,

body common control
{
 bundlesequence => { "main","issue" };

 inputs => { 
            "cfengine_stdlib.cf","issue.cf", 
           };

 version => "Community Promises.cf 1.0.0";
}

After saving the file, verify there are no errors in the configuration with the following command,

# cf-promises -f /var/cfengine/masterfiles/promises.cf

The prompt should be returned with no output if the file is clean. All that is required now is to wait and check the /etc/issue file. By default, CFEngine runs every 5 minutes. So, after a maximum of 5 minutes from your edit, you should see the lines listed below from within your /etc/issue file,

# cat /etc/issue
Fedora release 19 (Schrödinger’s Cat)
Kernel \r on an \m (\l)

Welcome to my CFEngine server

In Part 2 we will review a more relavent configuration change using a client machine and learn how to setup email notifications.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s