bla bla bla proxy
Ferme pas la porte, met des proxys dans ton IAAS
Un truc que j’adore particulièrement dans mon métier c’est les proxy.
Pas les proxy market hein 🙄 on ne parle pas d’aller chercher de la 8.6 et de la Amsterdam 🤷
Non, aujourd’hui on parle proxy caca est-ce que tu es familier avec le concept ? Non ?
Alors, reste bien jusqu’à la fin, cet article est sponsorisé par lotus confort.
et un proxy caca pour la 12
Imagine que tu traînes une appli dégueue, mais alors un truc sale, codée avec des moufles, avec des bugs, des vulnérabilités, pas tellement documentée avec le code offusqué par design tellement les devs ont fait des efforts de créativité.
Seulement voilà, le truc est en prod et c’est une application très importante pour le métier.
Pire encore, on ne sait pas la remplacer, mais on a besoin de faire évoluer l’écosystème qui consomme les données de cette application.
On dit que de toute façon on ne bougera pas le dinosaure. Le truc va finir de moisir dans son coin jusqu’à être recouvert de champignons. Ça coûterait une blinde de le bouger, ça demanderait des plombes avec finalement pas ou peu de plus-value.
Si le truc est plus ou moins abandonné, probablement que des tests n’ont jamais été implémentés.
Donc comment continuer à consommer cette application de manière plus sécurisée et sans trop perdre en performance ?
Lavez-vous les mains après
C’est là que vient en jeu le proxy caca 💩💩.
L’idée, c’est de faire un équipement intermédiaire avec le minimum de code, le plus simple et sécurisé possible. On vient faire le videur de boîte de nuit et filtrant très fortement les requêtes entrantes avant de les transférer au legacy. Pour faire ça, une solution légère, rapide et simple à maintenir.
Je vous conseille FastAPI qui est un framework python complètement dingue
Il a comme avantage majeur de produire un swagger auto généré et de filtrer les URL avec des objets propres, et bon nombre de petites astuces déjà incluses dans le framework pour faire des Middlewares.
Si vous ne connaissez pas swagger ou que vous avez abandonné l’idée c’est que probablement c’était trop relou à maintenir dans votre organisation.
Mais là c’est différent, on vous dit que c’est inclus dans le framework, autogénéré et hébergé dans ton python directement.
Également swagger permet de faire des requêtes directement formatées, un peu en mode postman du pauvre (oui je sais postman ça soûle gnagnagna)
Ça veut aussi dire que si tu n’as pas la motivation de changer le comportement par défaut de swagger, tu as un truc minimum qui fonctionne et qui se met à jour en même temps que tes routes. J’ai ton attention maintenant ? Non, parce que là vraiment tu fais pas d’efforts, tu soûles sérieux.
Un coup de pydantic pour vraiment filtrer les inputs.
Le but de pydantic c’est de décrire ton modèle de données et d’en faire de beaux objets et de décrire comment tu veux les valider.
Hey toi, tu rentre pas, t’es bourré 🤪
Bien sûr tu mets pas ça dans un compute comme un boulet 😏
Utilise plutôt une solution serverless, au hasard cloudrun, pour éviter de traîner un compute allumé tout le temps, comme un gros ringard.
Effets sympas:
- Les containers ça deploy et roolback ultra vite
- tu as les logs qui remontent sans conf particulière ou installation relou
- Tu peux dupliquer à volonté
- tu payes à la consommation (pas aussi chère qu’en boite de nuit, mais je digresse)
- autoscaling par défaut
et il est où le code ?
Je vous mets ici un exemple rapide que j’ai dev vite fait avec un demi-neurone. Je vous file un peu de contexte. J’ai pris une application qui sert à s’entraîner sur les outils de pentest. Donc bien évidemment, c’est du PHP 🤪 et c’est codé exprès (sans trop d’effort) avec des vulnérabilités.
Quelqu’un de sympa a packagé le truc dans un docker, donc je vous mets les sources
https://github.com/Cyrivs89/docker-dvws
|
|
on voit que le site est sensible à une requête SQL toute simple
|
|
Et paf, le user 2, mais aussi toute la famille, sauf que tu as prévu à manger que pour Gordon Brown ¯\_(ツ)_/¯.
Il prend juste en paramètre un id, donc là, on fait un code crado de gros débile.
|
|
et juste ce bout de code tout simple protège le point d’accès sans même altérer l’URL de base
requête legit
|
|
Et en plus on renvoie un beau HTTP 405 Method Not Allowed pour te dire d’aller t’injecter du SQL ailleurs que dans mes toilettes, heu mon appli.
|
|
BAM t’a cru que c’était du PHP, mais en fait non, rupture de langage, ça te la coupe hein ? Donc là on a un message d’erreur sale, mais l’URL est protégée.
En plus effet kiss cool,j’ai mon swagger auto généré qui me dit comment requêter mon appli.
Bien sûr mon exemple est ultra simple et c’est bien plus compliqué dans la vraie vie, mais vous avez compris l’idée.
Vous pouvez très bien transmettre des requêtes authentifiées et rajouter quelques petits trucs sympas par-dessus.
- forcer l’utilisation d’un host particulier avec TrustedHostMiddleware
- forcer la redirection des requêtes HTTP en HTTPS
optimisation, le proxy cacache 🤷
L’idée c’est de mettre en cache le résultat de tes requêtes read les plus courantes, dans un redis par exemple.
Par contre ça demande un peu plus de travail et de mettre en place une stratégie de cache .
Ma préconisation perso c’est de mettre une durée de vie du cache à 1/3 de sa durée de vie supposée.
L’idée c’est d’éviter au maximum de servir des données froides, mais de soulager les read rapides avec du cache récent.
Exemple, on sait que notre client met à jour ses produits au maximum 1 fois par jour. Ce n’est donc pas tellement déconnant de flush le cache toutes les 8h. (Avec une option de flush declenchable via api si on veut vivre dans le luxe et l’opulence)
Cet exemple est complètement éclaté au sol, mais vous comprenez le principe 🤷
fast api supporte l’utilisation d’un cache externe
(vous voulez ça pour éviter de trainer un cache in memory qui ne marchera pas en serverless)
https://github.com/long2ice/fastapi-cache
concept car
Après calmez vous, ça reste de la merde, un moteur de supercar à l’avant et une charrette avec des roues en bois à l’arrière. (La plupart des supercars ont le moteur à l’arrière, c’est dire si cette implémentation est bancale)
Une fois que vous avez ça, on peut commencer à être un peu plus malin et mettre dans le code un circuit breaker.
L’idée c’est qu’on sait que papy avance doucement, donc on met un coupe-circuit dans le proxy ou cas où des jeunes lui piquent sa canne. Et dès qu’il est de nouveau debout on renvoie les requêtes.
À vous de gérer ensuite les coupures de circuit dans l’appli qui consomme les données de papy 🤷
et BAM quelqu’un à déjà implémenté ça dans une lib python
https://github.com/fabfuel/circuitbreaker
on voit long terme, on enterre le legacy
Une fois qu’on a stabilisé le proxy, on peut pousser encore plus loin et utiliser le strangler pattern pour découper cette grosse merde et en faire une application modulaire 😏
Puisqu’on est dans la passion de la violence, l’idée du strangler pattern c’est d’étrangler les features du legacy une par une. Comprendre on réécrit les features dans du neuf et petit à petit on route les anciennes routes legacy vers le nouveau backend.
On recode une fonctionnalité du legacy d’une façon plus moderne, et cette fois-ci, on documente et on teste, on ne refait pas les mêmes erreurs de boulet. Une fois notre feature prête, on ajoute dans le proxy une route vers cette feature qui remplace l’ancien service.
Éviter autant que possible de faire évoluer la même appli en même temps sur le legacy, ça ne sortira jamais en prod sinon 🤷
Nouveau besoin, on reproduit la feature existante à l’identique et ensuite on ajoute du code.
Rocky bat le boa et pourtant c’est un boa constrictor.
On peut partir vers des microservices si on sait ce qu’on fait ( et que ça répond à notre besoin )
- Partir vers du kube a un coût important et le risque d’échec est important si on est mal accompagné.
- Partir vers du serverless peut réduire vos coûts d’entrée, mais ne répond pas à tout les besoins.
Pourquoi ne pas refaire un monolithe mieux construit?
(C’est le paradoxe, ça a l’air con, mais des microservices c’est pas toujours la solution à votre problème
et ça ajoute une complexité importante là où on a pas forcément le besoin)
On peut cette fois-ci :
- mettre en place un feature flag dès les premières étapes de conception
- découper proprement front-end et backend avec des contrats d’API
- faire un changement radical de technologies (mais ça ne veut pas forcément dire mettre la nouvelle stack à la mode kikoo lol)
Pour le feature flag, pas besoin de produit funky qui coute une blinde ou relou à installer et maintenir comme consul. Astuce de cyberpunk à chien, un bête yaml dans un blob storage peux faire le taf, oublie l’idée à partir de plus de 30 flags, prend un truc managé plus robuste.
Dernière solution, si votre application le permet, bouger votre appli dans le cloud en gardant le proxy pour profiter de machines plus puissantes voir de services managés. (Mais si votre machin n’évolue plus du tout, autant le laisser mourir sur place et le faire renaître en meilleure forme ailleurs)
conclusion
- Une appli de merde ce n’est pas forcément fatal, mais faut s’en occuper
- Une merde reste une merde, même bien emballé.
- Une appli ancienne et mal entretenue peut être une dépendance critique dans votre business
- Une appli en prod doit être entretenue et documentée pour éviter d’être un calvaire moyen ou long terme .
Avec une couche d’abstraction et un peu de code on peut:
- Ajouter une couche de sécurité
- Filtrer et documenter les inputs
- Faire une API auto documentée swagger
- Ajouter un circuit breaker
- Ajouter du cache en lecture sur les objets les plus consommés