Thursday, March 19, 2009

Getting Started With CFEngine's cfagent.conf On Linux And Unix

Hey there,

It seems like a year since primary on-call duty came by and knocked me off my high horse. But, as they say, there's a reason we all fall down. It's so that we can learn how to deal with public humiliation, come to know the true meaning of pain and realize just how alone we are in this great big universe ;) It's either that or so we can learn to get back up again. The latter seems more like common sense, though. Does anyone reading this blog need to learn this lesson (after the first time)? Unless you prefer sitting, or spending your days sprawled-out face-down in the dirt, the odds are you've gotten back up before and you'll get back up again. Class dismissed ;)

Today, we're going to take a look at cfengine. It's a great (free) program that can be used for a wide variety of things (think Tripwire, Nagios, Jumpstart/Kickstart pre/post installation helper, etc). It's a decent product, that can be configured to run as simple or as complicated a setup as you prefer. So far, in my usage, I've come nowhere near the boundaries that cfengine can reach. I don't even know, for sure, what those boundaries are, since (as a side effect of not using it to its fullest potential) I've never fully tested its limitations.

That being what it is (and that is what it's being ;), today we're going to look at a skeleton of a configuration file for the cfagent program (part of cfengine, along with cfenvd, cfrun, etc). The cfagent program will allow you to hit the ground running and begin to see what cfengine can do for you. We're assuming that you've already installed cfengine, which you can download from or, if you're running a Linux distro, odds are there are packages available for your OS. That means that installation could just be a command away ("rpm -i cfengineXXXX.i386.rpm" or something like that). If you do need to build it from source, we'll be sure to address that in a future post on this blog. For now, we'll just assume it's already been installed, you can install it or you can find someone who'll install it for you. Whatever works for you. We'll wait ;)

For today we're going to go with a setup so basic, it may be of no use whatsoever. But, then, that's not the point :) The file we'll be using today (to control the actions of cfagent) is called cfagent.conf (Don't be fooled by the clever name ;) If we make a very simple configuration file, we could get away with this (running on a single server, just to keep things simple):

actionsequence = (

/bin/ls=0555 owner=root group=bin action=fixall

And that's it. We're not going to get into specifics (like we'll only run this command on this set of servers, etc). The basic structure of our config file is pretty much this:



So, today, we'll just examine what those CAPITALIZED references mean. Obviously, they correspond to the contents of the cfagent.conf above :) It should be noted that all of the names we used in our sample configuration file are special to cfengine and don't require any specific definition by you. The only line where we really take any license is with the OBJECT RULES. More on that below!

CONTROL: This is a fundamental section in any cfagent.conf. Without this section, your cfagent run won't do anything! The colon at the end of the name "control:" indicates that the name is complete. This form can also be used to assign a value to a variable under a different context using a slightly different form (not to confuse... sorry; getting off track)

CLASSES:: This is sometimes known as "GROUPS::" although both will work at version 1.4 and above if I'm anywhere near correct. Hopefully you won't have to go back that far to get your setup working (They're on 3.x right now). The CLASSES:: variable ends with a double colon. Here we're not being as specific as we could be. We're setting the class "any" so that any defined class will match and cause cfagent to proceed deeper within the nest. "any" is pre-defined by cfagent and matches everything.

VARIABLE/FUNCTION In the CONTROL section, this generally defines the main flow of execution for the remainder of the configuration file. In this instance our variable is named "actionsequence." The "actionsequence" FUNCTION simply contains a list of the FACILITY's (pardon the improper spelling :) that we want to run through and in what order. If we had more than one, they would generally be listed one per line and executed from top to bottom. The FACILITY we chose to use is called "files"

FACILITY: As we noted just above, the FACILITY: "files" is the first FACILITY: executed by our CONTROL: section above. The "files" keyword (as also noted higher above) is special to cfagent and denotes files ;) That is to say that there are a lot of basic options you can choose from when you define your files and built-in actions that you can use simply by calling them within the configuration. The FACILITY: definition ends with a colon.

CLASSES:: This works the same as above. "any"-thing will match this!

OBJECT RULES This is where we set up what we want to do with our "files." We've only selected one rule, and it breaks down like this. In standard format (and this can get very complicated if you like) your rule definition would begin with the "name" of the file you wanted to act upon, followed by specific "attributes" of that file (if necessary/required) and the "action(s)" you intend to take upon it. So our RULE

/bin/ls=0555 owner=root group=bin action=fixall

could be picked apart like so:

file name = /bin/ls
file permissions = 0555
(Note that we took the liberty of jamming the file "name" and an "attribute" together here: /bin/ls=0555. This could also be written as: /bin/ls mode=0555)
file "attribute" owner = root
file "attribute" group = bin
file "action" = fixall
<-- Again, this action is built-in and instructs cfagent to fix any problems it finds with /bin/ls. Those problems would be defined as "attributes" of the actual file that differ from the "attributes" set for it in our cfagent.conf rule.

So if we did a:

host # ls -l /bin/ls
-rwxr-xr-x 1 root root 174432 Nov 8 14:21 /bin/ls

and then we ran:

host # cfagent -qv ( the -q option turns of host sleeping - also referred to as "splaying" (???) and the -v option is the expected "verbose")

it would find /bin/ls, note that the file mode was incorrect (0755 instead of 0555 and with the group root instead of bin) and fix that for us, so that our next ls would show the "corrected" file, like so:

host # ls -l /bin/ls
-r-xr-xr-x 1 root bin 174432 Nov 8 14:21 /bin/ls

And I think that's enough for today. You never realize how much there is to explain about something until you try to explain it. But, as they say, that's why we learn to fall down... Or am I mixing my metaphors again? ;)


, Mike

Discover the Free Ebook that shows you how to make 100% commissions on ClickBank!

Please note that this blog accepts comments via email only. See our Mission And Policy Statement for further details.