From 2bcbeed95143448625eccbbf3a3245a1eec26dce Mon Sep 17 00:00:00 2001 From: Claire Date: Mon, 20 May 2024 16:59:23 +0200 Subject: [PATCH] Add some error handling to OTP secret migration (#30344) --- ...80905_migrate_devise_two_factor_secrets.rb | 26 ++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/db/post_migrate/20240307180905_migrate_devise_two_factor_secrets.rb b/db/post_migrate/20240307180905_migrate_devise_two_factor_secrets.rb index 360e4806d..6194cf9ee 100644 --- a/db/post_migrate/20240307180905_migrate_devise_two_factor_secrets.rb +++ b/db/post_migrate/20240307180905_migrate_devise_two_factor_secrets.rb @@ -18,7 +18,13 @@ class MigrateDeviseTwoFactorSecrets < ActiveRecord::Migration[7.1] users_with_otp_enabled.find_each do |user| # Gets the new value on already-updated users # Falls back to legacy value on not-yet-migrated users - otp_secret = user.otp_secret + otp_secret = begin + user.otp_secret + rescue OpenSSL::OpenSSLError + next if ENV['MIGRATION_IGNORE_INVALID_OTP_SECRET'] == 'true' + + abort_with_decryption_error(user) + end Rails.logger.debug { "Processing #{user.email}" } @@ -36,4 +42,22 @@ class MigrateDeviseTwoFactorSecrets < ActiveRecord::Migration[7.1] def users_with_otp_enabled MigrationUser.where(otp_required_for_login: true, otp_secret: nil) end + + def abort_with_decryption_error(user) + abort <<~MESSAGE + + ERROR: Unable to decrypt OTP secret for user #{user.id}. + + This is most likely because you have changed the value of `OTP_SECRET` at some point in + time after the user configured 2FA. + + In this case, their OTP secret had already been lost with the change to `OTP_SECRET`, and + proceeding with this migration will not make the situation worse. + + Please double-check that you have not accidentally changed `OTP_SECRET` just for this + migration, and re-run the migration with `MIGRATION_IGNORE_INVALID_OTP_SECRET=true`. + + Migration aborted. + MESSAGE + end end