Archives de catégorie : Automation

CFengine3

Installation

Install effectuée sur Debian 8.2 Jessie et avec CFengine3.6

Installation du paquet cfengine3

apt-get install cfengine3

Vérification de la bonne génération de la clé

cf-key

A key file already exists at /var/lib/cfengine3/ppkeys/localhost.pub

Ceci est déjà fait par le paquet.

Attachement de l’agent sur le serveur policy

cf-agent --bootstrap 192.168.21.156

Résulat :

R: This host assumes the role of policy server
R: Updated local policy from policy server
R: Started the server
R: Started the scheduler
2015-09-25T15:24:10+0200   notice: Bootstrap to '192.168.21.156' completed successfully!

Vérification du lancement correct

ps aux
 root       672  0.0  1.2  46420  6184 ?        Ss   15:24   0:00 /var/lib/cfengine3/bin/cf-execd
 root       678  0.0  1.4  50128  7152 ?        Ss   15:24   0:00 /var/lib/cfengine3/bin/cf-serverd
 root       690  0.0  1.7  49992  8956 ?        Ss   15:24   0:00 /var/lib/cfengine3/bin/cf-monitord

Configuration

Démarrage du cf-servd au boot système

modification de /etc/default/cfengine3

RUN_CFMONITORD=0
RUN_CFSERVERD=0
RUN_CFEXECD=1

modification de /etc/init.d/cfengine3

# defaults

RUN_CFMONITORD=0
RUN_CFEXECD=1
RUN_CFSERVERD=0

Ajout au boot

insserv cfengine3
systemctl enable cfengine3

Suite à la modification de l’init script

systemctl daemon-reload

Redémarrage pour vérification

reboot
root       832  0.0  0.9  46592  4844 ?        Ss   17:32   0:00 /usr/sbin/cf-execd

Test du reboot : OK

cf-execd est l’ordonnanceur, il lancera les autres processus de CFengine suivant les besoins.

Journaux & Arborescence

/etc/defaults/cfengine3        fichier de configuration démarrage
/etc/init.d/cfengine3          script de démarrage
/var/lib/cfengine3/masterfiles configuration to push client
/var/lib/cfengine3/inputs      configuration globale
/var/lib/cfengine3             Install dir
/var/log/cfengine3             Logs

/usr/share/cfengine3/masterfiles fichiers d’exemple copier et intégré dans /var/lib/cfengine3/masterfiles par l’installeur dpkg

Installation des agents

Installation du paquet cfengine3

apt-get install cfengine3 

Configuration

Lancement au boot du serveur.

Modification /etc/default/cfengine3

RUN_CFMONITORD=0
RUN_CFEXECD=1
RUN_CFSERVERD=0

modification /etc/init.d/cfengine3

RUN_CFMONITORD=0
RUN_CFEXECD=1
RUN_CFSERVERD=0

Attachement de l’agent avec le serveur de policy

cf-agent -B 192.168.21.156

Vérification OK rôle Client.

R: This autonomous node assumes the role of voluntary client
R: Updated local policy from policy server
R: Started the scheduler
2015-09-25T17:47:01+0200   notice: Bootstrap to '192.168.21.156' completed successfully!

Journaux

/etc/defaults/cfengine3        fichier de configuration démarrage
/etc/init.d/cfengine3          script de démarrage
/var/lib/cfengine3/inputs      configuration globale
/var/lib/cfengine3             Install dir
/var/log/cfengine3             Logs
/var/lib/cfengine3/outputs/previous  dernier run de l'agent

Test des Configurations

Afin de tester les configurations précédentes faire sur le Serveur :

cf-agent -x
self-diagnostics for agent using workdir '/var/lib/cfengine3'
self-diagnostics for agent using inputdir '/var/lib/cfengine3/inputs'
self-diagnostics for agent using logdir '/var/log/cfengine3'
[ YES ] Check that agent is bootstrapped: 192.168.21.156
[ YES ] Check if agent is acting as a policy server: Acting as a policy server
[ YES ] Check private key: OK at '/var/lib/cfengine3/ppkeys/localhost.priv'
[ YES ] Check public key: OK at '/var/lib/cfengine3/ppkeys/localhost.pub'
...

