从Rails引擎初始化程序访问主要应用程序秘密信息

18

我一直在尝试(但不成功)从我的Rails可装载引擎中访问主应用程序的应用程序秘密。 可装载引擎的整个重点是提供模块化。因此,一个常见的模式是在主应用程序中提供可配置的参数,其中一些需要是秘密,然后由引擎使用。

在我的具体情况中,我在我的引擎中使用carrierwavefog上传文件到AWS存储桶。确切的存储桶和AWS凭据未在引擎中指定,而是在主应用程序中指定,因为它们将根据安装引擎的应用程序不同而变化。

但是,当引擎中的carrierwave初始化器失败时,它找不到主应用程序的Rails.application.secrets:

require 'carrierwave'
require 'carrierwave/storage/fog'

CarrierWave.configure do |config|
  config.fog_provider = 'fog/aws'

  config.fog_credentials = {
    :provider               => 'AWS',
  :aws_access_key_id      => Rails.application.secrets.S3_AWS_ACCESS_KEY_ID,
  :aws_secret_access_key  => Rails.application.secrets.S3_AWS_SECRET_ACCESS_KEY
  }
  config.fog_directory  = Rails.application.secrets.CARRIERWAVE_CONFIG_FOG_DIRECTORY
  config.storage = :fog
end

当引擎启动时,这个会失败。

Missing required arguments: aws_access_key_id, aws_secret_access_key (ArgumentError)

实际上,在初始化器中Rails.application.secrets.S3_AWS_ACCESS_KEY_ID (以及其他变量)的值是nil。但是在引擎控制器运行时,它会被正确地计算出来。我已将其修改为以下内容:

:aws_access_key_id      => Rails.application.secrets.S3_AWS_ACCESS_KEY_ID || ENV["S3_AWS_ACCESS_KEY_ID"]

在每个生产环境中导出ENV变量以供引擎使用,但这并不理想。 欢迎任何解决方案。


1
你好,你是将 aws_access_key_idaws_secret_access_key 直接存储在 config/secrets.yml 文件中吗?还是使用 config/application.yml 来实现呢? - Danger Rodriguez Gálvez
1
不再使用任何一种,但我相当确定那时我正在使用config/secrets.yml。这是Rails 5.1的推荐解决方案。 - Augusto Samamé Barrientos
1
是的,我明白。我曾经遇到过类似的问题,我使用 application.yml 存储我的秘密凭据,并通过环境变量访问它们来解决了这个问题。请参见此处的代码 https://gist.github.com/dangerrg/e42005e28bfb9fea66188f0504e1614a。 - Danger Rodriguez Gálvez
是的。我现在正在使用dotenv文件,因为我有点迷失了所有Rails推荐的解决方案,这些解决方案随着每个小版本的增加而不断变化。仍在寻找一种使用“Rails方式”并与Rails 6推荐的secrets策略兼容的解决方案。 - Augusto Samamé Barrientos
尝试使用Rails凭据功能怎么样? - kevinluo201
2个回答

1
在您的引擎初始化程序(config/initializers/engine_name.rb)中,定义一个配置选项来存储AWS凭证和fog目录:
# config/initializers/engine_name.rb
EngineName.configure do |config|
  config.aws_access_key_id = nil
  config.aws_secret_access_key = nil
  config.fog_directory = nil
end


在主应用程序中,通过初始化器为这些配置选项提供值。
# config/initializers/engine_name.rb
EngineName.configure do |config|
  config.aws_access_key_id = Rails.application.secrets.S3_AWS_ACCESS_KEY_ID
  config.aws_secret_access_key = Rails.application.secrets.S3_AWS_SECRET_ACCESS_KEY
  config.fog_directory = Rails.application.secrets.CARRIERWAVE_CONFIG_FOG_DIRECTORY
end


修改引擎中的载波初始化器,使用配置选项:
# engine_name/config/initializers/carrierwave.rb
require 'carrierwave'
require 'carrierwave/storage/fog'

CarrierWave.configure do |config|
  config.fog_provider = 'fog/aws'

  config.fog_credentials = {
    provider: 'AWS',
    aws_access_key_id: EngineName.configuration.aws_access_key_id,
    aws_secret_access_key: EngineName.configuration.aws_secret_access_key
  }

  config.fog_directory = EngineName.configuration.fog_directory
  config.storage = :fog
end


通过使用这种方法,您可以让主应用程序通过引擎的配置提供必要的密钥,从而避免直接从引擎访问主应用程序的密钥的问题。

0

你应该能够从引擎的初始化器中访问到秘密。


# path/to/your/engine/my_engine/lib/my_engine/engine.rb
module MyEngine
    class Engine
        initializer :my_custom_initializer do |app|
            puts app.secrets
        end
    end
end

有趣。我会把Carrierwave配置代码放在那里,如果它有效的话就接受这个答案。不过我仍然认为这应该更加简洁,并且会在某个时候向Rails团队提出这个问题。 - Augusto Samamé Barrientos

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接