cfengine par la pratique

Jehan Procaccia MCI INT-EVRY- jehan.procaccia@int-evry.fr

16 mai 2005

Table des matières

Résumé : Ce document décrit pas à pas la mise en place de cfengine. Il s'attache simplement à installer et configurer un serveur de strategie cfengine et de lui associer un client sur lequel sera installé et deployé cfengine. Enfin appliquera de façon réguliere les choix de strategie centrale de configurations.

1  Introduction

Le site de référence est www.cfengine.org, on y trouvera les sources du programmes et de la documentation (Tutorial, reference ...). Une tres bonnes documentation de mise en oeuvre pratique est disponible sur http://thierrylhomme.developpez.com/cfengine.html. La suite de ce document est un relevé pas à pas de la mise en oeuvre d'un serveur cfengine et d'un simple client. Ce document à été écrit sous forme de prise de notes des fins didactiques, avec prise en compte des problemes rencontrés au fur et à mesure du deploiement. Le tout se base sur une simple plate-forme mono systeme (Fedora Core 3) , entre un serveur (calaz.int-evry.fr) et un client (arvouin.int-evry.fr) . Dans ces conditions, on ne révellera pas toute la puissance de cfengine, et encore moins ses capacités multi systeme, voir la présentaion évoquée ci-dessus et la doc de référence pour aller plus loin .

2  Installation

Nous avons packagé la distribution cfengine afin d'automatiser son deploiement et ses mises à jour, cela permet aussi dès l'installation sur les clients de distribuer et personnaliser certains fichiers de configuration. voire le chapitre package RPM cfengine plus loin pour les détails du package. Néanmoins, on peux se passer du format RPM et utiliser le tar.gz de base .

2.1  Installation rpm


[root@calaz /usr/src/redhat/SPECS]
$ rpm -Uvh /usr/src/redhat/RPMS/i386/cfengine-2.1.14-1_int.i386.rpm
Préparation...              ########################################### [100%]
   1:cfengine               ########################################### [100%]

2.2  Contenu du répertoire principal

Outre les scripts de demarrage ajoutés par notre package /etc/cron.d/cfengine , /etc/init.d/cfengine , /etc/init.d/cfinit et les binaires disponibles dans /var/cfengine/sbin/cf* , le répertoire principal est /var/cfengine
[root@calaz /var/cfengine]
$ ls -R
.:
bin  inputs  outputs  plugins  ppkeys  sbin  share

./bin:
cfagent

./inputs:

./outputs:

./plugins:

./ppkeys:
root-157.159.50.197.pub

./sbin:
cfagent  cfenvd      cfexecd  cfrun    cfshow
cfdoc    cfenvgraph  cfkey    cfservd  vicf

./share:
cfengine

./share/cfengine:
cfagent.conf-advanced.example  cf.main.example       cf.solaris.example
cfagent.conf.example           cf.motd.example       cf.sun4.example
cf.chflags.example             cf.preconf.example    cf.users.example
cfengine.el                    cfrc.example          ChangeLog
cf.freebsd.example             cfrun.hosts.example   INSTALL
cf.ftp.example                 cfservd.conf.example  NEWS
cf.groups.example              cf.services.example   README
cf.linux.example               cf.site.example       update.conf.example

2.3  Services utilisés

Le répertoire sbin contien un certain nombre de binaires décrits ici http://thierrylhomme.developpez.com/cfengine.html#executables.
Dans cette mise en oeuvre simplifiée , nous nous contenterons d'utiliser le serveur de fichier cfservd et le client de configuration cfagent . On utilisra aussi cfkey afin de générér les clés d'authentification . Plus aller plus loin voir la documentation de référence.

3  Configuration

Le serveur va distribuer sur les clients les stratégies de configuration. Le serveur de fichiers (de strategie et de configurations) cfservf lira son fihcier de configuration cfservd.conf. Celui ci devra entre autre distribuer le fichier de configuration du service client (cfagent), fichier cfagent.conf

3.1  Principe de configuration

Le principe est de modifier les stratégies de configuration dans le fichier centralisés cfagent.conf qui se trouve sur le serveur cfengine. Ensuite il s'agit de distribuer ce fichier sur les clients au travers d'une strategie simple et quasi immuable deployée dès l'initialisation d'un client par le fichier update.conf. C'est donc dans ce fichier update.conf qui comme son nom l'indique, va nous permettre avant que le client execute son fichier local de configuration /var/cfengine/inputs/cfagent.conf de mettre à jour ce meme fichier cfagent.conf en fonction des modifications apportées à sa copie centralisée sur le serveur cfengine.

3.2  Distribution de la configuration

Afin d'eviter de ``scier la branche sur laquelle on est assis'' !, bref d'eviter par une erreure de syntaxe de casser le bon fonctionnement de cfengine et ainsi rendre incapables toutes les machines du parc de s'autocorriger, on va ditribuer les fichiers de configuration à partir d'une configuration cfengine tres simple et quasi immuable . C'est pour cela que le client cfagent lit et execute le fichier update.conf avant de se lancer sur (le vif du sujet !) cfagent.conf . De plus , pour rendre plus lisible et plus modulaire le fichiers de configuration cfagent.conf, ce dernier sera eclaté en sous fichiers spécifiques, le fichier cfagent.conf se chargant de faire un include (import) des sous fichiers. Sur le serveur, on créera un répertoire /var/cfengine/masterinputs qui contiendra le cfagent.conf et ses inclusions.

