76 votes

Distribuer des projets Django avec des SECRET_KEYs uniques

J'ai un projet Django que j'aimerais distribuer sur un dépôt public comme bitbucket ou github. J'aimerais qu'il soit aussi facile à installer que possible, c'est pourquoi j'inclus le projet complet, et pas seulement les applications enfichables. Cela signifie que le settings.py sera également inclus.

Comment puis-je éviter le problème de settings.SECRET_KEY étant la même pour chaque installation ?

Est le seul simple solution pour que l'utilisateur modifie manuellement settings.py ?

Devrais-je stocker la clé dans la base de données par défaut et avoir settings.py l'initialiser s'il n'existe pas ? Cela résoudrait le problème, mais je me demande s'il existe déjà un moyen standard de le faire.

Gracias.

1 votes

Pourquoi modifiez-vous les paramètres ? On peut faire confiance à tous ceux qui téléchargent et installent une application Django pour réparer les paramètres.

4 votes

Changez votre clé secrète en quelque chose comme "--- INSERT SECRET KEY HERE ---".

6 votes

On ne peut pas faire confiance à tous ceux qui déploient un serveur SSH pour générer des clés privées uniques, je ne vois pas pourquoi il devrait en être autrement pour les projets Django. Moins il y a de configuration à faire, moins il y a de risques d'erreurs, surtout avec quelque chose comme SECRET_KEY où vous ne pouvez pas simplement taper quelque chose d'aussi simple qu'un chemin de répertoire.

120voto

Umang Points 2227

Pour ajouter à ce que Carles Barrobés dit, vous pouvez générer une nouvelle clé en utilisant la méthode que Django utilise dans startproject :

from django.utils.crypto import get_random_string

chars = 'abcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*(-_=+)'
get_random_string(50, chars)

Pour Django 1.10 et les versions ultérieures, le bout de code ci-dessus est joliment enveloppé dans une fonction.

from django.core.management.utils import get_random_secret_key
get_random_secret_key()

Lien vers le dépôt GitHub

0 votes

@MKaras Toute chaîne de caractères fonctionnerait. Je pense que le jeu de caractères d'entrée est restreint afin d'augmenter la lisibilité/accessibilité. Je conseillerais donc de ne pas utiliser string.printable car il contient des caractères "délicats" tels que tabulation, nouvelle ligne, deux-points et point-virgule, espace et autres.

3 votes

Si vous mettez cela dans votre projet, chaque processus Django séparé que vous avez aura une clé différente. Cela signifie par exemple que si vous exécutez plusieurs processus Django simultanés (ou sur des serveurs distincts), ils obtiendront des clés secrètes différentes, de sorte que les documents signés à partir d'une instance ne fonctionneront pas sur une autre. De même, lorsque votre processus Django est redémarré, vous obtenez une nouvelle clé secrète, ce qui entraîne des problèmes similaires.

52voto

Carles Barrobés Points 5283

Je m'y prendrais de cette façon :

Avoir la clé secrète dans un fichier séparé "secret_key.py". Ce fichier n'existe pas pour une installation vierge. Dans votre settings.py incluez quelque chose comme :

try:
    from .secret_key import SECRET_KEY
except ImportError:
    SETTINGS_DIR = os.path.abspath(os.path.dirname(__file__))
    generate_secret_key(os.path.join(SETTINGS_DIR, 'secret_key.py'))
    from .secret_key import SECRET_KEY

La fonction generate_secret_key(filename) que vous allez écrire génère un fichier appelé filename (qui, comme nous l'appelons, sera secret_key.py dans le même répertoire que settings.py ) avec le contenu :

SECRET_KEY = '....random string....'

Où la chaîne aléatoire est la clé générée sur la base d'un nombre aléatoire.

Pour la génération de clés, vous pouvez utiliser la suggestion d'Umang. https://stackoverflow.com/a/16630719/166761 .

0 votes

Votre méthode est plus propre que mon idée de stocker la clé dans la base de données. Merci !

4 votes

Cette méthode exige également que l'utilisateur charge le settings.py a un accès en écriture au répertoire dans lequel il réside.

0 votes

C'est probablement évident, mais lorsque vous générerez le fichier, vous voudrez le placer dans un fichier de type try au cas où un autre processus de travail en cours de démarrage crée le fichier avant que vous ne l'atteigniez, mais après que vous ayez testé son existence... cela, ou un verrou. Dans le except bloc, vous allez juste importer le fichier à nouveau. En fait, il serait préférable d'essayer de le créer et de l'importer en cas d'échec, afin d'éviter la duplication de la logique.

5voto

Jim Points 39574

D'une manière générale, vous pouvez diviser la configuration de Django en deux catégories : les éléments spécifiques à l'application et les éléments spécifiques au serveur. Ceci tombe dans la dernière catégorie.

Il existe un certain nombre de façons d'aborder le problème de la configuration spécifique du serveur, qui est abordé plus en détail dans la section cette question .

Dans ce cas particulier, en utilisant l'approche que j'ai décrite dans ma réponse à l'autre question, je mettrais un espace réservé dans le fichier settings_local.py.sample pour la distribution, et pendant l'installation, j'ai copié cela sur settings_local.py et modifiez-le à votre guise.

0 votes

Je n'ai pas abordé ce point dans ma question initiale afin de la rendre moins verbeuse, mais j'ai déjà un fichier settings_local.py avec MEDIA_ROOT, TEMPLATE_DIRS, SECRET_KEY, etc. Je cherche un moyen d'automatiser la génération de la clé pour éviter que les personnes qui installent le projet oublient de générer des clés, ou génèrent de mauvaises clés. Je pense que je vais la stocker dans la base de données et faire en sorte que settings_local.py vérifie son existence.

2voto

hugo_leonardo Points 1936

Je résoudrais le problème de la façon suivante :

  • Fournir une clé secrète factice comme : I_AM_A_DUMMY_KEY_CHANGE_ME
  • Créez une commande de gestion pour en générer une nouvelle : ./manage.py gen_secret_key
  • Dans la documentation, il est fortement conseillé aux utilisateurs d'exécuter la commande dès que possible.

1voto

hum3 Points 60

Dans mon code, j'ai trois niveaux de fichiers de paramètres inspirés par Two Scoops of Django, donc le niveau intermédiaire est le suivant : BASE_PRIVATE_DIR est configuré dans le modèle de base. Dans mon cas, il s'agit du répertoire django ../../mysite_private mais quelque part à côté des fichiers normaux sous l'application git.. :

from .base import *

ALLOWED_HOSTS = ['staging.django.site'] 
#Allow local override which is per deployment instance.  There should probably then be
#  an instance git for version control of the production data
try:
    import sys
    private_path = BASE_PRIVATE_DIR.child('production')
    sys.path.append(private_path)
    from private_settings import *
except ImportError:
    print(" No production overide private_settings.py found.  This is probably an error  = {}".format(private_path))
    # If it doesnt' exist that is fine and just use system and environment defaults

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X