BigW Consortium Gitlab

secret_token_spec.rb 6.5 KB
Newer Older
1 2 3 4 5 6 7 8 9
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)
10
    allow(File).to receive(:delete)
11 12
    allow(Rails).to receive_message_chain(:application, :secrets).and_return(secrets)
    allow(Rails).to receive_message_chain(:root, :join) { |string| string }
13 14
    allow(self).to receive(:warn)
    allow(self).to receive(:exit)
15 16
  end

17
  context 'setting secret_key_base and otp_key_base' do
18 19 20 21 22 23 24 25 26 27 28
    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

29
        keys = secrets.values_at(:secret_key_base, :otp_key_base, :db_key_base)
30 31 32 33 34 35

        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
36
        expect(self).to receive(:warn_missing_secret).with('secret_key_base')
37 38 39 40 41 42 43 44
        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|
45
          new_secrets = YAML.load(contents)[Rails.env]
46

47 48 49
          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)
50 51 52 53 54
        end

        create_tokens
      end

55 56
      it 'does not write a .secret file' do
        expect(File).not_to receive(:write).with('.secret')
57 58 59 60 61 62 63 64 65 66 67 68 69

        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

70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95
      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

96 97 98 99 100
      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
101 102 103 104 105 106 107

        it 'does not write any files' do
          expect(File).not_to receive(:write)

          create_tokens
        end

108
        it 'sets the the keys to the values from the environment and secrets.yml' do
109 110
          create_tokens

111
          expect(secrets.secret_key_base).to eq('secret_key_base')
112 113 114
          expect(secrets.otp_key_base).to eq('otp_key_base')
          expect(secrets.db_key_base).to eq('db_key_base')
        end
115 116 117 118 119 120

        it 'deletes the .secret file' do
          expect(File).to receive(:delete).with('.secret')

          create_tokens
        end
121 122
      end

123
      context 'when secret_key_base and otp_key_base do not exist' do
124 125 126 127 128 129
        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

130
        it 'uses the file secret' do
131
          expect(File).to receive(:write) do |filename, contents, options|
132
            new_secrets = YAML.load(contents)[Rails.env]
133

134 135
            expect(new_secrets['secret_key_base']).to eq('file_key')
            expect(new_secrets['otp_key_base']).to eq('file_key')
136
            expect(new_secrets['db_key_base']).to eq('db_key_base')
137 138 139 140
          end

          create_tokens

141
          expect(secrets.otp_key_base).to eq('file_key')
142 143 144 145 146 147 148 149
        end

        it 'keeps the other secrets as they were' do
          create_tokens

          expect(secrets.db_key_base).to eq('db_key_base')
        end

150 151
        it 'warns about the missing secrets' do
          expect(self).to receive(:warn_missing_secret).with('secret_key_base')
152 153 154 155
          expect(self).to receive(:warn_missing_secret).with('otp_key_base')

          create_tokens
        end
156 157 158 159 160 161

        it 'deletes the .secret file' do
          expect(File).to receive(:delete).with('.secret')

          create_tokens
        end
162 163
      end
    end
164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198

    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
199 200
  end
end