3.3  update.conf


[root@calaz /var/cfengine/inputs]
$ cat update.conf

#######
#
# BEGIN update.conf
#
# This script distributes the configuration, a simple file so that,
# if there are syntax errors in the main config, we can still
# distribute a correct configuration to the machines afterwards, even
# though the main config won't parse. It is read and run just before the
# main configuration is parsed.
#
#######

control:

 actionsequence  = ( copy tidy )  # Keep this simple and constant

 domain          = ( int-evry.fr )  # Needed for remote copy

 #
 # Which host/dir is the master for configuration roll-outs?
 #
 policyhost      = ( calaz.int-evry.fr )

# le répertoire masterinputs contient entre autre le cfagent.conf et toute ses inclusions

 masterinputs  = ( /var/cfengine/masterinputs )

 #
 # Some convenient variables
 #

 workdir         = ( /var/cfengine )
 cf_install_dir  = ( /var/cfengine/sbin )

 # Avoid server contention

 SplayTime = ( 5 )

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

 #
 # Make sure there is a local copy of the configuration and
 # the most important binaries in case we have no connectivity
 # e.g. for mobile stations or during DOS attacks
 #

copy:

# Tout le contenu du masterinputs ira dans $(workdir)/inputs

     $(masterinputs)            dest=$(workdir)/inputs
                                  r=inf
                                  mode=700
                                  type=binary
                                  exclude=*.lst
                                  exclude=*~
                                  exclude=#*
                                  server=$(policyhost)
#####################################################################

tidy:

     #
     # Cfexecd stores output in this directory.
     # Make sure we don't build up files and choke on our own words!
     #

     $(workdir)/outputs pattern=* age=7



L'objectif principal de ce fichier est donc qu'a chaque lancement du client cfagent l'ensemble des fichiers se trouvant dans le répertoire /var/cfengine/masterinputs du serveur soient copiés dans le répertoire /var/cfengine/inputs sur le client.
Pour information voici le contenu de masterinputs que nous distriburons.
[root@calaz /var/cfengine/masterinputs]
$ ls
cfagent.conf  cf.groups  cf.linux  cf.main  cfservd.conf  update.conf

4  Cle cfengine

Afin d'authentifier le serveur et les clients lors des echanges, les services cfservd et cfagent s'accordent sur un echange de clé. Il s'agit de créer la paire de clé pour chaque machine. Pour démonstration, sur le serveur on lance la commande cfkey ci-dessous. Les clients peuvent en faire autant. Ici notre package rpm cfengine contient un script /var/init.d/cfinit qui lance au premier boot d'une station fraichement installée cette commande cfkey.
[root@calaz /var/cfengine]
$ /var/cfengine/sbin/cfkey
Making a key pair for cfengine, please wait, this could take a minute...
Writing private key to /var/cfengine/ppkeys/localhost.priv
Writing public key to /var/cfengine/ppkeys/localhost.pub

5  Configuration du serveur cfservd

Lancement du serveur de fichier cfservd sur le serveur cfengine.
[root@calaz /var/cfengine]
$ /var/cfengine/sbin/cfservd -F -d 2
cfservd: Debug mode: running in foreground
AddClassToHeap(any)
....
Loaded /var/cfengine/ppkeys/localhost.priv
Loaded /var/cfengine/ppkeys/localhost.pub
New Parser Object::(BEGIN PARSING /var/cfengine/inputs/cfservd.conf)
Looking for an input file /var/cfengine/inputs/cfservd.conf
(No file /var/cfengine/inputs/cfservd.conf)
(END OF PARSING /var/cfengine/inputs/cfservd.conf)
Finished with /var/cfengine/inputs/cfservd.conf

On voit clairement qu'il manque le fichier de configuration cfservd.conf .

5.1  Définition du cfservd.conf


[root@calaz /var/cfengine/inputs]
$ cat cfservd.conf
#########################################################
#
# This is a cfd config file
#
control:
 
  domain = ( int-evry.fr )
# Autorisation de connexion depuis 2 reseaux IP
  AllowConnectionsFrom = ( 157.159.27.0/24 157.159.50.0/24 )
# Autorisation de connexion depuis un service cfengent lancé par root sur le client
  AllowUsers = ( root )
 
  any::
 
  ChecksumDatabase = ( /tmp/testDATABASEcache )
  IfElapsed = ( 1 )
  MaxConnections = ( 100 )
 
#########################################################
 
admit:   # or grant:

# Autorisation de transferts de fichiers du serveur vers les clients sur les reseaux ip suivants:

/var/cfengine/masterinputs 157.159.27.*
/var/cfengine/masterinputs 157.159.50.*
/var/cfengine/data 157.159.27.*
/var/cfengine/data 157.159.50.*

5.2  Lancement de cfservd


[root@calaz /var/cfengine/inputs]
$ /var/cfengine/sbin/cfservd -F -d 2

Loaded /var/cfengine/ppkeys/localhost.priv
Loaded /var/cfengine/ppkeys/localhost.pub
New Parser Object::(BEGIN PARSING /var/cfengine/inputs/cfservd.conf)
Looking for an input file /var/cfengine/inputs/cfservd.conf
# BEGIN PARSING /var/cfengine/inputs/cfservd.conf
Path: /var/cfengine/masterinputs (encrypt=0)
   Admit: 157.159.50.* root=
   Admit: 157.159.27.* root=
