Quels sont les avantages de mettre les valeurs secrètes d'un site Web en tant que variables d'environnement?

24

Les directives devops sur https://12factor.net/config suggèrent de mettre les secrets du site Web (mots de passe de base de données, clés api, etc.) dans des variables d'environnement. Quels avantages cela a-t-il au lieu d'utiliser des fichiers texte (JSON, XML, YAML, INI ou similaire) ignorés du contrôle de version?

Je trouve qu'il est beaucoup plus facile de copier un fichier de configuration avec des secrets que de gérer les variables d'environnement dans la configuration .bash_profile et le serveur Web. Dois-je manquer quelque chose?

Aidas Bendoraitis
la source
1
En théorie, il est plus facile de lire un fichier que la mémoire, vous pouvez donc considérer la surface d'attaque plus grande et la complexité plus petite.
Florin Asăvoaie
La règle de base de mon développeur est que le stockage des paramètres dans les variables d'environnement est préférable uniquement dans les environnements de type docker. En dehors des VM de conteneurs, il approuve / préfère tous les autres points de 12factor.net et l'utilisation des fichiers de configuration. Aucun de nous n'a aimé la nature non sécurisée des variables d'environnement lors des déploiements de serveurs réguliers.
Corey Ogburn

Réponses:

21

L'auteur énumère leur raisonnement, bien que ce soit un peu décousu. Leur principal argument est qu'il est facile d'archiver accidentellement un fichier de configuration, et que les fichiers de configuration ont des formats différents et peuvent être dispersés dans le système (tous les trois sont au mieux des arguments médiocres pour une configuration liée à la sécurité comme les jetons d'authentification et les informations d'identification).

Compte tenu de ma propre expérience, vous avez essentiellement les trois options suivantes, avec les avantages et inconvénients associés:

Stockez les données dans des fichiers de configuration.

Lorsque vous adoptez cette approche, vous devez idéalement les isoler du référentiel lui-même et vous assurer qu'ils se trouvent en dehors de la zone dans laquelle l'application stocke son contenu.

