Le guide ultime pour créer un package Python sécurisé
Gourav Singh Bais
8 mai 2024
0 minutes de lectureLa création d’un package Python implique plusieurs étapes : définir une structure de répertoires adaptée, créer les fichiers du package et configurer ses métadonnées avant de le déployer. Vous devrez également suivre quelques autres étapes, notamment créer un sous-répertoire pour les tests et rédiger une documentation claire. Une fois le package prêt, vous pouvez le distribuer dans différents dépôts. Votre package Python sera alors prêt à être installé et utilisé.
Ce guide détaille toutes les étapes pour créer un package Python moderne. Vous trouverez le code nécessaire pour suivre ce tutoriel dans ce dépôt GitHub. À l’issue de ce tutoriel, vous verrez que créer un package Python peut être aussi simple que d’en utiliser un existant. Mais commençons par apprendre à utiliser les packages en Python.
Comment créer un package Python
Avant de créer un package Python, vous devez passer en revue les différentes méthodes d’installation et d’importation, ainsi que la structure générale des packages.
Installer des packages en Python
Pour utiliser des packages Python, vous pouvez recourir aux packages publics disponibles sur PyPI ou à des index privés contenant du code propriétaire au sein d’une organisation.
Voici deux façons d’installer un package Python :
Utiliser PyPI
PyPI est le dépôt officiel qui héberge tous les packages Python publics.
Utiliser un index privé
Dans certains cas, vous devrez peut-être utiliser des packages publics disponibles sur PyPI et des packages privés accessibles via un index privé. Les grandes organisations utilisent généralement ces index pour leurs projets propriétaires, dont le code source n’est pas destiné à être rendu public. Ils permettent de stocker et de distribuer des packages Python en interne.
Pour installer des packages depuis un index privé, vous pouvez utiliser la commande pip install avec l’option -- index-url, suivie de l’URL de l’index privé et du nom du package. Voici un exemple de commande à exécuter pour installer un package :
Pour des raisons de sécurité, il est recommandé d’utiliser Transport Layer Security (TLS) sur tout index de packages privé. Si votre index privé ne dispose pas d’un certificat TLS valide, vous devrez spécifier l’option -- trusted-host dans votre commande pip install pour y installer des packages. En effet, sans certificat TLS valide, pip considère que l’index n’est pas fiable.
Importer un package Python
Vous pouvez importer un package en Python à l’aide de l’instruction import. L’interpréteur Python recherche alors le package dans le cache, les bibliothèques intégrées et les chemins d’installation. Si le package est introuvable, une ImportError est déclenchée.
Vous pouvez également importer des modules spécifiques d’un package avec le mot-clé from, comme ceci :
Vous pouvez aussi importer plusieurs modules ou tous les modules d’un package à l’aide des commandes suivantes :
Vous pouvez également attribuer un alias à un package à l’aide du mot-clé as. Par exemple, vous pouvez utiliser le package `pandas` sous le nom pd, comme ceci :
De quoi se compose un package Python ?
Les packages Python doivent respecter une structure de répertoires qui comprend les fichiers et sous-répertoires suivants :
Un répertoire
srccontenant un sous-répertoire au nom du package, avec un fichier d’initialisation__init__.py. Le répertoiresrccontient également un ou plusieurs fichiersmodule.pyavec le code source du package.Un répertoire
testscontenant des scripts pour tester différentes fonctions du package. C’est à vous de décider si vous souhaitez inclure ce répertoire dans le package.Un fichier
pyproject.tomlcontenant la configuration de votre package et ses dépendances.Un fichier
LICENSEdéfinissant les conditions d’utilisation de votre package. Vous pouvez choisir parmi de nombreuses licences ou créer la vôtre.Un fichier
README.mdcontenant une documentation claire, des instructions d’utilisation et toute autre information utile pour les utilisateurs du package.
Les fichiers et répertoires mentionnés précédemment constituent les éléments de base nécessaires à la création de votre package. Vous rencontrerez peut-être des structures plus complexes, avec des fichiers, des sous-modules ou des tests supplémentaires.
Empaqueter votre code
Pour rendre un package Python accessible au public, vous devez commencer par le créer. Ce tutoriel vous guide dans la création d’un programme Python simple qui convertit des kilomètres (km) en miles (mi).
Choisir le nom de votre package Python
Pour nommer votre package Python, vous devez vérifier sur PyPI si le nom choisi est déjà utilisé. En général, les développeurs utilisent le même nom sur PyPI et pour leur package, mais vous pouvez en choisir un autre si vous le souhaitez.
Lors de l’installation d’un package, vous devez utiliser son nom sur PyPI. Pour importer un package, vous devez utiliser le nom du package.
Configurer votre package Python
Vous devez structurer votre package conformément à la structure de répertoires requise décrite précédemment. Placez ce code dans le fichier km2miles.py. Vous pouvez créer un fichier __init__.py avec ce code.
Le fichier km2miles.py contient une fonction qui convertit les kilomètres en miles à l’aide de la bibliothèque NumPy. Le fichier __init__.py importe le module principal et indique la version du package.
Avant de publier le package, vous devez configurer le fichier pyproject.toml, dans lequel vous préciserez également le système de build, comme nous le verrons ensuite.
Configurer le système de build
Vous avez besoin d’un système de build pour générer les fichiers que vous publiez dans le package Python. Vous pouvez utiliser un outil frontal de build, comme pip, ou un outil dorsal, comme setuptools, Flit, Hatchling ou PDM.
Ici, vous allez utiliser setuptools, un outil de build qui résout automatiquement les dépendances des packages Python existants. Cela vous sera utile pour créer un package Python répondant à un besoin réel.
Le système de build utilise le fichier pyproject.toml, qui contient les instructions destinées aux outils dorsaux pour créer les packages de distribution du projet. Les spécifications du système de build sont définies dans ce fichier :
Vous trouverez peut-être en ligne des tutoriels qui n’utilisent pas le fichier pyproject.toml, mais plutôt un fichier setup.py pour configurer leurs packages Python. Auparavant, setuptools utilisait le fichier setup.py pour lancer le processus d’installation des packages complexes. Toutefois, pour les projets modernes, le fichier pyproject.toml est généralement recommandé pour configurer les projets Python, plutôt que les fichiers setup.py ou setup.cfg.
Configurer le package Python
Une fois le système de build configuré, vous devez renseigner les informations propres au package. Ces détails de configuration sont ajoutés sous les paramètres du système de build dans le fichier .toml :
La configuration d’un projet comprend généralement les informations suivantes. Il est recommandé de les inclure dans tous les packages, même si elles ne sont pas toutes obligatoires :
Nom : (obligatoire) nom du package utilisé sur PyPI
Version : (obligatoire) version actuelle du package, également affichée sur sa page PyPI principale.
Description : (obligatoire) informations complémentaires sur le package, affichées sur sa page PyPI.
Auteurs : (obligatoire) informations sur les développeurs du package.
Readme : (facultatif) description du package au format Markdown, avec notamment des instructions d’utilisation. Elle sera affichée sur la page PyPI principale du package.
Licence : (facultatif, mais vivement recommandé) informations sur les conditions d’utilisation du package.
Classificateurs : (facultatif) catégories décrivant le public cible, la compatibilité avec les plateformes et le niveau de maturité du package, qui facilitent sa recherche sur PyPI. Consultez la liste complète des classificateurs acceptés ici.
Mots-clés : (facultatif) liste de mots qui aident les utilisateurs à trouver le package sur PyPI en recherchant des termes associés. Par exemple, pour trouver un package qui convertit les miles en kilomètres, un utilisateur peut rechercher des mots-clés comme « convertisseur », « miles » et « kms ».
Spécifier les dépendances
Pour spécifier les dépendances dans le fichier `pyproject.toml`) d’un projet, ajoutez un champ dependencies après la description du projet :
Cela indique que le projet dépend de la bibliothèque NumPy. Lors de l’installation du projet, pip résoudra ces dépendances. Lorsque vous spécifiez des dépendances, gardez les points suivants à l’esprit :
Ne spécifiez pas les dépendances déjà prises en charge par des packages tiers.
Utilisez
>=pour spécifier une version minimale des dépendances nécessaires aux nouvelles fonctionnalités ajoutées dans une version donnée.Utilisez
<pour spécifier une version maximale des dépendances susceptibles d’entraîner des problèmes de compatibilité lors d’une mise à jour majeure.
Vous pouvez ajouter des dépendances facultatives à l’aide du champ project.optional-dependencies :
Ces dépendances ne sont pas installées automatiquement. Vous pouvez les spécifier lors de l’installation du projet avec la syntaxe pip install package_name[optional_dependency_name].
Gérer les versions de votre package
Comme indiqué précédemment dans ce tutoriel, vous pouvez attribuer une version à votre package Python à l’aide d’un numéro de version, que vous indiquerez dans la documentation du package. Ce numéro doit respecter le format de versionnage sémantique couramment utilisé MAJOR.MINOR.PATCH, où MAJOR désigne les changements importants apportés au projet, MINOR les nouvelles fonctionnalités et PATCH les corrections de bugs ou les améliorations des performances.
Voici comment ajouter une version au fichier de configuration :
Cela définit la version de votre projet sur 1.0.0. Vous pouvez ensuite mettre à jour le numéro de version lors de la publication de nouvelles versions du projet.
Tester votre package
Il existe plusieurs façons de tester votre package Python. Pour les petits projets, des tests manuels peuvent parfois suffire, mais il est toujours préférable de mettre en place d’autres types de tests automatisés pour vérifier que le code respecte certaines normes sans intervention manuelle. La disponibilité de tests automatisés renforce la confiance dans la fiabilité d’un package.
Tests unitaires : testez des portions de code spécifiques de manière isolée à l’aide d’un framework de test comme `robot`, `pytest`, `testify` ou `nose`.
Tests d’intégration : testez le fonctionnement conjoint des différentes parties du package en configurant des environnements de test et en exécutant le code. Vous pouvez utiliser un package comme `tox` pour mettre en œuvre des tests d’intégration.
Tests manuels : exécutez le code et vérifiez que les résultats obtenus sont ceux attendus. Vous pouvez utiliser n’importe quel client Python pour effectuer des tests manuels.
Vous pouvez placer tous ces tests dans le répertoire tests mentionné précédemment dans ce tutoriel. Les projets complexes nécessitent généralement des rapports d’analyse et de visibilité, ainsi que des rapports de couverture des tests. Pour cela, vous pouvez utiliser des packages comme coverage.py et `pytest-cov`.
Ajouter des fichiers de ressources à votre package
Pour inclure dans votre package Python des fichiers autres que le code source, comme des fichiers de données, des binaires, des manuels et des fichiers de configuration, vous pouvez créer un fichier de ressources appelé MANIFEST.in. Utilisez des règles dans ce fichier pour indiquer les fichiers à inclure ou à exclure lors de la création du package.
Par exemple, le code suivant inclura tous les fichiers .toml présents dans le répertoire src/mileConverter :
Vous pouvez également spécifier un fichier .toml distinct à cet effet.
Choisir une licence pour votre package
Pour inclure une licence dans votre package Python et permettre à d’autres de l’utiliser, créez un fichier nommé LICENSE dans le répertoire du package et choisissez une licence existante parmi les options proposées, par exemple sur choosealicense.com.
Dans le fichier pyproject.toml, vous devez indiquer le nom du fichier LICENSE dans la variable license pour que la licence apparaisse sur la page PyPI, comme vous l’avez fait lors de la configuration initiale du fichier pyproject.toml de votre package.
Parmi les licences open source les plus populaires, on trouve la licence MIT, la licence Apache et la GNU General Public License (GPL), mais vous avez le choix parmi de nombreuses autres.
Installer votre package en local
À ce stade, vous avez créé tous les fichiers nécessaires et effectué toutes les configurations requises pour votre package. Avant de le publier sur PyPI, vous devriez essayer de l’installer en local avec pip afin de détecter d’éventuelles erreurs. Pour cela, il vous suffit d’utiliser l’option -e ou - editable, qui indique que vous souhaitez installer le package en local, comme dans la commande suivante :
Maintenant que vous avez installé votre package en local, vous pouvez le publier sur PyPI.
Publier votre package sur PyPI
Pour publier votre package, vous devez d’abord le compiler.
Compiler votre package
Utilisez le package build pour générer un fichier wheel pour votre package Python. Pour installer le frontal de compilation, exécutez la commande suivante :
Accédez ensuite au répertoire contenant votre fichier pyproject.toml et exécutez la commande suivante :
Un dossier dist/ sera créé au même emplacement que le fichier .toml. Il contiendra deux fichiers :
Le fichier `.whl` est une distribution compilée, tandis que le fichier tar.gz est une distribution source. Vous pourrez ensuite téléverser ces fichiers sur PyPI, mais vous devez d’abord les tester.
Tester votre package
Pour tester votre package, vous devez installer `twine`, une bibliothèque qui vous aidera également à téléverser votre package sur PyPI. Vous pouvez l’installer à l’aide de la commande suivante :
Une fois twine installé, vous pouvez vérifier avec cette commande que la description de votre package s’affichera correctement sur PyPI :
La sortie de la commande précédente devrait ressembler à ceci :
Si tous vos tests réussissent, votre package est prêt.
Téléverser votre package sur le service TestPyPI
Avant de rendre votre package accessible au public, vous devriez le tester et le vérifier à l’aide du service TestPyPI. Pour cela, vous pouvez le téléverser sur TestPyPI, mais vous devez d’abord créer un compte sur le site web de PyPI. Vous pouvez ensuite utiliser twine pour téléverser votre package en exécutant la commande suivante. Vous aurez besoin de votre nom d’utilisateur et de votre mot de passe PyPI :
Une fois la commande exécutée avec succès, une URL vous sera fournie pour consulter les résultats. Vous pourrez également rechercher votre package sur le site web de TestPyPI. Pour télécharger votre package depuis le service TestPyPI, utilisez la commande suivante :
Une fois le package téléchargé, vous pourrez le tester pour vérifier qu’il fonctionne correctement.
Téléverser votre package sur le véritable service PyPI
Le téléversement sur le véritable service PyPI se déroule de façon similaire à celui sur TestPyPI. Après avoir validé votre package à l’étape précédente, vous pouvez le téléverser sur le véritable service PyPI. Utilisez à nouveau l’outil twine pour téléverser les fichiers de votre package sur PyPI.
Dans votre terminal, exécutez la commande suivante en remplaçant dist/* par le chemin d’accès aux fichiers de votre package :
Après avoir téléversé le package, vous pouvez vous rendre sur le site web et le rechercher.
Installer votre package
Vous devez maintenant tester votre package. Vous pouvez le télécharger à l’aide de la commande suivante :
Une fois le package installé, ouvrez un éditeur Python ou un environnement d’exécution Python et vérifiez qu’il fonctionne :
Le résultat devrait ressembler à ceci :
Votre package a été téléversé sur PyPI et est désormais accessible via pip dans n’importe quel environnement Python.
Publier votre package dans un index Python privé
Vous avez vu précédemment pourquoi certaines organisations peuvent souhaiter distribuer leurs packages à l’aide d’un index Python privé. De plus, publier votre package Python dans un index privé est simple. Il vous suffit de suivre ces étapes :
Créez une structure de répertoires pour votre package contenant des fichiers
.whlou.tar.gzà distribuer.Configurez votre serveur web pour qu’il serve le répertoire racine de votre package avec l’indexation automatique activée.
Utilisez
twinepour téléverser votre package dans l’index privé, en indiquant l’URL de votre serveur web privé$ twine upload - repository-url your_web_server milesConverter/*.Pour installer le package depuis l’index privé, utilisez la commande pip avec l’URL de votre serveur web (
$ pip install - extra-index-url your_web_server milesConverter).
Une fois ces étapes terminées, votre package sera disponible sur votre serveur web privé pour vous et votre équipe.
Bonnes pratiques de sécurité pour créer des packages Python
Maintenant que vous savez publier votre package, voici quelques bonnes pratiques à prendre en compte avant de le publier, afin de vous assurer qu’il est sécurisé et fonctionne correctement.
Soyez attentif à vos dépendances
Avant d’utiliser une dépendance tierce dans votre projet, consultez sa documentation pour voir si elle prévoit des contrôles de sécurité ou de vulnérabilités. De nombreuses bibliothèques consacrent une section entière de leur documentation aux problèmes de sécurité connus et à la façon de les gérer. Ces informations vous aideront à choisir un package tiers en toute confiance.
En l’absence de documentation, un outil comme Snyk peut vous aider à détecter les vulnérabilités dans les bibliothèques tierces que vous envisagez d’utiliser.
Soyez prudent avec les chaînes de caractères et le SQL brut
Il est recommandé de faire très attention lorsque vous manipulez des chaînes de caractères en Python, en particulier si vous utilisez du SQL brut dans votre code. Une mauvaise gestion de ce point peut vous exposer à des attaques par injection de chaînes de caractères ou par injection SQL. Un attaquant peut injecter du code malveillant dans une chaîne ou, plus probablement, dans une requête SQL, ce qui peut entraîner l’exécution de commandes SQL imprévues et arbitraires dans votre base de données.
Vous pouvez prévenir ce type d’attaque en réfléchissant soigneusement à la façon dont vous formatez les chaînes de caractères, en particulier lorsque vous utilisez des données saisies par l’utilisateur. Il est toujours préférable d’utiliser les bibliothèques standard pour formater les chaînes, en faisant appel à la fonctionnalité f-string.
Pour le SQL brut, vous devez utiliser des requêtes paramétrées plutôt que de concaténer directement les données saisies par l’utilisateur dans la chaîne SQL brute. Cela peut aider à prévenir les injections SQL en garantissant que ces données sont correctement échappées, mises entre guillemets et vérifiées.
Désérialisez avec prudence et en toute sécurité
Le module Python pickle n’est pas très sécurisé et peut être vulnérable à des attaques telles que la bombe pickle. Pour garantir la sécurité de votre package, vous pouvez envisager d’utiliser une autre bibliothèque de désérialisation, comme `dill`, qui est essentiellement une couche sécurisée reposant sur pickle.
L’une des vulnérabilités de pickle est qu’il peut permettre l’exécution de code arbitraire lors de la désérialisation. Dans ce cas, un attaquant peut injecter un fichier pickle malveillant contenant du code qui sera exécuté lors de la désérialisation du fichier. dill résout ce problème en vous permettant de spécifier les modules ou fonctions dont le déballage est autorisé, ce qui empêche toute exécution de code arbitraire lors de la désérialisation et rend dill plus sûr que pickle.
N’oubliez pas de supprimer les secrets
Il est essentiel de stocker les secrets de manière sécurisée lorsque vous manipulez des données sensibles. S’ils ne sont pas stockés en toute sécurité, un attaquant peut y accéder et s’en servir pour obtenir un accès non autorisé à votre système et à vos données. Pour éviter cela, stockez vos secrets de manière sécurisée à l’aide d’une bibliothèque de gestion des secrets, comme keyring, passlib, pycryptodome ou pycrypto, qui les conservera sous forme chiffrée.
Vous devriez également renouveler régulièrement vos secrets. Cela réduit le risque qu’ils soient compromis. Certains des outils mentionnés ci-dessus offrent cette fonctionnalité, tout comme d’autres outils tels que HashiCorp Vault.
Utilisez un outil pour analyser régulièrement votre code à la recherche de vulnérabilités
Comme vous l’avez vu, il est important de connaître les différentes menaces qui peuvent affecter votre projet Python, notamment en matière de gestion des dépendances, de formatage des chaînes, de requêtes SQL brutes et de désérialisation. Il est peut-être possible de résoudre tous ces problèmes par vous-même, mais ce n’est pas recommandé. Mieux vaut utiliser un outil capable d’analyser votre projet et de corriger les vulnérabilités.
Un outil comme Snyk peut vous simplifier la vie en analysant régulièrement votre code à la recherche de vulnérabilités. Avec Snyk, vous pouvez détecter et corriger les problèmes potentiels de votre projet Python. Vous sécurisez ainsi votre projet et réduisez le nombre de bugs et de problèmes de fonctionnement dans votre application.
Conclusion
Ce tutoriel vous a montré comment créer un package Python. Vous avez également découvert en quoi cette méthode est utile pour organiser et écrire votre code, et comment elle le rend réutilisable et pérenne.
Ce tutoriel a également expliqué pourquoi il est essentiel de connaître les différentes menaces et vulnérabilités susceptibles de compromettre votre projet. Vous avez appris à prendre vous-même en charge certaines d’entre elles en écrivant davantage de code. Cependant, toutes les organisations et équipes n’ont pas les moyens de le faire et, même si elles les ont, ce n’est pas la meilleure approche. Mieux vaut utiliser un produit complet et éprouvé qui gère en continu les vulnérabilités et les menaces, pour vous simplifier la vie.
Un produit comme Snyk peut vous aider à atténuer ces menaces en analysant minutieusement votre code pour détecter les vulnérabilités et en corrigeant automatiquement certains de ces problèmes.
Sécurisez vos applications Python dès maintenant
Détectez et corrigez gratuitement les vulnérabilités Python avec Snyk.
Aucune carte de crédit requise.
Ou inscrivez-vous avec Azure AD Docker ID Bitbucket
En utilisant Snyk, vous acceptez de respecter nos politiques, notamment nos Conditions d’utilisation et notre Politique de confidentialité.



