cfengine [3/3] : Using cfengine in a client/server setup
Posted by Steve on Tue 23 Aug 2005 at 09:44
After the previous coverage of cfengine we'll now look at actually installing it and using it for real on a number of different hosts. The rules will come from one central host and be automatically pushed to a collection of managed servers where they will be executed.
The rules file cfagent.conf which controls the jobs which are actually executed we've previously discussed.
For the purpose of this example we will be using three hosts:
- The central server from which all rules are downloaded, and which manages the clients.
- A client we wish to remotely manage.
- Another client system we wish to remotely manage.
As previously mentioned installing cfengine is as simple as running :
apt-get install cfengine2
(Here cfengine2 is the most recent version of the software; newer and incompatible with the previous package cfengine).
After installing the package upon each host you'll be presented with a debconf dialog asking if you wish to start several processes at boot time, along with an explanation of what each process is used for.
I chose to enable all services at boot time for the moment, although you'll likely not need all services running upon each host.
Now comes the hardest part actually configuring the software to do something useful. I strongly recommend that you also install the cfengine2-doc package upon at least one host and read the information it installs. This will be located beneath the directory:
/usr/share/doc/cfengine2-doc/ |-- examples `-- html
To do someting useful you'll need two things:
- A client-server setup which we'll explore in this article.
- A collection of useful rules, which you'll largely have to create by yourself (or find from elsewhere!).
A Note On Security
We are going to setup is a centralised server which will host a file cfagent.conf containing the actions to be conducted upon each of the hosts we manage.
Each managed client will retrieve this rule file and then execute the rules locally.
The server itself will be able to force "pushes" of this file, and thus execute the rules upon any of the managed clients, either individually or en masse.
Setting Up The Server
If you setup cfengine in anger one of the biggest difficulties you'll encounter is getting the keyfile negotiation to work properly.
As discussed in the introductory piece cfengine uses a two-way trust. This means that the server's public key must be copied to the client, and the client's key must also be known to the server.
The fine documentation will explain the process of generating the keys with the command cfkey, and copying/renaming the keys appropriately. However due partly to misleading error messages and a lack of good discussion this is a common stumbling point.
As the communication is key to getting something working if you don't manage to get the keys setup correctly you'll not get anything working if you have problems.
So instead of using keys I'm going to ignore keyfiles completely - and trust all machines on the LAN.
This simplifies the description of the setup enormously; but it does weaken security.
(With a bit of firewalling it is possible to setup each client such that it only accepts connections from the central host. If you choose to ignore keyfiles, as I do, then this is something you should investigate.)
Setting Up The Clients
The role of the server is going to be twofold:
- It contains the central cfagent.conf file which has the rules to be applied to hosts.
- It maintains a list of clients which it manages.
What is less obvious is that the clients have to fetch the most current version of the cfagent.conf file on every run (if it has changed), so to make that explicit I will create a new location for this file to exist in:mkdir -p /var/lib/cfengine2/masterfiles/inputs
Once you've done that you can install the cfagent.conf file there. A simple example file is:# # /var/lib/cfengine2/masterfiles/inputs/cfagent.conf # # Master cfagent file on the server, # control: domain = ( my.flat ) access = ( root ) cfrunCommand = ( "/usr/sbin/cfagent" ) actionsequence = ( files directories tidy resolve ) maxage = ( 7 ) # # Fix some basic file permissions. # files: /etc/sudoers mode=440 owner=root group=root action=fixall /etc/passwd mode=644 owner=root group=root action=fixall /etc/shadow mode=640 owner=root group=shadow action=fixall # # Clean out *ALL* files older than $(maxage) days from /tmp. # # Clean out files older than $(maxage) which match the pattern *~ # inside user home directories. # tidy: /tmp pattern=* age=$(maxage) recurse=inf /home pattern=*~ age=$(maxage) recurse=inf directories: /tmp mode=1777 owner=root group=root resolve: "search my.flat" 192.168.1.1 "# Edit with cfengine"
(This file is available for download.)
As you can see there is a "domain" setting right at the top, this is important as most of the cfengine files will use a "domain" when testing if accesses are allowed, as we'll see in the server configuration file.
You should change all domain settings to match your local network setup.
The server's configuration file is /etc/cfengine/cfservd.conf and ours will look like this:# # /etc/cfengine/cfservd.conf - for the server control: domain = ( my.flat ) TrustKeysFrom = ( 192.168.1.0/24 ) AllowUsers = ( root ) any:: IfElapsed = ( 0 ) ExpireAfter = ( 15 ) MaxConnections = ( 50 ) MultipleConnections = ( true ) grant: # Grant access to all hosts in my.flat. /var/lib/cfengine2/masterfiles/inputs *.my.flat
You can download this file if you wish.
For your setup you will need to modify the two mentions of my.flat, along with the local IP address range you're using.
The last job for the server is to build up a list of hosts you're going to manage. Do that by creating the file /etc/cfengine/cfrun.hosts:domain = my.flat # # Clients # scratchy.my.flat lappy.my.flat
(Again this file is available for download.)
Now that you've created the two file cfrun.hosts, and cfservd.conf inside /etc/cfengine you can restart the server:/etc/init.d/cfengine2 restart
Using the installation
The client setup really consists of three things:
- Creating an update.conf file.
- Creating a minimal cfservd.conf file.
- Connecting to the server once manually, required to get the keys setup.
As we've covered the server we know that the cfagent.conf rule file will be stored on the host in the directory /var/lib/cfagent/masterfiles/input - the update file contains the magic which will copy it from there into /etc/cfengine on our host - where it can actually be used.
This means that our rulefile will always be current.
The /etc/cfengine/update.conf file will look like this:# # /etc/cfengine/update.conf - for the clients # control: actionsequence = ( copy ) domain = ( my.flat ) policyhost = ( mystery.my.flat ) # smtpserver = ( smtp.domain.com ) # sysadm = ( email@example.com ) master_cfinput = ( /var/lib/cfengine2/masterfiles/inputs ) repository = ( /var/lib/cfengine2/outputs ) # # Download the most recent 'cfagent.conf' file from the # server, and install it to /etc/cfengine # copy: $(master_cfinput)/cfagent.conf dest=/etc/cfengine/cfagent.conf mode=600 server=$(policyhost) force=true trustkey=true
(This file is available for download.)
You will need to change "my.flat" to your own domain, and "mystery.my.flat" to the name of your server if you wish to use it. No other changes should be required.
Once you've created the update file you're ready to create the cfservd.conf file for this client.
The following is a good sample:# # /etc/cfengine/cfservd.conf for the clients # control: domain = ( my.flat ) AllowConnectionsFrom = ( 192.168.1.0/24 ) TrustKeysFrom = ( 192.168.1.0/24 ) cfrunCommand = ( "/usr/sbin/cfagent" ) AllowUsers = ( root ) LogAllConnections = ( true ) IfElapsed = ( 1 ) ExpireAfter = ( 15 ) MaxConnections = ( 50 ) MultipleConnections = ( true ) grant: /usr/sbin/cfagent *.my.flat
(This file is available for download.)
Again you will need to modify the domain, grant, and the various IP addresses if you wish to use this yourself.
Now that you've copied everything onto the client properly you should be ready to restart the cfengine processes and run the initial agent test.
To restart run:/etc/init.d/cfengine2 restart
Once this is done become root upon the client and run:root@scratchy:~# cfagent -q cfengine:: Trusting server identity and willing to accept key from mystery.my.flat=192.168.1.80
This should give you a message indicating successful trust, as we see, and you should discover the key of the server has now appeared within /var/lib/cfengine2/ppkeys:root@scratchy:~# ls -l /var/lib/cfengine2/ppkeys/ total 12 -rw------- 1 root root 1743 2005-08-22 06:44 localhost.priv -rw------- 1 root root 426 2005-08-22 06:44 localhost.pub -rw-r--r-- 1 root root 426 2005-08-22 17:22 root-192.168.1.80.pub
Now that you've setup the basic connection with the server and the clients you're ready to have fun!
To get started you should experiment with adding rules to the master cfagent.conf you've installed in /var/lib/cfengine2/masterfiles/inputs on the server.
To execute these rules against a host run:cfrun hostname.as.in.cfrun.hosts
(e.g. "cfrun scratchy.my.flat").
Or against all managed hosts with just cfrun.
Note that the rules dont' all get applied in one run, sometimes it will take several executions.
As a sample I've added a rule to make sure the file permissions on /etc/gshadow are correct:files: /etc/gshadow mode=440 owner=root group=root action=fixall
Running this against a host gives me this :root@mystery:~# cfrun scratchy.my.flat cfrun(0): .......... [ Hailing scratchy.my.flat ] .......... cfengine:: Update of image /etc/cfengine/cfagent.conf from master /var/lib/cfengine2/masterfiles/inputs/cfagent.conf on mystery.my.flat cfengine:: Moved /etc/cfengine/cfagent.conf.cfsaved to repository location /var/lib/cfengine2/outputs/_etc_cfengine_cfagent.conf.cfsaved cfengine:scratchy: Object /etc/gshadow had permission 0, changed it to 640 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(As you can see I ran "chmod 0 /etc/gshadow" on scratchy first to see that the change worked)
If you're using this in production you'll want to do three things, most likely:
- Learn more about the rules you can include in cfagent.conf.
- Learn all about the key-based authentication.
- Examining "classes" so you can have different rules for different OS types.