Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduce compressor option to ActiveRecord::Encryption::Encryptor #51735

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

heka1024
Copy link
Contributor

@heka1024 heka1024 commented May 4, 2024

Motivation / Background

There are more performant algorithms than zlib, like zstd or snappy. So I made it possible to configure the compressor to take advantage of these more performant algorithms.

Detail

Make compressor as argument which default value is zlib.

Additional information

Checklist

Before submitting the PR make sure the following are checked:

  • This Pull Request is related to one change. Unrelated changes should be opened in separate PRs.
  • Commit message has a detailed description of what changed and why. If this PR fixes a related issue include it in the commit message. Ex: [Fix #issue-number]
  • Tests are added or updated if you fix a bug or add a feature.
  • CHANGELOG files are updated for the changed libraries if there is a behavior change or additional feature. Minor bug fixes and documentation changes should not be included.

Discussion

What do you thinks about make compressor as property of ActiveRecord::Encryption ?

Copy link
Member

@flavorjones flavorjones left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The naming of the custom compressor's methods seems inconsistent to me. Would you consider using Encryptor's convention and name them compress/uncompress instead of ZLib's deflate/inflate?

I also think this PR should update the Rails Guides page on encryption, guides/source/active_record_encryption.md to explain how to implement a custom compressor.

@rails-bot rails-bot bot added the docs label May 7, 2024
@heka1024 heka1024 force-pushed the encryption-compressor branch 2 times, most recently from 883a321 to 3231918 Compare May 7, 2024 08:58
@heka1024
Copy link
Contributor Author

heka1024 commented May 7, 2024

Hi, @flavorjones ! I changed signature of compressor (compress/uncompress) and make compressor configurable. And add some document about compression. Could you review it? I'd really appreciate it if you could provide feedback!

activerecord/CHANGELOG.md Outdated Show resolved Hide resolved
@heka1024 heka1024 force-pushed the encryption-compressor branch 5 times, most recently from a34e1dd to d2de562 Compare May 14, 2024 05:50
@zzak
Copy link
Member

zzak commented May 19, 2024

CI failures seem unrelated, you might want to rebase just to be sure as I think most of those have been fixed

@heka1024 heka1024 force-pushed the encryption-compressor branch 4 times, most recently from 5664b8c to d0a8297 Compare May 19, 2024 06:46
@heka1024
Copy link
Contributor Author

CI failures seem unrelated, you might want to rebase just to be sure as I think most of those have been fixed

@zzak I just rebased it, and it looks like all CI failures are fixed now. 😄

Copy link
Member

@flavorjones flavorjones left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, so I'm only realizing now that Rails already has prior art for this sort of compression API, see the docs for ActiveSupport::Cache::Store.new and the :compressor option.

In summary, "Must respond to deflate and inflate"

So I hate to ask, especially since I asked you to change it in the first place, but can you update this PR to use that naming convention? I sincerely apologize for not realizing this sooner.

activerecord/CHANGELOG.md Outdated Show resolved Hide resolved
guides/source/active_record_encryption.md Outdated Show resolved Hide resolved
@@ -497,6 +533,10 @@ The digest algorithm used to derive keys. `OpenSSL::Digest::SHA256` by default.
Supports decrypting data encrypted non-deterministically with a digest class SHA1. Default is false, which
means it will only support the digest algorithm configured in `config.active_record.encryption.hash_digest_class`.

#### `config.active_record.encryption.compressor`

The compressor used to compress encrypted payloads. It should respond to `compress` and `uncompress`. Default is `Zlib`. You can find more information about compressors in the [Compression](#compression) section.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same comment here -- please use the full namespaced name to disambiguate.

Copy link
Contributor Author

@heka1024 heka1024 May 20, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So I hate to ask, especially since I asked you to change it in the first place, but can you update this PR to use that naming convention? I sincerely apologize for not realizing this sooner.

@flavorjones Don't mind. It's not a big deal.

By using inflate/deflate, we don't need wrapper class for zlib, ActiveRecord::Encryption::Compressor::Zlib. Because Zlib can respond to inflate/deflate. So I think using Zlib in document is right. What do you think?

ref: ActiveSupport::Cache

compressor = @options.delete(:compressor) { Zlib }

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yup, makes sense.

@heka1024 heka1024 force-pushed the encryption-compressor branch 3 times, most recently from a7ff27d to a0be4ad Compare May 20, 2024 14:30
@@ -497,6 +533,10 @@ The digest algorithm used to derive keys. `OpenSSL::Digest::SHA256` by default.
Supports decrypting data encrypted non-deterministically with a digest class SHA1. Default is false, which
means it will only support the digest algorithm configured in `config.active_record.encryption.hash_digest_class`.

#### `config.active_record.encryption.compressor`

The compressor used to compress encrypted payloads. It should respond to `compress` and `uncompress`. Default is `Zlib`. You can find more information about compressors in the [Compression](#compression) section.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yup, makes sense.

@flavorjones flavorjones added the ready PRs ready to merge label May 20, 2024
@heka1024 heka1024 force-pushed the encryption-compressor branch 2 times, most recently from 666952d to 18b4cc2 Compare May 21, 2024 00:15
@heka1024
Copy link
Contributor Author

There is a ci failure but it looks like unrelated.

Failure:
--
  | ActiveRecord::ConnectionAdapters::ReaperTest#test_connection_pool_starts_reaper_in_fork [test/cases/reaper_test.rb:161]:
  | Expected #<Process::Status: pid 79 SIGABRT (signal 6) (core dumped)> to be success?.

Copy link
Member

@eileencodes eileencodes left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The feature seems like a good idea to me, thanks for working on it @heka1024

I left a comment about the API design and I also think this should provide a config option so apps that want the same custom compressor for every model can just set it once.

end

class User
encrypts :name, encryptor: ActiveRecord::Encryption::Encryptor.new(compressor: ZstdCompressor)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This API doesn't feel right. Having to initialize a new Encryptor in your app to set the compressor feels cumbersome and un-Rails like. I have two suggestions:

  1. I think if we want a compressor option for every model then Rails should do the initialization for the app. The AR code would check if the compressor option is set and then Rails would do the initialization for the application. Then it's a much cleaner API because it becomes:
encrypts :name, compressor: ZstdCompressor
  1. Rails should provide a config option so that applications can set all encryptors to use the same custom compressor.
config.active_record_encryption.compressor = ZstdCompressor

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants