Introduction
Un paramètre de débogage temporaire est revenu dans une nouvelle version du service DeskLite. Les requêtes réussissent toujours, mais les journaux opérationnels contiennent maintenant un identifiant fictif. Une simple vérification de réussite fonctionnelle n'a pas détecté cette régression.
Vous suivrez les preuves de véritables requêtes, arrêterez les nouvelles fuites, remplacerez l'identifiant exposé et ajouterez une assertion qui bloque un candidat présentant réellement une fuite. Les journaux historiques restent des preuves ; aucun document d'investigation n'est requis. L'émetteur local, le client, le service, les témoins de comparaison et les utilitaires d'artefacts sont préparés.
Repérer l'événement réel de l'incident
Dans cette étape, vous mettrez en relation une requête avec la version et la configuration de journalisation actuelles.
cd /srv/ticket-regression
tail -n 5 lit les cinq dernières lignes, ce qui limite l'affichage. Utilisez votre lecture autorisée en tant qu'administrateur pour le journal du service préparé :
sudo tail -n 5 /opt/labex-ticket-regression/requests.log
Repérez request_id=initial-001, version=logging-v2, path=/tickets et status=200. Cette requête historique a réussi, mais la même ligne contient Authorization et l'ancien jeton fictif. Toutes les valeurs appartiennent uniquement à ce lab isolé.
grep affiche les lignes contenant un motif textuel fourni. Les apostrophes maintiennent ce motif littéral dans un seul argument :
sudo grep 'request_id=initial-001' /opt/labex-ticket-regression/requests.log
cat logging.conf
include_authorization = true explique la présence du champ sensible. L'heure, l'ID de requête, la version et le statut de l'événement relient le comportement observé à la configuration active. Conservez le journal d'origine ; l'effacer supprimerait des preuves sans empêcher les fuites futures.
Arrêter les champs sensibles dans les nouveaux événements
Dans cette étape, vous modifierez la politique de journalisation tout en conservant des champs d'audit utiles.
nano logging.conf
Utilisez :
[logging]
include_authorization = false
Enregistrez avec Ctrl+O, Enter et Ctrl+X. Appliquez la configuration enregistrée avec le point d'entrée de redémarrage préparé :
bash restart.sh
Donnez à une nouvelle requête de santé un ID connu. X-Request-ID est un en-tête de requête utilisé pour retrouver son nouvel événement :
curl -H 'X-Request-ID: after-policy-fix' http://127.0.0.1:8080/health
sudo grep 'request_id=after-policy-fix' /opt/labex-ticket-regression/requests.log
L'heure, la version, l'ID, le chemin et status=200 sont attendus, sans champ Authorization. L'ancien événement initial-001 reste présent. Évaluez les nouveaux événements à partir de leurs propres ID au lieu d'exiger que chaque ligne historique soit exempte de secret.
Révoquer et remplacer l'identifiant exposé
Dans cette étape, vous retirerez le pouvoir d'authentification de l'ancien jeton avec la méthode d'émetteur déjà apprise.
Modifier la politique de journalisation n'invalide pas une valeur exposée. Révoquez son ID de gestion :
course-token revoke legacy
curl -i -H 'Authorization: Bearer labex_012345abcdefghijklmnopqrstuvwxyz' http://127.0.0.1:8080/tickets
Le résultat attendu est 401. Émettez maintenant l'identifiant de remplacement sans l'afficher :
course-token issue /srv/ticket-regression/api.token
Protégez-le avec le modèle administrateur/groupe du client des labs sur les permissions et les jetons :
sudo chown root:deskclient api.token
sudo chmod 640 api.token
L'émetteur a créé la valeur ; vous définissez seulement son accès. Ne la copiez pas dans le code source des tests, le script client ou un rapport écrit.
Rétablir le client qui lit le fichier
Dans cette étape, vous ferez utiliser au client existant l'identifiant de remplacement protégé.
nano sender.sh
Enregistrez la même forme de lecture de fichier enseignée précédemment :
#!/bin/bash
exec sudo -u deskclient /usr/bin/python3 /opt/labex-ticket-regression/send.py --token-file /srv/ticket-regression/api.token
Utilisez Ctrl+O, Enter, Ctrl+X.
bash sender.sh
La sortie attendue est HTTP 200 et le ticket Printer offline d'origine. Lisez les événements opérationnels récents :
sudo tail -n 5 /opt/labex-ticket-regression/requests.log
La nouvelle requête réussie conserve les champs d'audit sans valeur d'identifiant. Une ancienne valeur divulguée peut rester dans l'historique d'incident conservé alors que son pouvoir d'authentification a été retiré. Cette distinction évite à la fois de supprimer les preuves et de considérer l'ancienne exposition comme un chemin d'authentification qui réussit encore.
Comprendre pourquoi le test existant a manqué la fuite
Dans cette étape, vous inspecterez le petit modèle de test avant d'ajouter la nouvelle exigence.
cat test_security.py
Le test positif utilise le modèle de requête du lab sur l'écriture de tests. L'utilitaire api préparé fournit token depuis la source d'identifiants de la cible et renvoie le véritable statut HTTP, le corps et l'événement de journal réel de cette requête. "Bearer " + token assemble deux chaînes pour former une valeur d'en-tête ; la valeur n'est pas copiée dans le code source.
Deux témoins distincts utilisent le jeton de test public fictif : good omet les champs sensibles du journal, tandis que logging-regression enregistre délibérément ce jeton de test. Ils n'utilisent ni n'exposent votre nouvel identifiant de remplacement opérationnel.
course-regression-tests good
course-regression-tests logging-regression
Les deux réussissent actuellement test_valid_token : le statut et les données métier restent corrects dans chaque implémentation. L'exigence manquante concerne le véritable événement dans response["log"]. Chaque requête de l'utilitaire utilise un ID unique : le journal renvoyé appartient donc à cette nouvelle requête, pas à un événement historique sans rapport.
Ajouter une véritable assertion de masquage des données sensibles du journal
Dans cette étape, vous compléterez le test avec des exigences d'absence et de présence pour le nouvel événement.
En Python, in vérifie si une chaîne apparaît à l'intérieur d'une autre. not in exige son absence. Ces assertions concernent le véritable texte du journal renvoyé, pas un fichier de preuve fourni manuellement.
nano test_security.py
Conservez le test positif et utilisez ce fichier complet :
from api import request, token
def test_valid_token():
response = request("/tickets", {"Authorization": "Bearer " + token})
assert response["status"] == 200
assert response["body"] == {"tickets": [{"id": 1, "title": "Printer offline"}]}
def test_log_is_redacted():
response = request("/tickets", {"Authorization": "Bearer " + token})
assert response["status"] == 200
assert "Authorization" not in response["log"]
assert token not in response["log"]
assert "request_id=" in response["log"]
assert "path=/tickets" in response["log"]
assert "status=200" in response["log"]
Enregistrez avec Ctrl+O, Enter, Ctrl+X. Le nouveau test rejette le champ sensible et la valeur d'identifiant tout en exigeant l'ID de requête, le chemin métier et le statut de réussite. Vider le journal ferait échouer ces exigences positives.
L'utilitaire fournit en interne un jeton propre à la cible. Les tests du service normal lisent l'identifiant de remplacement protégé ; les témoins de comparaison utilisent le jeton de test public fictif. Aucune de ces valeurs n'a sa place dans ce fichier de test.
Prouver que le test détecte la régression connue
Dans cette étape, vous validerez la nouvelle assertion face à un comportement sûr et à un comportement présentant délibérément une fuite.
course-regression-tests good
Les deux tests doivent réussir.
course-regression-tests logging-regression
Seul test_log_is_redacted doit échouer avec AssertionError, en renvoyant le code de sortie 1. Il s'agit d'une détection intentionnelle, pas d'une demande d'affaiblir l'assertion. Le test métier positif doit continuer à réussir.
course-regression-tests live
Les deux tests doivent réussir contre votre véritable service corrigé. Ces tests n'inspectent que les événements de leurs nouvelles requêtes ; l'événement historique divulgué d'origine est intentionnellement conservé. Une erreur de syntaxe, une erreur de connexion ou un échec inconditionnel ne démontrerait pas une couverture efficace du masquage des données sensibles.
Relier le nouveau test à la livraison du candidat
Dans cette étape, vous empêcherez la livraison d'un futur candidat lorsque la nouvelle assertion échoue.
Le contrôle préparé utilise la même structure vérification/construction/test/déploiement que dans le lab précédent sur les contrôles bloquants. build.sh empaquette le serveur d'origine et la politique de journalisation actuelle, puis démarre ce véritable candidat sur un port local distinct. Le test.sh existant vérifie son comportement avec jeton valide/absent/erroné ; il ne vérifie pas les journaux.
nano gate.sh
Ajoutez l'appel de non-régression après la construction et avant les tests fonctionnels existants. Utilisez :
#!/bin/bash
bash checks.sh
status=$?
if [ "$status" -eq 1 ]; then
exit 1
fi
if [ "$status" -ne 0 ]; then
exit 2
fi
bash build.sh || exit 2
bash regression.sh candidate || exit 2
bash test.sh || exit 2
bash deploy.sh
Enregistrez avec Ctrl+O, Enter, Ctrl+X. candidate sélectionne la véritable application qui vient d'être construite : l'assertion ajoutée protège donc l'artefact sur le point d'être déployé. || exit 2 arrête la livraison si ses tests échouent.
bash gate.sh
Le contrôle préalable des identifiants, la construction du véritable candidat, la réussite des nouveaux tests de non-régression, celle des tests fonctionnels et le déploiement de ce candidat sur le port local opérationnel sont attendus. Laisser simplement un fichier de test inutilisé n'apporterait pas cette prévention.
Confirmer les nouveaux événements et l'historique conservé
Dans cette étape, vous vérifierez le comportement livré et réfléchirez aux preuves sans rédiger de fichier de rapport.
bash sender.sh
sudo tail -n 5 /opt/labex-ticket-regression/requests.log
Les nouveaux événements opérationnels doivent conserver l'heure, la véritable version livrée, les ID de requêtes, les chemins et les statuts sans identifiants. La version livrée est maintenant une empreinte d'artefact au lieu du libellé logging-v2 d'origine.
sudo grep 'request_id=initial-001' /opt/labex-ticket-regression/requests.log
L'événement d'incident d'origine existe toujours. Son ancien jeton est révoqué ; l'identifiant de remplacement protégé fonctionne. Le témoin distinct de régression délibérée est une comparaison pédagogique, pas le service déployé.
Expliquez-vous quel événement a révélé le problème, quel paramètre l'a causé, pourquoi la seule correction de politique était insuffisante et comment la nouvelle assertion sur le candidat empêche sa réapparition. La vérification du cours exerce un candidat présentant réellement la régression, confirme que le contrôle le bloque et vérifie que l'artefact sûr précédemment en cours d'exécution est préservé. Aucun document d'investigation à format imposé n'est requis.
Résumé
Vous avez relié un véritable événement d'incident à sa politique de journalisation, arrêté les nouvelles fuites, révoqué et remplacé l'identifiant exposé, et conservé les preuves historiques. Une nouvelle assertion détecte la régression délibérée et s'exécute sur le véritable candidat à l'intérieur du contrôle de livraison, préservant un comportement sûr en cours d'exécution lorsqu'un futur candidat échoue.



