30 juillet 2020

Retour sur l’EuroPython 2020

Cette année, BSSI était virtuellement présent à l’EuroPython 2020. Chaque année cette conférence se déroule durant le mois de juillet dans un pays différent. Cette fois-ci elle devait se dérouler à Dublin, cependant avec cette année un peu particulière, l’EuroPython à tout de même eu lieu malgré la crise du COVID-19, le tout 100% en ligne.

Docker and Python: Making them play nicely and securly

(Par Tania ALLARD)

Tania ALLARD est Cloud Developer chez Microsoft. Elle a été intervenante durant cette conférence et a décidé de nous parler de Docker et Python, le fonctionnement de docker, son utilisation, la mise en place de sécurité et a fini en nous donnant quelques astuces et conseils à ce sujet.

Qu’est-ce que Docker ?

Docker est un logiciel Open Source distribué depuis mars 2013. L’utilisation de celui-ci permet d’améliorer et faciliter la flexibilité́ ainsi que la portabilité́ d’applications ou d’environnements de production afin de les faire fonctionner de manière fiable et prévisible sur différentes machines hôtes.

Cet outil permet de créer, déployer et faire fonctionner des projets en utilisant des conteneurs qui apportent une facilité de portabilité des logiciels lorsqu’ils passent d’un environnement informatique à un autre. Lorsqu’un développeur crée une application, il est nécessaire d’utiliser des librairies, des dépendances ou des fichiers de configurations. Cependant l’ensemble de ces éléments n’est pas forcément présent s’il change d’environnement, Docker permet de faciliter cette portabilité.

Grâce à Docker chaque conteneur fonctionne de manière indépendante sur la couche application de la machine et tourne comme un processus isolé contrairement à une machine virtuelle : 

 

Les images et conteneurs

Pour lancer un conteneur il est nécessaire de choisir une image. Cela représente une archive avec l’ensemble des éléments et des données nécessaires pour faire fonctionner l’application. L’exécution de cette image lance un conteneur.

Il est possible de créer sa propre image Docker à l’aide d’un Dockerfile en lui fournissant les instructions pour installer un logiciel, configurer votre image ou copier des fichiers ainsi qu’exécuter des commandes.

Le Dockerfile suivant va créer une image personnalisée sur la base d’une image python pré-existante (FROM python:3) mais avec Flask et Pandas déjà installés (pip install flask / pip install pandas).

Il y a tout de même de bonnes pratiques à appliquer lors de la création d’un Dockerfile :

  • Sachez ce que vous voulez (évitez d’utiliser les tags « latest » et utilisez des tags spécifiques pour éviter des problèmes lors de l’ajout de nouvelles images)
  • Ajoutez les contextes à l’aide du champ LABELS (afin de savoir qui est le mainteneur ou ajoutez des liens de documentations)
  • Ne groupez pas tous les RUN ensemble
  • Favorisez l’instruction COPY plutôt que ADD
  • Utilisez le cache afin de construire les images plus vite

Il est également possible de monter un volume entre le conteneur et la machine hôte afin de partager un répertoire :

Sécurité et performance

Il est important de minimiser les privilèges accordés lors de l’utilisation d’un conteneur afin de minimiser ou prévenir les attaques. En premier lieu il est nécessaire d’instancier le conteneur en utilisateur ne disposant pas des droits root. En effet, par défaut, Docker utilise l’utilisateur root afin de mettre à jour les librairies ou réaliser une installation avec un simple “apt-get”.

Pour cela il est nécessaire de rajouter l’des instructions (RUN useradd et USER) au sein du Dockerfile :

Il est également nécessaire de faire attention aux fuites d’informations, car il est fréquent que les variables d’environnements correspondent à des mots de passes ou des clés d’API. La première façon de sécuriser vos conteneurs est d’ajouter les fichiers qui contiennent ces clés à votre .dockerignore afin qu’ils n’y entrent pas. Il ne faut surtout pas les mettre au sein du Dockerfile.

Un autre moyen de sécuriser ses conteneurs et garder ses informations secrètes est d’utiliser Docker multi-stage build. Si ces informations sont gérées dans une couche intermédiaire, elles ne seront pas présentes dans l’image finale. Il est également conseillé d’utiliser une image compilée qui va compiler les éléments dans une image et par la suite une autre image runtime qui va s’occuper de copier ou installer les packages. Généralement cela permet également de créer des images moins volumineuses.

Exemple d’un Dockerfile multi-stage :

L’image finale obtenue est la runtime image qui sera par la suite utilisée afin de déployer un conteneur. A la suite de cette commande, il restera une image résiduelle de compile-image qu’il sera possible de supprimer.

