AAP Containerized TLS avec CA interne

L’objectif est de sécuriser les services Gateway et EDA d’Ansible Automation Platform (AAP) avec les certificats internes de votre entreprise.

Contraintes : pas de clé privée globale pour la CA - on dispose seulement des certificats serveur signés et des intermédiaires.

Problème initial

Le playbook échoue systématiquement avec des erreurs SSL.

Exemple Gateway :

FAILED - RETRYING: [hostname.sub.company.org]: Ensure automation gateway proxy is ready (1 retries left).
fatal: [hostname.sub.company.org]: FAILED! => {"attempts": 30, "changed": false, "elapsed": 0, "msg": "Status code was -1 and not [200]: Request failed: <urlopen error [Errno 111] Connection refused>", "redirected": false, "status": -1, "url": "https://hostname.sub.company.org:443"}

Exemple EDA :

FAILED - RETRYING: [hostname.sub.company.org]: Ensure automation eda is ready (1 retries left). 
fatal: [hostname.sub.company.org]: FAILED! => {"attempts": 5, "changed": false, "content": "", "elapsed": 0, "msg": "Status code was -1 and not [200]: Request failed: <urlopen error [SSL: certificatE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1147)>", "redirected": false, "status": -1, "url": "https://hostname.sub.company.org:8445/api/eda/v1/status/"}

Exemple avec mauvaise paire certificat/clé :

TASK [ansible.containerized_installer.preflight : Ensure TLS certificate and key match]
fatal: [hostname.sub.company.org]: FAILED! => { "assertion": "_local_cert_info.public_key_data == _local_key_info.public_data", "changed": false, "evaluated_to": false, "msg": "The TLS certificate and key do not match together" }

Identifier les certificats disponibles

Ces fichiers sont ceux spécifiques au serveur AAP :

$ ls -l /home/aap
total 20
-rw------- 1 aap aap 2390 Mar 15 2024 hostname.sub.company.org.cert.pem
-rw------- 1 aap aap 1675 Mar 15 2024 hostname.sub.company.org.key.pem
Fichier Rôle
cert.pem certificat public du serveur
key.pem Clé privée correspondante, nécessaire pour TLS
fullchain.pem Concaténation de cert.pem + intCA.pem pour former la chaîne complète que le serveur présente aux clients (à créer, voir plus bas)

L’entreprise fait ici office d’autorité de certification interne. On dispose de :

$ ls -l /etc/pki/ca-trust/source/anchors/
-rw-r--r-- 1 root root 2305 COMPANY-SUB-RootCA.pem
-rw-r--r-- 1 root root 2325 COMPANY-SUB-intCA1.pem
-rw-r--r-- 1 root root 2325 COMPANY-SUB-intCA2.pem
-rw-r--r-- 1 root root 2325 COMPANY-SUB-intCA3.pem
[...]
Fichier Rôle
COMPANY-SUB-RootCA.pem Root CA → certificate de confiance ultime de l’entreprise
COMPANY-SUB-intCA1.pem intCA intermédiaire 1 → a signé le certificat du serveur AAP
COMPANY-SUB-intCA2.pem intCA intermédiaire 2 → pas utilisé ici
COMPANY-SUB-intCA3.pem intCA intermédiaire 3 → pas utilisé ici

Vérifier le certificat serveur et identifier l’intermédiaire

Si le serveur a été signé par une autre intCA, remplacer COMPANY-SUB-intCA1.pem par celle indiquée dans l’issuer.

Pour identifier l’intermédiaire (issuer) :

$ sudo openssl x509 -in /home/aap/hostname.sub.company.org.cert.pem -noout -issuer -subject

Sortie typique :

issuer=C=FR, ST=PACA, O=COMPANY , OU=SAD - Super Admin Division, CN=COMPANY  - SAD intCA - intCA1, [email protected]
subject=C=FR, ST=PACA, L=My-City, O=COMPANY , OU=SAD - Super Admin Division, CN=hostname.sub.company.org, [email protected]

L’issuer est CN = COMPANY - SAD intCA - intCA1, c’est l’intermédiaire qu’il faut utiliser pour compléter la chaîne.

Construire le fullchain.pem

