73 lines
		
	
	
		
			1.7 KiB
		
	
	
	
		
			Ruby
		
	
	
	
			
		
		
	
	
			73 lines
		
	
	
		
			1.7 KiB
		
	
	
	
		
			Ruby
		
	
	
	
| # frozen_string_literal: true
 | |
| 
 | |
| require 'spec_helper'
 | |
| 
 | |
| RSpec.describe Gitlab::OtpKeyRotator do
 | |
|   let(:file) { Tempfile.new("otp-key-rotator-test") }
 | |
|   let(:filename) { file.path }
 | |
|   let(:old_key) { Gitlab::Application.secrets.otp_key_base }
 | |
|   let(:new_key) { "00" * 32 }
 | |
|   let!(:users) { create_list(:user, 5, :two_factor) }
 | |
| 
 | |
|   after do
 | |
|     file.close
 | |
|     file.unlink
 | |
|   end
 | |
| 
 | |
|   def data
 | |
|     CSV.read(filename)
 | |
|   end
 | |
| 
 | |
|   def build_row(user, applied = false)
 | |
|     [user.id.to_s, encrypt_otp(user, old_key), encrypt_otp(user, new_key)]
 | |
|   end
 | |
| 
 | |
|   def encrypt_otp(user, key)
 | |
|     opts = {
 | |
|       value: user.otp_secret,
 | |
|       iv: user.encrypted_otp_secret_iv.unpack("m").join,
 | |
|       salt: user.encrypted_otp_secret_salt.unpack("m").join,
 | |
|       algorithm: 'aes-256-cbc',
 | |
|       insecure_mode: true,
 | |
|       key: key
 | |
|     }
 | |
|     [Encryptor.encrypt(opts)].pack("m")
 | |
|   end
 | |
| 
 | |
|   subject(:rotator) { described_class.new(filename) }
 | |
| 
 | |
|   describe '#rotate!' do
 | |
|     subject(:rotation) { rotator.rotate!(old_key: old_key, new_key: new_key) }
 | |
| 
 | |
|     it 'stores the calculated values in a spreadsheet' do
 | |
|       rotation
 | |
| 
 | |
|       expect(data).to match_array(users.map { |u| build_row(u) })
 | |
|     end
 | |
| 
 | |
|     context 'new key is too short' do
 | |
|       let(:new_key) { "00" * 31 }
 | |
| 
 | |
|       it { expect { rotation }.to raise_error(ArgumentError) }
 | |
|     end
 | |
| 
 | |
|     context 'new key is the same as the old key' do
 | |
|       let(:new_key) { old_key }
 | |
| 
 | |
|       it { expect { rotation }.to raise_error(ArgumentError) }
 | |
|     end
 | |
|   end
 | |
| 
 | |
|   describe '#rollback!' do
 | |
|     it 'updates rows to the old value' do
 | |
|       file.puts("#{users[0].id},old,new")
 | |
|       file.close
 | |
| 
 | |
|       rotator.rollback!
 | |
| 
 | |
|       expect(users[0].reload.encrypted_otp_secret).to eq('old')
 | |
|       expect(users[1].reload.encrypted_otp_secret).not_to eq('old')
 | |
|     end
 | |
|   end
 | |
| end
 |