Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Set secret_key_base early enough for rails processes #23351

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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