Cybersécurité d’un **cluster** de serveurs
Cybersécurité d’un cluster de serveurs
Ce contenu est fusionné dans le dépôt
cluster(viagit subtree) sousbootstrap/security/. Pour l’invocation à jour depuis ce répertoire, voir le RUNBOOK cluster. Les sections « Installation / Lancement » ci-dessous décrivent l’usage autonome historique (avant fusion) et sont conservées pour mémoire.
👉 Avant d’activer une couche, lire les
implications — chaque couche est
désormais opt-in explicite (sans --tags, le playbook ne touche à rien). Le
menu des commandes y est aussi listé.
👉 Pour voir ce qui est actuellement actif sur les nœuds : lancer
report.sh
— il agrège, par hôte, les preuves observables (services, sshd sondé, IPs
bannies, dernier log unattended-upgrades, etc.).
Objectif
- Mettre en place une politique de cybersécurité
- Automatiser le plus possible son installation sur les serveurs
Méthode
Nous allons déployer une architecture de sécurité en plusieurs étapes, en utilisant un outil d’automatisation pour garantir la cohérence et la rapidité de la mise en œuvre.
Ansible est un outil d’automatisation qui permet de gérer la configuration et le
déploiement d’applications sur des serveurs distants. Il utilise un langage de
description simple basé sur YAML pour définir l’état souhaité des systèmes.
Concrètement, un playbook Ansible - ici le fichier ./secure.yml - est un
fichier YAML qui décrit les tâches à exécuter sur les hôtes cibles - décrits
dans le fichier /etc/ansible/hosts. Parfois, ces tâches sont regroupées au
sein d’un ou plusieurs rôles.
Notre playbook exécute plusieurs rôles pour sécuriser les serveurs. Il commence
par charger les paramètres (rôle settings) pour exposer les variables
d’environnement (décrites dans ./.env), puis exécute en série (un hôte à la
fois) une mise à jour complète du système en appelant la tâche upgrade-now du
rôle os, et enfin applique, avec privilèges élevés, l’ensemble des rôles de
durcissement (os, network, alert, audit, detection) pour configurer le
compte administrateur, activer les mises à jour automatiques, sécuriser SSH et
le pare‑feu, rediriger les mails système, déployer les règles d’audit et
configurer la détection d’intrusion — bref, il met à jour puis durcit chaque
machine de façon ordonnée.
Nous détaillons ensuite chaque rôle ci-dessous.
alert
Ce rôle - dans le fichier ./roles/alert - installe et active un agent de
messagerie minimal (postfix) pour permettre l’envoi d’emails système, puis
configure l’alias root dans aliases afin de rediriger les mails système vers
l’adresse administrateur (définie la variable MAIL_ROOT_REDIRECT du fichier
.env); si le fichier d’alias change, il déclenche la régénération des alias et
appliquer immédiatement la redirection.
audit
Le rôle - dans le fichier ./roles/audit - installe et active auditd, déploie
les règles d’audit depuis files/audit.rules vers /etc/audit/rules.d/ et
redémarre auditd si les règles ont été modifiées pour garantir la collecte des
événements système.
detection
Le rôle - dans le fichier ./roles/detection - installe et démarre fail2ban,
déploie la configuration locale jail.local et recharge le service au besoin pour
bloquer automatiquement les IP malveillantes détectées dans les logs.
network
Le rôle - dans le fichier ./roles/network - applique les règles du pare-feu
UFW (ufw.yml). C’est désormais sa seule responsabilité : le durcissement
sshd et le dépôt de la clé publique sont assurés uniquement par
bootstrap/first-access.sh
(drop-in /etc/ssh/sshd_config.d/, clé via ssh-copy-id). Les anciennes tasks
sshd.yml/ssh.yml faisaient doublon et ont été supprimées.
os
Le rôle - dans le fichier ./roles/os - configure le compte administrateur
(expiration de mot de passe via users.yml), installe et paramètre
unattended-upgrades (génération d’une minute aléatoire et déploiement du
template templates/20auto-upgrades.j2) et fournit une tâche optionnelle
(upgrade-now.yml) pour appliquer immédiatement les upgrades et redémarrer si
nécessaire.
settings
Le rôle - dans le fichier ./roles/settings - importe les variables
d’environnement clés (ex. MAIL_ROOT_REDIRECT, HOST_USER,
PASSWORD_EXPIRATION, PUBLIC_SSH_KEY), les expose sous forme de facts
settings_*, vérifie qu’elles sont définies et affiche un debug des valeurs
importées.
Utilisation
Pré-requis
Nous utilisons un ordinateur de contrôle (un ordinateur de bureau) pour orchestrer à distance la configuration et la sécurisation d’un ou de plusieurs serveurs. L’automatisation est effectuée à l’aide de scripts et de playbooks Ansible.
Sur l’ordinateur de contrôle, assurez-vous d’avoir installé les dépendances nécessaires :
- Ansible : pour l’exécution des playbooks ;
- Python : pour les scripts et modules utilisés ;
- SSH : pour la connexion aux serveurs distants.
Concernant les serveurs à sécuriser, nous considérons qu’ils bénéficient chacun de :
- Une installation minimale et récente de Debian bookworm (12) ;
- Un seul compte utilisateur avec un accès
sudoet un mot de passe robuste ; - Une adresse IP avec le port 22 accessible depuis l’ordinateur de contrôle.
Installation
Sur l’ordinateur de contrôle, clonez ce dépôt localement :
git clone https://github.com/univ-lehavre/server-security.gitÀ la racine de ce dépôt cloné, renommez le fichier .env.example en .env et
remplacez toutes les valeurs des variables d’environnement.
Lancement
Pour sécuriser les serveurs, lancez la commande suivante :
Attention : le mot de passe est actuellement celui de la console de management
set -a; source .env; set +a; ansible-playbook --ask-pass --ask-become-pass secure.ymlCette commande exécute le playbook Ansible secure.yml en utilisant les
informations d’identification fournies dans le fichier .env.
Contribution à ce dépôt de code
Il est recommandé d’installer les modules suivants pour garantir la qualité et la cohérence du code :
- prettier : pour le formatage automatique du code.
- ansible : pour l’exécution des playbooks et rôles Ansible.
- ansible-lint : pour l’analyse statique et le linting des fichiers Ansible.
Pour formatter le code et exécuter le linter :
npm run formatnpm run lintAvant de soumettre, lancez ce script afin que toutes les variables
d’environnement du fichier privé .env soient bien obfusquées dans le fichier
public .env-example :
python3 ./blur_env.py