Path: /var/cfengine/data (encrypt=0)
   Admit: 157.159.50.* root=
   Admit: 157.159.27.* root=
ACCESS DENIAL ------------------------ :
 
Host IPs allowed connection access :
 
IP: 157.159.27.0/24
IP: 157.159.50.0/24

Bound to address :: on linux=6
Listening for connections ...
Checking file updates on /var/cfengine/inputs/cfservd.conf (4284bfe4/4284c008)

Effectivement le serveur c'est ``bindé'' en ipv6 ! sur le port cfengine (tcp:5308)
[root@calaz /var/cfengine/inputs]
$ lsof -i tcp | grep cfser
cfservd   14660    root    4u  IPv6 279008       TCP *:cfengine (LISTEN)

Le serveur cfengine est maintenant opérationnel, il écoute sur le port 5308 et s'apprete a recevoir des connexions depuis les reseaux ip 157.159.27.0/24 et 50.0/24 tels que demandé dans le fichier de configuration cfservd.conf

6  Firewall iptables

On viens de le voir, le serveur écoute sur le port 5308, il faut donc prévoir d'ouvrir son firewall en conséquance. Pour preuve, voici l'exemple de lancement d'un client (arvouin) sans ouverture du port en question:
[root@arvouin /var/cfengine/inputs]
$/var/cfengine/sbin/cfagent -q -v
....
Connect to calaz.int-evry.fr = 157.159.50.197 on port cfengine
cfengine:: Time out

Ouverture du port.
[root@calaz /var/cfengine]
$ grep 5308 /etc/sysconfig/iptables
-A RH-Firewall-1-INPUT -m state --state NEW -m tcp -p tcp --dport 5308 -j ACCEPT
[root@calaz /var/cfengine]
$ /etc/init.d/iptables restart

7  Client cfengine

7.1  Installation cfengine packagé sur le client


[root@arvouin /var]
$rpm -Uvh /root/cfengine-2.1.14-1_int_sample.i386.rpm
Préparation...              ########################################### [100%]
   1:cfengine               ########################################### [100%]

7.2  Cle serveur

La clé du serveur a bien été intégrée par le package:
[root@arvouin /var/cfengine]
$ls ppkeys/
root-157.159.50.197.pub

7.3  Fichiers de configuration

Pour le momment il n'y a rien, c'est au premier lancement de cfagent que l'update.conf assurera le transfert des fichiers de configuration depuis le serveur central.
[root@arvouin /var/cfengine/inputs]
$ls

7.4  Distribution initiale

Voici le contenu du répertoire principal apres l'installation du package RPM.
[root@arvouin /var/cfengine]
$ls -R
.:
bin  inputs  outputs  plugins  ppkeys  sbin  share
 
./bin:
cfagent
 
./inputs:
 
./outputs:
 
./plugins:
 
./ppkeys:
root-157.159.50.197.pub
 
./sbin:
cfagent  cfenvd      cfexecd  cfrun    cfshow
cfdoc    cfenvgraph  cfkey    cfservd  vicf
 
./share:
cfengine
 
./share/cfengine:
cfagent.conf-advanced.example  cf.main.example       cf.solaris.example
cfagent.conf.example           cf.motd.example       cf.sun4.example
cf.chflags.example             cf.preconf.example    cf.users.example
cfengine.el                    cfrc.example          ChangeLog
cf.freebsd.example             cfrun.hosts.example   INSTALL
cf.ftp.example                 cfservd.conf.example  NEWS
cf.groups.example              cf.services.example   README
cf.linux.example               cf.site.example       update.conf.example

7.5  Initialisation / Déploiement des fichiers sur le client

Afin que les fichiers de strategies soient deployés sur le client, il faut que ce dernier dispose d'une copie du fichier de distribution de ces fichiers -> le fichier update.conf evoqué auparavant lors de sa conception sur le serveur central de configuration cfengine.
Exemple de ditribution par simple copie manuelle, l'idéal étant d'integrer ce fichier dans le package RPM cfengine qui sera installé sur les clients.
[root@arvouin /var/cfengine]
$scp root@calaz:/var/cfengine/masterinputs/update.conf ./inputs/

7.6  Clé du client

Si on lance tout de suite un cfagent (-parse et -verbose ) on constate ceci:
[root@arvouin /var/cfengine/inputs]
$/var/cfengine/sbin/cfagent -p -v
Unable to detect environment from cfenvd
 
cfengine:: No preconfiguration file
 * (Changing context state to: update) *
Looking for an input file /var/cfengine/inputs/update.conf
Finished with update.conf
LogDirectory = /var/cfengine
cfengine:: Couldn't find a private key (/var/cfengine/ppkeys/localhost.priv) - use cfkey to get one
cfengine:: open: No such file or directory

En effet il manque la paire de clé sur le client. Pour la démonstration nous la générons ici manuellement. Dans le cadre d'un deploiement ``industriel'' on assurera la création automatique de cette clé par un script (dans notre RPM; cfinit) qui se chargera au premier boot de la station fraichement installée de lancer le cfkey).
[root@arvouin /var/cfengine/inputs]
$/var/cfengine/sbin/cfkey
Making a key pair for cfengine, please wait, this could take a minute...
Writing private key to /var/cfengine/ppkeys/localhost.priv
Writing public key to /var/cfengine/ppkeys/localhost.pub

7.7  Echange de clé entre client et serveur

