Guide de survie en situations compliqués
Bien le bonjour à toi, qui passes en ces contrées reculées !
Est-ce que tu as déjà récupéré du code ou une infra que tu ne connais pas ? C’est une situation peu enviable et qui peut arriver à n’importe qui.
Imagine une personne centrale à une organisation qui part et qui laisse tout en plan : pas de documentation, pas de certitude sur le versionnement des applications, aucune procédure sur l’installation des applications, pas de certitudes sur les dépendances et les services installés.
C’est la merde, non ? un peux ! mais je vais te donner mes astuces pour rentrer en résistance face a une base code médiocre et une infra claqué au sol !
Récupérer de l’information, humaine et technique
Il te faut par tous les moyens, obtenir de l’information sur la ou les applications que tu récupères. Transforme-toi en reporter du Daily Planet et fais la «fouine journalistique». Renseigne-toi sur comment l’application est utilisée, ce qu’en disent les utilisateurs, faits ou ragots te donnent une première idée de la popularité ou de la détestation du produit.
La réputation de fiabilité ou de nid à bugs du produit donne une première indication sur la qualité des développements du code. Un code non documenté n’a pas été pensé pour être partagé ou étendu et indique probablement un développeur ou une équipe repliée sur elle-même. Un code non documenté n’est pas un bon signe de la bonne santé d’une application.
Cherche des informations sur le projet dans un board Kanban. Le suivi dans Jira ou un autre outil, donne une idée assez précise de la maturité des développeurs et du sérieux de la gestion du management de l’équipe. Pas de Jira ou pas de suivi de tickets annoncent une organisation chaotique et une mauvaise gestion de projet. Idéalement, le gestionnaire de repo Git est garant de la dernière version du code déployée en production ; il donne aussi quelques informations historiques et infalsifiables sur la manière dont le produit a été conçu, à condition que le code ait été versionné de manière rigoureuse et régulière.
Il te faut récupérer des accès sur les machines dès que possible, une clef SSH nominative et un compte utilisateur sur toutes les machines sous ta responsabilité.
Idéalement, un playbook Ansible pour ajouter et révoquer des utilisateurs et leurs clefs, il doit être automatisé en CICD pour assurer un audit et une propagation des autorisations garanties.
Bien sûr, si tu utilises un vrai Cloud Provider comme GCP, utilise gcloud SSH ou les métadonnées de Compute Engine pour la gestion des clefs.
Une fois les accès obtenus, voici les points à vérifier systématiquement :
- regarder le dossier home des utilisateurs à la recherche de fichiers ou dossier intéressants (scripts, credentials, codes, clefs SSH autorisées et clefs privées)
- lister les processus et les sockets bind
- chercher si des containers tournent sur cette machine
- chercher des cron dans crontab sur chaque utilisateur et dans /etc/cron*
Si des services de bases de données sont actifs sur la machine, il faut absolument s’assurer que des backups externalisés sont en place.
/!\ Si du code est présent dans la machine, fais un différentiel systématiquement avec la dernière version du code dans Git avant de faire la moindre modification. Versionne les secrets dans un vault ou dans le gestionnaire de version avec Ansible Vault ou Git Crypt.
Reverse Engineering
C’est une action controversée (assure-toi d’avoir l’autorisation de le faire), scanne les adresses publiques des machines pour identifier les ports ouverts sur Internet.
Audite les secrets pour rechercher des mots de passe trop simples et des bases de données exposées publiquement. Assure toi de connaître toutes les applications connectées à la base de données si tu dois modifier le mot de passe de l’utilisateur de la base de données. Pense toujours à la disponibilité de l’application et prévient les utilisateurs d’une plage horaire d’indisponibilité.
Il est essentiel de ne pas compromettre la confiance des utilisateurs et d’éviter autant que possible les interventions non planifiées.
Fait un diagramme macro des services utilisés par l’application et des flux de données. Documente les fonctionnalités de l’application au fur et à mesure de tes découvertes. Alerte immédiatement en cas de risque sécuritaire majeur et proposez des actions correctives rapides.
Commit or Delete
Une fois que tu as fait tout ça, c’est là que la fête commence !
Pose-toi la question : à quoi sert ce code ?
Si le code n’est pas normalisé, pas reformaté, pas commenté et est dénué de toute structure, il faut se demander si on peut le maintenir ou si il faut le supprimer. Je vais utiliser ici mon expérience de joueur de jeux vidéo pour faire quelques analogies avec notre situation ! Un boss de jeux vidéo est toujours conçu avec un ou plusieurs points faibles. Ce qui veut dire que le problème est forcément abordable, soit par connaissance des points faibles, soit avec de la technique et beaucoup de persévérance. Un ou plusieurs humains a pondu cette merde donc les leviers sur lesquels tu peux t’appuyer sont les suivants :
- la complexité est relative : plus tu passes du temps à étudier le produit, plus tu le maîtrises.
- le produit repose sur la somme des compétences de ceux qui l’ont produit.
- un code personnalisé = des problèmes personnalisés (tu peux rencontrer des problèmes uniques à ton produit)
- ta persévérance et ta résilience ne doivent pas épuiser ta santé mentale.
- demande de l’aide :
- si tu n’as pas d’amis, utilise chatgpt pour chopper des astuces ou comprendre le code
- /!\ fais très attention à ne pas donner de code sensible : utilise des exemples génériques et ne donne pas tes secrets
- automatise la livraison de l’application le plus rapidement possible pour être sûr des livraisons et de leurs rollback.
Savoir abandonner un produit qui pu des pieds, ou changer de chaussure
Si ton produit pose trop de problèmes et ne rend pas service avec peu de résultats tangibles, dégage cette grosse merde ! Dans tous les cas, il est important d’avoir au moins un deuxième environnement pour tester les modifications.
Si ton application est unique et qu’un seul code personnalisé peut rendre ce service, tu es dans le pire scénario possible :
- Fais des tests automatisés pour documenter le fonctionnement de l’application
- Mets en place un strangler pattern pour reproduire le fonctionnement testé à l’identique avec une nouvelle codebase
- Supprime petit à petit les morceaux d’applications que tu viens de remplacer, en continuant de maintenir et documenter la nouvelle codebase.
Si ton application est remplaçable, mets en place une stratégie de migration de données :
- Mets en place un ETL pour migrer les données au fur et à mesure que tu remplaces le fonctionnement de ton application
- L’application de remplacement doit avoir une base synchronisée en read-only, pour ne pas avoir des modifications de données des deux côtés
- Une fois que le fonctionnement en read-only est validé, bascule vers la nouvelle application en read/write et teste les écritures
- Décommissionne l’ancienne application.
Conclusion
Le code déglingué n’est pas une fatalité ! Il faut apporter de l’organisation et de la structure pour réduire la pénibilité de la maintenance du code. L’automatisation apporte une réduction de la fatigue des tâches répétitives et apporte plus de sérénité et de temps pour améliorer l’existant. La santé mentale est primordiale et doit être préservée au maximum, ce n’est pas un sprint mais une longue course de fond ! Un changement applicatif ne fonctionnera que si la nouvelle application est testée correctement.