"AgileSoft" - De la ligne de commande au Service Système

Contexte et Situation
Vous êtes l'administrateur système de la start-up AgileSoft.
Les développeurs ont créé une petite application interne en Python (un simple serveur de temps/info).
Le problème :
Actuellement, pour lancer l'application, le Lead Dev doit se connecter en SSH, taper une commande, et laisser son terminal ouvert. S'il ferme son PC ou si l'application plante, le service est coupé.
C'est inacceptable pour la production.
Architecture du TP
Votre mission :
- Créer un utilisateur système dédié pour isoler l'application (sécurité).
- Créer un Service Systemd pour que l'app démarre au boot et redémarre seule en cas de crash.
- Créer une Autorité de Certification interne, signer un certificat serveur via CSR, et configurer Nginx en HTTPS.
- Verrouiller le réseau avec nftables pour empêcher l'accès direct au port 8000.
- Configurer la résolution du domaine via le fichier hosts du client et importer la CA dans Firefox.
Workflow
PARTIE 1 : L'état des lieux (Simulation du problème)
Sur srv-app
Installez Python et créez l'environnement virtuel :
apt update && apt install -y python3 python3-pip python3-venv
Créez le dossier de l'application :
mkdir -p /opt/agile_app
Créez le fichier /opt/agile_app/app.py avec le contenu suivant :
from datetime import datetime
def app(environ, start_response):
now = datetime.now().strftime("%d/%m/%Y %H:%M:%S")
body = f"""<!DOCTYPE html>
<html lang="fr">
<head><meta charset="UTF-8"><title>AgileSoft</title></head>
<body>
<h1>Bienvenue sur l'App AgileSoft v1</h1>
<p>Heure serveur : {now}</p>
<hr>AgileSoft Internal App
</body>
</html>""".encode("utf-8")
start_response("200 OK", [
("Content-Type", "text/html; charset=utf-8"),
("Content-Length", str(len(body)))
])
return [body]
Installez Gunicorn dans un environnement virtuel :
python3 -m venv /opt/agile_app/venv
/opt/agile_app/venv/bin/pip install gunicorn
Lancez l'application manuellement :
cd /opt/agile_app
/opt/agile_app/venv/bin/gunicorn --bind 0.0.0.0:8000 app:app
Depuis admin-station, vérifiez que l'application répond :
curl http://192.168.10.10:8000
Le Crash :
Faites CTRL+C sur srv-app. Relancez le curl depuis admin-station.
Que constatez-vous ?
C'est ce problème que vous allez résoudre.
PARTIE 2 : Création du Service Systemd
Mission A : Utilisateur système dédié
Créez un utilisateur système appuser sans dossier home et sans accès shell.
Attribuez le dossier /opt/agile_app à cet utilisateur.
Vérification :
La commande ls -la /opt/agile_app doit afficher appuser comme propriétaire.
Mission B : Rédaction du Service
Créez le fichier de service /etc/systemd/system/agile-app.service avec les contraintes suivantes :
- L'application est lancée par appuser.
- Le dossier de travail est /opt/agile_app.
- Gunicorn doit écouter uniquement sur localhost port 8000.
- Le service redémarre automatiquement en cas de crash avec un délai de 5 secondes.
- Le service doit démarrer après le réseau.
Activez et démarrez le service.
Vérification :
systemctl status agile-app doit afficher Active: active (running). La commande ps aux | grep gunicorn doit afficher appuser dans la colonne USER et non root.
Mission C : Preuve de robustesse
Relevez le PID du processus Gunicorn.
Tuez violemment le processus :
kill -9 [PID]
Vérifiez que Systemd a relancé l'application automatiquement.
Consultez les logs pour voir la preuve du redémarrage :
journalctl -u agile-app -n 20
PARTIE 3 : PKI Interne et Certificat Serveur
Vous allez créer une vraie chaîne de confiance interne. L'objectif n'est pas de générer un simple certificat auto-signé, mais de mettre en place une Autorité de Certification (CA) qui signera les certificats de vos serveurs.
La chaîne PKI à construire :
Étape 1 : Créer la CA AgileSoft → agilesoft-ca.key + agilesoft-ca.crt
Étape 2 : Créer une clé + CSR serveur → agile.key + agile.csr
Étape 3 : La CA signe le CSR → agile.crt
Mission A : Créer l'Autorité de Certification
Créez la structure de dossiers :
mkdir -p /etc/ssl/agilesoft/{ca,server}
chmod 700 /etc/ssl/agilesoft
Générez la clé privée de la CA (4096 bits) dans /etc/ssl/agilesoft/ca/.
Générez le certificat racine de la CA (auto-signé, valide 5 ans) avec les informations suivantes :
Pays : FR
Organisation : AgileSoft
CN : AgileSoft Internal CA
Vérification : La commande suivante doit afficher Subject et Issuer identiques :
openssl x509 -in /etc/ssl/agilesoft/ca/agilesoft-ca.crt -text -noout | grep -E "Subject:|Issuer:"
Mission B : Créer la clé et le CSR du serveur
Générez la clé privée du serveur (2048 bits) dans /etc/ssl/agilesoft/server/.
Créez un fichier de configuration /etc/ssl/agilesoft/server/agile.cnf pour le CSR.
Il doit contenir :
CN : app.agilesoft.local
Un champ Subject Alternative Name (SAN) avec :
▪ DNS.1 = app.agilesoft.local
▪ IP.1 = 192.168.10.10
Générez le CSR à partir de cette configuration.
Vérification : Le SAN doit être présent dans le CSR :
openssl req -text -noout -in /etc/ssl/agilesoft/server/agile.csr | grep -A3 "Subject Alternative"
Mission C : Signer le CSR avec la CA
Créez un fichier d'extensions /etc/ssl/agilesoft/server/agile_ext.cnf précisant :
basicConstraints = CA:FALSE
extendedKeyUsage = serverAuth
Le SAN identique à celui du CSR
Signez le CSR avec la CA pour produire agile.crt (valide 365 jours).
Vérification :
La chaîne de confiance doit être valide :
openssl verify -CAfile /etc/ssl/agilesoft/ca/agilesoft-ca.crt \
/etc/ssl/agilesoft/server/agile.crt
Attendu : agile.crt: OK
Mission D : Configuration Nginx
Installez Nginx.
Créez un vhost /etc/nginx/sites-available/agile qui :
- Redirige le trafic HTTP (port 80) vers HTTPS (301).
- Écoute en HTTPS (port 443) avec le certificat signé.
- Utilise les protocoles TLS 1.2 et 1.3 uniquement.
- Renvoie le trafic vers Gunicorn sur 127.0.0.1:8000.
- Transmet les headers client au backend.
Activez le vhost, désactivez le vhost par défaut, testez la syntaxe et redémarrez Nginx.
Vérification :
curl -k https://127.0.0.1
Attendu : HTML de bienvenue AgileSoft
PARTIE 4 : Verrouillage Réseau avec nftables
Objectif :
Bloquer l'accès direct au port 8000 depuis l'extérieur. Seuls les ports 22, 80 et 443 doivent être accessibles depuis le réseau.
Avant de commencer : Comprendre nftables
| Concept | Rôle
| Table | Conteneur global des règles
| Chain | Groupe de règles pour un type de trafic
| Rule | Règle individuelle
Rédigez le fichier /etc/nftables.conf avec les règles suivantes :
- Politique par défaut en entrée : tout bloquer.
- Autoriser les connexions déjà établies.
- Autoriser le loopback (indispensable pour la communication interne Nginx → Gunicorn).
- Autoriser SSH (port 22).
- Autoriser HTTP (port 80) et HTTPS (port 443).
- Le port 8000 ne doit pas être autorisé.
- Politique en sortie : tout autoriser.
Appliquez les règles et activez le chargement automatique au démarrage.
Tests depuis admin-station :
Test 1 : Doit fonctionner
curl -k https://192.168.10.10
Test 2 : Doit échouer (timeout)
curl http://192.168.10.10:8000
PARTIE 5 : Configuration du poste client (admin-station)
Mission A : Résolution du domaine
Sur admin-station, configurez le fichier /etc/hosts pour que app.agilesoft.local pointe vers 192.168.10.10.
Vérification :
ping app.agilesoft.local
Doit répondre depuis 192.168.10.10
Mission B : Récupérer le certificat CA
Récupérez le certificat de la CA (et non du serveur) depuis srv-app via scp et déposez-le sur le Bureau d'admin-station.
Mission C : Importer la CA dans Firefox
Ouvrez Firefox → Paramètres → recherchez certificat.
Cliquez sur Afficher les certificats → onglet Autorités → Importer.
Sélectionnez agilesoft-ca.crt et cochez "Faire confiance à cette AC pour identifier des sites web".
Mission D : Test final
Dans Firefox, accédez à https://app.agilesoft.local.
La page doit s'afficher sans aucun avertissement de sécurité.
Cliquez sur le cadenas et vérifiez que le certificat est bien signé par AgileSoft Internal CA.
Choix Technologiques
VM 1 (srv-app) : Debian 12/13, mode CLI. Hébergera Python + Gunicorn + Nginx. IP : 192.168.90.10
VM 2 (admin-station) : Debian 12/13, mode graphique avec Firefox. Servira à tester l'accès. IP : 192.168.9020
Les deux machines doivent pouvoir se pinger entre elle
Le domaine interne utilisé : app.agilesoft.local
Schéma de l'Infrastructure

Cliquer pour agrandir
Pré-requis pour ce TP
Avant de commencer ce TP, assurez-vous d'avoir installé et configuré :
Cliquez sur un pré-requis pour voir le tutoriel d'installation complet
Ressources à télécharger
Aucune ressource disponible pour ce TP.