Cryptage Python
La cryptographie à clé publique simplifiée
Une perspective DevOps sur la sécurisation des paramètres de déploiement
Photo by Towfiqu barbhuiya on Unsplash
Une perspective DevOps sur la sécurisation des paramètres de déploiement Public-key
Les builds de code et l'automatisation du déploiement ont ouvert la voie à de nombreuses grandes choses. L'époque des versions mensuelles et manuelles du code est révolue depuis longtemps ; les pipelines CI/CD modernes ont désormais la possibilité de publier chaque validation de code qui passe les tests automatisés dans les environnements de développement et de mise en production vers la production.
Pour que cette magie opère, les équipes DevOps doivent créer un code indépendant de l'environnement. Le même code doit être déployé dans DEV, TEST, STAGE, puis dans PROD, en transmettant les paramètres appropriés au moment du déploiement pour que la solution se comporte de manière appropriée. L'architecture des microservices et le découplage des sous-composants indépendants qui doivent se découvrir après avoir été déployés pour travailler ensemble en font une tâche très difficile. Garder une trace de ces paramètres de déploiement, la "colle" qui fera fonctionner ensemble tous ces composants naïfs dans n'importe quel environnement donné, est devenu un nouveau défi en soi.
Bien qu'il soit de notoriété publique, cela ne peut probablement pas faire de mal de le répéter une fois de plus : vous ne devez jamais, en aucun cas, intégrer des informations d'identification de quelque nature que ce soit, y compris des clés d'API, dans votre code ou une image de conteneur. Les informations d'identification téléchargées dans un référentiel de code ou un registre d'images doivent être considérées comme ayant été compromises et modifiées immédiatement.
Mais, vous vous demandez peut-être : si vous ne pouvez pas suivre ces précieux paramètres de déploiement dans un référentiel de code source, que pouvez-vous faire ? Conserver ces valeurs critiques dans un référentiel sous contrôle de version est une bonne idée, mais tant qu'elles sont chiffrées. La cryptographie à clé publique/privée fournit la meilleure solution car le secret chiffré ne peut pas être déchiffré sans la clé privée, de sorte qu'ils peuvent être téléchargés en toute sécurité vers un référentiel GitHub privé tant que la clé de déchiffrement ne l'est pas.
Les bons vieux fichiers de configuration ou fichiers ".INI" sont étonnamment bien adaptés pour stocker les paramètres de déploiement car ils permettent de stocker le même nom de clé avec des valeurs différentes dans plusieurs sections représentant les différents environnements. Par exemple:
[DEFAULT]
db_user = dbuser
[DEV]
db_pwd = devpassword
[PROD]
db_pwd = prodpassword
La valeur de mon nom d'utilisateur de base de données db_user sera la même pour toutes les sections (DEFAULT) mais la valeur de db_pwd peut être différente dans DEV que dans PROD.
La bibliothèque Python rsa_crypto et l'utilitaire de ligne de commande vous permettent de combiner la flexibilité du stockage des valeurs dans les fichiers de configuration avec la sécurité du chiffrement à clé privée/publique. Des fichiers binaires autonomes pour Windows, Mac et Linux sont également disponibles pour plus de commodité.
La première étape consiste à générer de nouvelles clés :
rsa_crypto create
Enter key password:
Re-enter key password:
Creating key...
Created password-protected private/public keys file /Users/me/rsa_key.bin
Use the "extract" keyword to create public and private key files.
Par défaut, l'outil crée une nouvelle paire de clés RSA 4096 bits (secrète) et l'enregistre dans un fichier unique, protégé par un mot de passe répondant à la norme PKCS # 8 et utilisant la fonction de dérivation de clé scrypt pour contrecarrer les attaques par force brute par dictionnaire. La clé est sécurisée avec un bon mot de passe, mais elle ne doit toujours jamais être stockée dans un référentiel de code.
Avoir encore un autre mot de passe ne se prête pas bien à l'automatisation du déploiement. L'outil fournit également un moyen d'extraire ce fichier protégé par mot de passe dans des fichiers de clé publics et privés séparés qui ne nécessitent pas de mot de passe.
rsa_crypto extract
Using key: /Users/me/rsa_key.bin
Opening encrypted key.
Enter key password:
Created private key file /Users/me/rsa_private.pem (File can decrypt data and is not password-protected, keep it safe!)
Created public key file /Users/me/rsa_public.pem (distribute this one to anyone who needs to encrypt data, it cannot be used for decryption!)
Le fichier de clé publique peut être distribué en toute sécurité à quiconque doit pouvoir chiffrer des valeurs, il ne peut pas être utilisé pour le déchiffrement. Il s'agit d'une excellente option car les informations d'identification sont généralement gérées par un groupe distinct dans la plupart des organisations.
Inversement, la clé privée doit être gardée avec une extrême prudence car elle peut être utilisée pour déchiffrer n'importe quelle valeur sans mot de passe. L'outil recherchera ces fichiers clés dans le répertoire courant (celui à partir duquel vous exécutez la commande), le répertoire où se trouve le script, ainsi que dans le répertoire personnel de l'utilisateur. Il recherchera également les fichiers clés en tant que variables d'environnement, ce qui pourrait être une meilleure option dans de nombreuses situations.
export rsa_private=$(cat /Users/me/rsa_private.pem)
Le fichier de clé privée peut alors être supprimé en toute sécurité, il peut toujours être regénéré à partir du fichier de clé chiffré par mot de passe :
rsa_crypto clear
Using key: /Users/me/rsa_private.pem
Private key deleted: /Users/me/rsa_private.pem
L'outil peut également être utilisé avec l'option -k pour spécifier un préfixe de nom de clé différent, permettant aux utilisateurs d'avoir plusieurs clés pour différents environnements ou objectifs ou des informations d'identification gérées par différentes équipes :
rsa_crypto create -k dev
Enter key password:
Re-enter key password:
Creating key...
Created password-protected private/public keys file /Users/me/dev_key.bin
Use the "extract" keyword to create public and private key files.
Ces paramètres get et set du script peuvent également être utilisés pour stocker et récupérer des valeurs chiffrées dans un fichier de configuration. Le fichier de configuration doit déjà exister :
touch ~/.rsa_values.conf
La structure du fichier est assez simple, il contient des sections délimitées par des crochets [MA_SECTION]. Notez que le nom de la section peut être sensible à la casse. La section [DEFAULT] est utilisée par défaut.
Chaque section contiendra alors plusieurs "options" et valeurs (couples clé/valeur). Seule la valeur sera cryptée, le nom de l'option restera en clair.
Cette structure est très bien adaptée pour garder une trace des valeurs qui doivent être différentes selon l'environnement, comme pour garder une trace des mots de passe de base de données dans un environnement DEV, TEST et PRODUCTION.
Pour enregistrer une valeur d'une option nommée database_password dans la section DEV à l'aide de la clé de chiffrement par défaut :
rsa_crypto set -s DEV -o database_password
Using key: /Users/me/Documents/rsa_public.pem
Enter value:
DEV my_password
set
Updated /Users/me/.rsa_values.conf
Si vous ne spécifiez pas de valeur, le script vous demandera la valeur afin qu'elle ne soit pas visible dans l'historique de la ligne de commande. En option, si vous préférez, vous pouvez également spécifier la valeur en tant que paramètre de ligne de commande à l'aide du paramètre -v.
rsa_crypto set -s DEV -o database_password -v my_secret_password
Using key: /Users/me/Documents/rsa_public.pem
DEV my_secret_password
set
Updated /Users/me/.rsa_values.conf
Pour déchiffrer la valeur :
rsa_crypto get -s DEV -o database_password
Using key: /Users/me/rsa_private.pem
get
Reading from /Users/me/.rsa_values.conf
DEV database_password my_secret_password
my_secret_password
Notez que dans l'exemple ci-dessus, la clé privée rsa_private.pem nous a permis de déchiffrer les données sans demander de mot de passe. Encore une fois, soyez extrêmement prudent car toute personne disposant de ce fichier peut décrypter les données . Si la clé privée n'est pas présente, le script demandera alors un mot de passe pour ouvrir le fichier de paire de clés protégées rsa_key.bin.
rsa_crypto clear
Using key: /Users/me/rsa_private.pem
Private key deleted: /Users/me/rsa_private.pem
rsa_crypto get -s DEV -o database_password
Using key: /Users/me/rsa_key.bin
Opening encrypted key.
Enter key password:
get
Reading from /Users/me/.rsa_values.conf
DEV database_password my_secret_password
my_secret_password
Maintenant, définissons et récupérons le mot de passe PROD :
rsa_crypto set -s PROD -o database_password -v super-secret
Using key: /Users/me/Documents/workspaces/rsa_public.pem
PROD super-secret
set
Updated /Users/me/.rsa_values.conf
rsa_crypto get -s PROD -o database_password
Using key: /Users/me/rsa_key.bin
Opening encrypted key.
Enter key password:
get
Reading from /Users/me/.rsa_values.conf
PROD database_password super-secret
super-secret
Le contenu du fichier de configuration .rsa_values.conf ressemblera à ceci :
cat ~/.rsa_values.conf
[DEFAULT]
test = VvXy8NcqL94lBDYS56EnQm03vq9Kvg17VNU1Tu0T1j_hn-OxOTmXv_NoQHWcvWZuJto4awbq1Y_yvi_MKYE5uXOv15iVBZAuHO_xlUmujrL9pdUfxnBe8SAzH7sy2GTx42tLkb2MB9E-49GmKYqbx9dBzTNRDJj8D8LDZku6CJeSDPGy9l6UzG2vl53V3GY97an4Gb4UJ7XYEeEqMsZFRqaxgdWd_IMA_L5FtAlEaU3j4SYvqq-9QDxuab0vv8ZgzP6KuR05jXcLTrEZdrfmy_zRHuLiThu5_-ofsUNoXGNByGWAdBuuMONQj1s2QiI7qsqbFw66RBh0zUMzF2XFtSHY4AklF6uiDkieAhjBldbIjGEhrt3eMVBRBtRIDQ-LlYMcP8HnMPjBe-FBn8rYNscDrOWJIcqyTXwspfnyI6iSjEfTNQilMG6V17NXaJNipbJpoFm0aiKokZXawgav9yWWXAjRitMBtCGbqeEXVw704uY2s2K0m8XQhBLuwtCSS2Q616e4CgBxhEZOHNC0FPDpLWgvUwSFJ9vLphYSEQXeak3GRPDUfzxnjIUi8uLtifJGVEUycyRf8PV_Zf-0i8SAxFbB9OYawAKBpwwTGt4B8Pir351AcID4-s-9TG7LwrOxDvDiGxTH6Kho0SnMubXdpfDESFlwb61KzD3Yap0=
[dev]
test = Nfe5yc-FegHyEODNAX-ndIs8kf6Tjn1V3fjy7PSZ4J4NuOq7bOHCfooVb2mK4KS7Q0U8MSIIo_JmAZVqY__CvWR4zaczr4Es1d64YNX8CyVKvfIK7sPVSfv-v54-edcdtKHEj6dJRo1Pdbvc8ESgMxEUK9J64lS0FloZoXJGE1NVdkgf19IX4ZlHm2XjhyQ1pgfEg0cJPqDukM6cHfXwqexVjWGGF9-eYw6jeUFm59O3_D5Z44ull9HCdEtG85Hv99R4lpQJWYRLF1b7-HPPnyAoXwnCuR-mKi7KdiZw4q_bTruuKYltTKIYbMxXzW5m-kjNUcHSaYdOxSGVbOYdhMiBOnvTRZS5KVVpJCfS5fkQG2HLRlkRhW2PWwaG8ieP-bXvK7jvImKqRbGryPNHtdNBSv3yIXhQKqHfs6JxVXg_pBJywv7q-oymxw4hk3jf11CyZaDmAS-XQQU0KxnnkJ7Cm1h1KYVSfFMZWw9teEd3fRsiBktqPaIOnw0U5liK5WG52uBN_hdoAM73aOpsuDLPy1fYEL5Wuw3nuSZt48Gf7q6AFWS8WRCwIXa0oJJjudObfkeCw7jA0-ufIEHa4wBk2X93D2Mjr-nLOSayLM71UOdT94B4-2oVV-44Djuo-iY3iKQQkllFvuQmZr2Ozs68knOA70qbIYewVBcO4fY=
[DEV]
database_password = YrUidTfrK3w-y2KneYUSWugR0IVjmPvBpjqlBZ_5Oic5td0rO2aeWOuyeiujSe7G9YoBnKLxtIkGGzeOs0EQ6kEJCmLCq2MVNOECj4__majFlmp3De_ypebwq0SbRn4UGRzrGSV6oO93jnoHpH8Rky2L5yeJMAqjwsMAgOQBrfdpdcgqLRATUumoaRkvfMafdTYKjhJj5m6EUB9-la8YPK9kxMKu2-l9GlEnqug5S91xAOXb2laX2b3T5KCeQxxAZ2L9KtUG0NJulmaEtUFoRNWSVyBLsAvDdRkXoYXuHLSIhD-8x1RwxOjPyJ-t4cc7uNJF8ZfCsLHuesQj4jauXSmiVe5wI718rC4PS9kYH5Z5IKgl19d7jRaUI2jx-lPs4Rues1SZpHQKpH8GG3Id7z5RAtJ3OdlCrx7b3uOPL5GinlG4QdyiF7ROIsShAZPTdrQybRDDCU8ju-6R0RkMO8Qds7VNRANSwXYQAn2D62IQx3cAr40TMOHy697QgklomfT-k52GCQsfyJqFASYJ4DDhnjZB8uXzx1eHLhmVTikVt1yYXjoPOD0HPX0uYTd8L-TNwU9OnU36Q8m9dTez9rUHrX2xKapkYf0SIRPeSiLRbey_h9tnynoQYXtKsca-jxdBUDZvw2t_KbU__z_zuRWv65CrJpkcBGMvYkqeXj4=
[PROD]
database_password = g1G_zRij0D6nerTHn1bJ7fr_HiWLFv4Qi-a2Y9QfjeWy5lRCO4L_9ENuiG4hbqyJj2NtbLJ7-NCpN3wd_i8djTGcY2yTcgsFZQEceco-n1bK9yX3Fq8Go1r2D82ccdlNSASeFwA5XDEiBbjpDmsgeawYQNJJUC84oAdv52cFIqTVHecYXGp8cr93eUI3Cpj8Q67zoMH3bJNXkF1KIcFCdrlFfwOQA3RsVuoYdw_JXztVAGaUBWfnBKWjDuTcM9WJyB2-Zfw8Pv0W4Dd2YkJvjvMcCJakxoVEz1OGFBlLyBwleTXBQVKLxGBkK7Xfr7s0FArM6yBAe5BFOfd-vfNeoR38X-Rc00ojUTpbsforLKTWuvHGx1tXi8F5b7TAhNKsICptmBn52ZZmYQjCyIktgL_v0Trngk0Y3uYiaAZpFJyvNHcebjSJ445c_knbcFdn158tud9WX8dHOcXcx5LXFrfh-hU1Vc0U6MUVXgja7T_-O5N59Hob4DIyb4sHF8x-FGFiBvZK-dvIY_FDt82Z0Bk-AETPCykdkmtTx4eg-_o2eEb9ewKHlgLpnBjUs1FajMcfGYiQnaRQNfubBRHY34nmdJtfqQVqVIcQkD0N19qI-8Mg0RSwLaxKSDPlK06JdZew1Nrli-l7U5wYZV4zLdIzXG4tqy6qIb_8Y5yMXm0=
L'outil peut également être utilisé pour chiffrer des fichiers entiers, tels qu'un fichier de configuration Kubernetes Parameter Store .yaml, à l'aide de l'option -f.