Stratégie pour garder les informations secrètes telles que les clés API en dehors du contrôle de source?

217

Je travaille sur un site Web qui permettra aux utilisateurs de se connecter en utilisant des informations d'identification OAuth telles que Twitter, Google, etc. Pour ce faire, je dois m'inscrire auprès de ces différents fournisseurs et obtenir une clé API super secrète que j'ai. protéger avec des gages contre diverses parties du corps. Si ma clé est gankée, la pièce est tirée.

La clé d'API doit voyager avec ma source, car elle est utilisée au moment de l'exécution pour exécuter les demandes d'authentification. Dans mon cas, la clé doit exister dans l'application dans un fichier de configuration ou dans le code lui-même. Ce n'est pas un problème lorsque je construis et publie à partir d'une seule machine. Cependant, lorsque nous intégrons le contrôle de source dans le mix, les choses se compliquent.

Comme je suis un bâtard pas cher, je préférerais de beaucoup utiliser des services de contrôle de source gratuits tels que TFS dans le cloud ou GitHub. Cela me laisse avec une légère énigme:

Comment conserver mon corps intact lorsque mes clés d'API sont dans mon code et que mon code est disponible dans un référentiel public?

Je peux penser à un certain nombre de façons de gérer cela, mais aucune d’elles n’est aussi satisfaisante.

  • Je pourrais supprimer toutes les informations privées du code et les rééditer après le déploiement. Ce serait une douleur sévère à mettre en œuvre (je ne détaillerai pas les nombreuses manières), et n'est pas une option.
  • Je pourrais le chiffrer. Mais comme je dois le déchiffrer, n'importe qui avec la source pourrait comprendre comment le faire. Inutile.
  • Je pourrais payer pour le contrôle de source privé. LOL j / k dépenser de l'argent? S'il vous plaît.
  • Je pourrais utiliser les fonctionnalités du langage pour séparer les informations sensibles du reste de ma source et donc les garder du contrôle de code source. C’est ce que je suis en train de faire à présent, mais cela pourrait facilement être gâché en vérifiant par erreur le fichier secret.

Je suis vraiment à la recherche d'un moyen sûr de ne pas partager mes données privées avec le monde entier (sauf sur Snapchat), qui fonctionnera sans heurts pendant le développement, le débogage et le déploiement, et sera également infaillible. C'est complètement irréaliste. Alors, que puis-je faire de manière réaliste?

Détails techniques: VS2012, C # 4.5, le contrôle de source sera soit un service TF, soit GitHub. Nous utilisons actuellement une classe partielle pour scinder les clés sensibles dans un fichier .cs séparé qui ne sera pas ajouté au contrôle de source. Je pense que GitHub pourrait avoir l’avantage de pouvoir utiliser .gitignore pour s’assurer que les fichiers de classe partiels ne sont pas archivés, mais j’ai tout gâché. J'espère un "oh, problème commun, voici comment vous le faites" mais je pourrais devoir me contenter de "cela ne craint pas autant qu'il aurait pu",: /

Volonté
la source
6
Vous pouvez vous assurer que le fichier de configuration contenant votre clé API ne se trouve pas dans le répertoire contrôlé par la source, ce qui rendra impossible son archivage en premier lieu.
David Sergey
22
BitBucket.org a un nombre illimité de référentiels privés. Libre. Et l'importateur de référentiel gitHub (conserve l'historique)
Rob van der Veer
4
@Dainius Je ne fais pas confiance à mes développeurs parce que je les connais. Intimement. En fait, je suis au moins intime avec moi-même ... non, je vais laisser cela mentir. Mais je sais à quel point il est facile de bousiller et à quel point il sera difficile de récurer l’histoire de cette histoire.
Will
15
@Dainius: Oui. Je regarde chaque personnage de mon code d'équipe. Sérieusement. Je n'ai pas le choix. Je ne peux pas coder les yeux bandés. Pas de manière fiable, du moins. Mais je le fais parce que je suis mon équipe. Je suis le I en équipe. Il y a un développeur, et c'est moi. Je suis lui Oui. Je suis le gars qui va tout gâcher s'il ne le fait pas correctement. Moi.
Will
3
Pourquoi essayez-vous de compiler la clé dans le code en premier lieu? Il est habituel de mettre ce genre de chose dans un fichier de configuration.
Donal Fellows

Réponses:

128