Sur le client :

self-diagnostics for agent using workdir '/var/lib/cfengine3'
self-diagnostics for agent using inputdir '/var/lib/cfengine3/inputs'
self-diagnostics for agent using logdir '/var/log/cfengine3'
[ YES ] Check that agent is bootstrapped: 192.168.21.156
[ NO  ] Check if agent is acting as a policy server: Not acting as a policy server
[ YES ] Check private key: OK at '/var/lib/cfengine3/ppkeys/localhost.priv'
[ YES ] Check public key: OK at '/var/lib/cfengine3/ppkeys/localhost.pub'

Test d’une promesse non distribuée au client

Dans un fichier nommé test.cf par exemple

body common control  
{
bundlesequence => { "test" };
}

bundle agent test
{
reports:
  cfengine_3::
      "Hello world!";
}

test :

cf-agent test.cf

R: Hello world!

Promesses distribuées

Création d’une promesse dans le but de la diffuser à tous les cfengine3 et qui crée un fichier dans /root

dans/var/lib/cfengine3/masterfiles

Création du fichier mypolicy.cf

bundle agent test_file
{
files:
   cfengine_3::      

       "/root/test_cf.txt"  
       create => "true";       
}

Dans /var/lib/cfengine3/masterfiles

modifier promises.cf

 bundlesequence => {
                        # Common bundle first (Best Practice)
                          inventory_control,
                          @(inventory.bundles),
                          ha_def,
                          def,
                          cfe_internal_hub_vars,
                          test_file,                       # ici 

 inputs => {
                 # File definition for global variables and classes
                  "cfe_internal/ha/ha_def.cf",
                  "def.cf",
                  "mypolicy.cf",                          # et là

Validation des promesses

cf-promises -f /var/lib/cfengine3/masterfiles/promises.cf

Mise à jour des promesses du masterfiles vers input

cf-agent /var/lib/cfengine3/masterfiles/update.cf

Test en dry run

cf-agent -KIn

Lancer les modifications

cf-agent -KI

Résultat :

root@CFengine-01:~# ls
test_cf.txt

Suppression du fichier et remise en place par Cfengine : OK

Rédaction de promesses

exemple : modifier les valeurs dans sysctl.conf

net.ipv4.conf.default.rp_filter=1
net.ipv4.conf.all.rp_filter=1
net.ipv4.conf.all.accept_redirects = 0
net.ipv6.conf.all.accept_redirects = 0
net.ipv4.conf.all.send_redirects = 0
net.ipv4.conf.all.accept_source_route = 0
net.ipv6.conf.all.accept_source_route = 0
net.ipv6.conf.all.disable_ipv6 = 1

Création de la promesse

Dans /var/lib/cfengine3/masterfiles/sysctl.cf

bundle agent configfiles
{
	vars:
		"files[sysctl]" string => "/etc/sysctl.conf";
		"sysctl[net.ipv4.conf.default.rp_filter]" string => "1";
		"sysctl[net.ipv4.conf.all.rp_filter]" string => "1";
		"sysctl[net.ipv4.conf.all.accept_redirects]" string => "0";
		"sysctl[net.ipv6.conf.all.disable_ipv6]" string => "1";
                "sysctl[net.ipv4.conf.all.send_redirects]" string => "0";
		"sysctl[net.ipv4.conf.all.accept_source_route]" string => "0";
		"sysctl[net.ipv6.conf.all.disable_ipv6]" string => "1";
	methods:
		"sysctl" usebundle => edit_sysctl,
		comment => "Configuration de  $(files[sysctl])";
}

bundle agent edit_sysctl
{
	files:
		"$(configfiles.files[sysctl])"
		handle => "edit_sysctl",
		comment => "Application des protection de base pour sysctl.conf",
		create => "true",
		edit_line => set_variable_values("configfiles.sysctl"),
		classes => if_repaired("sysctl_modified");

	commands:
		sysctl_modified.!no_restarts::
		"/sbin/sysctl -p"
		handle => "reload_sysctl",
		comment => "Application des modifications si besoin";

Ajout dans /var/lib/cfengine3/masterfiles/promises.cf

bundlesequence => {
+++ configfiles,
}

inputs => {
+++ "sysctl.cf",
}

Validation des promesses

cf-promises -f /var/lib/cfengine3/masterfiles/promises.cf

Mise à jour de la promesse pour la distribution

cf-agent update.cf

Le but est de faire appliquer à CFengine des règles suivant le type de machine.

Environnement multiples

Afin d’émuler la réalité on utilisera 4 VMs

cfengine-01.lan   192.168.21.156
client-dev.lan    192.168.21.152
client-pprod.lan  192.168.21.119
client-prod.lan   192.168.21.142

Le nommage des vm est ici important car la bonne application des promesses en dépend. Mais on verra que l’on peut s’en affranchir.

Note : les codes suivants s’appliquent pour la version 3.6.2 de CFengine.

afin de placer les hostnames correctement éditer les fichiers :

/etc/hosts

127.0.0.1	localhost
127.0.1.1	client-dev.lan

et /etc/hostname

client-dev.lan

Répéter l’opération avec les noms choisi sur les 3 VM clientes.

Ensuite lancer cfengine

sur le serveur en premier

cf-agent --bootstrap 192.168.21.156

Sur les clients ensuite.

Configuration de l’environnement de déploiement des promesses

Sur le serveur CFengine, création des dossier suivants :

dans /var/lib/cfengine/masterfiles

mkdir environment_dev environment_prod environment_pprod environment_none

Dans chacun d’eux placer un fichier vide nommé env_promises.cf nous l’utiliserons ensuite.

touch env_promises.cf

On a donc

environment_dev
    env_promises.cf
environment_none
    env_promises.cf
environment_pprod
    env_promises.cf
environment_prod
    env_promises.cf
    

Dans le fichier masterfiles/promises.cf

Ajouter

bundle common environments
{
        classes:
          "environment_dev"  or =>  { classmatch(".*dev_lan"), };

          "environment_pprod" or => { classmatch(".*pprod_lan"), };

          "environment_prod" or  => { classmatch(".*prod_lan"), };

        vars:
          any::
		"groupe" string => "none", policy => "overridable";
            environment_prod::
                "groupe" string => "prod", policy => "overridable";
            environment_pprod::
                "groupe" string => "pprod", policy => "overridable";
            environment_dev::
                "groupe" string => "dev", policy => "overridable";
}

Explications :

classmath a été gardé dans une liste même si il est seul car on peut aisément rajouter des choses du genre

{
classmatch(".*dev_lan"),
"ipv4_192_168_21_66",
"debian_8",
};

Ainsi le or permet de définir la classe si une seule des valeur est vraie. Attention si des valeurs voisines sont choisis dans la définition de la classe c’est la plus spécifique qui match et défini ainsi la variable $groupe.

Overridable permet de modifier la classe ultérieurement dans un autre bundle afin d’affiner le déploiement.

Permet de ne pas générer d’erreur sur le serveur car il est exclu des promesses.

"groupe" string => "none", policy => "overridable";

Source de non validation des règles. You’ve been warned.

Ensuite toujours dans masterfiles\promises.cf

Ajouter dans la section input du common control

  "environment_$(environments.groupe)/env_promises.cf",

Dans la section bundle séquence ajouter :

environments,
env_main,

Ensuite dans les fichiers env_promises.cf on peut ajouter à des fins de tests une promesses qui va pour le moment afficher l’environnement, histoire de voir si cela fonctionne.

env_promise.cf dans chacun des dossiers contient maintenant :

bundle agent env_main
{
reports:
  cfengine::
        "Environment: $(environments.groupe)";
}

Validation de ces promesses

cf-promises -f /var/lib/cfengine3/masterfiles/promises.cf

Update des fichiers de promesses

cf-agent  /var/lib/cfengine3/masterfiles/update.cf

On force le run afin de gagner du temps

cf-agent -KI

Résultat :

R: Environment: pprod
root@client-pprod:~# 

R: Environment: dev
root@client-dev:~# 

R: Environment: dev
root@client-prod:~#

Nous avons ici un squelette de déploiement multi-environnement où leur promesses respectives sont dans un répertoire qui leur est propre.