sequel_vault 0.2 → 0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Gemfile.lock +15 -15
- data/lib/sequel_vault.rb +47 -18
- data/sequel_vault.gemspec +1 -1
- data/spec/sequel_vault_spec.rb +14 -5
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 165282372b352387b3f41c17d6a652db49e6fd88
|
4
|
+
data.tar.gz: bcf9013ae07860c426d1e9895dac5c8fc50eed21
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 35567135ac68c423cba3e794f1f4e96a336fdb8c34bbea44857ecc02b630175f455f06dc46b50f85d1a1127ce5cc642efe6d749a5db7fc83826ec15c0fed2ebf
|
7
|
+
data.tar.gz: 161c4e25ecad6ff8720f419803c415183971853c0884f6d18480137d6983954abd6a5c66b5a199bf608344407267b283a3b46287f48c7c1159fbdf9bb36c7acf
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
sequel_vault (0.
|
4
|
+
sequel_vault (0.2)
|
5
5
|
fernet (~> 2.1, >= 2.1)
|
6
6
|
sequel (~> 4.21, >= 4.21.0)
|
7
7
|
|
@@ -10,23 +10,23 @@ GEM
|
|
10
10
|
specs:
|
11
11
|
diff-lcs (1.2.5)
|
12
12
|
docile (1.1.5)
|
13
|
-
fernet (2.1)
|
13
|
+
fernet (2.1.1)
|
14
14
|
valcro (= 0.1)
|
15
|
-
multi_json (1.11.
|
16
|
-
rspec (3.
|
17
|
-
rspec-core (~> 3.
|
18
|
-
rspec-expectations (~> 3.
|
19
|
-
rspec-mocks (~> 3.
|
20
|
-
rspec-core (3.
|
21
|
-
rspec-support (~> 3.
|
22
|
-
rspec-expectations (3.
|
15
|
+
multi_json (1.11.1)
|
16
|
+
rspec (3.3.0)
|
17
|
+
rspec-core (~> 3.3.0)
|
18
|
+
rspec-expectations (~> 3.3.0)
|
19
|
+
rspec-mocks (~> 3.3.0)
|
20
|
+
rspec-core (3.3.1)
|
21
|
+
rspec-support (~> 3.3.0)
|
22
|
+
rspec-expectations (3.3.0)
|
23
23
|
diff-lcs (>= 1.2.0, < 2.0)
|
24
|
-
rspec-support (~> 3.
|
25
|
-
rspec-mocks (3.
|
24
|
+
rspec-support (~> 3.3.0)
|
25
|
+
rspec-mocks (3.3.1)
|
26
26
|
diff-lcs (>= 1.2.0, < 2.0)
|
27
|
-
rspec-support (~> 3.
|
28
|
-
rspec-support (3.
|
29
|
-
sequel (4.
|
27
|
+
rspec-support (~> 3.3.0)
|
28
|
+
rspec-support (3.3.0)
|
29
|
+
sequel (4.23.0)
|
30
30
|
simplecov (0.9.2)
|
31
31
|
docile (~> 1.1.0)
|
32
32
|
multi_json (~> 1.0)
|
data/lib/sequel_vault.rb
CHANGED
@@ -1,40 +1,47 @@
|
|
1
1
|
require "fernet"
|
2
|
+
require "sequel"
|
2
3
|
|
3
4
|
module Sequel
|
4
5
|
module Plugins
|
5
6
|
module Vault
|
6
7
|
class InvalidCiphertext < Exception; end
|
7
8
|
|
8
|
-
def self.
|
9
|
+
def self.apply(model, keys = [], *attrs)
|
10
|
+
model.instance_eval do
|
11
|
+
@vault_attrs = attrs
|
12
|
+
@vault_keys = keys
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.configure(model, keys = [], *attrs)
|
9
17
|
model.vault_attributes(keys, *attrs) unless attrs.empty?
|
10
18
|
end
|
11
19
|
|
12
20
|
module ClassMethods
|
13
|
-
|
21
|
+
attr_reader :vault_attrs
|
22
|
+
attr_reader :vault_keys
|
23
|
+
attr_reader :vault_module
|
24
|
+
|
25
|
+
Plugins.inherited_instance_variables(self, :@vault_attrs => :dup, :@vault_keys => :dup)
|
14
26
|
|
15
27
|
def vault_attributes(keys, *attrs)
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
define_method(attr) do
|
20
|
-
cypher = super()
|
21
|
-
decrypt(keys, cypher) unless cypher.nil?
|
22
|
-
end
|
28
|
+
raise(Error, 'must provide both keys name and attrs when setting up vault') unless keys && attrs
|
29
|
+
@vault_keys = keys
|
30
|
+
@vault_attrs = attrs
|
23
31
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
send("#{attr}_digest=", digest)
|
32
|
+
self.class.instance_eval do
|
33
|
+
attrs.each do |attr|
|
34
|
+
define_method("#{attr}_lookup") do |plain|
|
35
|
+
digests = keys.map { |key| Sequel.blob(digest(key, plain)) }
|
36
|
+
where("#{attr}_digest": digests).first
|
30
37
|
end
|
31
38
|
end
|
32
39
|
end
|
33
40
|
end
|
34
|
-
end
|
35
41
|
|
36
|
-
|
37
|
-
|
42
|
+
def digest(keys, plain)
|
43
|
+
OpenSSL::HMAC.digest(OpenSSL::Digest.new('sha512'), Array(keys).first, plain)
|
44
|
+
end
|
38
45
|
|
39
46
|
def encrypt(keys, plain)
|
40
47
|
::Fernet.generate(keys.first, plain)
|
@@ -49,6 +56,28 @@ module Sequel
|
|
49
56
|
raise InvalidCiphertext, "Could not decrypt field"
|
50
57
|
end
|
51
58
|
end
|
59
|
+
|
60
|
+
module DatasetMethods
|
61
|
+
end
|
62
|
+
|
63
|
+
module InstanceMethods
|
64
|
+
def []=(attr, plain)
|
65
|
+
if model.vault_attrs.include?(attr) && !plain.nil?
|
66
|
+
send("#{attr}_digest=", self.class.digest(model.vault_keys, plain))
|
67
|
+
value = self.class.encrypt(model.vault_keys, plain)
|
68
|
+
end
|
69
|
+
super(attr, value || plain)
|
70
|
+
end
|
71
|
+
|
72
|
+
def [](attr)
|
73
|
+
if model.vault_attrs.include?(attr)
|
74
|
+
cypher = super(attr)
|
75
|
+
self.class.decrypt(model.vault_keys, cypher) unless cypher.nil?
|
76
|
+
else
|
77
|
+
super(attr)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
52
81
|
end
|
53
82
|
end
|
54
83
|
end
|
data/sequel_vault.gemspec
CHANGED
@@ -13,7 +13,7 @@ Gem::Specification.new do |gem|
|
|
13
13
|
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
14
14
|
gem.name = "sequel_vault"
|
15
15
|
gem.require_paths = ["lib"]
|
16
|
-
gem.version = '0.
|
16
|
+
gem.version = '0.3'
|
17
17
|
|
18
18
|
gem.add_runtime_dependency 'sequel', '~> 4.21', '>= 4.21.0'
|
19
19
|
gem.add_runtime_dependency 'fernet', '~> 2.1', '>= 2.1'
|
data/spec/sequel_vault_spec.rb
CHANGED
@@ -2,42 +2,51 @@
|
|
2
2
|
require "spec_helper"
|
3
3
|
|
4
4
|
describe Sequel::Plugins::Vault do
|
5
|
-
let(:db) { Sequel.mock }
|
5
|
+
let(:db) { Sequel.mock(autoid: 1) }
|
6
6
|
let(:klass) do
|
7
7
|
Class.new(Sequel::Model(db[:vm])) do
|
8
8
|
set_primary_key :id
|
9
|
+
unrestrict_primary_key
|
9
10
|
set_columns([:id, :secret, :secret_digest])
|
10
11
|
|
11
12
|
plugin :vault
|
12
13
|
end
|
13
14
|
end
|
15
|
+
let(:dataset) { klass.dataset }
|
14
16
|
let(:model) { klass.new }
|
15
17
|
let(:keys) do
|
16
18
|
["woRXJWevRaxZLxgoiEQtCDPBSf9TNg57bki0RUK1U48=",
|
17
19
|
"fih3l0Z9e4NBpy5KIj+rmXVexY5O9LspzuqCFyqavjg="]
|
18
20
|
end
|
19
|
-
let(:sqls) { db.sqls }
|
20
21
|
let(:secret) { "Attack at once." }
|
22
|
+
let(:cypher) { klass.encrypt(keys, secret) }
|
21
23
|
let(:digest) { OpenSSL::HMAC.digest('sha512', keys.first, secret) }
|
22
24
|
|
23
25
|
it "should encrypt vault attributes" do
|
24
|
-
|
26
|
+
klass.vault_attributes(keys, :secret)
|
25
27
|
model.secret = secret
|
26
28
|
expect(model.values[:secret]).to_not eq(secret)
|
27
29
|
expect(model.secret).to eq(secret)
|
28
30
|
end
|
29
31
|
|
30
32
|
it "should allow nil value" do
|
31
|
-
|
33
|
+
klass.vault_attributes(keys, :secret)
|
32
34
|
model.secret = nil
|
33
35
|
expect(model.values[:secret]).to be_nil
|
34
36
|
expect(model.secret).to be_nil
|
35
37
|
end
|
36
38
|
|
37
39
|
it "should write a digest of the value" do
|
38
|
-
|
40
|
+
klass.vault_attributes(keys, :secret)
|
39
41
|
model.secret = secret
|
40
42
|
expect(model.values[:secret_digest]).to_not eq(secret)
|
41
43
|
expect(model.secret_digest).to eq(digest)
|
42
44
|
end
|
45
|
+
|
46
|
+
it "should provide a digest lookup" do
|
47
|
+
dataset._fetch = { id: 1, secret: cypher, secret_digest: digest }
|
48
|
+
klass.vault_attributes(keys, :secret)
|
49
|
+
lookup = klass.secret_lookup("secret")
|
50
|
+
expect(lookup.secret).to eq(secret)
|
51
|
+
end
|
43
52
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sequel_vault
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: '0.
|
4
|
+
version: '0.3'
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Timothée Peignier
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-06-
|
11
|
+
date: 2015-06-29 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: sequel
|