Skip to content

Commit

Permalink
Add an ActiveSupport option to allow setting a digest class
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
dbussink committed Sep 23, 2020
1 parent fb85266 commit 0f6c9bc
Show file tree
Hide file tree
Showing 5 changed files with 30 additions and 3 deletions.
9 changes: 9 additions & 0 deletions activesupport/lib/active_support/railtie.rb
Expand Up @@ -85,8 +85,17 @@ class Railtie < Rails::Railtie # :nodoc:
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
Expand Down
4 changes: 2 additions & 2 deletions guides/source/configuring.md
Expand Up @@ -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.

Expand Down Expand Up @@ -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`

Expand Down
6 changes: 6 additions & 0 deletions railties/CHANGELOG.md
@@ -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.

Expand Down
2 changes: 1 addition & 1 deletion railties/lib/rails/application/configuration.rb
Expand Up @@ -115,7 +115,7 @@ def load_defaults(target_version)

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)
Expand Down
12 changes: 12 additions & 0 deletions railties/test/application/configuration_test.rb
Expand Up @@ -2225,6 +2225,18 @@ class D < C
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

Expand Down

0 comments on commit 0f6c9bc

Please sign in to comment.