modeleChezlepro (99999) clone en modeleChezlepro-travail (99998). L'original n'a pas ete touche. Deux defauts de mon propre outillage, trouves en l'utilisant : - l'inventaire d'un seul hote ne porte aucun group_vars, donc aucun utilisateur de connexion : Ansible tentait le compte local. MODELE_HOTE passe desormais ansible_user. - les playbooks ciblent hosts: modeles_vm, et un inventaire d'un seul hote place la machine dans all. La commande etait juste et la cible introuvable (« skipping: no hosts matched »). J'avais verifie l'affichage, pas l'effet. Les trois acceptent maintenant cible_modele. Le nettoyage vide /etc/resolv.conf (il portait l'identite du reseau de fabrication) et supprime les CLES D HOTE SSH — le gabarit transportait une cle privee. Sur que parce que cloud-init les recree au premier demarrage, verifie avant de l'ecrire. Reste a faire, et ce n'est pas a moi : basculer proxmox_clone_* sur le nouveau une fois qu'une VM en sera nee et aura fonctionne. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
135 lines
5.5 KiB
YAML
135 lines
5.5 KiB
YAML
---
|
|
- name: Vérifier le template Debian 13 Proxmox
|
|
# Le gabarit n'est pas un hote du tenant : son adresse vit sur le reseau de
|
|
# fabrication, donc il ne peut pas venir du plan et le groupe `modeles_vm` reste vide.
|
|
# `MODELE_HOTE` passe alors `cible_modele`, et l'inventaire d'un seul hote (`-i "<ip>,"`)
|
|
# place la machine dans `all` — PAS dans `modeles_vm`. Sans cette indirection, la
|
|
# commande etait juste et la cible introuvable : « skipping: no hosts matched ».
|
|
hosts: "{{ cible_modele | default('modeles_vm') }}"
|
|
become: true
|
|
gather_facts: true
|
|
|
|
tasks:
|
|
- name: Vérifier que la cible est Debian 13
|
|
ansible.builtin.assert:
|
|
that:
|
|
- ansible_facts.distribution == "Debian"
|
|
- ansible_facts.distribution_major_version == "13"
|
|
fail_msg: "Ce template doit être une Debian 13."
|
|
|
|
- name: Afficher les partitions
|
|
ansible.builtin.command: lsblk -f
|
|
register: lsblk_output
|
|
changed_when: false
|
|
|
|
- name: Résultat lsblk
|
|
ansible.builtin.debug:
|
|
var: lsblk_output.stdout_lines
|
|
|
|
- name: Vérifier l'absence de swap actif
|
|
ansible.builtin.command: swapon --show
|
|
register: swapon_output
|
|
changed_when: false
|
|
failed_when: swapon_output.stdout | length > 0
|
|
|
|
- name: Collecter les paquets installés
|
|
ansible.builtin.package_facts:
|
|
manager: auto
|
|
|
|
- name: Valider les paquets requis du template
|
|
ansible.builtin.assert:
|
|
that:
|
|
- "'sudo' in ansible_facts.packages"
|
|
- "'openssh-server' in ansible_facts.packages"
|
|
- "'qemu-guest-agent' in ansible_facts.packages"
|
|
- "'cloud-init' in ansible_facts.packages"
|
|
- "'cloud-guest-utils' in ansible_facts.packages"
|
|
- "'chrony' in ansible_facts.packages"
|
|
- "'apparmor' in ansible_facts.packages"
|
|
- "'auditd' in ansible_facts.packages"
|
|
- "'fail2ban' in ansible_facts.packages"
|
|
- "'nftables' in ansible_facts.packages"
|
|
- "'unattended-upgrades' in ansible_facts.packages"
|
|
fail_msg: "Un paquet requis du golden template est absent."
|
|
|
|
- name: Vérifier l'absence d'environnement graphique
|
|
ansible.builtin.assert:
|
|
that:
|
|
- "'task-desktop' not in ansible_facts.packages"
|
|
- "'xserver-xorg' not in ansible_facts.packages"
|
|
- "'gdm3' not in ansible_facts.packages"
|
|
- "'sddm' not in ansible_facts.packages"
|
|
- "'lightdm' not in ansible_facts.packages"
|
|
fail_msg: "Un environnement graphique semble installé."
|
|
|
|
- name: Collecter les services
|
|
ansible.builtin.service_facts:
|
|
|
|
- name: Valider les services de base
|
|
ansible.builtin.assert:
|
|
that:
|
|
- ansible_facts.services['ssh.service'].state == 'running'
|
|
- ansible_facts.services['qemu-guest-agent.service'].state == 'running'
|
|
- ansible_facts.services['chrony.service'].state == 'running'
|
|
- ansible_facts.services['auditd.service'].state == 'running'
|
|
- ansible_facts.services['fail2ban.service'].state == 'running'
|
|
fail_msg: "Un service de base n'est pas actif."
|
|
|
|
- name: Vérifier que AppArmor est actif
|
|
ansible.builtin.command: aa-enabled
|
|
register: apparmor_state
|
|
changed_when: false
|
|
|
|
- name: Valider l'état nftables du template
|
|
ansible.builtin.assert:
|
|
that:
|
|
- ansible_facts.services['nftables.service'].state != 'running'
|
|
fail_msg: "nftables ne doit pas être actif par défaut dans le template."
|
|
|
|
- name: Vérifier cloud-init
|
|
ansible.builtin.command: cloud-init --version
|
|
register: cloud_init_version
|
|
changed_when: false
|
|
|
|
- name: Afficher cloud-init
|
|
ansible.builtin.debug:
|
|
var: cloud_init_version.stdout
|
|
|
|
- name: Vérifier sudo NOPASSWD du compte Ansible
|
|
ansible.builtin.command: sudo -n true
|
|
become: false
|
|
changed_when: false
|
|
|
|
- name: Collecter la configuration SSH effective
|
|
ansible.builtin.command: sshd -T
|
|
register: sshd_effective_config
|
|
changed_when: false
|
|
|
|
- name: Valider le hardening SSH effectif
|
|
ansible.builtin.assert:
|
|
that:
|
|
- "'passwordauthentication no' in sshd_effective_config.stdout"
|
|
- "'kbdinteractiveauthentication no' in sshd_effective_config.stdout"
|
|
- "'permitrootlogin no' in sshd_effective_config.stdout"
|
|
- "'pubkeyauthentication yes' in sshd_effective_config.stdout"
|
|
- "'authenticationmethods publickey' in sshd_effective_config.stdout"
|
|
- "'x11forwarding no' in sshd_effective_config.stdout"
|
|
- "'allowtcpforwarding no' in sshd_effective_config.stdout"
|
|
- "'allowagentforwarding no' in sshd_effective_config.stdout"
|
|
- "'allowstreamlocalforwarding no' in sshd_effective_config.stdout"
|
|
- "'permittunnel no' in sshd_effective_config.stdout"
|
|
- "'permituserenvironment no' in sshd_effective_config.stdout"
|
|
- "'maxauthtries 3' in sshd_effective_config.stdout"
|
|
- "'logingracetime 20' in sshd_effective_config.stdout"
|
|
- "'maxsessions 2' in sshd_effective_config.stdout"
|
|
fail_msg: "La configuration SSH effective ne respecte pas le hardening attendu."
|
|
|
|
- name: Vérifier les erreurs critiques du boot courant
|
|
ansible.builtin.command: journalctl -b -p err..alert --no-pager
|
|
register: boot_errors
|
|
changed_when: false
|
|
failed_when: false
|
|
|
|
- name: Afficher les erreurs du boot courant
|
|
ansible.builtin.debug:
|
|
var: boot_errors.stdout_lines
|