Nous vivons dans un monde où les applications sont utilisées pour tout faire, qu’il s’agisse de négocier des actions ou de réserver un salon, mais dans les coulisses, la connectivité se fait à l’aide de secrets. Les secrets, tels que les mots de passe de base de données, les clés API, les jetons, etc., doivent être gérés de manière appropriée pour éviter toute violation.
La nécessité de gérer les secrets est essentielle pour toute organisation. Les secrets peuvent être divulgués de plusieurs façons, notamment par le biais de systèmes de contrôle de version (ne jamais coder en dur des secrets dans votre code), messages privés, e-mail et autres canaux de communication. Si des secrets sont divulgués, cela peut entraîner une perte de confiance, de crédibilité et même d’activité. Dans certains cas, les secrets divulgués peuvent également entraîner des poursuites judiciaires. C’est pourquoi il est si important d’avoir un plan de gestion des secrets.
Dans cet article, nous discuterons de quatre façons différentes de gérer efficacement les secrets en Python.
Conditions préalables
Avant de commencer, voici quelques éléments à garder à l’esprit pour éviter tout problème ultérieur :
- Python et pip installés sur votre machine.
- Compréhension de Python et CLI.
- Python IDE, tel que PyCharm ou VS Code.
- Une compréhension de base du cloud.
Nous utiliserons MacOS pour cet appareil. Veuillez utiliser les commandes selon votre système d’exploitation.
Quatre façons de gérer les secrets en Python
Dans cette section, nous aborderons quatre manières différentes de gérer vos secrets en Python :
1. À partir d’un fichier
Utilisation d’un fichier .env
Le .env
file est un fichier utilisé pour stocker les variables d’environnement en Python. Les variables d’environnement sont des variables définies en dehors du code Python et sont utilisées pour configurer le code Python. Le .env
Le fichier est généralement utilisé pour stocker des clés secrètes et des mots de passe.
Nous utiliserons le python-dotenv
package pour accéder au contenu du .env
déposer. Pour commencer, installez d’abord le package à l’aide de la commande suivante :
$ pip install python-dotenv
Créer un .env
fichier à des fins de test et collez les secrets suivants :
API_KEY=test-key
API_SECRET=test-secret
Bien entendu, ce fichier ne doit pas être validé dans votre référentiel git. Sinon, il serait versionné et lisible même après sa suppression.
Ajoutez cette ligne à votre .gitignore
déposer:
Une fois terminé, créez un main.py
fichier et collez l’extrait de code mentionné ci-dessous. Dans ce code, nous utilisons le load_dotenv()
fonction pour charger le contenu de la .env
déposer:
from dotenv import load_dotenv
import os
load_dotenv()
api_key = os.getenv("API_KEY")
api_secret = os.getenv("API_SECRET")
print("API_KEY: ", api_key)
print("API_SECRET: ", api_secret)
Nous pouvons également utiliser le dotenv_values()
fonction, qui convertit les secrets en un dictionnaire. Les secrets sont accessibles à l’aide de l’extrait de code suivant :
from dotenv import dotenv_values
secrets = dotenv_values(".env")
def main():
print(secrets["API_KEY"])
print(secrets["API_SECRET"])
if __name__ == "__main__":
main()
Lorsque vous travaillez sur un grand projet, vous pouvez constater que vous avez besoin de plusieurs .env
des dossiers. Par exemple, vous pouvez avoir un .env
fichier pour votre environnement de développement local et un .env.dev
fichier pour votre environnement de production de développement cloud. L’extrait de code suivant peut être utile si vous avez plusieurs .env
des dossiers:
from dotenv import dotenv_values
secrets = dotenv_values(".env")
local_secrets = dotenv_values(".env.dev")
def main():
print(secrets["API_KEY"])
print(local_secrets["API_SECRET"])
if __name__ == "__main__":
main()
Utilisation d’un fichier JSON
Pour mieux organiser les secrets, vous pouvez également utiliser un fichier JSON. Créons un secrets.json
fichier et collez-y les secrets suivants :
{
"db": {
"host": "localhost",
"port": 27017,
"name": "test"
},
"server": {
"host": "localhost",
"port": 3000
}
}
La même chose que ci-dessus s’applique, ne validez pas ce fichier.
Maintenant que le fichier JSON est prêt, écrivons une fonction pour accéder aux secrets du fichier :
# main.py
import json
def get_value_from_json(json_file, key, sub_key):
try:
with open(json_file) as f:
data = json.load(f)
return data[key][sub_key]
except Exception as e:
print("Error: ", e)
print(get_value_from_json("secrets.json", "db", "host")) # prints localhost
2. Utilisation de variables d’environnement
Les variables d’environnement sont des variables définies par le système d’exploitation ou un utilisateur spécifique et utilisées par les programmes pour déterminer divers paramètres. Nous pouvons utiliser ces variables pour stocker nos secrets, puis y accéder dans notre programme. Vous pouvez utiliser la syntaxe suivante pour créer une variable d’environnement dans macOS ou une machine Linux :
$ export variable_name=value
$ export API_KEY_TEST=dummykey
Sur une machine Windows, vous utilisez l’interface graphique pour ajouter des variables d’environnement ou utilisez la commande suivante pour ajouter une variable :
$ setx [variable_name] “[value]”
Vous pouvez utiliser le package du système d’exploitation pour accéder à la variable d’environnement du système d’exploitation. Mentionné ci-dessous est l’exemple de code:
import os
# Get the secret key from the environment
secret_key = os.environ.get('api_key_test')
print(secret_key) // prints dummykey
Les secrets de la ligne de commande doivent également être traités avec un soin particulier.
3. Utilisez un gestionnaire de secrets cloud
La plupart des fournisseurs de services cloud proposent un gestionnaire de secrets intégré qui peut être utilisé pour créer et utiliser des secrets dans l’infrastructure cloud. Suite aux gestionnaires de secrets proposés par les fournisseurs de cloud :
- Gestionnaire de secrets AWS
- Gestionnaire secret (par Google Cloud)
- Coffre de clés Azure
AWS Secrets Manager est largement utilisé dans l’industrie. Écrivons une fonction pour créer et accéder à un secret dans AWS à l’aide de Boto3 :
import boto3
def fetch_secret_from_aws(secret_name):
try:
session = boto3.session.Session()
client = session.client(service_name="secretsmanager", region_name="us-east-1")
get_secret_value_response = client.get_secret_value(SecretId=secret_name)
return get_secret_value_response['SecretString']
except Exception as e:
print(e)
return None
def create_secret_in_aws(secret_name, secret_value):
try:
session = boto3.session.Session()
client = session.client(service_name="secretsmanager", region_name="us-east-1")
client.create_secret(Name=secret_name, SecretString=secret_value)
return True
except Exception as e:
print(e)
return False
4. Utiliser un KMS
Un KMS est un système de gestion de clés utilisé pour gérer les clés cryptographiques. Il est généralement utilisé dans les organisations pour gérer et sécuriser les clés de manière centralisée. Un KMS peut être utilisé pour générer, stocker et distribuer des clés. Il peut également être utilisé pour révoquer des clés et surveiller l’utilisation des clés.
KMS est un moyen pratique de gérer de manière centralisée les clés utilisées par vos applications et services et permet de garantir que seuls les utilisateurs autorisés y ont accès.
Hashicorp Vault est l’un des meilleurs KMS open source disponibles sur le marché qui offre de nombreuses fonctionnalités et avantages, notamment la possibilité de gérer les secrets et les clés dans plusieurs environnements, des contrôles de sécurité solides et une bonne évolutivité.
Écrivons une fonction pour lire et écrire des secrets dans un chemin spécifique dans le coffre-fort.
Note: Veuillez vous assurer que hvac (client Python pour Vault) est installé et que vous disposez d’une configuration Hashicorp Vault :
import hvac
def read_secret_from_vault(secret_path, token, secret_name):
try:
client = hvac.Client(
url="http://localhost:8200",
token=token,
)
read_response = client.secrets.kv.read_secret_version(path=secret_path)
return read_response['data']['data'][secret_name]
except Exception as e:
print(e)
return None
def write_secret_to_vault(secret_path, token, secret_name, secret_value):
try:
client = hvac.Client(
url="http://localhost:8200",
token=token,
)
create_response = client.secrets.kv.v2.create_or_update_secret(
path=secret_path,
secret={secret_name: secret_value},
)
return create_response
except Exception as e:
print(e)
return None
Emballer
La gestion des secrets est une partie essentielle du développement d’applications. Lorsque les développeurs codent en dur des secrets en texte clair dans leurs applications, cela crée une faille de sécurité potentielle. Un attaquant peut utiliser ces secrets pour accéder à des données sensibles si ces secrets sont découverts.
Une autre alternative aux méthodes proposées ici est de vérifier les secrets dans le code source et de les partager avec votre équipe crypté. Cela peut être une solution très flexible si vous apprenez à tirer parti d’un outil tel que Mozilla SOPS.