From b3f5705121b81b7a9b4d8dda56faf6271785a4e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Javi=20Mart=C3=ADn?= Date: Thu, 28 Mar 2024 23:14:58 +0100 Subject: [PATCH] Use SHA256 to encrypt messages and cookies Note that enabling this options means all encrypted messages and cookies generated the application become invalid, so we're adding a cookie rotator in order to keep sessions from expiring when upgrading the application, as recommended in the "Upgrading Ruby on Rails" guideline [1]. Since we haven't seen any Consul Democracy applications using encrypted messages and these messages become invalid with this change, we're also removing the pre-Rails 5.2 encryption to authenticate messages (AES-256-CBC) and switching to the default one since Rails 5.2 (AES-256-GCM). Since the configured encryption is used by the cookie rotator initializer (through the ActiveSupport::MessageEncryptor.key_len method), at first I thought this might affect the cookie rotator, but it doesn't: upgrading works as expected, and existing sessions are still active. I'm adding a comment to remove the initializer once all cookies have been migrated. I've added "Rails 7.1" in the comment because we usually check for these comments when upgrading Rails, but we rarely check for them when after releasing new versions of Consul Democracy. [1] https://guides.rubyonrails.org/v7.0/upgrading_ruby_on_rails.html#key-generator-digest-class-changing-to-use-sha256 --- .rubocop.yml | 1 + config/application.rb | 4 ---- config/initializers/cookie_rotator.rb | 23 +++++++++++++++++++ .../new_framework_defaults_7_0.rb | 2 +- 4 files changed, 25 insertions(+), 5 deletions(-) create mode 100644 config/initializers/cookie_rotator.rb diff --git a/.rubocop.yml b/.rubocop.yml index 9fffe97aa..cf411617d 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -163,6 +163,7 @@ Layout/LineLength: - "config/environments/staging.rb" - "config/initializers/devise.rb" - "config/initializers/backtrace_silencers.rb" + - "config/initializers/cookie_rotator.rb" - "db/migrate/*create_delayed_jobs.rb" - "db/migrate/*create_active_storage_variant_records.active_storage.rb" - "app/models/budget/stats.rb" diff --git a/config/application.rb b/config/application.rb index ae3ef7b8f..fc512ff98 100644 --- a/config/application.rb +++ b/config/application.rb @@ -27,10 +27,6 @@ module Consul # Rails 4 models worked config.active_record.belongs_to_required_by_default = false - # Keep using AES-256-CBC for message encryption in case it's used - # in any CONSUL DEMOCRACY installations - config.active_support.use_authenticated_message_encryption = false - # Don't enable has_many_inversing because it doesn't seem to currently # work with the _count database columns we use for caching purposes config.active_record.has_many_inversing = false diff --git a/config/initializers/cookie_rotator.rb b/config/initializers/cookie_rotator.rb new file mode 100644 index 000000000..b82c9de1d --- /dev/null +++ b/config/initializers/cookie_rotator.rb @@ -0,0 +1,23 @@ +# This code was copied from: +# https://guides.rubyonrails.org/v7.0/upgrading_ruby_on_rails.html#key-generator-digest-class-changing-to-use-sha256 +# TODO: safe to remove after upgrading to Rails 7.1 or releasing a new +# version of Consul Democracy +Rails.application.config.after_initialize do + Rails.application.config.action_dispatch.cookies_rotations.tap do |cookies| + authenticated_encrypted_cookie_salt = Rails.application.config.action_dispatch.authenticated_encrypted_cookie_salt + signed_cookie_salt = Rails.application.config.action_dispatch.signed_cookie_salt + + secret_key_base = Rails.application.secret_key_base + + key_generator = ActiveSupport::KeyGenerator.new( + secret_key_base, iterations: 1000, hash_digest_class: OpenSSL::Digest::SHA1 + ) + key_len = ActiveSupport::MessageEncryptor.key_len + + old_encrypted_secret = key_generator.generate_key(authenticated_encrypted_cookie_salt, key_len) + old_signed_secret = key_generator.generate_key(signed_cookie_salt) + + cookies.rotate :encrypted, old_encrypted_secret + cookies.rotate :signed, old_signed_secret + end +end diff --git a/config/initializers/new_framework_defaults_7_0.rb b/config/initializers/new_framework_defaults_7_0.rb index 39df8d8fd..c8c21ad4c 100644 --- a/config/initializers/new_framework_defaults_7_0.rb +++ b/config/initializers/new_framework_defaults_7_0.rb @@ -23,7 +23,7 @@ Rails.application.config.action_view.button_to_generates_button_tag = true # # See upgrading guide for more information on how to build a rotator. # https://guides.rubyonrails.org/v7.0/upgrading_ruby_on_rails.html -# Rails.application.config.active_support.key_generator_hash_digest_class = OpenSSL::Digest::SHA256 +Rails.application.config.active_support.key_generator_hash_digest_class = OpenSSL::Digest::SHA256 # Change the digest class for ActiveSupport::Digest. # Changing this default means that for example Etags change and