Pour que la communication entre le client et le serveur cfengine se fasse, les deux machines s'authentifient mutuellement. Le client dispose de la clé publique du serveur avec laquelle il signe l'echange, ce sera au serveur cfengine de verifier cette signature avec sa clé privé. De meme le serveur doit disposer de la clé publique du client afin de proceder à la même verification en sens inverse . Ici le client dispose bien de la clé publique du serveur root-157.159.50.197.pub (distribuée par notre package RPM, sinon il faut faire un scp vers chaque clients ..)
[root@arvouin /var/cfengine/ppkeys]
$/var/cfengine/sbin/cfagent  -q -v
Checking copy from calaz.int-evry.fr:/var/cfengine/masterinputs to /var/cfengine/inputs
Connect to calaz.int-evry.fr = 157.159.50.197 on port cfengine
Updating last-seen time for calaz.int-evry.fr
Loaded /var/cfengine/ppkeys/root-157.159.50.197.pub
cfengine:: BAD: key could not be accepted on trust
cfengine:: Authentication dialogue with calaz.int-evry.fr failed
cfengine:: Unable to establish connection with calaz.int-evry.fr (failover)

En revanche, le serveur ne dispose pas encore de la clé publique de ce client !.

7.7.1  Echange manuel

Nous pouvons proceder à un transfert manuelle de la clé du client vers le serveur :
[root@arvouin /var/cfengine/ppkeys]
$scp localhost.pub root@calaz:/var/cfengine/ppkeys/root-157.159.27.199.pub
root@calaz's password:
localhost.pub                                 100%  426     1.1MB/s   00:00

Mais cela n'est pas tres industrialisable !

7.7.2  Echange automatique de confiance

On peux autrement déclarer dans le fichier de configuration du serveur cfservd que l'on accepte de recevoir des clé publiques des machines que nous allons gerer (exemple ici le sous reseau 157.159.50.27.0/24 )
$ grep Trust /var/cfengine/inputs/cfservd.conf
  TrustKeysFrom = ( 157.159.27.0/24 )

Relancer cfservd :
[root@calaz /var/cfengine/outputs]
$ /var/cfengine/sbin/cfservd -F -d 2
Host IPs from whom we shall accept public keys on trust :
 
IP: 157.159.27.0/24

Répertoire des cles sur le serveur avant le lancement du client:
[root@calaz /var/cfengine/ppkeys]
$ ls
localhost.priv  localhost.pub  root-157.159.50.197.pub

Lancement du client
[root@arvouin /var/cfengine/inputs]
$/var/cfengine/sbin/cfagent -q -v

cfservd -F -d 2 sur calaz signal:

Received: [CAUTH 157.159.27.199 arvouin.int-evry.fr root 0] on socket 5
Connecting host identifies itself as 157.159.27.199 arvouin.int-evry.fr root 0
(ipstring=[157.159.27.199],fqname=[arvouin.int-evry.fr],username=[root],socket=[::ffff:157.159.27.199])
cfservd: Allowing 157.159.27.199 to connect without (re)checking ID
Non-verified Host ID is arvouin.int-evry.fr (Using skipverify)
Non-verified User ID seems to be root (Using skipverify)
Havekey(root-157.159.27.199)
Did not have key root-157.159.27.199
cfservd: Weak authentication of trusted client arvouin.int-evry.fr/::ffff:157.159.27.199 (key accepted on trust).

Répertoire de clés sur le serveur apres le lancement du client:
[root@calaz /var/cfengine/ppkeys]
$ ls
localhost.priv  localhost.pub  root-157.159.27.199.pub  root-157.159.50.197.pub

On y retrouve bien le clé du client root-157.159.27.199.pub .

7.8  Deploiement effectif initial