Avant de construire fullchain.pem, il faut s’assurer que le certificat serveur et la clé privée correspondent parfaitement. Sinon, le playbook échouera.

Concaténer le certificat serveur avec l’intermédiaire :

$ sudo cat /home/aap/hostname.sub.company.org.cert.pem \
/etc/pki/ca-trust/source/anchors/COMPANY-SUB-intCA1.pem \
> /home/aap/fullchain.pem

Puis ajouter les bons droits et owner :

$ chown aap:aap /home/aap/fullchain.pem
$ chmod 600 /home/aap/fullchain.pem

Vérifier la chaîne complète :

$ openssl verify \
-CAfile /etc/pki/ca-trust/source/anchors/COMPANY-SUB-RootCA.pem \
-untrusted /etc/pki/ca-trust/source/anchors/COMPANY-SUB-intCA1.pem \
/home/aap/hostname.sub.company.org.cert.pem

Résultat attendu :

/home/aap/hostname.sub.company.org.cert.pem: OK

Pour une double vérifintCAtion côté serveur :

$ openssl s_client -connect hostname.sub.company.org:8446 -CAfile /etc/pki/ca-trust/source/anchors/COMPANY-SUB-RootCA.pem

ou

$ openssl s_client -connect hostname.sub.company.org:8445 -showcerts

Sortie attendue à la fin du handshake :

Verify return code: 0 (ok)

Mise à jour du CA local

Pour garantir que la machine connaît bien le RootCA et peut valider le serveur :

$ sudo update-ca-trust extract

Vérifier côté EDA/Gateway

Si la chaîne est correcte et que le fullchain.pem est utilisé dans la config AAP, il n’y aura plus d’erreur certificatE_VERIFY_FAILED :

$ openssl s_client -connect hostname.sub.company.org:8445 -showcerts
$ curl -v https://hostname.sub.company.org:8445/api/eda/v1/status/

Configuration finale AAP

À mettre dans la section ‘[all:vars]’ du fichier ‘inventory-growth’ :

[all:vars]

# Régénération des certificats AAP (optionnel)
aap_service_regen_cert=true

# certificat + clé Gateway
gateway_tls_cert=/home/aap/fullchain.pem
gateway_tls_key=/home/aap/hostname.sub.company.org.key.pem

# certificat + clé EDA
eda_tls_cert=/home/aap/fullchain.pem
eda_tls_key=/home/aap/hostname.sub.company.org.key.pem

# Root CA de confiance pour AAP (Root de l'entreprise)
custom_ca_cert=/etc/pki/ca-trust/source/anchors/COMPANY-SUB-RootCA.pem

Puis relancer le playbook :

$ ansible-playbook -i inventory-growth collections/ansible_collections/ansible/containerized_installer/playbooks/install.yml

Résumé des fichiers et role

Élément Fichier
Cert serveur hostname.sub.company.org.cert.pem
Clé privée hostname.sub.company.org.key.pem
Intermédiaire COMPANY-SUB-intCA1.pem
Root CA COMPANY-SUB-RootCA.pem
Cert présenté par le gateway fullchain.pem = cert + intCA1
CA de confiance AAP RootCA.pem

Notes importantes

Comme il n’est pas possible, pour des raisons de sécurité, d’obtenir la clé privée du CA global, on ne peut pas générer de certificats, il faut travailler avec ceux fournis.

L’étape critique est de déterminer le bon intermédiaire (intCA1) à concaténer avec le cert serveur.

Les droits sur fullchain.pem doivent être stricts (chmod 600) pour éviter des erreurs de lecture par AAP.

Les erreurs fréquentes rencontrées :

SSL: certificatE_VERIFY_FAILED
unable to get local issuer certificate
Connection refused

Toutes ces erreurs disparaissent une fois la chaîne complète construite et fullchain.pem utilisé partout.

Si malgré tout ça ne passe pas, il est parfois nécessaire de stopper tous les containers AAP pour repartir sur une base propre :

$ podman stop -a

Certains containers peuvent redémarrer seuls, d’autres restent arrêtés. Une fois la configuration correcte appliquée, et le playbook executé, les services devraient démarrer sans erreur SSL.

Documentation

Red Hat Doc

🡅 Partager