Rails Rails 5.1.1 新特性 [添加新的加密的 secret] 示例

rocLv · June 28, 2017 · Last by ecnelises replied at October 22, 2018 · 4260 hits

最近把 App 从 Rails 5.0.2 升级至 5.1.1,升级过程还算顺利。

既然升级到 Rails 5.1.1,所以就迫不及待的想使用一下这个新的特性。

在 Rails 5.1.1 之前,环境变量的设置在开发环境和生产环境里的设置总是避免不了的一种痛。 尤其是多台服务器部署更甚。

由于我的生产服务器用的是 nginx + passenger,因此无法直接读取环境变量。 后来参照网上一下建议,将一些私密信息直接写在 nginx 配置文件中。

passenger_env_var REDIS_PASSWD YOUR_REDIS_PASSWD;

对于多台服务器部署,一旦这些信息需要修改,就必须登陆每个服务器进行修改。

这严重不符合我们的 DRY 的精神 啊。

因此 Rails 5.1.1 引入了这个加密的 secret 特性。

使用方法:

首先,要安装,在你的 APP 目录下,运行以下命令

$ rails secrets:setup

这条命令会做三件事情:

  • 在.gitignore 里添加一条记录,忽略config/secrets.yml.key文件。
  • 创建 config/secrets.yml.key 文件,这个文件保存的是RAILS_MASTER_KEY,一旦这个 key 丢失,就是神仙也帮补了你了 😅
  • 创建 config/secrets.yml.enc, 这个文件保存的是加密的 secret 信息

通常,在生产服务器可以把这个信息保存至你相应的 nginx 配置文件中,如:

#  /etc/nginx/sites-enabled/my-site.conf

passenger_env_var RAILS_MASTER_KEY YOUR_PASSWD;

后续需要添加新的 secret 时,运行命令:

$ rails secrets:edit

运行命令后会解密config/secrets.yml.enc文件中的内容,你可以按照普通的 yml 文件进行编辑。

应用:

在需要的时候可以在 APP 中,通过以下方式获取其中的 key 值。

Rails.application.secrets会返回所有的 secrets,包含 secret.yml 文件中的内容,或者也可以用 YOUR_APP_NAME::Application.secrets

使用某个值:

Rails.application.secrets.my_secret_key

哦对了,别忘了在config/enviroments/production.rb 文件中添加

config.read_encrypted_secrets = true

UPDATE: shared 如果有一部分需要在不同环境中共享的环境变量,可以这样写:

default: &default
    mykey: value

staging:
   <<: *default

production:
  <<: *default

还有一种更好的方法,使用shared

shared:
    mykey: value

staging:
  other: value

production:
  other_key: value

在 rails 控制台可以试试:

 $ RAILS_ENV=production rails c
>> Rails.application.secrets
=> {:secret_key_base=>"3e3", :mykey=>"value"}

PS: 不过在开发环境是看不到 shared 下面的键值的。

感觉没什么鸟用,还是 ENV 好用。。。。

Reply to pynix

肯定是这个方便 现在集成第三方的 sdk 越来越多,可以把所有的 key 都用版本控制起来 除了第一次部署的时候设置一下 rails master key,后面都不用了

Reply to rocLv

没太懂,楼主是怎么版本控制起来的?

Reply to robertyu

可以把用到的环境变量放在这个文件 config/secrets.yml.enc 里。

这个文件里的内容是加密的

这个和 secrets.yml 是可以共存的。我现在把所有的 env 都丢进去了..生产环境用的加密保存..直接丢在 git 里面,挺方便的。

  1. 生产环境提供了很好的 ENV 设置接口,类似 heroku config:set (貌似用 passenger 的话 ENV 会很麻烦)
  2. 方便切换时不要重新部署 (虽然大多数情况下都不会切换)

我寧願直接用環境變量,服務器多的話用布署工具(比如 Ansible)。把配置存在文件裡,非常不 12 factor……

Reply to pynix

passenger 也不麻烦,就是在 nginx 配置文件里直接添加就好了。代码如下:

#  /etc/nginx/sites-enabled/my-site.conf

passenger_env_var RAILS_MASTER_KEY YOUR_PASSWD;
Reply to franklinyu

你对 12factor 理解有偏差,其中关于配置的论述里有这么一句:

判断一个应用是否正确地将配置排除在代码之外,一个简单的方法是看该应用的基准代码是否可以立刻开源,而不用担心会暴露任何敏感的信息。

通过这样的处理,完全满足这个要求。

Reply to rocLv

這只是「簡單的方法」,並不是「精確的標準」。配置的核心在於

配置文件在各部署间存在大幅差异,代码却完全一致。

所以,只要各布署間有差異的,就叫應該用環境變量歸類為「配置」而不是「代碼」。換言之,如果某個項目的代碼,給另一個項目使用,能夠不修改代碼就馬上使用,才滿足 12 factor。注意 12 factor 並不是說「一定要用環境變量」,也可以用「未被版本控制的文件」,只不過(12 factor 認為)環境變量更方便而已。

所以新特性什么的还是要在适合的场景使用。

Reply to franklinyu

确实很 rails, 对于 prototype 阶段的开发很有用。等到了产品正式部署的时候,再把 secrets.yml.enc 从 repo 删除即可。

不打算使用。

One Question: 如果是一个开源项目,或者是需要用不同的密钥部署到多个地方的项目,这个特性是不是完全没有意义了?把 secrets 加密放到 repo 里,安全是安全,就是觉得哪里怪怪的。

You need to Sign in before reply, if you don't have an account, please Sign up first.