Quel est le moyen préféré pour stocker les configurations d'application?

38

La plupart du temps, je stocke la configuration de l'application de développement dans le répertoire racine du projet, comme suit:

app
|-- config.json

Mais cela ne semble pas être la meilleure approche, car cette configuration finit par être stockée dans le système de contrôle de version, ce qui peut entraîner une fuite des noms d'utilisateur, mots de passe et autres informations sensibles.

Le Guide de l’ application Factor recommande de supprimer complètement les fichiers de configuration et d’utiliser des variables d’environnement pour la configuration:

... stocke la configuration dans des variables d'environnement. Env vars sont faciles à changer d'un déploiement à l'autre sans changer de code; contrairement aux fichiers de configuration, il y a peu de chance qu'ils soient archivés accidentellement dans le dépôt de code; et contrairement aux fichiers de configuration personnalisés, ou à d'autres mécanismes de configuration tels que les propriétés système Java, ils constituent une norme indépendante du langage et du système d'exploitation.

Cela me semble très agréable, mais où stocker lesdites variables d’environnement sans les vérifier dans le contrôle de source? Et quels outils puis-je utiliser pour transmettre ces variables à l'application? Il peut y avoir des dizaines d'options de configuration, et les taper à la main chaque fois que vous lancez l'application n'est pas agréable - elles doivent donc être stockées dans un type de fichier quelque part. Ce fichier se retrouvera donc dans le contrôle de code source et nous reviendrons à l’origine.

Existe-t-il une manière universellement acceptée de gérer les options de configuration, sans risque de stocker la configuration locale dans le contrôle de source?

Rogach
la source
1
Eh bien, git a au moins quelque chose comme .gitignoreoù je peux définir des fichiers ou des dossiers qui ne doivent pas être archivés dans le contrôle de version. Comme vous le dites, je ne vois pas où Env vars devrait vraiment aider, car vous avez un script pour les définir et vous devriez les stocker avec le projet ou vous les avez 'quelque part' sur votre système (répertoire de départ ou même au démarrage de la machine). scripts), ce qui semble créer beaucoup de problèmes, surtout si une configuration importante est nécessaire. Dans tous les cas, je scinderais les fichiers de configuration pour que les informations confidentielles soient placées dans des fichiers différents.
Thorsten Müller
@ thorstenmüller - seul problème avec .gitignore que la configuration de base / modèle doit encore être stockée, ce qui signifie que l'application doit lire deux configurations - la première, avec les options par défaut (stockées dans scm), et la locale, qui écrase la base (et n'est pas stocké dans scm). Avec env vars, j’imagine que le déploiement de masse devient plus facile: il est plus simple de spécifier des variables d’environnement pour la nouvelle configuration de la machine virtuelle que d’écrire quelque chose dans un fichier non standard.
Rogach
Bonne question, après que j'ai commencé à utiliser pour cela le magasin de données d'applications propres à l'utilisateur, la vie est devenue plus facile ;-)
Wolf
1
Avez-vous essayé "Redis" redis.io . Il est spécialement conçu pour le stockage de la structure clé-valeur uniquement.
Karan
2
@jporcenaluk - J'aime les stockages de valeurs-clés, mais ajouter une application redis complète à une application destinée uniquement à gérer la gestion de la configuration donne l'impression d'être un peu excessif. D'autre part, je n'ai peut-être jamais travaillé sur des projets assez grands.
Rogach

Réponses:

16

Peut-être n'y a-t-il pas une seule bonne réponse à cela. Il semble que vous deviez stocker ces données dans un endroit sûr, car elles le seront un jour à des fins de récupération après sinistre. Ceci s'applique également aux fichiers de propriétés et aux scripts qui définissent les variables d'environnement.

  • Avec le code source (en SVN / GIT, etc.), c’est une très mauvaise idée, car ces données contiendront des mots de passe de base de données de production, etc.
  • Les sauvegardes nocturnes de votre entreprise peuvent suffire, mais il est peu probable que l'historique des changements reste facilement accessible.
  • Les données doivent être versionnées séparément du logiciel consommateur. Dans notre système actuel, un changement de configuration conduit à une nouvelle version de l'application, ce qui est tout simplement faux.

