Accueil Développement Applications Sécurisation du code : un guide pour réussir à gérer les secrets...

Sécurisation du code : un guide pour réussir à gérer les secrets en Python

AVIS D’EXPERT – 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 rendez-vous chez le coiffeur, en coulisses, la connectivité se fait à l’aide de secrets tels que les mots de passe des bases de données, les clés API, les jetons, etc. Ces derniers doivent être gérés de manière appropriée pour éviter toute violation.

Keshav Malik, guest security expert chez GitGuardian, nous livre ici un guide complet à destination des développeurs pour gérer correctement les secrets en langage Python.

La nécessité de gérer les secrets est essentielle pour toute organisation. Les secrets peuvent être divulgués de nombreuses façons, notamment par le biais des systèmes de contrôle de version (ne jamais coder de secrets en dur dans le code !), de messages privés, d’e-mails et d’autres canaux de communication. Une fuite de secrets peut entraîner une perte de confiance, de crédibilité et même d’activité. Dans certains cas, la fuite de secrets peut également entraîner des poursuites judiciaires. C’est pourquoi il est si important d’avoir un plan pour gérer les secrets.

Avant de commencer, voici quelques éléments à garder à l’esprit pour éviter tout problème par la suite.

  • Python et pip installés sur un appareil
  • Compréhension de Python et du CLI
  • IDE Python tel que PyCharm ou VS Code
  • Compréhension de base du Cloud

MacOS est utilisé pour ce dispositif. Il faut utiliser les commandes en fonction de son système d’exploitation.

Il existe 4 façons différentes de gérer efficacement les secrets en Python pour une entreprise.

1. A partir d’un fichier

Le fichier .env est un fichier utilisé pour stocker les variables d’environnement en Python. Ces dernières sont définies en dehors du code Python et sont utilisées pour configurer le code Python. Le fichier .env est généralement utilisé pour stocker des clés secrètes et des mots de passe. Il est possible d’utiliser le package python-dotenv pour accéder au contenu du fichier .env. Pour commencer, il suffit d’installer le package à l’aide de la commande suivante.

$ pip install python-dotenv

Créer un fichier .env à des fins de test et collez les secrets suivants :

API_KEY=test-key
API_SECRET=test-secret

Bien sûr, ce fichier ne doit pas être commité dans un dépôt git ! Sinon, il serait versionné et lisible même après l’avoir supprimé. Ensuite, il faut ajouter cette ligne au fichier .gitignore :

.env

Si le fichier est commité, pas d’inquiétude, voici quelques instructions à suivre ici. Une fois fait, un fichier main.py doit être créer et l’extrait de code ci-dessous doit y être collé. Dans ce code, la fonction load_dotenv() pour charger le contenu du fichier .env est utilisée.

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)

La fonction dotenv_values(), qui convertit les secrets en dictionnaire peut être utiliser. Les secrets sont accessibles en utilisant l’extrait de code suivant :

from dotenv import dotenv_values
secrets = dotenv_values(“.env”)
def main() :
print(secrets[“API_KEY”])
print(secrets[“API_SECRET”])
si __name__ == “__main__” :
main()

Lorsqu’une entreprise travaille sur un grand projet, elle peut se rendre compte qu’elle a besoin de plusieurs fichiers .env. Par exemple, elle peut avoir un fichier .env pour son environnement de développement local et un fichier .env.dev pour son environnement de production de développement cloud. L’extrait de code suivant peut être utile si elle a plusieurs fichiers env.

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”])
si __name__ == “__main__” :
main()

Utilisation d’un fichier JSON

Pour garder les secrets organisés, les organisations peuvent aussi utiliser un fichier JSON. Créons un fichier secret.json et collons-y les secrets suivants.

{
“db” : {
“host” : “localhost”,
“port” : 27017,
“nom” : “test”
},
“serveur” : {
“host” : “localhost”,
“port” : 3000
}
}

La même chose que ci-dessus s’applique, ne pas “commiter” ce fichier !

Maintenant que le fichier JSON est prêt, il est possible d’écrire une fonction pour accéder aux secrets du fichier :

# main.py
import json
def get_value_from_json(json_file, key, sub_key) :
essayer :
avec open(json_file) as f :
données = json.load(f)
return data[key][sub_key]
except Exception as e :
print(“Erreur : “, e)
print(get_value_from_json(“secrets.json”, “db”, “host”)) # imprime localhost

2. Utiliser des variables d’environnement

Les variables d’environnement sont définies par le système d’exploitation ou un utilisateur spécifique, et sont utilisées par les programmes pour déterminer divers paramètres. Ces variables peuvent servir à stocker des secrets et y accéder ensuite dans un programme. La syntaxe suivante peut créer une variable d’environnement dans macOS ou sur une machine Linux.

$ export variable_name=valeur
$ export API_KEY_TEST=dummykey

Sur une machine Windows, il est possible d’utiliser l’interface graphique pour ajouter des variables d’environnement ou utiliser la commande suivante pour ajouter une variable.

$ setx [nom_variable] “[valeur]”.

Le package os sert à accéder à la variable d’environnement os. En voici un exemple de code :

import os
# Obtenir la clé secrète de l’environnement
secret_key = os.environ.get(‘api_key_test’)
print(secret_key) // imprime la clé factice

Les secrets en ligne de commande doivent également être traités avec une attention particulière ! 

3. Recourir à un gestionnaire de secrets dans le cloud

La plupart des fournisseurs de services cloud offrent un gestionnaire de secrets intégré qui peut être utilisé pour créer et utiliser des secrets dans l’infrastructure cloud. Voici les gestionnaires de secrets proposés par les fournisseurs de services cloud :

AWS Secrets Manager est largement utilisé dans l’industrie. Écrivons une fonction pour créer et accéder à un secret dans AWS en utilisant Boto3.

import boto3
def fetch_secret_from_aws(nom_secret) :
essayer :
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 comme e :
print(e)
return None

def create_secret_in_aws(nom_secret, valeur_secrète) :
essayez :
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
sauf Exception comme e :
print(e)
return False

4. Installer un KMS (Key Management System)

Un KMS est un système de gestion des clés qui est utilisé pour gérer les clés cryptographiques. Il est généralement utilisé dans les organisations afin de gérer et de 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 leur utilisation. Le 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 s’assurer 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 un certain nombre de fonctionnalités et d’avantages, notamment la possibilité de gérer des secrets et des clés dans plusieurs environnements, de solides contrôles de sécurité et une bonne évolutivité.

Écrivons une fonction pour lire et écrire des secrets vers un chemin spécifique dans le coffre-fort. Il est nécessaire d’installer hvac (client Python pour Vault) et avoir une configuration de Vault Hashicorp.

import hvac
def read_secret_from_vault(chemin_secret, token, nom_secret) :
essayer :
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(chemin_secret, token, nom_secret, valeur_secret) :
essayer :
client = hvac.Client(
url=’http://localhost:8200′,
token=token,
)
create_response = client.secrets.kv.v2.create_or_update_secret(
chemin=chemin_secret,
secret={nom_secret : valeur_secret},
)
return create_response
sauf Exception comme e :
print(e)
return None

La gestion des secrets est une partie essentielle du développement d’applications. Lorsque les développeurs codent en dur des secrets dans leurs applications, cela crée une brèche 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 son équipe de manière cryptée. Cette solution peut être très souple si l’on apprend à tirer parti d’un outil tel que Mozilla SOPS.

Keshav Malik, guest security expert chez GitGuardian