[Puppet] Renouveler le certificat racine de puppet
Votre journée commençait tranquillement quand vous avez lancé une première commande puppet ce matin et là …
Warning: Certificate 'Puppet CA: XXX.company.tld' will expire on 2021-08-22T08:45:12GMT
Le certificat racine de votre infrastructure puppet va expirer dans les prochains jours !
Nous allons donc voir ici comment renouveler ce certificat et le distribuer sur votre infrastructure.
Présentation du fonctionnement des certificats avec Puppet
Quand vous utiliser puppet chaque serveur qui est provisionné a un
certificat qui lui permet de s’authentifier sur l’infrastructure. Aussi
sur chaque nœud vous trouverez plusieurs certificats dans le dossier
/var/lib/puppet/ssl
[email protected]:/var/lib/puppet/ssl# tree
.
├── certificate_requests
│ └── myserver.pem
├── certs
│ ├── ca.pem
│ └── myserver.pem
├── crl.pem
├── private
├── private_keys
│ └── myserver.pem
└── public_keys
└── myserver.pem
5 directories, 6 files
Comme on peut le voir ci-dessus, nous avons une clé privée et un certificat
(private_keys/myserver.pem
et certs/myserver.pem
) qui permet à l’hôte
(ici nommé myserver
) de s’authentifier sur le serveur puppetmaster
. Nous
remarquons aussi que nous avons un fichier certs/ca.pem
. Ce fichier
permet à l’hôte de valider que le serveur puppetmaster
est bien toujours
le même et que nous ne faisons pas fasse à une attaque de type man in the middle
.
L’avertissement que nous avons plus haut nous informe donc que ce certificat n’est bientôt plus valide. Nous allons voir ici comment le renouveler et le mettre à jour sur notre nos nœuds.
Une fois connecté sur le serveur puppet (puppetmaster
) nous pouvons
constater que le dossier /var/lib/rancher/ssl est un peu plus fournit
que sur un simple nœud puppet client.
[email protected]:/var/lib/puppet/ssl# tree
.
├── ca
│ ├── ca_crl.pem
│ ├── ca_crt.pem
│ ├── ca_key.pem
│ ├── inventory.txt
│ ├── private
│ │ └── ca.pass
│ ├── requests
│ │ ├── future-server.pem
│ ├── serial
│ └── signed
│ ├── myserver.pem
│ ├── myserver2.pem
│ ├── myserver3.pem
...
├── certificate_requests
│ └── puppetmaster-server.pem
├── certs
│ ├── puppetmaster-server.pem
│ └── ca.pem
├── crl.pem
├── private
├── private_keys
│ └── puppetmaster-server.pem
└── public_keys
└── puppetmaster-server.pem
9 directories, 199 files
En effet sur le puppetmaster nous avons à la fois le certificat et la clé de la CA mais aussi tous les certificats qui ont été signés pour nos agents. Notre objectif est donc ici de régénérer le fichier
ca/ca_crt.pem` sans
casser la validation des certificats déjà signés.
Il est assez facile de constater si une CA est valide pour un certificat
avec un simple commande openssl
.
[email protected]:/var/lib/puppet/ssl# openssl verify -CAfile ca/ca_crt.pem ca/signed/myserver2.pem
ca/signed/myserver2.pem: OK
Nous utiliserons cette commande pour valider la bonne tenue de nos actions.
Renouvellement du certificat racine
Nous allons donc renouveler le certificat racine de puppet.
Pour cela nous devons utiliser un fichier CSR. Les fichiers de CSR
(Certificat Signing Request) sont des fichiers qui contiennent une
partie des informations d’une clé privée ainsi que toutes les
informations que nous souhaitons voir dans notre certificat cible (CN,
Alt Name, …). Il se peut que ce fichier csr soit déjà présent dans le
fichier /var/lib/puppet/ssl/ca/ca_csr.pem
mais si comme moi ce n’est
pas le cas vous pouvez régénérer ce CSR à partir du certificat et de la
clé privée de la CA.
[email protected]:/var/lib/puppet/ssl# openssl x509 -x509toreq -in ca/ca_crt.pem -signkey ca/ca_key.pem -out ca/ca_csr.pem
Getting request Private Key
Generating certificate request
Maintenant que nous avons un CSR valide il nous faut créer une
configuration OpenSSL valide pour pouvoir régénérer notre CA. Nous
allons pour cela créer le fichier /var/lib/puppet/ssl/ca/extension.cnf
avec le contenu suivant
[CA_extensions]
basicConstraints = critical,CA:TRUE
nsComment = "Puppet Ruby/OpenSSL Internal Certificate"
keyUsage = critical,keyCertSign,cRLSign
subjectKeyIdentifier = hash
Nous pouvons maintenant générer un nouveau certificat pour notre CA.
[email protected]:/var/lib/puppet/ssl# openssl x509 -req -days 3650 -in ca/ca_csr.pem -signkey ca/ca_key.pem -out ca/new_ca_crt.pem -extfile ca/extension.cnf -extensions CA_extensions
Signature ok
subject=/CN=Puppet CA: puppetmaster-server
Getting Private key
Avant de mettre en ligne ce certificat nous pouvons valider que ce certificat est valide.
[email protected]:/var/lib/puppet/ssl# openssl verify -CAfile ca/new_ca_crt.pem ca/signed/myserver3.pem
ca/signed/myserver3.pem: OK
Si vous avez un résultat valide nous pouvons remplacer l’ancien
certificat par le précédent et redémarrer le serveur puppet. Dans notre
cas le serveur puppet est démarré par un passenger
nous devons donc
rebooter apache. (Vous pouvez identifier le service à redémarrer via
netstat -patune |grep LIST | grep 8140
).
[email protected]:/var/lib/puppet/ssl# mv ca/ca_crt.pem{,.old}
[email protected]:/var/lib/puppet/ssl# mv ca/{new_,}ca_crt.pem
[email protected]:/var/lib/puppet/ssl# service apache2 restart
Restarting web server: apache2
Déploiement du certificat sur les agents puppet
Il nous faut maintenant déployer ce fichier ca_crt.pem
sur l’ensemble
de nos agents puppet. Nous allons pour cela … Utiliser puppet :).
Dans notre dépôt puppet nous pouvons créer un fichier contenant le nouveau certificat de la CA.
$ vim files/puppet/ca.crt
...
Il ne nous reste qu'à l’envoyer dans le bon fichier. Le certificat doit
être placé sur les nœuds dans /var/lib/puppet/ssl/certs/ca.pem
. Voici
un exemple de manifest.
file { '/var/lib/puppet/ssl/certs/ca.pem':
source => 'puppet:///modules/mymodule/puppet/ca.pem',
owner => 'puppet',
group => 'puppet',
}
Et les agents dans tout ca?
Il est possible que vous rencontriez en même temps que l’expiration du certificat de la CA, l’expiration des certificats de vos agents. Ceux-ci aussi doivent être renouvelés. Il existe des modules puppet qui permettent de faire ceci automatiquement mais si vous voulez le faire manuellement voici la marche à suivre.
Sur le serveur puppetmaster
[email protected]:~# puppet cert clean myserver2
Notice: Revoked certificate with serial 72
Notice: Removing file Puppet::SSL::Certificate myserver2 at '/var/lib/puppet/ssl/ca/signed/myserver2.pem'
Notice: Removing file Puppet::SSL::Certificate myserver2 at '/var/lib/puppet/ssl/certs/myserver2.pem'
Sur le serveur myserver2
[email protected]:~# find /var/lib/puppet/ssl -name myserver2.pem -delete
[email protected]:~# puppet agent -t
Info: Creating a new SSL key for myserver2
Info: csr_attributes file loading from /etc/puppet/csr_attributes.yaml
Info: Creating a new SSL certificate request for
myserver2
Info: Certificate Request fingerprint (SHA256):
...
Si vous n’avez pas de signature automatique il vous faut retourner sur
le serveur puppetmaster
pour signer ce nouveau certificat.
[email protected]:~# puppet cert sign myserver2
Notice: Signed certificate request for myserver2
Notice: Removing file Puppet::SSL::CertificateRequest myserver2 at '/var/lib/puppet/ssl/ca/requests/myserver2.pem'
Note: Le script suivant permet d’identifier les certificats qui vont expirer d’ici le mois prochain.
for i in $( ls /var/lib/puppet/ssl/ca/signed/ )
do
end_date=$( openssl x509 -noout -in /var/lib/puppet/ssl/ca/signed/${i} -dates | grep notAf | cut -d"=" -f2 )
end_date_s=$( date -d "$end_date" +%s )
test $end_date_s -lt $( date --date='+1 month' +"%s" ) && echo "Should renew $i (will expire at $end_date)"
done
Conclusion
Après un passage global de puppet sur nos agents notre certificat racine a bien été renouvelé et nous pouvons reprendre notre journée de travail normalement :).