Avantages:

  • Très facile à isoler et à contrôler l'accès, surtout si vous utilisez des choses comme SELinux ou AppArmor pour améliorer la sécurité globale du système.
  • Généralement facile à changer pour les utilisateurs non techniques (c'est un avantage pour les logiciels publiés, mais pas nécessairement pour les logiciels spécifiques à votre organisation).
  • Facile à gérer sur de grands groupes de serveurs. Il existe toutes sortes d'outils pour le déploiement de la configuration.
  • Raisonnablement facile de vérifier quelle est la configuration exacte utilisée.
  • Pour une application bien écrite, vous pouvez généralement modifier la configuration sans interrompre le service en mettant à jour le fichier de configuration, puis en envoyant un signal particulier à l'application (généralement SIGHUP).

Désavantages:

  • Une bonne planification est nécessaire pour sécuriser les données.
  • Vous devrez peut-être apprendre différents formats (bien que de nos jours il n'y ait qu'une poignée de soucis et qu'ils aient généralement une syntaxe similaire).
  • Les emplacements de stockage exacts peuvent être codés en dur dans l'application, ce qui rend le déploiement potentiellement problématique.
  • L'analyse des fichiers de configuration peut être problématique.

Stockez les données dans des variables d'environnement.

Habituellement, cela se fait en obtenant une liste de variables et de valeurs d'environnement à partir du script de démarrage, mais dans certains cas, il peut simplement les indiquer sur la ligne de commande avant le nom du programme.

Avantages:

  • Comparé à l'analyse d'un fichier de configuration, extraire une valeur d'une variable d'environnement est trivial dans à peu près n'importe quel langage de programmation.
  • Vous n'avez pas à vous soucier autant de la publication accidentelle de la configuration.
  • Vous obtenez un certain degré de sécurité par l'obscurité, car cette pratique est rare, et la plupart des gens qui piratent votre application ne vont pas penser à regarder les variables d'environnement tout de suite.
  • L'accès peut être contrôlé par l'application elle-même (lorsqu'elle génère des processus enfants, elle peut facilement nettoyer l'environnement pour supprimer les informations sensibles).

Désavantages

  • Sur la plupart des systèmes UNIX, il est relativement facile d'accéder aux variables d'environnement d'un processus. Certains systèmes offrent des moyens d'atténuer cela (l' hidepidoption de montage pour /procsur LInux par exemple), mais ils ne sont pas activés par défaut et ne protègent pas contre les attaques de l'utilisateur propriétaire du processus.
  • Il n'est pas trivial de voir les paramètres exacts que quelque chose utilise si vous gérez correctement le problème de sécurité mentionné ci-dessus.
  • Vous devez faire confiance à l'application pour nettoyer l'environnement lorsqu'il génère des processus enfants, sinon cela entraînera une fuite d'informations.
  • Vous ne pouvez pas facilement modifier la configuration sans redémarrer complètement l'application.

Utilisez des arguments de ligne de commande pour transmettre les données.

Sérieusement, évitez cela à tout prix, ce n'est pas sûr et c'est une douleur dans le cul à maintenir.

Avantages:

  • Encore plus simple à analyser que les variables d'environnement dans la plupart des langues.
  • Les processus enfants n'héritent pas automatiquement des données.
  • Fournit un moyen simple de tester rapidement des configurations particulières lors du développement de l'application.

Désavantages:

  • Tout comme les variables d'environnement, il est facile de lire la ligne de commande d'un autre processus sur la plupart des systèmes.
  • Extrêmement fastidieux pour mettre à jour la configuration.
  • Fixe une limite stricte sur la durée de la configuration (parfois aussi faible que 1024 caractères).
Austin Hemmelgarn
la source
1
Un point non négligeable est le (redémarrage) sans surveillance d'un serveur, sans avoir à donner manuellement de mots de passe, à la fin ils sont quelque part sur le disque pour cela
PlasmaHH
7
Sur la plupart des systèmes UNIX, vous pouvez lire à peu près toutes les variables d'environnement de processus sans avoir besoin de privilèges importants. -- Pouvez-vous développer? Le fichier / proc / #### / environ est uniquement lisible par le propriétaire, vous devez donc être root ou avoir sudo.
rrauenza
Je pense qu'une partie de cette tendance de config env est également venue de choses comme docker où vous utilisez un conteneur standard et le configurez en passant des variables env au conteneur.
rrauenza
@rrauenza La propriété d'un processus n'est pas un privilège important, sauf si vous faites un très bon travail de séparation des choses par compte, et que vous n'avez en fait besoin de la capacité CAP_SYS_ADMIN (que la racine a implicitement) si vous n'êtes pas le propriétaire. En outre, en ce qui concerne la variable d'environnement, vous avez probablement raison, mais c'est une conception marginale même avec Docker.
Austin Hemmelgarn
3
Je suis d'accord avec l'argument de @rrauenza. La réponse est assez bonne tout autour, mais j'aimerais avoir des précisions sur la façon dont vous pouvez lire à peu près toutes les variables d'environnement de processus sans avoir besoin de privilèges importants . Concernant " et vous n'avez en fait besoin que de la capacité CAP_SYS_ADMIN (que root a implicitement) ..." et bien, si un agent malveillant a des privilèges root, une discussion plus approfondie est redondante, et CAP_SYS_ADMIN pourrait tout aussi bien être privilège root (voir man7.org/linux /man-pages/man7/capabilities.7.html , CAP_SYS_ADMIN et Notes aux développeurs du noyau )
Nubarke
13

Les variables d'environnement seront héritées par chaque processus enfant du serveur Web. C'est chaque session qui se connecte au serveur et chaque programme généré par eux. Les secrets seront automatiquement révélés à tous ces processus.

Si vous conservez des secrets dans des fichiers texte, ils doivent être lisibles par le processus serveur, et donc potentiellement aussi par chaque processus enfant. Mais au moins, les programmes doivent aller les trouver; ils ne sont pas fournis automatiquement. Vous pouvez également exécuter certains processus enfants sous différents comptes et rendre les secrets lisibles uniquement par ces comptes. Par exemple, suEXEC le fait dans Apache.

Andrew Schulman
la source
1
"C'est chaque session qui se connecte au serveur" est une déclaration trompeuse. Vous ne pouvez pas ouvrir une session http sur le serveur et accéder à ses variables d'environnement, ni vous connecter à un shell sur ce serveur et les obtenir à moins d'avoir un accès root ou de posséder le processus du serveur Web.
Segfault
Chaque processus engendré par le serveur Web hérite de son environnement, sauf si vous prenez des mesures actives autrement. Une page HTML n'a pas la capacité d'utiliser ces informations, mais un script le fait.
Andrew Schulman
Bien que correcte, cette réponse pourrait concerner certaines corrections / concessions, en particulier en ce qui concerne les sessions de session . À première vue, il semble peindre l'utilisation des variables d'environnement sous un mauvais jour presque pour suggérer des possibilités de divulgation d'informations à un client externe. En outre, une concession comparable à suexec peut être faite pour un paramétrage limité d'env-vars, par exemple, le paramétrage d'env-vars par processus (à la la MYVAR=foo /path/to/some/executable) limite la propagation à un processus et ses enfants uniquement - et lorsque les démons maîtres nécessaires peuvent frotter / réinitialiser / modifier l'environnement des processus enfants.
shalomb
2

Même s'il y a des compromis à faire en matière de sécurité en ce qui concerne les variables d'environnement ou les fichiers, je ne pense pas que la sécurité ait été le principal moteur de cette recommandation. N'oubliez pas que les auteurs de 12factor.net sont également (ou étaient également?) Des développeurs de Heroku PaaS. Amener tout le monde à utiliser les variables d'environnement a probablement simplifié un peu leur développement. Il y a tellement de variété dans les différents formats et emplacements des fichiers de configuration et il aurait été difficile pour eux de les prendre en charge tous. Les variables d'environnement sont faciles à comparer.

Il ne faut pas beaucoup d'imagination pour deviner certaines des conversations qui ont eu lieu.

Développeur A: "Ah, l'interface utilisateur de ce fichier de configuration secret est trop encombrée! Avons-nous vraiment besoin d'une liste déroulante qui permute entre json, xml et csv?"

Développeur B: "Oh, la vie serait si belle si tout le monde utilisait des variables d'environnement pour la configuration de l'application."

Développeur A: "En fait, il y a des raisons plausibles liées à la sécurité de le faire. Les variables d'environnement ne seront probablement pas accidentellement vérifiées dans le contrôle de code source."

Développeur B: "Ne définissez-vous pas les variables d'environnement avec un script qui lance le démon ou un fichier de configuration?"

Développeur A: "Pas dans Heroku! Nous allons les faire taper dans l'interface utilisateur."

Développeur B: "Oh regardez, mon alerte de nom de domaine pour 12factor.net vient de se déclencher." 1


1 : source: composée.

Segfault
la source
1

TL; DR

Il existe un certain nombre de raisons pour utiliser des variables d'environnement au lieu de fichiers de configuration, mais deux des plus courantes à ignorer sont la valeur utilitaire de la configuration hors bande et la séparation améliorée entre les serveurs, les applications ou les rôles organisationnels. Plutôt que de présenter une liste exhaustive de toutes les raisons possibles, j'aborde uniquement ces deux sujets dans ma réponse, et j'aborde légèrement leurs implications en matière de sécurité.

Configuration hors bande: séparation des secrets du code source

Si vous stockez tous vos secrets dans un fichier de configuration, vous devez distribuer ces secrets à chaque serveur. Cela signifie soit vérifier les secrets dans le contrôle de révision avec votre code, soit disposer d'un référentiel ou d'un mécanisme de distribution entièrement séparé pour les secrets.

Crypter vos secrets n'aide pas vraiment à résoudre ce problème. Tout ce que cela fait, c'est de supprimer le problème, car vous devez maintenant vous soucier également de la gestion et de la distribution des clés!

En bref, les variables d'environnement sont une approche pour déplacer des données par serveur ou par application hors du code source lorsque vous souhaitez séparer le développement des opérations. Ceci est particulièrement important si vous avez publié du code source!

Améliorez la séparation: serveurs, applications et rôles

Bien que vous puissiez certainement avoir un fichier de configuration pour conserver vos secrets, si vous stockez les secrets dans le code source, vous avez un problème de spécificité. Avez-vous une branche ou un référentiel distinct pour chaque ensemble de secrets? Comment vous assurez-vous que le bon ensemble de secrets parvient aux bons serveurs? Ou réduisez-vous la sécurité en ayant des «secrets» qui sont les mêmes partout (ou lisibles partout, si vous les avez tous dans un seul fichier), et constituent donc un plus grand risque si les contrôles de sécurité d'un système échouent?

Si vous voulez avoir des secrets uniques sur chaque serveur, ou pour chaque application, les variables d'environnement éliminent le problème d'avoir à gérer une multitude de fichiers. Si vous ajoutez un nouveau serveur, une nouvelle application ou un nouveau rôle, vous n'avez pas besoin de créer de nouveaux fichiers ou de mettre à jour d'anciens: vous mettez simplement à jour l'environnement du système en question.

Réflexions sur la sécurité

Bien qu'une exploration approfondie de la sécurité noyau / mémoire / fichier soit hors de portée pour cette réponse, il convient de souligner que les variables d'environnement par système correctement implémentées ne sont pas moins sécurisées que les secrets "chiffrés". Dans les deux cas, le système cible doit encore conserver le secret déchiffré en mémoire à un moment donné pour l'utiliser.

Il convient également de souligner que lorsque des valeurs sont stockées dans une mémoire volatile sur un nœud donné, aucun fichier sur disque ne peut être copié et attaqué hors ligne. Ceci est généralement considéré comme un avantage pour les secrets en mémoire, mais ce n'est certainement pas concluant.

Le problème des variables d'environnement par rapport aux autres techniques de gestion des secrets concerne davantage les compromis de sécurité et d'utilisabilité que les absolus. Votre kilométrage peut varier.

CodeGnome
la source
2
Ce n'est pas convaincant, car tous les inconvénients que vous mentionnez pour les fichiers de configuration s'appliquent également aux variables d'environnement. Les variables d'environnement sont des données de configuration. Ils ne se fixent pas comme par magie. Ils doivent être distribués à chaque système et une sorte de mécanisme de configuration doit être utilisé pour les définir.
jpaugh
@jpaugh Vous faites un argument de paille et attaquez quelque chose que je n'ai jamais dit. Les problèmes que j'aborde sont la configuration hors bande et la séparation des données. Comme expliqué clairement, vous pouvez faire ces choses comme bon vous semble. Si vous préférez, vous pouvez publier vos secrets à côté de votre code sur GitHub, mais cela semble certainement imprudent dans le cas général. Cependant, vous seul pouvez déterminer les compromis nécessaires pour que votre système fonctionne correctement dans un modèle de menace donné.
CodeGnome
2
Tous vos points sont corrects, sauf qu'il s'applique aux variables d'environnement autant qu'aux autres données de configuration. Si vous stockez des variables d'environnement dans des fichiers, vous pouvez les valider; et si vous les envoyez hors bande, il est plus facile de le faire dans un fichier qu'en les tapant. Mais si vous préférez les taper, pourquoi ne pas taper un objet JSON à la place et le lire sur stdin? C'est en fait plus sécurisé que la ligne de commande.
jpaugh
1

Personnellement, je ne recommanderais pas de définir des variables d'environnement dans la .bashrcmesure où celles-ci deviennent visibles pour tous les processus démarrés par le shell, mais de les définir au niveau du démon / superviseur (script init / rc, configuration systemd) afin que leur portée soit limitée là où cela est nécessaire. .

Lorsque des équipes distinctes gèrent les opérations, les variables d'environnement fournissent une interface facile pour les opérations afin de définir l'environnement de l'application sans avoir à connaître les fichiers / formats de configuration et / ou à recourir à la manipulation de leur contenu. Cela est particulièrement vrai dans les paramètres multilingues / multi-frameworks où les équipes opérationnelles peuvent choisir le système de déploiement (OS, processus superviseur) en fonction des besoins opérationnels (facilité de déploiement, évolutivité, sécurité, etc.).

Une autre considération est les pipelines CI / CD - car le code passe par différents environnements(ie dev, test / qa, staging, production) les détails environnementaux (zones de déploiement, détails de connexion à la base de données, informations d'identification, adresses IP, noms de domaine, etc.) sont mieux définis par des outils / cadres de gestion de configuration dédiés et consommés par l'application processus de l'environnement (dans un SEC, écrire une fois, exécuter n'importe où de façon). Traditionnellement, lorsque les développeurs ont tendance à gérer ces problèmes opérationnels, ils ont tendance à archiver les fichiers de configuration ou les modèles en plus du code - et finissent par ajouter des solutions de contournement et d'autres complexités lorsque les exigences opérationnelles changent (par exemple, de nouveaux environnements / déploiement / sites se présentent, l'évolutivité / la sécurité peser,

  • Env-vars simplifie la configuration / complexité à grande échelle.
  • Les Env-vars placent la configuration opérationnelle en face de l'équipe responsable de la des aspects non liés au code de l'application de manière uniforme (sinon standard) et sans engagement.
  • Env-vars prend en charge l'échange des processus maître / superviseur (par exemple, god, monit, supervisord, sysvinit, systemd, etc.) qui soutiennent l'application - et certainement même le système de déploiement (OS, images de conteneur, etc.) ou ainsi de suite en tant qu'exigences opérationnelles évoluer / changer. Bien que chaque framework de langage ait de nos jours une sorte d'exécution de processus, ceux-ci ont tendance à être inférieurs sur le plan opérationnel, mieux adaptés aux environnements de développement et / ou à augmenter la complexité dans les environnements de production multilingues / multi-framework.

Pour la production, je préfère définir l'application env-vars dans un fichier d' environnement tel que /etc/default/myapplication.confcelui qui est déployé par la gestion de la configuration et défini comme lisible uniquement de roottelle sorte que systemd(ou toute autre chose d'ailleurs) peut générer l'application sous un utilisateur système dédié défavorisé dans un privé groupe . Soutenu avec des groupes d'utilisateurs dédiés pour opset sudo- ces fichiers sont illisibles par monde par défaut. Ceci est compatible avec 12factor et prend en charge toutes les qualités de Dev + Ops plus a tous les avantages d'une sécurité décente tout en permettant aux développeurs / testeurs de déposer leurs propres fichiers d'environnement dans les environnements dev / qa / test.

shalomb
la source
0

Du point de vue d'un développeur, le stockage des données de configuration dans des variables d'environnement simplifie les déploiements entre différents environnements - développement, assurance qualité et production - et évite aux développeurs d'avoir à se soucier de déployer le mauvais fichier de configuration.

Les applications Web Azure offrent la possibilité d'utiliser ce modèle et cela fonctionne très bien.

En plus de cela, il garde ces données potentiellement sensibles hors du contrôle des sources. Ignorer ces fichiers à partir du contrôle de code source n'est pas vraiment faisable (au moins dans .NET) car une grande partie de la configuration passe-partout nécessaire est également présente dans ces fichiers.

Derek Gusoff
la source