有没有办法以编程方式将机密添加到 Rails 5.2 中的 config/credentials.yml.enc 中?
将credentials.yml.enc推送到存储库供内部使用可能没问题,但一旦其他人使用该应用程序,他们就需要在其环境中使用不同的秘密。与 Oauth2 凭据一样,每个实现的凭据都会有所不同。
在 docker 中运行应用程序(例如)将需要比平常更多的手动交互和 Docker 知识。在大多数情况下,只有在不需要付出太多努力的情况下才会使用更安全的方法。
需要先运行
docker exec <app-name> -it /bin/bash
才能运行 rails credentials:edit
。
如果能够以编程方式填充凭据文件会更好。 例如,可以提供一个临时凭证文件,例如:
production:
postgresql:
username: 'admin'
password: 'very_insecure'
然后可能有一个脚本将文件的内容添加到凭据文件中,然后删除临时文件。
当然,必须设置
RAILS_MASTER_KEY
环境变量(可能又是一个将 master.key 文件的内容移动到变量中的脚本)才能从中获利。
您可以使用
EDITOR
环境变量通过一些技巧来做到这一点。
通常,您会使用
EDITOR=nano rails credentials:edit
以便 Rails 将 credentials.yml.enc
(临时解密的副本)传递给 nano
进行修改,并在 nano
终止时重新加密结果。
如果我们用
nano
(cat
) 替换 EDITOR=cat rails credentials:edit
,Rails 会将(解密的)文件传递给 cat
,从而使其内容打印在屏幕上。换句话说,Rails 实际上只是在运行 $EDITOR tempfile.name
。
因此,如果我们这样做:
EDITOR='echo "foo: bar" >> ' rails credentials:edit
...那么结果将是这样的:
echo "foo: bar" >> tempfile.name
tl;dr: 您可以滥用
EDITOR
(间接)执行您对常规纯文本文件所做的几乎任何操作。
如果您想从 Ruby 脚本执行此操作,您可以重用 Rails 的内部
ActiveSupport::EncryptedConfiguration
:
def credentials_encrypted_file
ActiveSupport::EncryptedConfiguration.new(
config_path: "config/credentials.yml.enc",
key_path: "config/master.key",
env_key: "RAILS_MASTER_KEY",
raise_if_missing_key: true
)
end
credentials_injection = "\n\nfoo: bar"
credentials_encrypted_file.change do |tmp_path|
inject_into_file tmp_path, credentials_injection
end
Rails::Generators::CredentialsGenerator
中找到
我能够找到一种方法,使用 Spone 答案中的类以编程方式更新凭证文件,但使用内置的 ruby 方法,因为ject_into_file 是由 thor 定义的。
它确实假设您已经有一个 config/credentials/development.yml.enc 和一个带有有效密钥的 config/credentials/development.key 文件
这就是我的代码在 lib/set_credentials.rake 中的样子
namespace :set_credentials do
task stripe: :environment do
encrypted_file = ActiveSupport::EncryptedConfiguration.new(
config_path: "config/credentials/development.yml.enc",
key_path: "config/credentials/development.key",
env_key: "RAILS_MASTER_KEY",
raise_if_missing_key: true
)
stripe_credentials = "
stripe:
public_key: 12345
private_key: 12345
"
encrypted_file.change do |tmp_path|
File.open(tmp_path, 'w') { |file| file.write(stripe_credentials) }
end
end
end
然后你可以通过 cli 来调用它
rails set_credentials:stripe