Skip to content

Commit

Permalink
Merge pull request #23351 from jrafanie/set-secret-token-globally-ear…
Browse files Browse the repository at this point in the history
…lier-after-eager-load-hook

Set secret_key_base early enough for rails processes
  • Loading branch information
agrare committed Feb 24, 2025
2 parents 99489ca + e6d6cd7 commit 9213a9d
Show file tree
Hide file tree
Showing 8 changed files with 56 additions and 60 deletions.
1 change: 0 additions & 1 deletion app/models/mixins/miq_web_server_runner_mixin.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ def run
# The heartbeating will be done in a separate thread
worker_thread = Thread.new { super }

worker.class.configure_secret_token
start_rails_server(worker.rails_server_options)

# when puma exits allow the heartbeat thread to exit cleanly using #do_exit
Expand Down
17 changes: 0 additions & 17 deletions app/models/mixins/miq_web_server_worker_mixin.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,25 +18,8 @@ def binding_address
BINDING_ADDRESS
end

def preload_for_console
configure_secret_token(SecureRandom.hex(64))
end

def preload_for_worker_role
raise "Expected database to be seeded via `rake db:seed`." unless EvmDatabase.seeded_primordially?

configure_secret_token
end

def configure_secret_token(token = MiqDatabase.first.session_secret_token)
return if Rails.application.config.secret_key_base

Rails.application.config.secret_key_base = token

# To set a secret token after the Rails.application is initialized,
# we need to reset the secrets since they are cached:
# https://github.com/rails/rails/blob/7-0-stable/railties/lib/rails/application.rb#L392-L404
Rails.application.secrets = nil if Rails.version < "7.1"
end

def rails_server
Expand Down
5 changes: 5 additions & 0 deletions config/application.rb
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,11 @@ class Application < Rails::Application
end
end

# Run after code is eager loaded so we can autoload MiqDatabase and ApplicationRecord
initializer :init_secret_token, :after => :eager_load! do
Vmdb::Initializer.init_secret_token
end

config.after_initialize do
Vmdb::Initializer.init
ActiveRecord::Base.connection_pool.release_connection
Expand Down
13 changes: 10 additions & 3 deletions lib/vmdb/initializer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,18 @@ def self.init
MiqServer.my_server.starting_server_record
MiqServer.my_server.update(:status => "started")
end
end

def self.init_secret_token
return if Rails.application.config.secret_key_base

# Rails console needs session store configured
if defined?(Rails::Console)
MiqUiWorker.preload_for_console
token = if ActiveRecord::Base.connectable? && MiqDatabase.table_exists? && MiqDatabase.any?
MiqDatabase.first.session_secret_token
else
SecureRandom.hex(64)
end

Rails.application.config.secret_key_base = token
end

private_class_method def self.log_db_connectable
Expand Down
41 changes: 41 additions & 0 deletions spec/lib/vmdb/initializer_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
RSpec.describe Vmdb::Initializer do
describe ".init_secret_token" do
before do
@token = Rails.application.secret_key_base
end

after do
Rails.application.config.secret_key_base = @token
Rails.application.secrets = nil
end

it "defaults to MiqDatabase session_secret_token" do
MiqDatabase.seed
Rails.application.config.secret_key_base = nil
Rails.application.secrets = nil

described_class.init_secret_token
expect(Rails.application.secret_key_base).to eq(MiqDatabase.first.session_secret_token)
expect(Rails.application.config.secret_key_base).to eq(MiqDatabase.first.session_secret_token)
end

it "uses random hex when MiqDatabase isn't seeded" do
Rails.application.config.secret_key_base = nil
Rails.application.secrets = nil

described_class.init_secret_token
expect(Rails.application.secret_key_base).to match(/^\h{128}$/)
expect(Rails.application.config.secret_key_base).to match(/^\h{128}$/)
end

it "does not reset secrets when token already configured" do
existing_value = SecureRandom.hex(64)
Rails.application.config.secret_key_base = existing_value
Rails.application.secrets = nil

described_class.init_secret_token
expect(Rails.application.secret_key_base).to eq(existing_value)
expect(Rails.application.config.secret_key_base).to eq(existing_value)
end
end
end
1 change: 0 additions & 1 deletion spec/models/miq_ui_worker_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,6 @@

it "#preload_for_worker_role autoloads api collection classes and descendants" do
allow(EvmDatabase).to receive(:seeded_primordially?).and_return(true)
expect(MiqUiWorker).to receive(:configure_secret_token)
MiqUiWorker.preload_for_worker_role
expect(defined?(ServiceAnsibleTower)).to be_truthy
end
Expand Down
1 change: 0 additions & 1 deletion spec/models/miq_web_service_worker_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@

it "preload_for_worker_role autoloads api collection classes and descendants" do
allow(EvmDatabase).to receive(:seeded_primordially?).and_return(true)
expect(MiqWebServiceWorker).to receive(:configure_secret_token)
MiqWebServiceWorker.preload_for_worker_role
expect(defined?(ServiceAnsibleTower)).to be_truthy
end
Expand Down
37 changes: 0 additions & 37 deletions spec/models/mixins/miq_web_server_worker_mixin_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,43 +14,6 @@
end
end

before do
@token = Rails.application.secret_key_base
MiqDatabase.seed
end

after do
Rails.application.config.secret_key_base = @token
Rails.application.secrets = nil if Rails.version < "7.1"
end

it ".configure_secret_token defaults to MiqDatabase session_secret_token" do
Rails.application.config.secret_key_base = nil

test_class.configure_secret_token
expect(Rails.application.secret_key_base).to eq(MiqDatabase.first.session_secret_token)
expect(Rails.application.config.secret_key_base).to eq(MiqDatabase.first.session_secret_token)
end

it ".configure_secret_token accepts an input token" do
Rails.application.config.secret_key_base = nil

token = SecureRandom.hex(64)
test_class.configure_secret_token(token)
expect(Rails.application.secret_key_base).to eq(token)
expect(Rails.application.config.secret_key_base).to eq(token)
end

it ".configure_secret_token does not reset secrets when token already configured" do
existing_value = SecureRandom.hex(64)
Rails.application.config.secret_key_base = existing_value
Rails.application.secrets = nil if Rails.version < "7.1"

test_class.configure_secret_token
expect(Rails.application.secret_key_base).to eq(existing_value)
expect(Rails.application.config.secret_key_base).to eq(existing_value)
end

it "#rails_server_options" do
w = FactoryBot.create(:miq_ui_worker, :uri => "http://127.0.0.1:3000")
expect(w.rails_server_options).to include(
Expand Down

0 comments on commit 9213a9d

Please sign in to comment.