Getting started with CFEngine

Posted on Posted in CFEngine, linux

Welcome to another Sysadmin & DBA tips, in this post I’ll explain how install, configure, and getting started with CFEngine.

Imagine that you need configure in all of your machines the NTPD daemon with the same ntp server, or you need banning the SSH root access, or control the state of some process and in case of service down restart it. For this examples and many more, we have CFEngine a  Configuration Management Solution.

What is CFEngine

For everybody that don’t know what is CFEngine, I would describe it as a tool to keep our systems following a series of policies set by the System Administrators.

CFEngine is designed to scale cheaply and securely, with up to 5000 hosts per server-hub, so it will not break your hardware budget. It is written in lightweight C code, and has very few software dependencies, so its impact on host performance is negligible.  The CFEngine security model is modeled on the Secure Shell, avoiding costly and complex web certificate management, and exposing fewer vulnerabilities to users.

How CFEngine Works

As the official documentation of CFEngine says:

CFEngine combines modeling and monitoring to bring actual state into compliance with Desired State. You describe Desired State using a declarative, model-based or knowledge-oriented approach.

  • Define the Desired State of your infrastructure with a special knowledge-oriented language; or, use tools that help you design a Desired State from off-the-shelf resources.
  • Simulate configuration changes before committing to them, then study the impact of changes using the knowledge-based inference engine.
  • Confirm the decided Desired State for an automatic self-healing implementation. CFEngine then continuously corrects configuration drift, keeping systems in compliance with their Desired State.
  • Collect reports on the differences between Actual and Desired States and changes or failures encountered while implementing the Desired State using a highly compressed data stream.

The CFEngine infraestructure admit differents configurations, my favourite consist in a central sub-servion repository where we have our policies and one or more Distribution servers (Server-hub). 

In CFEngine the client (agent) is responsible to connect to the Distribution server and check if some policies have changed, if so, the client update his policies to the last version. Using this type of configuration CFEngine avoid unnecessary traffic.

In case of disconnection from the Distributed Server, the agent continues to work, based on last updates. This is a good way of working in case of mobile dispositives like mobiles (Android) and portable computers.

Installation

I’ll explain how install CFEngine from source code, but other possibilities are accepted like install from Pre-Compiled Binary Packages or Packages repositories.

Pre-Requisites

Before install CFEngine some packages are necessary:

yum install gcc openssl openssl-devel pcre pcre-devel gzip bzip2 bzip2-devel byacc libvirt libvirt-devel libxml2 libxml2-devel libacl libacl-devel mysql mysql-connector-odbc mysql-devel mysql-libs

Now download and install TokyoCabinet, a library of routines for managing a database.

wget http://fallabs.com/tokyocabinet/
tar xvfz tokyocabinet-1.4.48.tar.gz
 ./configure --libdir=/usr/lib64
make 
make install

CFEngine installation

Download the latest CFEngine version from  the official webpage, and extract it.

tar xvfz cfengine-3.4.0.tar.gz
 ./configure --prefix=/var/cfengine --sbindir=/var/cfengine/bin --localstatedir=/var/cfengine --with-workdir=/var/cfengine --with-openssl=/usr --with-mysql LDFLAGS="-L/usr/lib64/mysql"

Now generate the CF-KEY, this is the key that will use the server and the client for trusted communication.

/var/cfengine/bin/cf-key

Copy the CFEngine binaries to standard PATH

cp /var/cfengine/bin/cf-* /usr/local/sbin/

Copy configuration files to your MASTERFILE directory, that directory is where clients take the last policies version