Nous cherchons actuellement des solutions à ce problème et nous nous orientons vers un référentiel de code avec un accès restreint. Ce référentiel ne contiendrait que des données de cofiguration. Les autres ont-ils des expériences à partager?

Kiwiron
la source
2
Avoir deux référentiels distincts pour un projet semble ne pas être une bonne idée - vous ne pouvez pas effectuer de restauration en arrière ni de travailler avec des branches, car vous devrez alors manipuler deux référentiels simultanément (par exemple, une autre branche nécessite une nouvelle option de configuration). basculer vers cette nouvelle branche sans basculer également dans le référentiel de configuration, les choses se cassent de manière étrange).
Rogach
2
@Rogach je prends votre point. Il existe des raisons valables de conserver certaines configurations avec le code, mais comme vous le dites dans votre question, les éléments sensibles doivent aller ailleurs. Deux référentiels semblent donc inévitables. De plus, je n'ai pas mentionné que les serveurs d'applications aident souvent ici. Les sources de données et les variables JNDI peuvent être configurées par l'administrateur et ne seront pas publiques.
Kiwiron
Un deuxième magasin a du sens. Il est possible que d'autres types de données, également confidentielles, puissent être stockés avec la configuration (par exemple, des données de production en cours d'analyse pour résoudre les problèmes des clients).
Wolf
1
@Rogach Ils semblent attirer beaucoup de haine, mais les sous-modules git gèreraient cela très bien, je pense - si le principal était configuré correctement, et que le référentiel à accès restreint pourrait simplement y vivre.
SeldomNeedy
9

En examinant les problèmes et les solutions possibles, il m’aide à utiliser une méthode popularisée par Jeff Atwood : si Dieu créait un moyen de stocker des informations de configuration sensibles, comment le ferait-il?

Eh bien, il saurait qui a besoin d'informations de configuration et ne les communiquera qu'à ces personnes, et ces informations ne pourront jamais être consultées par quiconque.

La première partie devrait déjà être prise en charge: votre système de contrôle de code source devrait authentifier les utilisateurs. Et cette approche a également été validée conformément au numéro 10 des 10 commandements du contrôle de code de Troy Hunt , "les dépendances doivent être dans le contrôle de code".

Mais comment le garder en sécurité en cas de fuite? Eh bien, il n’est pas nécessaire de le stocker en texte brut! Utilisez le cryptage. Dans .NET, vous pouvez effectuer certaines étapes pour chiffrer les données de chaîne de connexion dans vos fichiers de configuration . Pour ce faire, vous devez trouver des méthodes équivalentes avec la technologie de votre choix.

Jporcenaluk
la source
3
Je voulais juste préciser - comment la configuration du chiffrement aidera-t-elle? Si j'ai bien compris, il vous sera demandé de partager le même mot de passe de déchiffrement entre tous les développeurs, ce qui ressemble à un appel à problèmes.
Rogach
Si une personne extérieure à votre entreprise accède à votre référentiel, vos mots de passe sont obscurcis. Si quelqu'un copie les fichiers d'un projet sur une clé USB et les laisse quelque part, c'est la même chose. Ce sera plus de travail à maintenir, bien sûr. Plus de sécurité vient généralement au prix de la commodité. Cette solution est un peu lourde, je vous le dirai. Je suis ouvert à une meilleure façon de résoudre la question du PO!
Jporcenaluk
5

