chore(encryption): task rotating api particulier token encrypted attributes

This commit is contained in:
Colin Darie 2024-08-22 17:33:45 +02:00
parent 3ac671576b
commit ca7100c7af
No known key found for this signature in database
GPG key ID: 4FB865FDBCA4BCC4
2 changed files with 72 additions and 0 deletions

View file

@ -0,0 +1,22 @@
# frozen_string_literal: true
module Maintenance
class RotateAPIParticulierTokenEncryptionTask < MaintenanceTasks::Task
def collection
# rubocop:disable DS/Unscoped
Procedure.unscoped.where.not(encrypted_api_particulier_token: nil)
# rubocop:enable DS/Unscoped
end
def process(procedure)
decrypted_token = procedure.api_particulier_token
procedure.api_particulier_token = decrypted_token
procedure.save!(validate: false)
end
def count
collection.count
end
end
end

View file

@ -0,0 +1,50 @@
# frozen_string_literal: true
require "rails_helper"
module Maintenance
RSpec.describe RotateAPIParticulierTokenEncryptionTask do
describe "#process" do
subject { described_class.process(procedure) }
let(:token) { "secret-token-0123456789" }
let(:procedure) { create(:procedure) }
let(:legacy_encryption_service) do
EncryptionService.new.tap { |legacy_service|
legacy_key = ActiveSupport::KeyGenerator
.new(Rails.application.secrets.secret_key_base, hash_digest_class: OpenSSL::Digest::SHA1)
.generate_key(Rails.application.secrets.encryption_service_salt, ActiveSupport::MessageEncryptor.key_len)
legacy_encryptor = ActiveSupport::MessageEncryptor.new(legacy_key)
legacy_service.instance_variable_set(:@encryptor, legacy_encryptor)
}
end
before do
# Encrypt the token using the legacy (SHA1) encryption service
legacy_encrypted_token = legacy_encryption_service.encrypt(token)
procedure.update_column(:encrypted_api_particulier_token, legacy_encrypted_token)
end
it 're-encrypts the api_particulier_token' do
old_encrypted_value = procedure.encrypted_api_particulier_token
expect { subject }.to change { procedure.reload.encrypted_api_particulier_token }
expect(procedure.api_particulier_token).to eq(token)
encrypted_value = procedure.encrypted_api_particulier_token
# Verify that the new encrypted value can't be decrypted with the legacy service
expect { legacy_encryption_service.decrypt(encrypted_value) }
.to raise_error(ActiveSupport::MessageEncryptor::InvalidMessage)
# Verify that the new encrypted value can be decrypted with the current service
current_service = EncryptionService.new
expect(current_service.decrypt(encrypted_value)).to eq(token)
# and with the services without rotations
current_service = EncryptionService.new
current_service.instance_variable_set(:@rotations, [])
expect(current_service.decrypt(encrypted_value)).to eq(token)
end
end
end
end