trocla 0.6.0 → 0.7.0

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.
data/spec/spec_helper.rb DELETED
@@ -1,315 +0,0 @@
1
- $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
2
- $LOAD_PATH.unshift(File.dirname(__FILE__))
3
- require 'jruby' if Object.const_defined?(:RUBY_ENGINE) and RUBY_ENGINE == 'jruby'
4
- require 'rspec'
5
- require 'rspec/pending_for'
6
- require 'yaml'
7
- require 'trocla'
8
-
9
- # Requires supporting files with custom matchers and macros, etc,
10
- # in ./support/ and its subdirectories.
11
- Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
12
-
13
- RSpec.shared_examples "encryption_basics" do
14
- describe 'storing' do
15
- it "random passwords" do
16
- expect(@trocla.password('random1', 'plain').length).to eql(16)
17
- end
18
-
19
- it "long random passwords" do
20
- expect(@trocla.set_password('random1_long','plain',4096.times.collect{|s| 'x' }.join('')).length).to eql(4096)
21
- end
22
- end
23
-
24
- describe 'retrieve' do
25
- it "random passwords" do
26
- stored = @trocla.password('random1', 'plain')
27
- retrieved = @trocla.password('random1', 'plain')
28
- retrieved_again = @trocla.password('random1', 'plain')
29
- expect(retrieved).to eql(stored)
30
- expect(retrieved_again).to eql(stored)
31
- expect(retrieved_again).to eql(retrieved)
32
- end
33
-
34
- it "encrypted passwords" do
35
- @trocla.set_password('some_pass', 'plain', 'super secret')
36
- expect(@trocla.get_password('some_pass', 'plain')).to eql('super secret')
37
- end
38
-
39
- it "resets passwords" do
40
- @trocla.set_password('some_pass', 'plain', 'super secret')
41
- expect(@trocla.reset_password('some_pass', 'plain')).not_to eql('super secret')
42
- end
43
-
44
- end
45
- describe 'deleting' do
46
- it "plain" do
47
- @trocla.set_password('some_pass', 'plain', 'super secret')
48
- expect(@trocla.delete_password('some_pass', 'plain')).to eql('super secret')
49
- end
50
- it "delete formats" do
51
- plain = @trocla.password('some_mysqlpass', 'plain')
52
- mysql = @trocla.password('some_mysqlpass', 'mysql')
53
- expect(@trocla.delete_password('some_mysqlpass', 'mysql')).to eql(mysql)
54
- expect(@trocla.delete_password('some_mysqlpass', 'plain')).to eql(plain)
55
- expect(@trocla.get_password('some_mysqlpass','plain')).to be_nil
56
- expect(@trocla.get_password('some_mysqlpass','mysql')).to be_nil
57
- end
58
-
59
- it "all passwords" do
60
- plain = @trocla.password('some_mysqlpass', 'plain')
61
- mysql = @trocla.password('some_mysqlpass', 'mysql')
62
- deleted = @trocla.delete_password('some_mysqlpass')
63
- expect(deleted).to be_a_kind_of(Hash)
64
- expect(deleted['plain']).to eql(plain)
65
- expect(deleted['mysql']).to eql(mysql)
66
- end
67
- end
68
- end
69
- RSpec.shared_examples "verify_encryption" do
70
- it "does not store plaintext passwords" do
71
- @trocla.set_password('noplain', 'plain', 'plaintext_password')
72
- expect(File.readlines(trocla_yaml_file).grep(/plaintext_password/)).to be_empty
73
- end
74
-
75
- it "makes sure identical passwords do not match when stored" do
76
- @trocla.set_password('one_key', 'plain', 'super secret')
77
- @trocla.set_password('another_key', 'plain', 'super secret')
78
- yaml = YAML.load_file(trocla_yaml_file)
79
- expect(yaml['one_key']['plain']).not_to eq(yaml['another_key']['plain'])
80
- end
81
- end
82
-
83
- RSpec.shared_examples 'store_validation' do |store|
84
- describe '.get' do
85
- it { expect(store.get('some_key','plain')).to be_nil }
86
- end
87
- describe '.set' do
88
- it 'stores nil values' do
89
- store.set('some_nil_value','plain',nil)
90
- expect(store.get('some_nil_value','plain')).to be_nil
91
- end
92
- it 'stores plain format' do
93
- store.set('some_value','plain','value')
94
- expect(store.get('some_value','plain')).to eql('value')
95
- end
96
- it 'stores other formats' do
97
- store.set('some_value','foo','bla')
98
- expect(store.get('some_value','foo')).to eql('bla')
99
- end
100
- it 'resets other formats on setting plain' do
101
- store.set('some_value','foo','bla')
102
- store.set('some_value','plain','value')
103
- expect(store.get('some_value','plain')).to eql('value')
104
- expect(store.get('some_value','foo')).to be_nil
105
- end
106
- end
107
- describe '.delete' do
108
- it { expect(store.delete('something','foo')).to be_nil }
109
- it { expect(store.delete('something')).to be_empty }
110
- it 'deletes the value of a format' do
111
- store.set('some_value','foo','bla')
112
- expect(store.delete('some_value','foo')).to eql('bla')
113
- expect(store.get('some_value','foo')).to be_nil
114
- end
115
- it 'deletes only the value of a format' do
116
- store.set('some_value','plain','value')
117
- store.set('some_value','foo','bla')
118
- expect(store.delete('some_value','plain')).to eql('value')
119
- expect(store.get('some_value','plain')).to be_nil
120
- expect(store.get('some_value','foo')).to eql('bla')
121
- end
122
- it 'deletes all values without a format' do
123
- store.set('some_value','plain','value')
124
- store.set('some_value','foo','bla')
125
- hash = store.delete('some_value')
126
- expect(hash).to be_a_kind_of(Hash)
127
- expect(hash['plain']).to eql('value')
128
- expect(hash['foo']).to eql('bla')
129
- expect(store.get('some_value','plain')).to be_nil
130
- expect(store.get('some_value','foo')).to be_nil
131
- end
132
- end
133
- describe 'expiration' do
134
- it 'will not return an expired key' do
135
- store.set('some_expiring_value','plain','to_be_expired',{ 'expires' => 2 })
136
- expect(store.get('some_expiring_value','plain')).to eql('to_be_expired')
137
- sleep 3
138
- expect(store.get('some_expiring_value','plain')).to be_nil
139
- end
140
- it 'increases expiration when setting anything for that key' do
141
- store.set('some_expiring_value','plain','to_be_expired',{ 'expires' => 2 })
142
- expect(store.get('some_expiring_value','plain')).to eql('to_be_expired')
143
- sleep 1
144
- store.set('some_expiring_value','bla','bla_to_be_expired',{ 'expires' => 3 })
145
- sleep 2
146
- expect(store.get('some_expiring_value','plain')).to eql('to_be_expired')
147
- sleep 2
148
- expect(store.get('some_expiring_value','plain')).to be_nil
149
- end
150
- it 'keeps expiration when setting another value' do
151
- store.set('some_expiring_value','plain','to_be_expired',{ 'expires' => 2 })
152
- store.set('some_expiring_value','foo','to_be_expired_foo')
153
- expect(store.get('some_expiring_value','plain')).to eql('to_be_expired')
154
- sleep 3
155
- expect(store.get('some_expiring_value','plain')).to be_nil
156
- expect(store.get('some_expiring_value','foo')).to be_nil
157
- end
158
- it 'setting plain clears everything including expiration' do
159
- store.set('some_expiring_value','plain','to_be_expired',{ 'expires' => 2 })
160
- sleep 1
161
- store.set('some_expiring_value','plain','to_be_expired2')
162
- expect(store.get('some_expiring_value','plain')).to eql('to_be_expired2')
163
- sleep 3
164
- expect(store.get('some_expiring_value','plain')).to eql('to_be_expired2')
165
- end
166
- it 'extends expiration when setting another value' do
167
- store.set('some_expiring_value','plain','to_be_expired',{ 'expires' => 4 })
168
- sleep 2
169
- store.set('some_expiring_value','foo','to_be_expired_foo')
170
- expect(store.get('some_expiring_value','plain')).to eql('to_be_expired')
171
- sleep 3
172
- expect(store.get('some_expiring_value','plain')).to eql('to_be_expired')
173
- sleep 2
174
- expect(store.get('some_expiring_value','plain')).to be_nil
175
- end
176
- it 'extends expiration when deleting a format' do
177
- store.set('some_expiring_value','plain','to_be_expired',{ 'expires' => 4 })
178
- store.set('some_expiring_value','foo','to_be_expired2')
179
- sleep 2
180
- expect(store.delete('some_expiring_value','foo')).to eql('to_be_expired2')
181
- sleep 3
182
- expect(store.get('some_expiring_value','plain')).to eql('to_be_expired')
183
- sleep 2
184
- expect(store.get('some_expiring_value','plain')).to be_nil
185
- end
186
- it 'keeps expiration although we\'re fetching a value' do
187
- store.set('some_expiring_value','plain','to_be_expired',{ 'expires' => 3 })
188
- sleep 2
189
- expect(store.get('some_expiring_value','plain')).to eql('to_be_expired')
190
- sleep 2
191
- expect(store.get('some_expiring_value','plain')).to be_nil
192
- end
193
- it 'readding a value with an expiration makes it expiring in the future' do
194
- store.set('some_expiring_value','plain','to_be_expired')
195
- store.set('some_expiring_value','plain','to_be_expired2',{ 'expires' => 2 })
196
- expect(store.get('some_expiring_value','plain')).to eql('to_be_expired2')
197
- sleep 3
198
- expect(store.get('some_expiring_value','plain')).to be_nil
199
- end
200
- it 'setting an expires of false removes expiration' do
201
- store.set('some_expiring_value','plain','to_be_expired2',{ 'expires' => 2 })
202
- expect(store.get('some_expiring_value','plain')).to eql('to_be_expired2')
203
- store.set('some_expiring_value','plain','to_be_expired',{ 'expires' => false })
204
- sleep 3
205
- expect(store.get('some_expiring_value','plain')).to eql('to_be_expired')
206
- end
207
- it 'setting an expires of 0 removes expiration' do
208
- store.set('some_expiring_value','plain','to_be_expired2',{ 'expires' => 2 })
209
- expect(store.get('some_expiring_value','plain')).to eql('to_be_expired2')
210
- store.set('some_expiring_value','plain','to_be_expired',{ 'expires' => 0 })
211
- sleep 3
212
- expect(store.get('some_expiring_value','plain')).to eql('to_be_expired')
213
- end
214
- it 'setting an expires of false removes expiration even if it\'s for a different format' do
215
- store.set('some_expiring_value','plain','to_be_expired2',{ 'expires' => 2 })
216
- expect(store.get('some_expiring_value','plain')).to eql('to_be_expired2')
217
- store.set('some_expiring_value','foo','to_be_expired_foo',{ 'expires' => false })
218
- sleep 3
219
- expect(store.get('some_expiring_value','plain')).to eql('to_be_expired2')
220
- expect(store.get('some_expiring_value','foo')).to eql('to_be_expired_foo')
221
- end
222
- it 'setting an expires of 0 removes expiration even if it\'s for a different format' do
223
- store.set('some_expiring_value','plain','to_be_expired2',{ 'expires' => 2 })
224
- expect(store.get('some_expiring_value','plain')).to eql('to_be_expired2')
225
- store.set('some_expiring_value','foo','to_be_expired_foo',{ 'expires' => 0 })
226
- sleep 3
227
- expect(store.get('some_expiring_value','plain')).to eql('to_be_expired2')
228
- expect(store.get('some_expiring_value','foo')).to eql('to_be_expired_foo')
229
- end
230
- end
231
- end
232
-
233
- def default_config
234
- @default_config ||= begin
235
- config_path = [
236
- File.expand_path(base_dir+'/lib/trocla/default_config.yaml'),
237
- File.expand_path(File.dirname($LOADED_FEATURES.grep(/trocla.rb/)[0])+'/trocla/default_config.yaml'),
238
- ].find { |p| File.exist?(p) }
239
- YAML.load(File.read(config_path))
240
- end
241
- end
242
-
243
- def test_config
244
- @test_config ||= default_config.merge({
245
- 'store' => :memory,
246
- })
247
- end
248
-
249
- def test_config_persistent
250
- @test_config_persistent ||= default_config.merge({
251
- 'store_options' => {
252
- 'adapter' => :YAML,
253
- 'adapter_options' => {
254
- :file => trocla_yaml_file
255
- },
256
- },
257
- })
258
- end
259
-
260
- def ssl_test_config
261
- @ssl_config ||= test_config_persistent.merge({
262
- 'encryption' => :ssl,
263
- 'encryption_options' => {
264
- :private_key => data_dir('trocla.key'),
265
- :public_key => data_dir('trocla.pub'),
266
- },
267
- })
268
- end
269
-
270
- def hooks_config
271
- @hooks_config ||= test_config.merge({
272
- 'hooks' => {
273
- 'set' => {
274
- 'set_test_hook' => File.expand_path(File.join(base_dir,'spec/fixtures/set_test_hook.rb'))
275
- },
276
- 'delete' => {
277
- 'delete_test_hook' => File.expand_path(File.join(base_dir,'spec/fixtures/delete_test_hook.rb'))
278
- }
279
- }
280
- })
281
- end
282
-
283
- def base_dir
284
- File.dirname(__FILE__)+'/../'
285
- end
286
-
287
- def data_dir(file = nil)
288
- File.expand_path(File.join(base_dir, 'spec/data', file))
289
- end
290
-
291
- def trocla_yaml_file
292
- data_dir('trocla_store.yaml')
293
- end
294
-
295
- def generate_ssl_keys
296
- require 'openssl'
297
- rsa_key = OpenSSL::PKey::RSA.new(4096)
298
- File.open(data_dir('trocla.key'), 'w') { |f| f.write(rsa_key.to_pem) }
299
- File.open(data_dir('trocla.pub'), 'w') { |f| f.write(rsa_key.public_key.to_pem) }
300
- end
301
-
302
- def remove_ssl_keys
303
- File.unlink(data_dir('trocla.key'))
304
- File.unlink(data_dir('trocla.pub'))
305
- end
306
-
307
- def remove_yaml_store
308
- File.unlink(trocla_yaml_file)
309
- end
310
- class Trocla::Formats::Sleep < Trocla::Formats::Base
311
- def format(plain_password,options={})
312
- sleep options['sleep'] ||= 0
313
- (options['sleep'] + 1 ).times.collect{ plain_password }.join(' ')
314
- end
315
- end
@@ -1,22 +0,0 @@
1
- require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
2
-
3
- describe "Trocla::Encryptions::None" do
4
-
5
- before(:each) do
6
- expect_any_instance_of(Trocla).to receive(:read_config).and_return(test_config_persistent)
7
- @trocla = Trocla.new
8
- end
9
-
10
- after(:each) do
11
- remove_yaml_store
12
- end
13
-
14
- describe "none" do
15
- include_examples 'encryption_basics'
16
-
17
- it "stores plaintext passwords" do
18
- @trocla.set_password('noplain', 'plain', 'plaintext_password')
19
- expect(File.readlines(trocla_yaml_file).grep(/plaintext_password/)).to eq([" plain: plaintext_password\n"])
20
- end
21
- end
22
- end
@@ -1,26 +0,0 @@
1
- require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
2
-
3
- describe "Trocla::Encryptions::Ssl" do
4
-
5
- before(:all) do
6
- generate_ssl_keys
7
- end
8
-
9
- after(:all) do
10
- remove_ssl_keys
11
- end
12
-
13
- before(:each) do
14
- expect_any_instance_of(Trocla).to receive(:read_config).and_return(ssl_test_config)
15
- @trocla = Trocla.new
16
- end
17
-
18
- after(:each) do
19
- remove_yaml_store
20
- end
21
-
22
- describe "encrypt" do
23
- include_examples 'encryption_basics'
24
- include_examples 'verify_encryption'
25
- end
26
- end
@@ -1,25 +0,0 @@
1
- require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
2
-
3
- describe 'Trocla::Format::Pgsql' do
4
- before(:each) do
5
- expect_any_instance_of(Trocla).to receive(:read_config).and_return(test_config)
6
- @trocla = Trocla.new
7
- end
8
-
9
- describe 'default pgsql' do
10
- it 'create a pgsql password keypair without options in sha256' do
11
- pass = @trocla.password('pgsql_password_sh256', 'pgsql', {})
12
- expect(pass).to match(/^SCRAM-SHA-256\$(.*):(.*)\$(.*):/)
13
- end
14
- end
15
-
16
- describe 'pgsql in md5 encode' do
17
- it 'create a pgsql password in md5 encode' do
18
- pass = @trocla.password(
19
- 'pgsql_password_md5', 'pgsql',
20
- { 'username' => 'toto', 'encode' => 'md5' }
21
- )
22
- expect(pass).to match(/^md5/)
23
- end
24
- end
25
- end
@@ -1,52 +0,0 @@
1
- require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
2
-
3
- describe "Trocla::Format::Sshkey" do
4
-
5
- before(:each) do
6
- expect_any_instance_of(Trocla).to receive(:read_config).and_return(test_config)
7
- @trocla = Trocla.new
8
- end
9
-
10
- let(:sshkey_options) do
11
- {
12
- 'type' => 'rsa',
13
- 'bits' => 4096,
14
- 'comment' => 'My ssh key'
15
- }
16
- end
17
-
18
- describe "sshkey" do
19
- it "is able to create an ssh keypair without options" do
20
- sshkey = @trocla.password('my_ssh_keypair', 'sshkey', {})
21
- expect(sshkey).to start_with('-----BEGIN RSA PRIVATE KEY-----')
22
- expect(sshkey).to match(/ssh-/)
23
- end
24
-
25
- it "is able to create an ssh keypair with options" do
26
- sshkey = @trocla.password('my_ssh_keypair', 'sshkey', sshkey_options)
27
- expect(sshkey).to start_with('-----BEGIN RSA PRIVATE KEY-----')
28
- expect(sshkey).to match(/ssh-/)
29
- expect(sshkey).to end_with('My ssh key')
30
- end
31
-
32
- it 'supports fetching only the priv key' do
33
- sshkey = @trocla.password('my_ssh_keypair', 'sshkey', { 'render' => {'privonly' => true }})
34
- expect(sshkey).to start_with('-----BEGIN RSA PRIVATE KEY-----')
35
- expect(sshkey).not_to match(/ssh-/)
36
- end
37
-
38
- it 'supports fetching only the pub key' do
39
- sshkey = @trocla.password('my_ssh_keypair', 'sshkey', { 'render' => {'pubonly' => true }})
40
- expect(sshkey).to start_with('ssh-rsa')
41
- expect(sshkey).not_to match(/-----BEGIN RSA PRIVATE KEY-----/)
42
- end
43
-
44
- it "is able to create an ssh keypair with a passphrase" do
45
- sshkey = @trocla.password('my_ssh_keypair', 'sshkey', { 'passphrase' => 'spec' })
46
- expect(sshkey).to start_with('-----BEGIN RSA PRIVATE KEY-----')
47
- expect(sshkey).to match(/ssh-/)
48
- end
49
-
50
- end
51
-
52
- end