Add an ActiveSupport option to allow setting a digest class

Right now it's already possible to set a digest class manually, but this
is not through a publicly supported and approved API. With these
configuration options, it is possible to configure a digest class to use
for digests inside Rails.

The reason for this is that it allows configuring other classes in
certain conditions like running in FIPS mode. FIPS disallows MD5 and
discourages SHA1. Even though this isn't used in Rails for security
related things, using newer hash algorithms means not having to explain
it to auditors which always makes life easier.

That's not the only reason though. If today Ruby is built and running
for example in an Ubuntu 18.04 FIPS approved environment, the default
Digest classes break, see https://bugs.ruby-lang.org/issues/13681 as
well.

By allowing a class to be configured, the following can be used so that
things work properly (using the new API proposed here):

```
Rails.application.config.active_support.hash_digest_class = OpenSSL::Digest::SHA256
```

This would then use the OpenSSL certified FIPS implementation as well.
This commit is contained in:
Dirkjan Bussink 2020-09-10 14:06:18 +02:00
parent fb852668df
commit 0f6c9bc786
No known key found for this signature in database
GPG Key ID: F1573D8E835753FD
5 changed files with 30 additions and 3 deletions

View File

@ -85,8 +85,17 @@ module ActiveSupport
initializer "active_support.set_hash_digest_class" do |app|
config.after_initialize do
if app.config.active_support.use_sha1_digests
ActiveSupport::Deprecation.warn(<<-MSG.squish)
config.active_support.use_sha1_digests is deprecated and will
be removed from Rails 6.2. Use config.active_support.hash_digest_class
instead.
MSG
ActiveSupport::Digest.hash_digest_class = ::Digest::SHA1
end
if klass = app.config.active_support.hash_digest_class
ActiveSupport::Digest.hash_digest_class = klass
end
end
end
end

View File

@ -819,7 +819,7 @@ There are a few configuration options available in Active Support:
* `config.active_support.time_precision` sets the precision of JSON encoded time values. Defaults to `3`.
* `config.active_support.use_sha1_digests` specifies whether to use SHA-1 instead of MD5 to generate non-sensitive digests, such as the ETag header.
* `config.active_support.hash_digest_class` allows configuring the digest class to use to generate non-sensitive digests, such as the ETag header.
* `config.active_support.use_authenticated_message_encryption` specifies whether to use AES-256-GCM authenticated encryption as the default cipher for encrypting messages instead of AES-256-CBC.
@ -1035,7 +1035,7 @@ text/javascript image/svg+xml application/postscript application/x-shockwave-fla
- `config.active_record.cache_versioning`: `true`
- `config.action_dispatch.use_authenticated_cookie_encryption`: `true`
- `config.active_support.use_authenticated_message_encryption`: `true`
- `config.active_support.use_sha1_digests`: `true`
- `config.active_support.hash_digest_class`: `::Digest::SHA1`
- `config.action_controller.default_protect_from_forgery`: `true`
- `config.action_view.form_with_generates_ids`: `true`

View File

@ -1,3 +1,9 @@
* Deprecate `config.active_support.use_sha1_digests`
`config.active_support.use_sha1_digests` is deprecated. It is replaced with `config.active_support.hash_digest_class` which allows setting the desired Digest instead. The Rails version defaults have been updated to use this new method as well so the behavior there is unchanged.
*Dirkjan Bussink*
* Change the default logging level from :debug to :info to avoid inadvertent exposure of personally
identifiable information (PII) in production environments.

View File

@ -115,7 +115,7 @@ module Rails
if respond_to?(:active_support)
active_support.use_authenticated_message_encryption = true
active_support.use_sha1_digests = true
active_support.hash_digest_class = ::Digest::SHA1
end
if respond_to?(:action_controller)

View File

@ -2225,6 +2225,18 @@ module ApplicationTests
assert_equal Digest::SHA1, ActiveSupport::Digest.hash_digest_class
end
test "ActiveSupport::Digest.hash_digest_class can be configured via config.active_support.hash_digest_class" do
remove_from_config '.*config\.load_defaults.*\n'
app_file "config/initializers/custom_digest_class.rb", <<-RUBY
Rails.application.config.active_support.hash_digest_class = Digest::SHA256
RUBY
app "development"
assert_equal Digest::SHA256, ActiveSupport::Digest.hash_digest_class
end
test "custom serializers should be able to set via config.active_job.custom_serializers in an initializer" do
class ::DummySerializer < ActiveJob::Serializers::ObjectSerializer; end