cp -Rp /var/cfengine/share/CoreBase/* /var/cfengine/masterfiles

Finally start the server specifiying the policy server, in this case the same computer. The CFEngine agent will start and detect that it is the Policy server and will assume the role of policy distribution host.

[root@cfserver cfengine-3.4.0]# /var/cfengine/bin/cf-agent --bootstrap --policy-server 192.168.18.100
** CFEngine BOOTSTRAP probe initiated

   @@@      
   @@@      CFEngine

 @ @@@ @    CFEngine Core 3.4.0
 @ @@@ @    
 @ @@@ @    
 @     @    
   @@@      
   @ @      
   @ @      
   @ @      

Copyright (C) CFEngine AS 2008-2012
See Licensing at http://cfengine.com/3rdpartylicenses

 -> This host is: cfserver.albertolarripa.com
 -> Operating System Type is linux
 -> Operating System Release is 2.6.32-279.el6
 -> 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.18.100:/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.18.100 completed successfully

CFEngine client installation

Client installation is like the  server but the CFEngine agent assumes the role of voluntary client. Because client doesn’t need special configuration I will install it from Pre-Compiled Binary Packages or Packages repositories.

Now start the agent specifying the policy server:

[root@cfclient]# /var/cfengine/bin/cf-agent --bootstrap --policy-server 192.168.18.100
** CFEngine BOOTSTRAP probe initiated

   @@@      
   @@@      CFEngine

 @ @@@ @    CFEngine Core 3.4.1
 @ @@@ @    
 @ @@@ @    
 @     @    
   @@@      
   @ @      
   @ @      
   @ @      

Copyright (C) CFEngine AS 2008-2012
See Licensing at http://cfengine.com/3rdpartylicenses

 -> This host is: cfclient.albertolarripa.com
 -> Operating System Type is linux
 -> Operating System Release is 2.6.18-238.5.1.el5
 -> Architecture = i686
 -> 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.18.100:/var/cfengine/masterfiles
 -> Attempting to initiate promised autonomous services...

R: This autonomous node assumes the role of voluntary client
R:  -> Updated local policy from policy server
R:  -> Started the scheduler
-> Bootstrap to 192.168.18.100 completed successfully

Your First Policy

Getting started with CFEngine I’ll create a custom logon message in all the CF-Clients. This is my motd-cfengine.cf file:

#####
# /var/cfengine/masterfiles/my_policies/motd-cfengine.cf
#####

bundle agent motd
{
	vars:
		"motd" string => "/etc/motd";
	files: 
		"$(motd)"
		create => "true", 
		edit_line => addmessage;
	reports: 
		cfengine::
			"Modifiying /etc/motd"; 
}

bundle edit_line addmessage 
{
	insert_lines:
		"-################################################################################################";
		"#-												 ";
		"#				This system is managed by CFEngine 3				 ";
		"#	   @@@		      									 ";
		"#	   @@@      CFEngine Core 3.4.1								 ";
		"#			---------------------------------------------------			 ";
		"#	 @ @@@ @   										 ";
		"#	 @ @@@ @    										 ";
		"#	 @ @@@ @    										 ";
		"#	 @     @    		Alberto Larripa Azcona						 ";
   		"#	   @@@      		alarripa@albertolarripa.com						 ";
   		"#	   @ @      		13/01/2013							 ";
   		"#	   @ @      										 ";
   		"#	   @ @  										 ";
		"#												 ";
		"###############################################################################################";

}
  •  bundle agent <name>: Subroutine, have promises that CFEngine evaluate and acts on, if needed.
    •  agent–> Indicate it’s an “execution” bundle that can be called directly
    • vars: Use to declare variables
    • files: Indicate the file-related operations we want to perform
      • “$(motd)”–> Expand the motd variable.
      • create –> If not exist the Cfengine daemon create it.
      • edit_line –> Call addmessage bundle
    • reports: Produce output during the execution of the policy.
      • cfengine –> This is a “class expression”, that indicate under which conditions the promises that follow it will executed. In this case the condition is always true, because the policy is executed by CFEngine. Other “class expression” are allowed, like “Monday”, the message will be printed only on Mondays
  • bundle edit_line <name>: this type of bundle must contain promises that perform edits on a file, in this case “insert_lines”

The clients automatically download the file if you save this file in the MASTERFILE directory but NOT apply it.

To activate this policy is necessary to modify the promises.cf file and add the bundlesequence and the policy file, in my case I created a directory with all my policies in the MASTERFILE directory

###############################################################################
#
#   /var/cfengine/masterfiles/promises.cf - Basic Policy for Community
#
###############################################################################

body common control

{

 bundlesequence => {
                    "def",
                    "cfsketch_run",
                    "main",
		    "motd",
                   };

 inputs => {
            "def.cf",
            "controls/cf_agent.cf",
            "controls/cf_execd.cf",
            "controls/cf_monitord.cf",
            "controls/cf_report.cf",
            "controls/cf_runagent.cf",
            "controls/cf_serverd.cf",
            "libraries/cfengine_stdlib.cf",
            "cf-sketch-runfile.cf",
            "services/init_msg.cf",
	    "my_policies/motd-cfengine.cf"
           };

 version => "Community Promises.cf 3.4.0";

}

###############################################################################

bundle agent main

{

 methods:

  any::

   "INIT MSG" usebundle => init_msg,
                comment => "Just a pre-defined policy bundled with the package",
                 handle => "main_methods_any_init_msg";

}

###############################################################################

With out doing anything more the client apply this policies and a welcome message appear on all CF-Clients when you connect 😉

[alarripa@host ~]$ ssh cfclient
alarripa@cfclient.albertolarripa.com's password: 
Last login: Sun Jan 13 21:19:00 2013 from alarripa.albertolarripa.com
-################################################################################################
#-												 
#				This system is managed by CFEngine 3				 
#	   @@@		      									 
#	   @@@      CFEngine Core 3.4.1								 
#			---------------------------------------------------			 
#	 @ @@@ @   										 
#	 @ @@@ @    										 
#	 @     @    		Alberto Larripa Azcona						 
#	   @@@      		alarripa@albertolarripa.com						 
#	   @ @      		13/01/2013							 
#	   @ @      										 
#	   @ @  										 
#												 
###############################################################################################
[alarripa@cfclient ~]$

If you are interested in CFEngine and need more information you can visit the official CFEngine manuals.

For some question or CFEngine support, you can contact me writing to:

 

Leave a Reply

Your email address will not be published. Required fields are marked *