diff options
Diffstat (limited to 'spec/initializers/secret_token_spec.rb')
-rw-r--r-- | spec/initializers/secret_token_spec.rb | 200 |
1 files changed, 200 insertions, 0 deletions
diff --git a/spec/initializers/secret_token_spec.rb b/spec/initializers/secret_token_spec.rb new file mode 100644 index 00000000000..837b0de9a4c --- /dev/null +++ b/spec/initializers/secret_token_spec.rb @@ -0,0 +1,200 @@ +require 'spec_helper' +require_relative '../../config/initializers/secret_token' + +describe 'create_tokens', lib: true do + let(:secrets) { ActiveSupport::OrderedOptions.new } + + before do + allow(ENV).to receive(:[]).and_call_original + allow(File).to receive(:write) + allow(File).to receive(:delete) + allow(Rails).to receive_message_chain(:application, :secrets).and_return(secrets) + allow(Rails).to receive_message_chain(:root, :join) { |string| string } + allow(self).to receive(:warn) + allow(self).to receive(:exit) + end + + context 'setting secret_key_base and otp_key_base' do + context 'when none of the secrets exist' do + before do + allow(ENV).to receive(:[]).with('SECRET_KEY_BASE').and_return(nil) + allow(File).to receive(:exist?).with('.secret').and_return(false) + allow(File).to receive(:exist?).with('config/secrets.yml').and_return(false) + allow(self).to receive(:warn_missing_secret) + end + + it 'generates different secrets for secret_key_base, otp_key_base, and db_key_base' do + create_tokens + + keys = secrets.values_at(:secret_key_base, :otp_key_base, :db_key_base) + + expect(keys.uniq).to eq(keys) + expect(keys.map(&:length)).to all(eq(128)) + end + + it 'warns about the secrets to add to secrets.yml' do + expect(self).to receive(:warn_missing_secret).with('secret_key_base') + expect(self).to receive(:warn_missing_secret).with('otp_key_base') + expect(self).to receive(:warn_missing_secret).with('db_key_base') + + create_tokens + end + + it 'writes the secrets to secrets.yml' do + expect(File).to receive(:write).with('config/secrets.yml', any_args) do |filename, contents, options| + new_secrets = YAML.load(contents)[Rails.env] + + expect(new_secrets['secret_key_base']).to eq(secrets.secret_key_base) + expect(new_secrets['otp_key_base']).to eq(secrets.otp_key_base) + expect(new_secrets['db_key_base']).to eq(secrets.db_key_base) + end + + create_tokens + end + + it 'does not write a .secret file' do + expect(File).not_to receive(:write).with('.secret') + + create_tokens + end + end + + context 'when the other secrets all exist' do + before do + secrets.db_key_base = 'db_key_base' + + allow(File).to receive(:exist?).with('.secret').and_return(true) + allow(File).to receive(:read).with('.secret').and_return('file_key') + end + + context 'when secret_key_base exists in the environment and secrets.yml' do + before do + allow(ENV).to receive(:[]).with('SECRET_KEY_BASE').and_return('env_key') + secrets.secret_key_base = 'secret_key_base' + secrets.otp_key_base = 'otp_key_base' + end + + it 'does not issue a warning' do + expect(self).not_to receive(:warn) + + create_tokens + end + + it 'uses the environment variable' do + create_tokens + + expect(secrets.secret_key_base).to eq('env_key') + end + + it 'does not update secrets.yml' do + expect(File).not_to receive(:write) + + create_tokens + end + end + + context 'when secret_key_base and otp_key_base exist' do + before do + secrets.secret_key_base = 'secret_key_base' + secrets.otp_key_base = 'otp_key_base' + end + + it 'does not write any files' do + expect(File).not_to receive(:write) + + create_tokens + end + + it 'sets the the keys to the values from the environment and secrets.yml' do + create_tokens + + expect(secrets.secret_key_base).to eq('secret_key_base') + expect(secrets.otp_key_base).to eq('otp_key_base') + expect(secrets.db_key_base).to eq('db_key_base') + end + + it 'deletes the .secret file' do + expect(File).to receive(:delete).with('.secret') + + create_tokens + end + end + + context 'when secret_key_base and otp_key_base do not exist' do + before do + allow(File).to receive(:exist?).with('config/secrets.yml').and_return(true) + allow(YAML).to receive(:load_file).with('config/secrets.yml').and_return('test' => secrets.to_h.stringify_keys) + allow(self).to receive(:warn_missing_secret) + end + + it 'uses the file secret' do + expect(File).to receive(:write) do |filename, contents, options| + new_secrets = YAML.load(contents)[Rails.env] + + expect(new_secrets['secret_key_base']).to eq('file_key') + expect(new_secrets['otp_key_base']).to eq('file_key') + expect(new_secrets['db_key_base']).to eq('db_key_base') + end + + create_tokens + + expect(secrets.otp_key_base).to eq('file_key') + end + + it 'keeps the other secrets as they were' do + create_tokens + + expect(secrets.db_key_base).to eq('db_key_base') + end + + it 'warns about the missing secrets' do + expect(self).to receive(:warn_missing_secret).with('secret_key_base') + expect(self).to receive(:warn_missing_secret).with('otp_key_base') + + create_tokens + end + + it 'deletes the .secret file' do + expect(File).to receive(:delete).with('.secret') + + create_tokens + end + end + end + + context 'when db_key_base is blank but exists in secrets.yml' do + before do + secrets.otp_key_base = 'otp_key_base' + secrets.secret_key_base = 'secret_key_base' + yaml_secrets = secrets.to_h.stringify_keys.merge('db_key_base' => '<%= an_erb_expression %>') + + allow(File).to receive(:exist?).with('.secret').and_return(false) + allow(File).to receive(:exist?).with('config/secrets.yml').and_return(true) + allow(YAML).to receive(:load_file).with('config/secrets.yml').and_return('test' => yaml_secrets) + allow(self).to receive(:warn_missing_secret) + end + + it 'warns about updating db_key_base' do + expect(self).to receive(:warn_missing_secret).with('db_key_base') + + create_tokens + end + + it 'warns about the blank value existing in secrets.yml and exits' do + expect(self).to receive(:warn) do |warning| + expect(warning).to include('db_key_base') + expect(warning).to include('<%= an_erb_expression %>') + end + + create_tokens + end + + it 'does not update secrets.yml' do + expect(self).to receive(:exit).with(1).and_call_original + expect(File).not_to receive(:write) + + expect { create_tokens }.to raise_error(SystemExit) + end + end + end +end |