Nic Lin's Blog

喜歡在地上打滾的 Rails Developer

Rails 5.2 Encrypted Credentials

雖然設置環境變數,都用 dotenv 很習慣了,不過 Rails 5.1 開始有針對這個問題討論一些解法,一開始拆兩支檔案 secrets.ymlsecrets.yml.enc 引起一些混亂

在 5.2 版本之後只有 credentials.yml.enc 加密憑證

要使用加密憑證,必須有一把密鑰,如果沒有密鑰將無法解密其內容,現在建立一個 5.2 版本以上的 rails project 時,會創建一支 matser key 放置於 config/master.key 並且很貼心的在 .gitignore 中加入忽略清單,可以避免不小心把 master.key commit 出去。

How to edit your credentials

EDITOR=vim rails credentials:edit

舉例來說

aws:
  access_key_id: 123
  secret_access_key: 345

保存之後,加密的版本將會存放在 config/credentials.yml.enc,並且跟著 commit 進去。

在 Rails 裡面呼叫的方式

Rails.application.credentials.aws[:access_key_id]
Rails.application.credentials.aws[:secret_access_key]

或是透過 command line 顯示

rails credentials:show

確保 production 有設置開啟(預設是關閉的)

config.require_master_key = true

這樣做的好處是,我只要在機器上設定好一樣的 master.kry,每次部屬時都可以直接吃到新的環境變量。

因為在以往的作法,必須確保在部屬前已經設定好環境變量,可能要手動去設定之類的,現在這個作法可以省掉這一道功夫。

只要確保機器上 copy 的 master.key 副本跟編輯時用的是同一把即可。

這樣的好處同時也讓所有的環境變量保存在一個檔案中,更集中管理。

不過也遇到一些問題,比方說 production 和 staging 上要用的 key 不一樣…

你總不會想要寫

production:
  aws:
    access_key_id: 123
    secret_access_key: 345
    
staging:
  aws:
    access_key_id: abc
    secret_access_key: def

然後依照環境判斷分別呼叫?

Rails.env.production? ? Rails.application.credentials.production[:aws][:secret_access_key] : Rails.application.credentials.staging[:aws][:secret_access_key].

或是加載不同的 master.key? (這樣也還要重新生成不同的加密結果, commit 裡面那隻可能也不能用了 XD)

RAILS_ENV=production RAILS_MASTER_KEY=content_of_master.key rails server

太麻煩了…,在 Ruby China 也有提到關於 Rails 5.2 的新 secret credentials 怎样让不同的环境使用不同的配置?

但目前還沒有一個比較整合的作法,正常來講應該要依照不同環境的需求有不同的環境變數,rails 6 看來在著手解決這個問題。

Add support for multi environment credentials.

結論

還是先用 dotenv 並觀望 rails 6 能不能解決這個問題 XD

參考資源

comments powered by Disqus