在公共 Rails 应用程序中将敏感数据存储在哪里?
Posted
技术标签:
【中文标题】在公共 Rails 应用程序中将敏感数据存储在哪里?【英文标题】:Where to store sensitive data in public rails app? 【发布时间】:2011-09-01 01:35:22 【问题描述】:我的个人 Rails 项目使用一些 API,我将 API 密钥/秘密存储在 config/environments/production.yml 和 development.yml 作为全局变量。我现在想把这个项目推送到 github 上供其他人使用,但我不希望他们拥有那些敏感数据。我也不希望 .gitignore 中有这个文件,因为它是应用程序运行所必需的。我考虑将它们放在数据库中的某个地方,但我希望找到更好的解决方案。
【问题讨论】:
【参考方案1】:它们可能最好放在初始化程序 (config/initializers/api.yaml) 中,尽管我认为你已经做好了。将实际密钥添加到您的 .gitignore 文件并运行 git rm config/environments/production.yml
以从您的存储库中删除该敏感数据。公平警告,它也会删除该文件,因此请先备份它。
然后,只需在您的实际文件旁边创建一个 config/environments/production.yml.example 文件,其中包含相关详细信息,但不包含敏感数据。当您将其投入生产时,只需复制不带 .example 的文件并替换适当的数据即可。
【讨论】:
是的,我听到了,但如前所述,我正在尝试找到一个不涉及从存储库中删除这些文件的解决方案。 出于兴趣,为什么?您是部署到 Heroku 还是类似的地方,不容易让您将文件直接复制到服务器上? 是的。那,我希望它尽可能简单地让其他人运行我的代码。 配置文件是常规的,不会给需要运行您的代码的人添加任何绊脚石。 Heroku 提供了一些关于如何在他们的环境中设置它们的文档:devcenter.heroku.com/articles/config-vars【参考方案2】:这个怎么样...
创建一个新项目并将其签入 GitHub,并在 production.yml 和 development.yml 文件中使用占位符值。
更新 .gitignore 以包含 production.yml 和 development.yml。
用您的秘密替换占位符值。
现在您可以在不泄露机密的情况下将代码签入 GitHub。
并且任何人都可以克隆您的存储库,而无需任何额外的步骤来创建丢失的文件(他们只会像您一样替换占位符值)。
这符合你的目标吗?
【讨论】:
不是真的,因为当我向那些确实需要进入其他存储库的文件中添加一些内容时会发生什么? 如果这种情况不会经常发生,只需恢复占位符值,从 .gitignore 中删除该行,将更改提交到 GitHub,编辑文件以恢复您的机密并再次编辑 .gitignore隐藏你的秘密。可能有更聪明的解决方案,但这种方法很简单。【参考方案3】:TLDR:使用环境变量!
我认为@Bryce 的comment 提供了一个答案,我将直接淘汰。似乎Heroku recommends 的一种方法是使用环境变量来存储敏感信息(API 密钥字符串、数据库密码)。所以调查你的代码,看看你在哪里有敏感数据。然后创建存储敏感数据值的环境变量(例如在您的 .bashrc 文件中)。例如对于您的数据库:
export MYAPP_DEV_DB_DATABASE=myapp_dev
export MYAPP_DEV_DB_USER=username
export MYAPP_DEV_DB_PW=secret
现在,在您的本地框中,您只需在需要敏感数据时参考环境变量。例如在 database.yml 中:
development:
adapter: mysql2
encoding: utf8
reconnect: false
database: <%= ENV["MYAPP_DEV_DB_DATABASE"] %>
pool: 5
username: <%= ENV["MYAPP_DEV_DB_USER"] %>
password: <%= ENV["MYAPP_DEV_DB_PW"] %>
socket: /var/run/mysqld/mysqld.sock
我认为 database.yml 只是在应用程序初始化或重启时被解析,所以这不会影响性能。因此,这将为您的本地开发和公开您的存储库解决它。剥离敏感数据后,您现在可以像私下一样使用相同的公共存储库。如果您在 VPS 上,它也可以解决问题。只需 ssh 到它并在您的生产主机上设置环境变量,就像您在开发框中所做的那样。
同时,如果您的生产设置涉及到手动部署,您无法像 Heroku 那样通过 ssh 连接到生产服务器,那么您需要了解如何远程设置环境变量。对于 Heroku,这是通过 heroku config:add
完成的。因此,根据同一篇文章,如果您将 S3 集成到您的应用中,并且您的敏感数据来自环境变量:
AWS::S3::Base.establish_connection!(
:access_key_id => ENV['S3_KEY'],
:secret_access_key => ENV['S3_SECRET']
)
只需让 Heroku 为其创建环境变量:
heroku config:add S3_KEY=8N022N81 S3_SECRET=9s83159d3+583493190
此解决方案的另一个优点是它与语言无关,而不仅仅是 Rails。适用于任何应用程序,因为它们都可以获取环境变量。
【讨论】:
这是迄今为止最好的解决方案。安全、简单、有效的跨平台和高性能。无法要求更多。 @yuvilio 我有一个后续问题:如何让在 Ubuntu 上使用 Apache2/Phusion Passenger 运行的 Ruby on Rails 可以访问上述环境变量? @YoLudke 对于通过 Apache 定向的应用程序,我会在应用程序的 Apache 主机文件中使用 SetEnv 指令。例如:SetEnv S3_KEY THESECRETKEY
。环境变量也可以通过 ENV 全局变量作为 ENV['S3_KEY'] 使用。
顺便提一下——当你将 Phusion Passenger 与 Apache2 一起使用时,你可以在其 Apache 配置中将 Phusion Passenger 引导到一个脚本,该脚本在运行 ruby 之前导出变量——而不是直接运行 ruby,这非常有效对我来说#!/bin/sh export EXAMPLE_VAR=example_value exec "/path/to/rvm/.rvm/wrappers/ruby-1.9.3-p371/ruby" "$@"
这里值得一提的是工头(Heroku 工具带的一部分):ddollar.github.io/foreman/#ENVIRONMENT【参考方案4】:
使用环境变量。
在 Ruby 中,它们可以这样访问:
ENV['S3_SECRET']
两个原因:
-
这些值不会进入源代码管理。
“敏感数据”又名密码往往会在每个环境的基础上发生变化。例如您应该为开发和生产使用不同的 S3 凭据。
这是最佳做法吗? 是的:http://12factor.net/config
如何在本地使用它们?foreman 和 dotenv 都很简单。或者,编辑您的shell。
如何在生产中使用它们? 在很大程度上,这取决于。但是对于 Rails,dotenv 很容易获胜。
平台即服务怎么样? 任何 PaaS 都应该为您提供设置它们的方法。例如 Heroku:https://devcenter.heroku.com/articles/config-vars
这不会增加为项目设置新开发人员的难度吗? 也许吧,但这是值得的。您始终可以将 .env.sample 文件签入源代码管理,其中包含一些示例数据。在项目的自述文件中添加关于它的注释。
【讨论】:
【参考方案5】:Rails 4.1 现在有一个约定。您将这些内容存储在 secrets.yml 中。因此,您最终不会在您的应用程序中分散一些全局 ENV 调用。
这个 yaml 文件就像 database.yml erb 解析的一样,所以你仍然可以在这里使用 ENV 调用。在这种情况下,您可以将其置于版本控制之下,然后它将仅用作必须使用 ENV vars 的文档。但是您也可以将其从版本控制中排除,并将实际的秘密存储在那里。在这种情况下,您可以将一些 secrets.yml.default 或类似内容放入公共 repo 以用于文档目的。
development:
s3_secret: 'foo'
production:
s3_secret: <%= ENV['S3_SECRET']%>
比你可以在下面访问这些东西
Rails.application.secrets.s3_secret
在this剧集开头有详细讨论
【讨论】:
这个文件应该存储在哪里?以上是关于在公共 Rails 应用程序中将敏感数据存储在哪里?的主要内容,如果未能解决你的问题,请参考以下文章