Enfin, voici quelques conseils donnés par Tania lors de sa présentation :

  1. Recréez son image de manière fréquente afin de garantir la mise à jour des différents packages
  2. Ne travaillez pas avec l’utilisateur root, minimizez les privilèges
  3. Il n’est pas nécessaire d’utiliser une image Alpine Linux, car celle-ci est très légère, mais possède très peu de ligne de commande.
  4. Exploitez le cache de construction a un impact significatif sur les performances et la sécurité de votre image
  5. Utilisez un dockerfile par projet (ne pas réutiliser ses anciens dockerfile)
  6. Utilisez les multi-stage builds (création d’un builder et d’un runner)
  7. Faites des images identifiables (test, production, R&D) et soyez prudent pour les accès aux bases de données et sur l’utilisation des variables d’environnements
  8. Si vous n’avez pas besoin d’un setup complexe ou d’une configuration spécifique, utilisez repo2docker (pour l’analyse de données ou le machine learning )
  9. Utiliser un linter (détecteur d’erreurs lors de la création des dockerfile et docker-compose)

Information supplémentaire :

Writing Good Python

(Par Prashant Chaubey)

Prashant Chaubey est un ingénieur logiciel chez HubSpot. Il a été intervenant sur le deuxième jour des conférences avec une présentation sur les bonnes pratiques et les bons outils à mettre en places pour écrire du code Python lisible et robuste.

Pendant la première partie de la conférence, Prashant explique que Python est un très un bon langage de programmation. Cela est dû au fait qu’il est très facilement lisible pour un novice comparé à d’autres langages bas niveau comme le C ou C++, qu’il dispose d’un écosystème massif, comportant des centaines de librairies, Frameworks et outils en tout genre. Pour finir, il conclut sur le point le plus important en nous expliquant que Python dispose de la communauté la plus importante et active dans le domaine de le programmation informatique.

Après avoir parlé des points forts de Python, Prashant nous explique comment produire du code de haute qualité. Cela commence par un calcul simple à mettre en place, celui de la maintenabilité de son code. Ce calcul aura pour but de voir si votre code peut facilement accepter les changements en réduisant le risque de briser la logique du code.

Une image contenant capture d’écran

Description générée automatiquement
  1. Produire du code de haute qualité.

Dans cette section nous allons voir deux modules nécessaires pour avoir du code respectant les standards du développement Python.

Commençons par du code de mauvaise qualité. Comme nous le constatons, la syntaxe de la classe ne respecte pas le standard PascalCase et les fonctions ne respectent pas le standard snake_case. Également, les Docstrings ne sont pas présentes sous la classe et les fonctions.

Pour remédier à ces problèmes de syntaxe, le module Pylint est là pour nous aider.

Pylint est un logiciel permettant de vérifier le code source ainsi que la qualité du code pour le langage de programmation Python. Pylint utilise les recommandations officielles du standard de développement PEP8.

L’installation de Pylint : pip install pylint
Utilisation de Pylint : python3 -m pylint bad_example.py

Une image contenant texte

Description générée automatiquement

Nous constatons qu’une multitude d’erreurs de syntaxe a lieu dans notre code. Il suffit de suivre les recommandations de Pylint pour corriger ces dernières.

 Voici le résultat après correction des erreurs.

Malgré la correction des erreurs de syntaxe, des erreurs dans les Docstrings persistent dans notre fichier.

Pour remédier à ce problème, l’outil Pydocstyle est nécessaire. Pydocstyle est un outil d’analyse statique de code permettant de vérifier le respect des conventions Docstrings de Python. Il va nous permettre de corriger les commentaires situés en dessous des classes et des fonctions tout en respectant le standard PEP257.

L’installation de Pydocstyle : pip install pydocstyle
Utilisation de Pydocstyle : python3 -m pydocstyle bad_example.py

  • Éviter les erreurs de types

À présent nous allons voir comment mettre en place le standard PEP484 permettant d’éviter les erreurs de types. Nous avons au préalable écrit dans notre code les types que nous souhaitons mettre en place pour nos arguments.

Mypy est un outil permettant de faire de l’analyse statique de code en Python et d’identifier les erreurs de types.

Installation de Mypy : pip install mypy
Utilisation de Mypy : python3 -m mypy bad_example.py

Une image contenant capture d’écran

Description générée automatiquement

Nous constatons une erreur de type, car dans notre code nous attendons Num1 = Float ; Num2 = Float et le retour de notre fonction = Float. Cependant notre fonction a reçu un type String. Il existe une alternative à Mypy nommé Typing permettant de créer nos propres types de données grâce à la classe TYPE_CHECKING.

Une image contenant capture d’écran

Description générée automatiquement
  • Détection de vulnérabilité dans le code Python

Le module Bandit est dédié à la recherche de vulnérabilité dans votre code Python. Il est fourni avec une multitude de tests comme la vérification des mots de passe codés dans les fichiers, les clés cryptographiques faibles, etc.

  • La mise en place des différents modules dans votre projet

Grâce à au module pré-commit vous allez pouvoir lancer tous les modules sur votre code Python avant le dépôt sur votre répertoire Github.

Installation de pré-commit : pip install pre-commit
Utilisation de pré-commit : pre-commit run

Pour configurer l’automatisation des tests, il est indispensable de créer un fichier .pre-commit-config.yaml afin d’y ajouter les modules de votre choix.

Une image contenant capture d’écran

Description générée automatiquement

Vous avez maintenant toutes les cartes en mains pour écrire du code Python lisible et robuste tout en respectant les standards définis par le langage Python.

« Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex. »

Vous souhaitez plus d’informations sur l’EuroPython, édition 2020 ? C’est par ici :

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *