Rails Rails 容器化部署 master.key 的处理

hiveer · 2021年12月26日 · 最后由 Rei 回复于 2021年12月28日 · 914 次阅读
  • Rails 的版本是: '6.1.4.1'
  • 代码仓库是:极狐 GitLab
  • 部署方式是:极狐 GitLab CI/CD

CI 阶段把最新的代码 build 成为 image,并且 push 到 极狐 GitLab container registry。在部署的时候通过 docker-compose 拉取最新的 image,并且运行即可。 在 build image 阶段,有一个步骤就是需要 precompile,但是 precompile 依赖master.key,给我带来了一些困扰:

RAILS_ENV=production rails assets:precompile
=> Missing encryption key to decrypt file with. Ask your team for your master key and write it to /Users/hiveerli/works/jihu-partner-portal/config/master.key or put it in the ENV['RAILS_MASTER_KEY']. 
  1. 代码仓库并没有 master.key(config/master.key 并没有提交到代码仓库)
  2. 我并不能把 master.key 直接放在 Dockerfile

当遇到这个问题的时候,首先我觉得不太合理,precompile 处理的都是前端的资源,为啥需要依赖 master.key。所以我想是不是这个不是必须的,可以通过什么方式规避。但是经过一番调查,发现这个依赖是必须。

最终采用的方式是生成一个假的 master.key.sample 和 credentials.yml.enc.sample 并且提交到代码仓库。在 build 的时候,首先隐藏真的 credentials.yml.enc,然后使用假的 master.key.sample 和 credentials.yml.enc.sample。具体代码如下:

RUN if [ "$RAILS_ENV" == "production" ]; then \
      mv config/credentials.yml.enc config/credentials.yml.enc.backup; \
      mv config/credentials.yml.enc.sample config/credentials.yml.enc; \
      mv config/master.key.sample config/master.key; \
      bundle exec rails assets:precompile; \
      mv config/credentials.yml.enc.backup config/credentials.yml.enc; \
      rm config/master.key; \
    fi

经过验证这个方法可以很好的工作,但是看起来不美观,不仅有代码上的冗余,还有逻辑上的误导性,但是至少确保了安全性。

参考: https://github.com/rails/rails/issues/32947

因为 12factor 我没有使用 credentials.yml,然后还需要 SECRET_KEY_BASE,我就用 env 把 SECRET_KEY_BASE 设为 1

RUN RAILS_ENV=production SECRET_KEY_BASE=1 bin/rails assets:precompile
Rei 回复

嗯嗯,在我参考的那个帖子里面也人提到您的这个方案。如果按照“代码和配置严格分离”,确实把所有这些都放到环境变量是最安全的。不过我不太确定 Rails 'credentials.yml', 从安全性的角度来讲,会有风险吗?或者说在没有 master.key 的情况下,想要获取里面的内容难度有多大?

放到环境变量里不一定安全,还有一些隐患,例如要注意错误捕获服务会不会在报错的时候把 env 一并提交造成外泄;容器编排工具传输 env 也是明文的,没有专门的 secret 机制安全。

用 env 一部分原因是 heroku 这样的服务只支持 env,另外如果是开源软件把 secrets 放到源码库里很怪异,即使别人看不到内容。

k8s 和 docker swarm 支持用文件方式挂载 secrets,这样选择就多了。

哪种方式好我还没定论,目前用的是 dotenv 通过 .env 文件管理环境变量,这样同时支持 env 和文件两种方式设置 secret.

开源项目不能用 credentials.yml

不是可以直接用 RAILS_MASTER_KEY 这个环境变量吗? custom-credentials

xinyifly 回复

可能你理解错了,这个环境变量没问题。这里是说利用 CI build 的时候,我们怎么避免 master key 暴露在 code 中。

gitlab 的项目设置里可以设置 CI 环境的环境变量的,而且还可以选择以文件形式挂载。

hiveer 回复

阿里云/AWS 配置 GitLab Runner,利用 Role 获取 OSS/S3 文件并用 KMS 解密?

试试 config.require_master_key = false 看看,有用的话可以弄成环境变量选择性关闭。

RAILS_MASTER_KEY 环境变量

Rei 回复

这个可以,设置为 false 之后,需要的就只有 SECRET_KEY_BASE,然后就可以用第一条评论的方法了。

RAILS_ENV=production rails assets:precompile
rails aborted!
ArgumentError: Missing `secret_key_base` for 'production' environment, set this string with `bin/rails credentials:edit`
huacnlee 回复

这个环境变量可以工作的,只是这里因为是在 Dockerfile 里面,所以不想暴露 master key。

xinyifly 回复

这个还没有研究过😁 ,到时候实践了再回来补充

lolychee 回复

嗯嗯,是的。不过我这里的情况是,precompile 在 Dockerfile,需要提交到代码库。所以 GitLab 的环境变量用不上,master key 又不能放代码库。所以才有了这个问题。

--build-arg 读环境变量?看下来你的 Gitlab CI 是能读环境变量的。

xinyifly 回复

主要问题是 CI 环境不应该获得这个密钥,不然很难预料在日志或什么地方泄露。

需要 登录 后方可回复, 如果你还没有账号请 注册新账号