Maintenant que tout est correctement configuré, nous pouvons relancer l'agent avec succes:
[root@arvouin /var/cfengine/ppkeys]
$/var/cfengine/sbin/cfagent  -q -v
Setting cfengine new port to 5308
Setting cfengine old port to 5308
Reference time set to Fri May 13 17:06:24 2005
GNU Configuration Engine -
2.1.14
Loaded /var/cfengine/ppkeys/localhost.priv
Loaded /var/cfengine/ppkeys/localhost.pub
Checksum database is /var/cfengine/checksum.db
Checking copy from calaz.int-evry.fr:/var/cfengine/masterinputs to /var/cfengine/inputs
Connect to calaz.int-evry.fr = 157.159.50.197 on port cfengine
Updating last-seen time for calaz.int-evry.fr
Loaded /var/cfengine/ppkeys/root-157.159.50.197.pub
cfengine:: Strong authentication of server=calaz.int-evry.fr connection confirmed
cfengine:: /var/cfengine/inputs/cf.main wasn't at destination (copying)
cfengine:: Copying from calaz.int-evry.fr:/var/cfengine/masterinputs/cf.main
cfengine:: Object /var/cfengine/inputs/cf.main had permission 600, changed it to 700
cfengine:: /var/cfengine/inputs/cf.linux wasn't at destination (copying)
cfengine:: Copying from calaz.int-evry.fr:/var/cfengine/masterinputs/cf.linux
cfengine:: Object /var/cfengine/inputs/cf.linux had permission 600, changed it to 700
cfengine:: /var/cfengine/inputs/cfagent.conf wasn't at destination (copying)
cfengine:: Copying from calaz.int-evry.fr:/var/cfengine/masterinputs/cfagent.conf
cfengine:: Object /var/cfengine/inputs/cfagent.conf had permission 600, changed it to 700
cfengine:: /var/cfengine/inputs/cf.groups wasn't at destination (copying)
cfengine:: Copying from calaz.int-evry.fr:/var/cfengine/masterinputs/cf.groups
cfengine:: Object /var/cfengine/inputs/cf.groups had permission 600, changed it to 700
cfengine:: /var/cfengine/inputs/cfservd.conf wasn't at destination (copying)
cfengine:: Copying from calaz.int-evry.fr:/var/cfengine/masterinputs/cfservd.conf
cfengine:: Object /var/cfengine/inputs/cfservd.conf had permission 600, changed it to 700
cfengine:: Update of image /var/cfengine/inputs/update.conf from master /var/cfengine/masterinputs/update.conf on calaz.int-evry.fr
cfengine:: Object /var/cfengine/inputs/update.conf had permission 600, changed it to 700
Checking copy from calaz.int-evry.fr:/var/cfengine/masterinputs/cfservd.conf to /var/cfengine/inputs
cfengine:: image exists but destination type is silly (file/dir/link doesn't match)
cfengine:: source=/var/cfengine/masterinputs/cfservd.conf, dest=/var/cfengine/inputs
Saving the setuid log in /var/cfengine/cfagent.arvouin.int-evry.fr.log

La copie des fichiers réalisés par update.conf a bien eu lieu . Cfagent poursuis sur le vif du sujet , l'excution du cfagent.conf local fraichement mis à jour par l'update.conf !:

 * (Changing context state to: main) *

#Execution du cfagent.conf ...

Looking for an input file /var/cfengine/inputs/cfagent.conf
Looking for an input file cf.groups
Looking for an input file cf.main
Looking for an input file cf.linux
Finished with cfagent.conf

Main Tree Sched: copy pass 1 @ Fri May 13 17:06:27 2005
*********************************************************************

Checking file(s) in /etc/passwd
cfengine:arvouin: File /etc/passwd was not in database - new file found
Checking file(s) in /etc/shadow
cfengine:arvouin: File /etc/shadow was not in database - new file found

 Main Tree Sched: editfiles pass 1 @ Fri May 13 17:06:28 2005
*********************************************************************
 
Begin editing /etc/inittab
End editing /etc/inittab

 Main Tree Sched: shellcommands pass 1 @ Fri May 13 17:06:28 2005
*********************************************************************
 
cfengine:arvouin: Executing script /bin/echo shellcommands de cf.main !...(timeout=0,uid=-1,gid=-1)
(Setting umask to 77)
cfengine:arvouin:/bin/echo shell: shellcommands de cf.main !
cfengine:arvouin: Finished script /bin/echo shellcommands de cf.main !

 Main Tree Sched: links pass 1 @ Fri May 13 17:06:28 2005
*********************************************************************
 
cfengine:arvouin: Linking files /usr/local/bin/tcsh -> /bin/tcsh
cfengine:arvouin: Linking files /usr/local/bin/bash -> /bin/bash

La strategie de configuration cliente c'est donc executée dans la foulée ... nous y reviendrons apres .

Verification de la présence des fichiers de source masterinputs du serveur sur la destination inputs sur le client:
[root@arvouin /var/cfengine/ppkeys]
$ls ../inputs/
cfagent.conf  cf.linux  cfservd.conf  update.conf.cfsaved
cf.groups     cf.main   update.conf

Remarque; la version anterieur d'un fichier déjà présent et renomée en .cfsaved

8  Exemple pratique de strategie

Nous montrons ici le début d'un configuration plus industrielle avec quelques exemples stratégiques.

8.1  Fichier cfagent.conf

Nous éclatons le fichier cfagent.conf en sous éléments par le biais le l'import des sous fichiers.
$ cat cfagent.conf
##################################################
#  cfagent.conf
##################################################
import:
# split things up to keep things tidy
        any::
                cf.groups
                cf.main
 
        linux::
                cf.linux

8.2  Classes de machines

Le premier fichier importé est cf.goups qui comprend la liste des classes de machines:
[root@calaz /var/cfengine/masterinputs]
$ cat cf.groups
#Fichier de definition des groupes/class
groups:
 
# machines unix du service s2ia
s2iaunix = ( calaz arvouin )
 
# machines windows du service s2ia
s2iawindows = ( pat4784 )
 
#classe s2ia -> toutes les machines du service s2ia
s2ia = ( s2iaunix s2iawindows )
 
# strategie de site linux
autoconfigMozilla = ( arvouin )
logoint = ( arvouin )

8.3  Configuration générale

Le fichier cf.main contient les définitions et taches (strategies) générales valables pour toutes les machines présentes et futures du parc à gerer. Seules les actions à mener propres à cet exemple sont commentées dans le fichier, pour les directives et variables cfengine, voir la documentation de référence.
[root@calaz /var/cfengine/masterinputs]
$ cat cf.main
##################################################
#  cf.main
##################################################
############# Control
control:
 
   EditfileSize = ( 70000 )
   moduledirectory = ( /var/cfengine/plugins )
   AddInstallable = ( restartgdm )
   addclasses = ( noboot )
   actionsequence = ( files directories copy editfiles shellcommands links tidy processes )
   domain         = ( int-evry.fr )
   timezone       = ( MET )
   smtpserver     = ( smtp-int.int-evry.fr )  # used by cfexecd
   sysadm         = ( root@calaz.int-evry.fr )     # where to mail output

# nous modifierons le fichier inittab, une veriable contient son chemin absolu
   inittab   = ( /etc/inittab )
# nous allons copier un fichier d'autoconfiguration de mozilla dans $MOZILA_HOME, ce chemin depend de la version mozilla installée, le nom du package sur le client permet de definir ce chemin qui sera /usr/lib/$mozilladir/
   mozilladir = ( ExecResult(/bin/rpm -q --queryformat "%{VERSION}" mozilla) )

# Definition de chemin absolue pour les machines linux 
   linux::
        grubconfigfile  = ( /etc/grub.conf )
        gdmconffile     = ( /etc/X11/gdm/gdm.conf )
######################################################################
resolve:
   # Add these name servers to the /etc/resolv.conf file
     157.159.10.12      # local nameserver
     157.159.10.13     # backup nameserver
 
######################################################################
copy:
# modification du prompt ($PS1=''[\u@\h \w]\n$'') par la copie du fichier system bashrc
        any::
        /var/cfengine/data/bashrc dest=/etc/bashrc mode=0644 server=calaz
 
######################################################################
 
shellcommands:

# un simpe test de commande shell -> envoie d'un echo
   any::
        "/bin/echo shellcommands de cf.main !"

######################################################################
links:

# Création de liens
       s2iaunix::
  
       /usr/local/bin/tcsh    -> /bin/tcsh
       /usr/local/bin/bash    -> /bin/bash
 
######################################################################
processes:

# action a mener sur des processus
 
   restartgdm::
       "gdm"   signal=hup
 
   any::
        "nscd"
        restart "/sbin/chkconfig --level 345 nscd on ; /etc/init.d/nscd restart" 
##########################EDITFILES
editfiles: 
        any::
# Edition du inittab -> desactivation des consoles text sur CRTL+ALT+F[3-6]
                                                                               
      { $(inittab)
       DeleteLinesMatching "[3-6]:2345:respawn:/sbin/mingetty tty[3-6]"
     }
 
################## Files
files:
# verifications sur le fichier password                                                                               
   /etc/passwd
         mode=644        # make sure the file permissions are right
         owner=root      # make sure it's owned by root
         action=fixall   # if anything is wrong, fix it immediately!
         checksum=md5    # keep a "tripwire" checksum to tell us
                         # if any changes occur here
                                                                                
   /etc/shadow mode=600 owner=root action=fixall checksum=md5                                                           
   /var/cfengine/checksum.db  mode=600 owner=root action=fixall

8.4  Configuration propre aux machines linux

Exemple de fichier de configuration propre aux machines linux:
[root@calaz /var/cfengine/masterinputs]
$ cat cf.linux
# cfagent file for linux stations
copy:
# copie du fichier d'autoconfiguration mozilla dans $MOZILLA_HOME = variable $mozilladir du cf.main
        autoconfigMozilla::
        /var/cfengine/data/mozilla.cfg   dest=/usr/lib/mozilla-$(mozilladir)/mozilla.cfg mod=644 server=calaz
 
# gestion d'un logo perso à la connexion GDM, copie récursive de l'arborescence INT_theme
        logoint::         /var/cfengine/data/fedora-3/INT_theme dest=/usr/share/gdm/themes/INT_theme server=calaz recurse=inf
 
##################################
editfiles:
 
# edition du gdm.conf afin d'y integrer notre logo copié ci-dessus
        logoint::
        { $(gdmconffile)
        BeginGroupIfNoSuchLine "GraphicalTheme=INT_theme"
        LocateLineMatching "GraphicalTheme=Bluecurve"
        ReplaceLineWith "GraphicalTheme=INT_theme"
        EndGroup
        DefineClasses "restartgdm"
        }
 
##################
shellcommands:

# a minuit et 20H , on lance une mise a jour systeme (yum update)
        Hr0|Hr20::
        "/bin/nice -n 20 /usr/bin/yum -y -d 2 update > /tmp/yum 2>&1"


8.5  Fichier sources du serveur

Les differents fichiers et dossiers évoqués dans les stratégies ci-dessus sont stockés sur le serveur cfengine /var/cfengine/data :
$ mkdir /var/cfengine/data
$ mkdir /var/cfengine/data/fedora-3/
[root@calaz /var/cfengine/data]
$ cp /etc/bashrc
[root@calaz /var/cfengine/data]
$ vi mozilla.cfg
[root@crotale /var/cfengine/data/fedora-3]
$ scp -r INT_theme root@calaz:/var/cfengine/data/fedora-3

[root@calaz /var/cfengine/data]
$ ls
bashrc  fedora-3  mozilla.cfg

8.6  Lancement du client


[root@arvouin /var/cfengine/ppkeys]
$/var/cfengine/sbin/cfagent  -q -v

$/var/cfengine/sbin/cfagent -q -v
Setting cfengine new port to 5308
Setting cfengine old port to 5308
Reference time set to Fri May 13 18:40:26 2005

$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
 * (Changing context state to: update) *
$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
 
Looking for an input file /var/cfengine/inputs/update.conf
Finished with update.conf
*********************************************************************
 Update Sched: copy pass 1 @ Fri May 13 18:40:26 2005
*********************************************************************
 
Checking copy from calaz.int-evry.fr:/var/cfengine/masterinputs to /var/cfengine/inputs
Connect to calaz.int-evry.fr = 157.159.50.197 on port cfengine
Updating last-seen time for calaz.int-evry.fr
Loaded /var/cfengine/ppkeys/root-157.159.50.197.pub

$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
 * (Changing context state to: main) *
$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$

Looking for an input file /var/cfengine/inputs/cfagent.conf
Looking for an input file cf.groups
Looking for an input file cf.main
Looking for an input file cf.linux
Finished with cfagent.conf

*********************************************************************
 Main Tree Sched: files pass 1 @ Fri May 13 18:40:28 2005
*********************************************************************
 
Checking file(s) in /etc/passwd
Checking file(s) in /etc/shadow
Checking file(s) in /var/cfengine/checksum.db
Saving the setuid log in /var/cfengine/cfagent.arvouin.int-evry.fr.log

*********************************************************************
 Main Tree Sched: copy pass 1 @ Fri May 13 18:40:29 2005
*********************************************************************
 
Checking copy from calaz:/var/cfengine/data/bashrc to /etc/bashrc
Connect to calaz = 157.159.50.197 on port cfengine
Updating last-seen time for calaz
Loaded /var/cfengine/ppkeys/root-157.159.50.197.pub

cfengine:arvouin: Strong authentication of server=calaz connection confirmed
Checking copy from calaz:/var/cfengine/data/mozilla.cfg to /usr/lib/mozilla-1.7.6/mozilla.cfg
cfengine:arvouin: /usr/lib/mozilla-1.7.6/mozilla.cfg wasn't at destination (copying)
cfengine:arvouin: Copying from calaz:/var/cfengine/data/mozilla.cfg
cfengine:arvouin: Object /usr/lib/mozilla-1.7.6/mozilla.cfg had permission 600, changed it to 644
Checking copy from calaz:/var/cfengine/data/fedora-3/INT_theme to /usr/share/gdm/themes/INT_theme
Saving the setuid log in /var/cfengine/cfagent.arvouin.int-evry.fr.log
 
*********************************************************************
 Main Tree Sched: editfiles pass 1 @ Fri May 13 18:40:30 2005
*********************************************************************
 
Begin editing /etc/inittab
Deleted item 3:2345:respawn:/sbin/mingetty tty3
Deleted item 4:2345:respawn:/sbin/mingetty tty4
Deleted item 5:2345:respawn:/sbin/mingetty tty5
Deleted item 6:2345:respawn:/sbin/mingetty tty6
End editing /etc/inittab
.....................................................................
cfengine:arvouin: Saving edit changes to file /etc/inittab
Begin editing /etc/X11/gdm/gdm.conf
(Begin Group - skipping, line exists)
End editing /etc/X11/gdm/gdm.conf
.....................................................................
 
*********************************************************************
 Main Tree Sched: shellcommands pass 1 @ Fri May 13 18:40:30 2005
*********************************************************************
 
cfengine:arvouin: Executing script /bin/echo shellcommands de cf.main !...(timeout=0,uid=-1,gid=-1)
(Setting umask to 77)
cfengine:arvouin:/bin/echo shell: shellcommands de cf.main !
cfengine:arvouin: Finished script /bin/echo shellcommands de cf.main !
 
*********************************************************************
 Main Tree Sched: links pass 1 @ Fri May 13 18:40:30 2005
*********************************************************************
 
cfengine:arvouin: Linking files /usr/local/bin/tcsh -> /bin/tcsh
cfengine:arvouin: Linking files /usr/local/bin/bash -> /bin/bash

*********************************************************************
 Main Tree Sched: processes pass 1 @ Fri May 13 18:40:30 2005
*********************************************************************
 
cfengine:arvouin: Running process command /bin/ps auxw
Defining classes
DoSignals(nscd)
Existing restart sequence found (/sbin/chkconfig --level 345 nscd on ; /etc/init.d/nscd restart)
cfengine:arvouin: Matches found for nscd - no restart sequence

Toutes les opérations se sont réalisées comme prevu .

9  Package RPM maison de cfengine

Voici un exemple de fichier de spec de construction du package cfengine, à partir du tar.gz, il apporte en valeur ajoutée la clé du serveur, les scripts de demarrage (cfengine, cfinit, cron cfengine), la construction de l'aborescence (faite aussi par cfexec ..) l'update.conf initial, eventuellement des pluggins etc .... Cela permet d'industrialiser le deploiement cfengine sur les clients dès leur installation par kickstart.
Pour les details de contruction de packages RPM voir:
http://www.freenix.fr/unix/linux/HOWTO/RPM-HOWTO-6.html
http://www.rpm.org/RPM-HOWTO/build.html
[root@calaz /usr/src/redhat/SPECS]
$ cat cfengine.spec
Summary: cfengine helps set up and maintain BSD and System-5-like systems
Name: cfengine
Version: 2.1.14
Release: 1_int_sample
Copyright: GPL
Group: Utilities/System
Source0: ftp://ftp.iu.hioslo.no/pub/%{name}-%{version}.tar.gz
Source1: %{name}.rc.init
Source2: localhost.pub
Source7: cfengine.cron
Source4: cfinit
BuildRoot: /tmp/%{name}-%{version}
Requires: dialog
%define ipserver 157.159.50.197

%description
Cfengine is a tool for setting up and maintaining BSD and System-5-like
operating systems optionally attached to a TCP/IP network.  You can think
of cfengine as a very high level language---much higher level than Perl
or shell: a single statement can result in many hundreds of operations
being performed on multiple hosts. Cfengine is good at performing a lot
of common system administration tasks, and allows you to build on its
strengths with your own scripts. You can also use it as a netwide
front-end for cron.  Once you have set up cfengine, you'll be
free to use your time being like a human being, instead of playing R2-D2
with the system.

%prep
%setup
cp -p $RPM_SOURCE_DIR/%{name}.rc.init .

%build
./configure --with-berkeleydb=/usr
make

%install
rm -rf $RPM_BUILD_ROOT
mkdir -p $RPM_BUILD_ROOT/usr/info
mkdir -p $RPM_BUILD_ROOT/etc/init.d
mkdir -p $RPM_BUILD_ROOT/etc/cron.d
mkdir -p $RPM_BUILD_ROOT/var/cfengine/inputs
mkdir -p $RPM_BUILD_ROOT/var/cfengine/outputs
mkdir -p -m 700 $RPM_BUILD_ROOT/var/cfengine/ppkeys
mkdir -p $RPM_BUILD_ROOT/var/cfengine/plugins
mkdir -p $RPM_BUILD_ROOT/var/cfengine/bin
make prefix=$RPM_BUILD_ROOT/var/cfengine install
cd doc
make prefix=$RPM_BUILD_ROOT/usr/share install-man
cd ..

#Copie de la clée public du serveur
cp $RPM_SOURCE_DIR/localhost.pub $RPM_BUILD_ROOT/var/cfengine/ppkeys/root-%{ipserver}.pub
#Copie des scripts de lancement.
cp $RPM_SOURCE_DIR/cfengine.cron $RPM_BUILD_ROOT/etc/cron.d/cfengine
install -m 755 $RPM_SOURCE_DIR/cfinit $RPM_BUILD_ROOT/etc/init.d
install -m 755 $RPM_SOURCE_DIR/%{name}.rc.init $RPM_BUILD_ROOT/etc/init.d/cfengine
cd $RPM_BUILD_ROOT/var/cfengine/bin/
ln -s ../sbin/cfagent  cfagent

%post
/sbin/chkconfig --add cfinit
/sbin/chkconfig --add cfengine

%clean
#rm -rf $RPM_BUILD_ROOT

%files
%defattr(-,root,root)
/usr/share/man/man8/cfengine.8.gz
/usr/share/man/man8/cfagent.8.gz
/usr/share/man/man8/cfenvd.8.gz
/usr/share/man/man8/cfshow.8.gz
/usr/share/man/man8/cfenvgraph.8.gz
/usr/share/man/man8/cfexecd.8.gz
/usr/share/man/man8/cfrun.8.gz
/usr/share/man/man8/cfkey.8.gz
/usr/share/man/man8/cfservd.8.gz
/var/cfengine
/etc/init.d/cfinit
/etc/init.d/cfengine
/etc/cron.d/cfengine
%doc AUTHORS ChangeLog COPYING INSTALL README NEWS TODO
%doc doc/ contrib/

%changelog
* Wed May 11 2005 Jehan Procaccia <jehan.procaccia@int-evry.fr> 2.1.14-1_int_sample
- test de conf cfengine initiale pour doc

* Fri Apr 29 2005 Jehan Procaccia <jehan.procaccia@int-evry.fr> 2.1.14-1
- update to 2.1.14

* Fri Feb 11 2005 Eric Doutreleau <Eric.Doutreleau@int-evry.fr> 2.1.13-1
- update to 2.1.13
- Ajout du module kernelclean

* Mon Feb 16 2004 Jehan Procaccia <jehan.procaccia@int-evry.fr> 2.1.3-5
- changed cfinit to wait 1mn for autorpm pb
- addapted module:hardware for another nvidia chipset

* Thu Feb 12 2004 Jehan Procaccia <jehan.procaccia@int-evry.fr> 2.1.3-4
- upgraded to 2.1.3
- added module:hardware

* Thu Oct 30 2003 Eric Doutreleau <Eric.Doutreleau@int-evry.fr> 2.0.8p1-3
- Added dialog message on cfinit

* Wed Sep 24 2003 Jehan Procaccia <jehan.procaccia@int-evry.fr> 2.0.8p1-1
- chmod 700 on ppkeys directory

* Wed Sep 24 2003 Jehan Procaccia <jehan.procaccia@int-evry.fr> 2.0.8p1-1
- upgraded to 2.0.8p1

* Thu Aug  3 2000 Ian Macdonald <ian@caliban.org>
- strip binaries

* Sat Jul 27 2000 Ian Macdonald <ian@caliban.org>
- 1.5.4 packaged as RPM

10  Configurations évoluées

Exemple de configurations évoluée (en cours d'écriture ....)

10.1  Gestion des packages

Plutot que de faire une installation de logiciels à partir de shellcommands lançants rpm ou yum etc ... depuis la version 2.1 de cfengine il est possible d'utiliser la directive package:

http://www.cfengine.org/docs/cfengine-Reference.html#packages

Exemple d'utilisation.
control:

 fedora::
actionsequence = ( files directories copy editfiles packages shellcommands links tidy processes )
 RPMInstallCommand = ( "/usr/bin/yum -y install %s" )

groups:
   logcommun2 = ( s2iaunix )

packages:

        logcommun2::
        RealPlayer pkgmgr=rpm action=install
        scilab pkgmgr=rpm action=install

10.2  Pluggins maison

... à continuer ...


Ce document a été traduit de LATEX par HEVEA.