如何开源我的Rails应用程序而不泄露应用程序的密钥和凭据。

24

我有许多Rails应用程序托管在GitHub上。它们目前都是私有的,我经常会从它们的GitHub存储库部署它们。我想能够使其中一些开源,就像您可以在http://opensourcerails.com上找到的那样。

我的问题是:如何在不泄露超级秘密凭据的情况下使这些存储库公开?

例如,我可以查看/config/initializers/cookie_verification_secret.rb,并查看几乎每个存储库的cookie secret。我不明白这是如何被接受的。这些用户是否都在部署环境中以某种方式更改这些值?

有些用户甚至会暴露他们的AWS秘密和密钥!其他人则将他们的AWS秘密设置为:

ENV['aws-secret']

虽然我不确定他们在何时设置了该值。

那么,开源Rails应用程序的最佳实践是什么,而不会 compromis e您的应用程序的安全性。

5个回答

16

最近我为自己的一个应用程序解决了这个问题。我的解决方案是将任何机密内容存储在一个被 git 忽略的 YAML 配置文件中,并使用初始目录下的一个简单类来访问该文件。配置文件存储在 Capistrano 部署的 "shared" 文件夹中,并在每次部署时复制到配置中。

配置存储: http://github.com/tsigo/jugglf/blob/master/config/initializers/juggernaut.rb

示例用法: https://github.com/tsigo/jugglf/blob/6b91baae72fbe4b1f7efa2759bb472541546f7cf/config/initializers/session_store.rb

您还可能希望从源代码控制中删除使用这些机密值的文件的所有历史记录。以下是我使用的 Git 操作指南:http://help.github.com/removing-sensitive-data/


1
很好的建议。此外,如果您不想删除历史记录,并且如果可行的话,您可以在新部署后简单地更改值(并在它们通过.gitignore隐藏后),从而使旧值无用。当然,这种方法有一定的失败风险,因为如果您忘记更改其中一个关键值,可能会出现问题。 - jefflunt
1
由于这个答案仍在得到投票,我觉得我应该更新一下我今天会(并且已经)如何做到这一点:https://github.com/bkeepers/dotenv - Robert Speicher

10
如果你正在使用foreman,把一个名为.env的文件放在你的应用程序根目录下。(foreman文档) .env将包含以下内容。
AWS_SECRET=xxx
AWS_ACCESS=yyy

然后当您需要使用这些键时,插入:

ENV['AWS_SECRET']
ENV['AWS_ACCESS']

虽然重要的是不要将.env提交到您的版本控制中。所以,如果您使用git,请将.env添加到您的.gitignore


加分回合! - Heroku

如果部署到Heroku,则还需要在Heroku环境中配置这些环境变量。有两个选项:

  1. 通过heroku config:add命令手动添加密钥
  2. 使用heroku-config gem来双向同步您的本地环境变量。

4

不在Git存储任何秘密值。在Git仓库的任何历史时刻都不应该存储这些值。
这些值应该存储在其他地方,只留下模板配置文件版本化,以及一个能够:

  • 从外部仓库读取正确值的脚本
  • 并构建完整的最终配置文件(其中包含秘密值)的脚本

通过将两组数据分开(源代码在一侧,秘密值在另一侧),您可以公开源代码仓库而不会泄露任何机密信息。


谢谢,这似乎是一个明显而聪明的答案。但是,如果我要部署到EngineYard或Heroku(我不能或不想永久存储除我的repo之外的任何东西),让该机器从我的本地机器上的一个repo中读取秘密值似乎并不容易。您对此过程有什么进一步的建议或链接吗? - ballgame
@ballgame:“让那台机器从我本地机器上的存储库中读取秘密值”,但它可以从任何你想要的地方读取值,而不仅仅是你的“本地机器”。它只需要(从部署的服务器)访问外部数据源。 - VonC
1
如果您正在使用foreman启动Web应用程序,您可以在存储库的根目录中创建一个.env文件,在其中设置变量,并将其添加到.gitignore中。 - Alban

3

我从你的问题中得到了启示,使用了ENV。

我有三个不同的秘密值,我不想让它们公开。当然,它们是应用程序的秘密令牌和Twitter的消费者密钥和秘密。在我的秘密令牌初始化器中:

KinTwit::Application.config.secret_token = ENV['SECRET_TOKEN']

Twitter.consumer_key                     = ENV['CONSUMER_KEY']
Twitter.consumer_secret                  = ENV['CONSUMER_SECRET']

我将我的项目托管在Heroku上,因此我将它们作为配置变量添加到了Heroku。

[03:07:48] [william@enterprise ~/dev/rwc/kintwit]$ heroku config:add CONSUMER_KEY=ub3rs3cr3tk3y
Adding config vars and restarting app... done, v7
  CONSUMER_KEY => ub3rs3cr3tk3y
[03:08:40] [william@enterprise ~/dev/rwc/kintwit]$ heroku config:add CONSUMER_SECRET=ub3rs3cr3tk3y
Adding config vars and restarting app... done, v8
  CONSUMER_SECRET => ub3rs3cr3tk3y
[03:08:57] [william@enterprise ~/dev/rwc/kintwit]$ heroku config:add SECRET_TOKEN=ub3rs3cr3tk3y
Adding config vars and restarting app... done, v9
  SECRET_TOKEN => ub3rs3cr3tk3y

现在,这些值已经准备好在我下一次推送时使用。但是,如果您没有使用Heroku呢?显然,我并不是每个单独的rails部署专家(天哪,甚至不是Heroku专家),但一个例子是为测试执行db:migrate。
$ RAILS_ENV=test rake db:migrate

在命令之前的KEY=value对设置了环境变量,因此运行此命令:echo ENV['RAILS_ENV']会打印test。所以无论你的环境如何设置,你都可以这样做。但是,环境变量不在你的代码中,这就是诀窍。

0

[编辑 - 下面的方法有一个烦恼的问题,就是必须切换到生产分支才能运行"rails server"以包含必需的cookie。因此,在服务器运行时进行编辑很困难...我仍在寻找一个好的解决方案]

进一步调查后,我认为我正在寻找的解决方案是从我的Git存储库主分支中排除存储机密值的任何内容(就像@VonC所说的那样)。但是,我不是从另一个存储库中读取这些文件,而是创建一个新的“生产”分支,并将它们添加到其中。

这样,它们就被排除在Master之外,我可以将其推送到Github或其他公共存储库中。当我准备好部署时,我可以检出Production分支并将Master合并到其中,然后部署Production。

我需要能够做到这一点,因为Heroku和其他主机要求将单个git存储库推送到他们的服务器上。

更多信息请参见:

http://groups.google.com/group/heroku/browse_thread/thread/d7b1aecb42696568/26d5249204c70574


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接