AWS SecretsManager 密码轮换在 Rails 中不起作用

问题描述 投票:0回答:2

我们使用 AWS SecretsManager (SM) 来存储 Rails 应用程序的轮换数据库密码。但是,当 SM 轮换密码时,我们收到“FATAL:用户密码验证失败”。

密码在database.yml中读取

password: '<%= AwsSecretService.new.get_db_pwd(ENV['DATABASE_USERNAME']) if Rails.env.production?   %>'

问题似乎是 ActiveRecord 在初始化时缓存 database.yml 中的数据库凭据,并且不重新解析 database.yml。

我的想法是以某种方式捕获身份验证失败错误并重新初始化 ActiveRecord。使用以下命令:

ActiveRecord::Base.establish_connection(::Rails.application.config.database_configuration[::Rails.env]) 

我不知道如何捕获错误。我是否需要在 application_record.rb 中放置一个错误处理程序,因为所有 activerecord 模型都继承自它?

或者使用某种观察者会更好吗?

想法?

ruby-on-rails-3 rails-activerecord aws-secrets-manager
2个回答
1
投票

我也在研究这个问题,也遇到了同样的问题。 Rails 似乎只在应用程序启动时读取一次密码。如果随后轮换密码,某些连接将成功(如果它们已经建立),但池中的新连接将失败,因为它们将尝试使用现已过时的密码。

如果 Rails 可以“强制”在启动时创建池中的所有连接,那么这将起作用。或者,如果 Rails 可以在每次建立新连接时动态提取密码,那也可以。 但是,我还没有能力做这两件事。


0
投票

lib/aws_secret_manager.rb:

class AwsSecretsManager class << self def database_config secret_json = fetch_secret_json return {} unless secret_json fetch_database_config(secret_json) end private def fetch_secret_json client = Aws::SecretsManager::Client.new(region: ENV.fetch('AWS_REGION', nil)) secret_value_response = client.get_secret_value(secret_id: ENV.fetch('AWS_SECRET_ID', nil)) secret_value_response.secret_string end def fetch_database_config(secret_json) secret_hash = JSON.parse(secret_json, symbolize_names: true) secret_hash.slice(:host, :port, :username, :password) end end end

Rails 使用 
ActiveRecord::DatabaseConfigurations::*

类来存储数据库配置,并调用

ActiveRecord::DatabaseConfigurations#resolve(config_or_env)
方法来获取新连接的配置。要为新连接应用新密码,您可以覆盖此方法并将更改添加到
ActiveRecord::DatabaseConfigurations
类。
lib/active_record/aws_database_configurations.rb:

module ActiveRecord module AwsDatabaseConfigurations def resolve(config) default_config = super(config) aws_config = AwsSecretsManager.database_config DatabaseConfigurations::HashConfig.new( default_config.env_name, default_config.name, default_config.configuration_hash.merge(aws_config) ) end end end

config/initializers/aws_credentials.rb:

require './lib/active_record/aws_database_configurations' ActiveRecord::DatabaseConfigurations.prepend(ActiveRecord::AwsDatabaseConfigurations)

© www.soinside.com 2019 - 2024. All rights reserved.