Ne mettez pas vos informations secrètes dans votre code. Placez-le dans un fichier de configuration qui est lu par votre code au démarrage. Les fichiers de configuration ne doivent pas être placés sur le contrôle de version, sauf s’ils sont définis par défaut, et ils ne devraient pas avoir d’informations privées.

Voir aussi la question Contrôle de version et fichier de configuration personnelle pour savoir comment le faire.

Philipp
la source
8
@RobertHarvey simplement en ne le mettant pas sur le contrôle de version, en ajoutant une règle ignore si nécessaire. Toute personne utilisant le logiciel doit créer son propre fichier de configuration avec sa propre clé API.
Philipp
10
Alors, quand vous allez construire et créer une distribution de votre logiciel, comment êtes-vous sûr qu'il est livré avec un fichier de configuration? Sauf si vous avez un fichier avec des valeurs par défaut raisonnables, il n’est généralement pas raisonnable de s’attendre à ce que votre utilisateur passe par un processus de création d’un fichier de configuration.
Thomas Owens
4
Eh bien, les paramètres d'usine par défaut ne sont qu'une partie, les "installateurs" ou les "premiers assistants" une autre
johannes
6
Si de nombreux utilisateurs ont leur propre installation, ne devraient-ils pas créer et utiliser leur propre clé API? Plusieurs sites / installations utilisant la même clé sont probablement une mauvaise idée. S'il ne s'agit que d'une installation, alors utiliser un fichier de configuration n'est pas un gros problème.
Mike Weller
10
@Will, si vous ne pouvez pas faire cela en raison de l'impraticité des détails d'implémentation, je dirais que vous n'avez tout simplement pas les outils appropriés pour le déploiement. Le déploiement à l'aide d'un fichier de configuration secret non soumis doit être totalement simple. Je ne peux pas vous offrir de conseils spécifiques, car je vis dans l'écosystème Ruby, pas en C #. Mais les gens de Ruby ont tendance à utiliser Capistrano pour des déploiements automatisés. Je suis sûr que C # a également son outil de déploiement automatisé, ce qui devrait faciliter le processus.
Ben Lee
29

Vous pouvez mettre toutes les clés privées / protégées en tant que variables d'environnement système. Votre fichier de configuration ressemblera à ceci:

private.key=#{systemEnvironment['PRIVATE_KEY']}

Voici comment nous traitons ces cas et rien ne va dans le code. Cela fonctionne très bien combiné avec différents fichiers de propriétés et profils. Nous utilisons différents fichiers de propriétés pour différents environnements. Dans notre environnement de développement local, nous plaçons les clés de développement dans les fichiers de propriétés pour simplifier la configuration locale:

private.key=A_DEVELOPMENT_LONG_KEY
Ioannis Tzikas
la source
Ce serait une solution raisonnable si je peux le faire fonctionner avec mon option d'hébergement. Ne seront pas des variables d'environnement, mais peut-être certaines paires de configuration clé / valeur qui ne seront pas effacées après la publication ...
Will
Pourquoi ne pas ajouter ces variables d’environnement dans votre serveur de build avant de les envoyer dans l’environnement réel? De cette façon, vous serez prêt pour les fichiers de ressources / configuration de production.
Ioannis Tzikas
Le serveur de compilation est la machine de développement, c'est pourquoi je crains que cette information ne soit éventuellement cochée accidentellement dans le contrôle de source.
Will
Le problème avec ceci peut être que l'environnement est lisible par n'importe qui sur le serveur.
JasonG
Les envvars d’un utilisateur ne sont lisibles que par l’utilisateur ou par root. (Ancient Linux et AIX ne l'ont pas fait cependant)
Neil McGuigan
27

Façon pure git

  • .gitignore fichier inclus avec données privées
  • Utilisez une branche locale dans laquelle vous remplacez TEMPLATEparDATA
  • Utilisez des filtres de nettoyage / nettoyage, dans lesquels le script du filtre (local) effectue le remplacement bidirectionnel TEMPLATE<->DATA

Chemin mercurial

  • Patch (s) MQ au-dessus du code factice, qui remplace TEMPLATEpar DATA(les ensembles de modifications sont publics, le patch est privé)
  • Extension de mot clé avec des mots clés spécialement conçus (développés uniquement dans votre répertoire de travail )

SCM-manière agnostique

  • Remplacer les mots-clés dans le cadre du processus de création / déploiement
Badger paresseux
la source
Hmmm ... Le conseil de git est bon, et votre conseil agnostique me donne une bonne idée ... Je peux utiliser les événements de construction pour introduire le fichier dans le processus de publication, puis le supprimer après, aidant ainsi à le prévenir. être ajouté accidentellement au contrôle de la source ..
Will
7
Non, non et encore une fois - non! ignorer des fichiers est utile pour ajouter une personnalisation très spécifique à un processus de construction, mais cela ne doit jamais être utilisé pour stocker des données sécurisées. Ne stockez pas de données sécurisées dans le référentiel, même si vous les ignorez.
shabunc
11
@shabunc - RTFM! Fichier ignoré non enregistré dans le référentiel
Lazy Badger
9
@LazyBadger - Je sais assez bien que c'est ignoré. Je sais aussi que, dans le repo, il y a TOUJOURS une chance que quelqu'un, malgré tout, l'ajoute par erreur à la repo. Certains chemins de configuration externes sont bien meilleurs.
shabunc
4
@shabunc - bon point pour garder la configuration en dehors du chemin du SCM. C'est pourquoi, par exemple, Postgres vous permet de contourner les contrôles de mot de passe en le mettant dans un fichier. Mais ils exigent que le fichier de mots de passe soit placé dans ~ / .pgpass - ce qui n’est vraisemblablement pas un emplacement très pratique pour vérifier le contrôle de code source. Ils savent que, pour l'automatisation, ils doivent vous donner une arme à feu, mais ils travaillent dur pour vous empêcher de vous tirer dans le pied.
Steve Midgley
14

Je mets des secrets dans des fichiers cryptés que je valide ensuite. La phrase secrète est fournie au démarrage du système ou est stockée dans un petit fichier que je ne valide pas. C'est bien qu'Emacs gère avec joie ces fichiers cryptés. Par exemple, le fichier init emacs inclut: (chargez "secrets.el.gpg"), ce qui fonctionne - en me demandant le mot de passe pour ces rares occurrences lorsque je lance l'éditeur. Je ne m'inquiète pas que quelqu'un casse le cryptage.

Ben Hyde
la source
3
C'est une excellente solution - je suis surpris que vous n'ayez pas plus de votes positifs. Je travaille avec une entreprise qui traite des données sur les étudiants, qui est réglementée par le gouvernement fédéral aux États-Unis. Elles doivent donc redoubler de prudence en ce qui concerne les diplômes et les secrets. Ils sont également une grande entreprise et doivent donc utiliser la gestion de la chaîne d'approvisionnement pour les informations d'identification afin que le service informatique puisse les trouver / les gérer après leur construction par le génie. Votre solution est exactement ce qu'ils font. Ils ont des fichiers de clé de déchiffrement qui contiennent des clés de déchiffrement pour dev / staging / prod / etc (un fichier pour chacun). Ensuite, tous les secrets sont cryptés et archivés. Les fichiers de déchiffrement sont utilisés pour les obtenir dans chaque environnement.
Steve Midgley
7
Eh bien, dans un certain sens, le cryptage du secret (la clé API dans ce cas) ne fait que déplacer le problème de ne pas commettre les données secrètes à ne pas commettre la phrase secrète (qui devient maintenant les données secrètes ). Mais bien sûr, le demander lors du lancement du système est une bonne option.
Siegi
J'aime cette solution. Le type de fichier crypté que vous avez validé pourrait être un fichier KeePass. Il aurait une entrée pour chaque environnement, en utilisant le noteschamp pour stocker le contenu du fichier .env. Il y a quelques mois, j'ai écrit un outil permettant de lire un fichier keepass et de créer un fichier .env à l'aide du noteschamp d'une entrée. Je songe à ajouter une fonctionnalité pour pouvoir effectuer des opérations require('switchenv').env()dans la partie supérieure du programme Node.js et créer des variables process.env en fonction de l'entrée qui correspond à NODE_ENV ou à un système similaire. -> github.com/christiaanwesterbeek/switchenv
Christiaan Westerbeek
14

Ceci est très spécifique à Android / Gradle mais vous pouvez définir les clés dans votre gradle.propertiesfichier global situé dans user home/.gradle/. Cela est également utile car vous pouvez utiliser différentes propriétés en fonction de buildType ou de la saveur, c'est-à-dire une API pour dev et une autre pour la version.

gradle.properties

MY_PRIVATE_API_KEY=12356abcefg

build.gradle

buildTypes {
        debug{
            buildConfigField("String", "GOOGLE_VERIFICATION_API_KEY", "\"" + MY_PRIVATE_API_KEY +"\"")
            minifyEnabled false
            applicationIdSuffix ".debug"
            }
        }

Dans le code que vous référencez comme ceci

String myAPI = BuildConfig.GOOGLE_VERIFICATION_API_KEY;
Scottyab
la source
BuildConfig étant traduit dans le fichier source correspondant, une ingénierie inverse simple sur votre apk révélera toutes les clés et tous les secrets que vous avez mis dans le BuildConfig
Dmitri Livotov
1
En effet, un point valable. Mais la question était de savoir comment garder les clés API hors du code source et non du binaire.
scottyab
11

Vous n'êtes pas censé distribuer cette clé avec votre application ou la stocker dans le référentiel de code source. Cette question demande comment faire cela, et ce n'est pas ce qui se fait normalement.

Application Web mobile

Pour Android / iPhone, l'appareil doit demander la clé à votre propre service Web lors de la première exécution de l'application. La clé est ensuite stockée dans un endroit sûr. La clé doit-elle être modifiée ou révoquée par l'éditeur? Votre service Web peut publier une nouvelle clé.

Application Web hébergée

Les clients utilisant une licence de votre logiciel devront saisir manuellement la clé lors de la première configuration du logiciel. Vous pouvez donner à chacun la même clé, des clés différentes ou obtenir la leur.

Code source publié

Vous stockez votre code source dans un référentiel public, mais pas la clé. Dans la configuration du fichier, vous ajoutez les lignes * place key ici * . Lorsqu'un développeur utilise votre code source, il en fait une copie sample.cfget ajoute sa propre clé.

Vous ne conservez pas votre config.cfgfichier utilisé pour le développement ou la production dans le référentiel.

Réactionnel
la source
4
Cette question demande comment faire cela non, absolument pas. Le fait est que ces clés doivent être utilisées par code, donc par code, ce qui signifie généralement via un code ou des fichiers de configuration qui, s’ils ne sont pas dans la source, sont au moins proches et risquent de se retrouver accidentellement. la source. L'application Web hébergée est malheureusement absurde. Vous n'avez pas besoin de demander une clé API pour vous connecter à StackOverflow via votre compte Facebook (hypothétique). placer la clé ici est une simplification excessive énorme qui ne fonctionnera pas dans les environnements de dev-> pub, comme décrit dans le Q.
Will
J'ai bien répondu à la question, comme beaucoup d'autres. Le fait que vous n'ayez pas accepté l'une d'entre elles implique que vous ne comprenez pas comment utiliser ces clés.
Reactgular
7
Alors, comment protégeons-nous le service Web de publication de clés? En utilisant une autre clé?
Jiangge Zhang
Idem ce que @JianggeZhang a dit - c'est un conseil dangereux
David K. Hess
5

Utilisez des variables d’environnement pour les éléments secrets qui changent pour chaque serveur.

http://en.wikipedia.org/wiki/Variable_Environnement

Leur utilisation dépend de la langue.

Filipe Giusti
la source
3
La sécurité par l'obscurité n'est pas une approche recommandée pour beaucoup. Voulez-vous élaborer sur votre réponse pour être plus clair?
2
Ce n'est pas obscur, les variables d'environnement ne sont disponibles que pour l'utilisateur auquel vous les avez ajoutées, de sorte que toutes vos informations d'identification bénéficient de la même protection que le contexte utilisateur exécuté par votre application. J'ai mis à jour la réponse pour inclure le concept de variables d'environnement. Est-ce plus clair?
Filipe Giusti
4

Je pense que c'est un problème avec lequel tout le monde a eu des problèmes à un moment donné.

Voici un flux de travail que j'ai utilisé, qui pourrait fonctionner pour vous. Il utilise .gitignore avec une torsion:

  1. Tous les fichiers de configuration vont dans un dossier spécial (w / sample config files - optionnel)
  2. Tous les fichiers de configuration sont inclus dans .gitignore, afin qu’ils ne deviennent pas publics
  3. Configurez un serveur gitolite (ou votre serveur git préféré) sur une boîte privée
  4. Ajouter un repo avec tous les fichiers de configuration du serveur privé
  5. Ajouter un script pour copier les fichiers de configuration dans le dossier spécial du référentiel principal (facultatif)

Désormais, vous pouvez cloner le référentiel de configuration sur n’importe quel système de développement et de déploiement. Il suffit d’exécuter le script pour copier les fichiers dans le bon dossier et vous avez terminé.

Vous obtenez toujours tous les bonbons GitHub, partagez votre code avec le monde entier et les données sensibles ne sont jamais dans le référentiel principal, elles ne sont donc pas rendues publiques. Ils ne sont encore qu'une attraction et une copie de tout système de déploiement.

J'utilise une boîte de 15 $ / an pour le serveur git privé, mais vous pouvez également en configurer une à la maison, selon les exigences de la politique de la radicale ;-)

PS: Vous pouvez également utiliser un sous-module git ( http://git-scm.com/docs/git-submodule ), mais j'oublie toujours les commandes, règles donc rapides et sales!

Kostas
la source
2

Utilisez le chiffrement, mais fournissez une clé principale au démarrage, sous forme de mot de passe sur la console, dans un fichier que seul l'utilisateur du processus peut lire, ou à partir d'un magasin de clés fourni par le système, tel que le trousseau Mac OS ou le magasin de clés Windows.

Pour une livraison continue, vous aurez besoin de diverses clés enregistrées quelque part. La configuration doit être distinguée du code, mais il est judicieux de la garder sous contrôle de révision.

Erickson
la source
1

3 stratégies, non encore mentionnées (?)

À l'enregistrement ou dans un pré-enregistrement VCS

  • rechercher des chaînes avec une entropie élevée, exemple- detect -secrets
  • regex recherche des modèles de clés d'API bien connus. Les clés AKIA * d’AWS en sont un exemple, git-secrets est un outil basé sur cela. En outre, les noms de variables comme «mot de passe» avec une affectation constante.
  • rechercher des secrets connus - vous connaissez vos secrets, recherchez un texte à leur sujet. Ou utilisez un outil, j'ai écrit cette preuve de concept .

Stratégies déjà mentionnées

  • stocker dans un fichier en dehors de l'arbre source
  • l'avoir dans l'arbre des sources, mais dire à VCS de l'ignorer
  • les variables d'environnement sont une variante du stockage de données en dehors de l'arbre source
  • il suffit de ne pas donner les secrets précieux aux développeurs
Matthew Martin
la source
0

Conservez les informations privées en dehors de votre contrôle de source. Créez une valeur par défaut non chargée pour la distribution et faites en sorte que votre VCS ignore le vrai. Votre processus d'installation (qu'il soit manuel, configure / build ou assistant) doit gérer la création et le remplissage du nouveau fichier. Modifiez éventuellement les autorisations sur le fichier pour vous assurer que seul l'utilisateur requis (serveur Web?) Peut le lire.

Avantages:

  • Ne suppose pas d'entité de développement == entité de production
  • Ne présume pas que tous les collaborateurs / réviseurs de code sont dignes de confiance
  • Évitez les erreurs faciles en le gardant hors du contrôle de version
  • Facile à automatiser les installations avec une configuration personnalisée pour QA / builds

Si vous le faites déjà et que vous l'enregistrez accidentellement, ajoutez-le à celui de votre projet .gitignore. Cela rendra impossible de faire à nouveau.

Il existe de nombreux hôtes Git gratuits dans le monde qui fournissent des référentiels privés. Bien que vous ne devriez jamais mettre à jour vos informations d'identification, vous pouvez également bénéficier de solutions de stockage bon marché et de pensions privées. ^ _ ^

Adrian Schneider
la source
-2

Au lieu d'avoir la clé OAuth stockée en tant que données brutes n'importe où, pourquoi ne pas exécuter la chaîne via un algorithme de cryptage et la stocker sous forme de hachage salé? Ensuite, utilisez un fichier de configuration pour le restaurer au moment de l'exécution. Ainsi, la clé n'est stockée nulle part, qu'elle soit stockée sur une boîte de développement ou sur le serveur lui-même.

Vous pouvez même créer une API de telle sorte que votre serveur génère automatiquement une nouvelle clé d'API salée et hachée, requête par requête. Ainsi, même votre équipe ne pourra pas voir la source OAuth.

Edit: essayez peut-être la bibliothèque de cryptographie Javascript de Stanford , elle permet un cryptage / décryptage symétrique plutôt sûr.

David Freitag
la source
1
Les hachages sont généralement à sens unique. Il existe des algorithmes de chiffrement symétriques qui feraient ce que vous suggérez.
3
Mec, vous ne pouvez pas déchiffrer (facilement) un hachage. C'est tout l'intérêt des hashes. Ceci concerne ME consommant l'API de quelqu'un d'autre, où ils lui attribuent une clé secrète. Mon hachage m'assure (à moins de choisir un mauvais algo et de le déchiffrer à chaque fois) que je ne peux pas utiliser leur API.
Will