rom-encrypted_attribute 0.0.3 → 0.0.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +61 -4
- data/lib/rom/encrypted_attribute/version.rb +1 -1
- data/lib/rom/encrypted_attribute.rb +7 -0
- data/lib/rom/plugins/schema/encrypted_attributes.rb +55 -0
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a7799a80222e1784ae54379331e44b52035d1fea0544723ab3ad69aac8d0416a
|
4
|
+
data.tar.gz: 1418ca1c2a31c539fec10c0c118c305216a439a19c19cdf1662ad1b158bed892
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e1854858926a001395967f06fc4dcce28ef066e2e3819d4a3f45375abc1e55c671000de7ff3f7431d6641f31b68d92f012f75532db2cc137e35e9939b61b745a
|
7
|
+
data.tar.gz: 5f8cf5402568abc7d46dd5cd96bf7443ed59d2bf74d69191349ff10ab0c41d89d1f9f154d180890d2344e1d973801c1f2294fae0d8aa2619cdfddf963135c77e
|
data/README.md
CHANGED
@@ -20,6 +20,59 @@ If bundler is not being used to manage dependencies, install the gem by executin
|
|
20
20
|
|
21
21
|
## Usage
|
22
22
|
|
23
|
+
There are two ways to use this library: via a ROM schema plugin or by a "bare metal" approach.
|
24
|
+
|
25
|
+
### ROM plugin
|
26
|
+
|
27
|
+
Somewhere in you code set the config for the gem. This is done using [`Dry::Configurable`](https://dry-rb.org/gems/dry-configurable/1.0/), so you can use all options available there. For example:
|
28
|
+
|
29
|
+
``` ruby
|
30
|
+
ROM::EncryptedAttribute.configure do |config|
|
31
|
+
config.primary_key = "your-primary-key" # required
|
32
|
+
config.key_derivation_salt = "your-derivation-salt" # required
|
33
|
+
config.hash_digest_class = OpenSSL::Digest::SHA256 # SHA1 by default
|
34
|
+
end
|
35
|
+
```
|
36
|
+
|
37
|
+
Then use the plugin in your ROM relation:
|
38
|
+
|
39
|
+
``` ruby
|
40
|
+
class SecretNotes < ::ROM::Relation[:sql]
|
41
|
+
schema(:secret_notes, infer: true) do
|
42
|
+
use :encrypted_attributes
|
43
|
+
encrypt :content
|
44
|
+
end
|
45
|
+
end
|
46
|
+
```
|
47
|
+
|
48
|
+
You can override individual configuration values if, for example, one database table uses different primary key:
|
49
|
+
|
50
|
+
``` ruby
|
51
|
+
class SecretNotes < ::ROM::Relation[:sql]
|
52
|
+
schema(:secret_notes, infer: true) do
|
53
|
+
use :encrypted_attributes, primary_key: ENV["SPECIAL_PRIMARY_KEY"]
|
54
|
+
encrypt :content
|
55
|
+
end
|
56
|
+
end
|
57
|
+
```
|
58
|
+
|
59
|
+
If you specify all configuration options, or use defaults, you can skip setting the global config.
|
60
|
+
|
61
|
+
You can also override global per-schema settings on a per-field level:
|
62
|
+
|
63
|
+
``` ruby
|
64
|
+
class SecretNotes < ::ROM::Relation[:sql]
|
65
|
+
schema(:secret_notes, infer: true) do
|
66
|
+
use :encrypted_attributes
|
67
|
+
encrypt :content
|
68
|
+
encrypt :title, :hash_digest_class: OpenSSL::Digest::SHA256
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
```
|
73
|
+
|
74
|
+
### "Bare metal"
|
75
|
+
|
23
76
|
In your relation, define custom types using a helper method from the gem. You need to provide the credentials to it somehow. This might be done via environmental variables, Hanami settings (if you're using Hanami) or any other means, really.
|
24
77
|
|
25
78
|
```ruby
|
@@ -36,7 +89,11 @@ class SecretNotes < ROM::Relation[:sql]
|
|
36
89
|
end
|
37
90
|
```
|
38
91
|
|
39
|
-
|
92
|
+
With this approach you can define the types globally in your application and reuse it, without having to pass primary_key and key_derivation_salt every time in the schema.
|
93
|
+
|
94
|
+
### Other considerations
|
95
|
+
|
96
|
+
By default the gem uses SHA1 for key derivation (same as Rails' default), but you can configure it by passing custom `hash_digest_class` option.
|
40
97
|
|
41
98
|
``` ruby
|
42
99
|
class SecretNotes < ROM::Relation[:sql]
|
@@ -56,9 +113,9 @@ end
|
|
56
113
|
|
57
114
|
### Caveats
|
58
115
|
|
59
|
-
* Due to [a bug](https://github.com/rom-rb/rom-sql/issues/423) in `rom-sql`, reading unencrypted data is always supported, which means that if there's a plain not-encrypted data in your database already, it will be read correctly. This might or might not be desirable, but for the time being there's no choice in
|
60
|
-
* Support for deterministic encryption from `ActiveRecord::Encryption` is not implemented
|
61
|
-
* Support for key rotation is not implemented
|
116
|
+
* Due to [a bug](https://github.com/rom-rb/rom-sql/issues/423) in `rom-sql`, reading unencrypted data is always supported, which means that if there's a plain not-encrypted data in your database already, it will be read correctly. This might or might not be desirable, but for the time being there's no choice in configuring this behaviour.
|
117
|
+
* Support for deterministic encryption from `ActiveRecord::Encryption` is not (yet) implemented
|
118
|
+
* Support for key rotation is not (yet) implemented
|
62
119
|
|
63
120
|
## Contributing
|
64
121
|
|
@@ -4,11 +4,18 @@ require_relative "encrypted_attribute/key_derivator"
|
|
4
4
|
require_relative "encrypted_attribute/decryptor"
|
5
5
|
require_relative "encrypted_attribute/encryptor"
|
6
6
|
require_relative "encrypted_attribute/version"
|
7
|
+
require_relative "plugins/schema/encrypted_attributes"
|
7
8
|
|
8
9
|
require "dry/types"
|
9
10
|
|
10
11
|
module ROM
|
11
12
|
module EncryptedAttribute
|
13
|
+
extend Dry::Configurable
|
14
|
+
|
15
|
+
setting :primary_key
|
16
|
+
setting :key_derivation_salt
|
17
|
+
setting :hash_digest_class, default: OpenSSL::Digest::SHA1
|
18
|
+
|
12
19
|
def self.define_encrypted_attribute_types(primary_key:, key_derivation_salt:, hash_digest_class: OpenSSL::Digest::SHA1)
|
13
20
|
key_derivator = KeyDerivator.new(salt: key_derivation_salt, secret: primary_key,
|
14
21
|
hash_digest_class: hash_digest_class)
|
@@ -0,0 +1,55 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "rom"
|
4
|
+
|
5
|
+
module ROM
|
6
|
+
module Plugins
|
7
|
+
module Schema
|
8
|
+
module EncryptedAttributes
|
9
|
+
def self.apply(schema, **options)
|
10
|
+
attributes = options.fetch(:attributes)
|
11
|
+
primary_key = options.fetch(:primary_key, ROM::EncryptedAttribute.config.primary_key)
|
12
|
+
key_derivation_salt = options.fetch(:key_derivation_salt, ROM::EncryptedAttribute.config.key_derivation_salt)
|
13
|
+
hash_digest_class = options.fetch(:hash_digest_class, ROM::EncryptedAttribute.config.hash_digest_class)
|
14
|
+
|
15
|
+
encrypted_string, encrypted_string_reader =
|
16
|
+
ROM::EncryptedAttribute.define_encrypted_attribute_types(
|
17
|
+
primary_key: primary_key, key_derivation_salt: key_derivation_salt, hash_digest_class: hash_digest_class
|
18
|
+
)
|
19
|
+
|
20
|
+
attrs =
|
21
|
+
attributes.map do |name|
|
22
|
+
ROM::Schema::DSL.new(schema.name).build_attribute_info(
|
23
|
+
name,
|
24
|
+
encrypted_string,
|
25
|
+
name: name, read: encrypted_string_reader
|
26
|
+
)
|
27
|
+
end
|
28
|
+
|
29
|
+
schema.attributes.concat(
|
30
|
+
schema.class.attributes(attrs, schema.attr_class)
|
31
|
+
)
|
32
|
+
end
|
33
|
+
|
34
|
+
module DSL
|
35
|
+
# @example
|
36
|
+
# schema do
|
37
|
+
# use :encrypted_attributes
|
38
|
+
# encrypt :api_key, :ssn, hash_digest_class: OpenSSL::Digest::SHA256
|
39
|
+
# end
|
40
|
+
def encrypt(*attributes, **opts)
|
41
|
+
options = plugin_options(:encrypted_attributes)
|
42
|
+
options.merge!(opts)
|
43
|
+
options[:attributes] ||= []
|
44
|
+
options[:attributes] += attributes
|
45
|
+
self
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
ROM.plugins do
|
54
|
+
register :encrypted_attributes, ROM::Plugins::Schema::EncryptedAttributes, type: :schema
|
55
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rom-encrypted_attribute
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Paweł Świątkowski
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-
|
11
|
+
date: 2024-10-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: dry-types
|
@@ -84,6 +84,7 @@ files:
|
|
84
84
|
- lib/rom/encrypted_attribute/key_derivator.rb
|
85
85
|
- lib/rom/encrypted_attribute/payload.rb
|
86
86
|
- lib/rom/encrypted_attribute/version.rb
|
87
|
+
- lib/rom/plugins/schema/encrypted_attributes.rb
|
87
88
|
- rom-encrypted_attribute.gemspec
|
88
89
|
homepage:
|
89
90
|
licenses: []
|