De nombreuses personnes critiquent le fait de stocker la configuration dans des fichiers ordinaires avec votre code source, mais d’après mon expérience, c’est une très bonne solution:

  • Simple à mettre en œuvre dans toutes les langues. Dans de nombreux cas, vous bénéficiez d'une assistance immédiate pour les fichiers de configuration complexes. Par exemple, dans le cas de Java avec Spring Boot, vous obtenez le support YAML qui peut exprimer n’importe quelle structure arborescente, et il est facile d’avoir des fichiers de configuration séparés pour différents environnements ainsi qu’une configuration de base à partir de laquelle des fichiers spécifiques à l’environnement peuvent hériter.
  • La configuration est nécessaire pour exécuter votre logiciel, et les modifications de code nécessitent souvent l'ajout / la modification de paramètres de configuration. Il est donc naturel de conserver la configuration et le code ensemble.
  • Le stockage de la configuration avec la source vous offre tous les avantages du contrôle de source, par exemple savoir qui a modifié quel paramètre et quand, ou pouvoir vérifier les configurations lors d'une révision de code normale.
  • À moins que vous ne travailliez pour la CIA, l'argument de la sécurité me semble exagéré. Votre mot de passe de base de données est donc stocké dans un fichier sur la machine sur laquelle votre application est exécutée. Eh bien, si quelqu'un a accès à la machine avec votre application, vous avez probablement déjà de gros problèmes: il peut par exemple supprimer votre application et démarrer sa propre application à sa place sur le même port. Dans un tel cas de figure, l'accès au mot de passe de la base de données pourrait ne pas être un gros problème. À moins que toutes vos connexions ne soient entièrement cryptées et qu'elles aient accès à votre ordinateur, elles peuvent néanmoins détecter une grande partie des données intéressantes des interfaces réseau.
  • Vous pouvez utiliser un outil tel que Hiera pour avoir un fichier de configuration textuel mais pas pour y stocker des mots de passe ou autres données sensibles.

Ainsi, dans de nombreux cas, la configuration textuelle stockée dans le contrôle de source avec le code est un bon début.

Si vous êtes sur des systèmes distribués ou souhaitez pouvoir échanger à chaud votre configuration sans redéployer vos applications, vous trouverez peut-être une solution basée sur un serveur de configuration. Spring Cloud prend en charge de tels mécanismes , et les configurations de serveurs d’arrière-plan peuvent être un référentiel git ou Eureka . Vous pouvez également lancer votre propre en utilisant par exemple Zookeeper . Chacune de ces approches facilitera la gestion de configurations cohérentes sur de nombreux serveurs afin de mettre à jour les configurations sans avoir à reconstruire et à redéployer votre logiciel. Bien entendu, cela a un coût: apprendre le serveur de configuration et comment l'utiliser à partir de vos applications, ainsi qu'un autre système à déployer et à gérer.

Michał Kosmulski
la source
Mais le code change de mains à quelqu'un qui ne possède pas les secrets dans les fichiers de configuration, il va y avoir un vrai désordre.
Tim Ludwinski
@TimLudwinski Les clés / secrets appartiennent à la société, pas à des développeurs individuels. Ils doivent donc être gérés de manière à ne pas se perdre si un seul individu s'en va. Ils peuvent être des problèmes et gérés par les administrateurs / l'équipe de sécurité par exemple, de sorte qu'il existe un registre central.
Michał Kosmulski le
5

Nous luttons contre le même problème où je travaille. À l'heure actuelle, toutes nos configurations sont basées sur des fichiers et contrôlées par les sources avec les applications individuelles qui les utilisent. Cela conduit à la duplication et permet aux développeurs d’avoir accès à des mots de passe de production / qa plutôt qu’à un simple développement.

Cela dit, je pense que nous avons trouvé une bonne solution pour l’avenir. Nous déplaçons nos fichiers de configuration vers un référentiel git distinct (appelé le référentiel de configuration). Nous avons ensuite mis en place un serveur spring-cloud-config (java) qui sert simplement les fichiers du référentiel de config en fonction des profils qui lui sont transmis. Cela convient parfaitement aux applications Java qui peuvent utiliser le client et les télécharger au démarrage. Pour nos applications PHP / non Java, nous allons extraire directement le fichier. (Pas idéal). À l'avenir, nous pourrons peut-être écrire quelque chose qui permettra à l'application PHP de télécharger elle-même les configurations et de les mettre en cache quelque part, mais ce n'est pas une priorité élevée pour la première exécution. Je considère cette solution comme une configuration en tant que service, qui n'enfreint pas explicitement les recommandations relatives aux applications à 12 facteurs.

Je pense que zookeeper peut être utilisé pour la même chose (j'ai vu une configuration avec kubernetes + zookeeper), donc je ne suis pas tout à fait sûr de savoir pourquoi cette réponse a un -1 en haut.

Liens:

https://spring.io/guides/gs/centralized-configuration/

https://cloud.spring.io/spring-cloud-config/

ssjcory
la source
3

Au lieu de stocker la configuration complète dans un seul fichier, stockez-la dans plusieurs fichiers.

  • Avoir un répertoire de configuration . Tous les fichiers sont interprétés comme des fichiers de configuration, sauf peut-être README*.
  • Tous les noms de fichiers sont triés par ordre alphabétique et les fichiers sont chargés dans cet ordre. Voilà pourquoi les fichiers dans de tels cas commencent souvent par un chiffre ou deux: 01-logging.json. 02-database.json, etc.
  • Les données de tous les fichiers sont chargées dans la même structure de configuration disponible pour l'application. C’est ainsi que plusieurs fichiers peuvent compléter les paramètres de chacun, et même les remplacer de manière prévisible.
  • Ne stockez dans le VCS que les fichiers de configuration avec des valeurs sans danger ou des valeurs par défaut. Ajoutez les fichiers de configuration avec des secrets lors du déploiement ou, mieux encore, utilisez un service de stockage de secrets authentifiés.

Sur votre machine Linux la plus proche, regardez /etc/sudoers.dou /etc/nginx/conf.d. Cela montre le même schéma.

La gestion des secrets est une bête différente. Vous pouvez les gérer comme une étape manuelle pendant que vous êtes petit. Vous pouvez utiliser des choses comme Zookeeper. Vous pouvez même vérifier les secrets dans un VCS sous forme chiffrée et les déchiffrer en tant qu'étape de déploiement. Un certain nombre d'autres options existent.

(En outre, un article d'opinion: JSON n'est pas un bon format de fichier de configuration, car il ne permet pas les commentaires; les commentaires sont cruciaux. Les formats TOML, YAML et même INI sont meilleurs dans la pratique.)

9000
la source
2

Je pense que vos options sont quelque peu définies par le système d'exploitation que vous déployez.

Je suggère, oui, mettez les valeurs dans le contrôle de source. MAIS seulement les versions 'dev'. Vous voulez que votre code source soit compilé ET fonctionne! ne pas inclure des étapes secrètes supplémentaires

Votre processus de génération et de déploiement doit ensuite échanger ces valeurs par environnement lors du déploiement. (la pieuvre a ce genre de modèle)

Ewan
la source
0

Apache zookeeper offre de merveilleuses options pour stocker les configurations d'applications pour les systèmes distribués. Les modifications apportées chez zookeeper peuvent être capturées et traitées en ayant un auditeur conservateur ou zookeeper à la fin de l'application.

Gmoney
la source
6
Quelles sont les options? Comment ça marche? Où les stocke-t-il? Est-ce qu'un préféré sur un autre? Quels sont les différents avantages et inconvénients de chaque option? Comment cela interagit-il sur différents systèmes d'exploitation?
3
@Gangz - Je souhaiterais une réponse plus détaillée, ne vous découragez pas des avis négatifs, et améliorez votre réponse afin qu'elle puisse être utile.
Jay Elston