trocla 0.1.2 → 0.2.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.
@@ -0,0 +1,22 @@
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
@@ -20,37 +20,7 @@ describe "Trocla::Encryptions::Ssl" do
20
20
  end
21
21
 
22
22
  describe "encrypt" do
23
- it "should be able to store random passwords" do
24
- @trocla.password('random1', 'plain').length.should eql(12)
25
- end
26
-
27
- it "should be able to store long random passwords" do
28
- @trocla.set_password('random1_long','plain',4096.times.collect{|s| 'x' }.join('')).length.should eql(4096)
29
- end
30
-
31
- it "should be able to retrieve stored random passwords" do
32
- stored = @trocla.password('random1', 'plain')
33
- retrieved = @trocla.password('random1', 'plain')
34
- retrieved_again = @trocla.password('random1', 'plain')
35
- retrieved.should eql(stored)
36
- retrieved_again.should eql(stored)
37
- end
38
-
39
- it "should be able to read encrypted passwords" do
40
- @trocla.set_password('some_pass', 'plain', 'super secret')
41
- @trocla.get_password('some_pass', 'plain').should eql('super secret')
42
- end
43
-
44
- it "should not store plaintext passwords" do
45
- @trocla.set_password('noplain', 'plain', 'plaintext_password')
46
- File.readlines(trocla_yaml_file).grep(/plaintext_password/).should be_empty
47
- end
48
-
49
- it "should make sure identical passwords do not match when stored" do
50
- @trocla.set_password('one_key', 'plain', 'super secret')
51
- @trocla.set_password('another_key', 'plain', 'super secret')
52
- yaml = YAML.load_file(trocla_yaml_file)
53
- yaml['one_key']['plain'].should_not eql(yaml['another_key']['plain'])
54
- end
23
+ include_examples 'encryption_basics'
24
+ include_examples 'verify_encryption'
55
25
  end
56
26
  end
@@ -0,0 +1,295 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
2
+ require 'date'
3
+
4
+ describe "Trocla::Format::X509" do
5
+
6
+ before(:each) do
7
+ expect_any_instance_of(Trocla).to receive(:read_config).and_return(test_config)
8
+ @trocla = Trocla.new
9
+ end
10
+
11
+ let(:ca_options) do
12
+ {
13
+ 'CN' => 'This is my self-signed certificate which doubles as CA',
14
+ 'become_ca' => true,
15
+ }
16
+ end
17
+ let(:cert_options) do
18
+ {
19
+ 'ca' => 'my_shiny_selfsigned_ca',
20
+ 'subject' => '/C=ZZ/O=Trocla Inc./CN=test/emailAddress=example@example.com',
21
+ }
22
+ end
23
+
24
+ def verify(ca,cert)
25
+ store = OpenSSL::X509::Store.new
26
+ store.purpose = OpenSSL::X509::PURPOSE_SSL_CLIENT
27
+ Array(ca).each do |c|
28
+ store.add_cert(c)
29
+ end
30
+ store.verify(cert)
31
+ end
32
+
33
+ describe "x509 selfsigned" do
34
+ it "is able to create self signed cert without being a ca by default" do
35
+ cert_str = @trocla.password('my_shiny_selfsigned_ca', 'x509', {
36
+ 'CN' => 'This is my self-signed certificate',
37
+ 'become_ca' => false,
38
+ })
39
+ cert = OpenSSL::X509::Certificate.new(cert_str)
40
+ # selfsigned?
41
+ expect(cert.issuer.to_s).to eq(cert.subject.to_s)
42
+ # default size
43
+ # https://stackoverflow.com/questions/13747212/determine-key-size-from-public-key-pem-format
44
+ expect(cert.public_key.n.num_bytes * 8).to eq(4096)
45
+ expect((Date.parse(cert.not_after.to_s) - Date.today).to_i).to eq(365)
46
+ # it's a self signed cert and NOT a CA
47
+ expect(verify(cert,cert)).to be false
48
+
49
+ v = cert.extensions.find{|e| e.oid == 'basicConstraints' }.value
50
+ expect(v).to eq('CA:FALSE')
51
+ # we want to include only CNs that look like a DNS name
52
+ expect(cert.extensions.find{|e| e.oid == 'subjectAltName' }).to be_nil
53
+ ku = cert.extensions.find{|e| e.oid == 'keyUsage' }.value
54
+ expect(ku).not_to match(/Certificate Sign/)
55
+ expect(ku).not_to match(/CRL Sign/)
56
+ end
57
+
58
+ it "is able to create a self signed cert that is a CA" do
59
+ ca_str = @trocla.password('my_shiny_selfsigned_ca', 'x509', ca_options)
60
+ ca = OpenSSL::X509::Certificate.new(ca_str)
61
+ # selfsigned?
62
+ expect(ca.issuer.to_s).to eq(ca.subject.to_s)
63
+ expect((Date.parse(ca.not_after.to_s) - Date.today).to_i).to eq(365)
64
+ expect(verify(ca,ca)).to be true
65
+
66
+ v = ca.extensions.find{|e| e.oid == 'basicConstraints' }.value
67
+ expect(v).to eq('CA:TRUE')
68
+ ku = ca.extensions.find{|e| e.oid == 'keyUsage' }.value
69
+ expect(ku).to match(/Certificate Sign/)
70
+ expect(ku).to match(/CRL Sign/)
71
+ end
72
+
73
+ end
74
+ describe "x509 signed by a ca" do
75
+ before(:each) do
76
+ ca_str = @trocla.password('my_shiny_selfsigned_ca', 'x509', ca_options)
77
+ @ca = OpenSSL::X509::Certificate.new(ca_str)
78
+ end
79
+ it 'is able to get a cert signed by the ca' do
80
+ cert_str = @trocla.password('mycert', 'x509', cert_options)
81
+ cert = OpenSSL::X509::Certificate.new(cert_str)
82
+ expect(cert.issuer.to_s).to eq(@ca.subject.to_s)
83
+ expect((Date.parse(cert.not_after.to_s) - Date.today).to_i).to eq(365)
84
+ expect(verify(@ca,cert)).to be true
85
+
86
+ v = cert.extensions.find{|e| e.oid == 'basicConstraints' }.value
87
+ expect(v).to eq('CA:FALSE')
88
+ ku = cert.extensions.find{|e| e.oid == 'keyUsage' }.value
89
+ expect(ku).not_to match(/Certificate Sign/)
90
+ expect(ku).not_to match(/CRL Sign/)
91
+ end
92
+
93
+ it 'does not simply increment the serial' do
94
+ cert_str = @trocla.password('mycert', 'x509', cert_options)
95
+ cert1 = OpenSSL::X509::Certificate.new(cert_str)
96
+ cert_str = @trocla.password('mycert2', 'x509', cert_options)
97
+ cert2 = OpenSSL::X509::Certificate.new(cert_str)
98
+
99
+ expect(cert1.serial.to_i).not_to eq(1)
100
+ expect(cert2.serial.to_i).not_to eq(2)
101
+ expect((cert2.serial - cert1.serial).to_i).not_to eq(1)
102
+ end
103
+
104
+ it 'is able to get a cert signed by the ca that is again a ca' do
105
+ cert_str = @trocla.password('mycert', 'x509', cert_options.merge({
106
+ 'become_ca' => true,
107
+ }))
108
+ cert = OpenSSL::X509::Certificate.new(cert_str)
109
+ expect(cert.issuer.to_s).to eq(@ca.subject.to_s)
110
+ expect((Date.parse(cert.not_after.to_s) - Date.today).to_i).to eq(365)
111
+ expect(verify(@ca,cert)).to be true
112
+
113
+ expect(cert.extensions.find{|e| e.oid == 'basicConstraints' }.value).to eq('CA:TRUE')
114
+ ku = cert.extensions.find{|e| e.oid == 'keyUsage' }.value
115
+ expect(ku).to match(/Certificate Sign/)
116
+ expect(ku).to match(/CRL Sign/)
117
+ end
118
+
119
+ it 'supports simple name constraints for CAs' do
120
+ ca2_str = @trocla.password('mycert_with_nc', 'x509', cert_options.merge({
121
+ 'name_constraints' => ['example.com','bla.example.net'],
122
+ 'become_ca' => true,
123
+ }))
124
+ ca2 = OpenSSL::X509::Certificate.new(ca2_str)
125
+ expect(ca2.issuer.to_s).to eq(@ca.subject.to_s)
126
+ expect((Date.parse(ca2.not_after.to_s) - Date.today).to_i).to eq(365)
127
+ pending_for(:engine => 'jruby',:reason => 'NameConstraints verification seem to be broken in jRuby: https://github.com/jruby/jruby/issues/3502') do
128
+ expect(verify(@ca,ca2)).to be true
129
+ end
130
+
131
+ expect(ca2.extensions.find{|e| e.oid == 'basicConstraints' }.value).to eq('CA:TRUE')
132
+ ku = ca2.extensions.find{|e| e.oid == 'keyUsage' }.value
133
+ expect(ku).to match(/Certificate Sign/)
134
+ expect(ku).to match(/CRL Sign/)
135
+ nc = ca2.extensions.find{|e| e.oid == 'nameConstraints' }.value
136
+ pending_for(:engine => 'jruby',:reason => 'NameConstraints verification seem to be broken in jRuby: https://github.com/jruby/jruby/issues/3502') do
137
+ expect(nc).to match(/Permitted:\n DNS:example.com\n DNS:bla.example.net/)
138
+ end
139
+ valid_cert_str = @trocla.password('myvalidexamplecert','x509', {
140
+ 'subject' => '/C=ZZ/O=Trocla Inc./CN=foo.example.com/emailAddress=example@example.com',
141
+ 'ca' => 'mycert_with_nc'
142
+ })
143
+ valid_cert = OpenSSL::X509::Certificate.new(valid_cert_str)
144
+ expect(valid_cert.issuer.to_s).to eq(ca2.subject.to_s)
145
+ expect(verify([@ca,ca2],valid_cert)).to be true
146
+ expect((Date.parse(valid_cert.not_after.to_s) - Date.today).to_i).to eq(365)
147
+
148
+ false_cert_str = @trocla.password('myfalseexamplecert','x509', {
149
+ 'subject' => '/C=ZZ/O=Trocla Inc./CN=foo.example.net/emailAddress=example@example.com',
150
+ 'ca' => 'mycert_with_nc'
151
+ })
152
+
153
+ false_cert = OpenSSL::X509::Certificate.new(false_cert_str)
154
+ expect(false_cert.issuer.to_s).to eq(ca2.subject.to_s)
155
+ expect(verify([@ca,ca2],false_cert)).to be false
156
+ expect((Date.parse(false_cert.not_after.to_s) - Date.today).to_i).to eq(365)
157
+ end
158
+
159
+ it 'supports simple name constraints for CAs with leading dots' do
160
+ ca2_str = @trocla.password('mycert_with_nc', 'x509', cert_options.merge({
161
+ 'name_constraints' => ['.example.com','.bla.example.net'],
162
+ 'become_ca' => true,
163
+ }))
164
+ ca2 = OpenSSL::X509::Certificate.new(ca2_str)
165
+ expect(ca2.issuer.to_s).to eq(@ca.subject.to_s)
166
+ expect((Date.parse(ca2.not_after.to_s) - Date.today).to_i).to eq(365)
167
+ pending_for(:engine => 'jruby',:reason => 'NameConstraints verification seem to be broken in jRuby: https://github.com/jruby/jruby/issues/3502') do
168
+ expect(verify(@ca,ca2)).to be true
169
+ end
170
+
171
+ expect(ca2.extensions.find{|e| e.oid == 'basicConstraints' }.value).to eq('CA:TRUE')
172
+ ku = ca2.extensions.find{|e| e.oid == 'keyUsage' }.value
173
+ expect(ku).to match(/Certificate Sign/)
174
+ expect(ku).to match(/CRL Sign/)
175
+ nc = ca2.extensions.find{|e| e.oid == 'nameConstraints' }.value
176
+ expect(nc).to match(/Permitted:\n DNS:.example.com\n DNS:.bla.example.net/)
177
+ valid_cert_str = @trocla.password('myvalidexamplecert','x509', {
178
+ 'subject' => '/C=ZZ/O=Trocla Inc./CN=foo.example.com/emailAddress=example@example.com',
179
+ 'ca' => 'mycert_with_nc'
180
+ })
181
+ valid_cert = OpenSSL::X509::Certificate.new(valid_cert_str)
182
+ expect(valid_cert.issuer.to_s).to eq(ca2.subject.to_s)
183
+ expect((Date.parse(valid_cert.not_after.to_s) - Date.today).to_i).to eq(365)
184
+ # workaround broken openssl
185
+ if %x{openssl version} =~ /1\.0\.[2-9]/
186
+ expect(verify([@ca,ca2],valid_cert)).to be true
187
+ else
188
+ skip_for(:engine => 'ruby',:reason => 'NameConstraints verification is broken on older openssl versions https://rt.openssl.org/Ticket/Display.html?id=3562') do
189
+ expect(verify([@ca,ca2],valid_cert)).to be true
190
+ end
191
+ end
192
+
193
+ false_cert_str = @trocla.password('myfalseexamplecert','x509', {
194
+ 'subject' => '/C=ZZ/O=Trocla Inc./CN=foo.example.net/emailAddress=example@example.com',
195
+ 'ca' => 'mycert_with_nc'
196
+ })
197
+ false_cert = OpenSSL::X509::Certificate.new(false_cert_str)
198
+ expect(false_cert.issuer.to_s).to eq(ca2.subject.to_s)
199
+ expect((Date.parse(false_cert.not_after.to_s) - Date.today).to_i).to eq(365)
200
+ expect(verify([@ca,ca2],false_cert)).to be false
201
+ end
202
+
203
+ it 'is able to get a cert signed by the ca that is again a ca that is able to sign certs' do
204
+ ca2_str = @trocla.password('mycert_and_ca', 'x509', cert_options.merge({
205
+ 'become_ca' => true,
206
+ }))
207
+ ca2 = OpenSSL::X509::Certificate.new(ca2_str)
208
+ expect(ca2.issuer.to_s).to eq(@ca.subject.to_s)
209
+ expect((Date.parse(ca2.not_after.to_s) - Date.today).to_i).to eq(365)
210
+ expect(verify(@ca,ca2)).to be true
211
+
212
+ cert2_str = @trocla.password('mycert', 'x509', {
213
+ 'ca' => 'mycert_and_ca',
214
+ 'subject' => '/C=ZZ/O=Trocla Inc./CN=test2/emailAddress=example@example.com',
215
+ 'become_ca' => true,
216
+ })
217
+ cert2 = OpenSSL::X509::Certificate.new(cert2_str)
218
+ expect(cert2.issuer.to_s).to eq(ca2.subject.to_s)
219
+ expect((Date.parse(cert2.not_after.to_s) - Date.today).to_i).to eq(365)
220
+ skip_for(:engine => 'jruby',:reason => 'Chained CA validation seems to be broken on jruby atm.') do
221
+ expect(verify([@ca,ca2],cert2)).to be true
222
+ end
223
+ end
224
+
225
+ it 'respects all options' do
226
+ co = cert_options.merge({
227
+ 'hash' => 'sha1',
228
+ 'keysize' => 2048,
229
+ 'days' => 3650,
230
+ 'subject' => nil,
231
+ 'C' => 'AA',
232
+ 'ST' => 'Earth',
233
+ 'L' => 'Here',
234
+ 'O' => 'SSLTrocla',
235
+ 'OU' => 'root',
236
+ 'CN' => 'www.test',
237
+ 'emailAddress' => 'test@example.com',
238
+ 'altnames' => [ 'test', 'test1', 'test2', 'test3' ],
239
+ })
240
+ cert_str = @trocla.password('mycert', 'x509', co)
241
+ cert = OpenSSL::X509::Certificate.new(cert_str)
242
+ expect(cert.issuer.to_s).to eq(@ca.subject.to_s)
243
+ ['C','ST','L','O','OU','CN'].each do |field|
244
+ expect(cert.subject.to_s).to match(/#{field}=#{co[field]}/)
245
+ end
246
+ expect(cert.subject.to_s).to match(/(Email|emailAddress)=#{co['emailAddress']}/)
247
+ hash_match = (defined?(RUBY_ENGINE) &&RUBY_ENGINE == 'jruby') ? 'RSA-SHA1' : 'sha1WithRSAEncryption'
248
+ expect(cert.signature_algorithm).to eq(hash_match)
249
+ expect(cert.not_before).to be < Time.now
250
+ expect((Date.parse(cert.not_after.to_s) - Date.today).to_i).to eq(3650)
251
+ # https://stackoverflow.com/questions/13747212/determine-key-size-from-public-key-pem-format
252
+ expect(cert.public_key.n.num_bytes * 8).to eq(2048)
253
+ expect(verify(@ca,cert)).to be true
254
+ expect(cert.extensions.find{|e| e.oid == 'subjectAltName' }.value).to eq('DNS:www.test, DNS:test, DNS:test1, DNS:test2, DNS:test3')
255
+
256
+ expect(cert.extensions.find{|e| e.oid == 'basicConstraints' }.value).to eq('CA:FALSE')
257
+ ku = cert.extensions.find{|e| e.oid == 'keyUsage' }.value
258
+ expect(ku).not_to match(/Certificate Sign/)
259
+ expect(ku).not_to match(/CRL Sign/)
260
+ end
261
+
262
+ it 'shold not add subject alt name on empty array' do
263
+ co = cert_options.merge({
264
+ 'CN' => 'www.test',
265
+ 'altnames' => []
266
+ })
267
+ cert_str = @trocla.password('mycert', 'x509', co)
268
+ cert = OpenSSL::X509::Certificate.new(cert_str)
269
+ expect(cert.issuer.to_s).to eq(@ca.subject.to_s)
270
+ expect((Date.parse(cert.not_after.to_s) - Date.today).to_i).to eq(365)
271
+ expect(verify(@ca,cert)).to be true
272
+ expect(cert.extensions.find{|e| e.oid == 'subjectAltName' }).to be_nil
273
+ end
274
+
275
+ it 'prefers full subject of single subject parts' do
276
+ co = cert_options.merge({
277
+ 'C' => 'AA',
278
+ 'ST' => 'Earth',
279
+ 'L' => 'Here',
280
+ 'O' => 'SSLTrocla',
281
+ 'OU' => 'root',
282
+ 'CN' => 'www.test',
283
+ 'emailAddress' => 'test@example.net',
284
+ })
285
+ cert_str = @trocla.password('mycert', 'x509', co)
286
+ cert = OpenSSL::X509::Certificate.new(cert_str)
287
+ ['C','ST','L','O','OU','CN'].each do |field|
288
+ expect(cert.subject.to_s).not_to match(/#{field}=#{co[field]}/)
289
+ end
290
+ expect(cert.subject.to_s).not_to match(/(Email|emailAddress)=#{co['emailAddress']}/)
291
+ expect((Date.parse(cert.not_after.to_s) - Date.today).to_i).to eq(365)
292
+ expect(verify(@ca,cert)).to be true
293
+ end
294
+ end
295
+ end
@@ -0,0 +1,6 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
2
+
3
+ require 'trocla/stores/memory'
4
+ describe Trocla::Stores::Memory do
5
+ include_examples 'store_validation', Trocla::Stores::Memory.new({},nil)
6
+ end
@@ -0,0 +1,6 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
2
+
3
+ require 'trocla/stores/moneta'
4
+ describe Trocla::Stores::Moneta do
5
+ include_examples 'store_validation', Trocla::Stores::Moneta.new({'adapter' => :Memory},{:expires => true})
6
+ end
@@ -4,31 +4,43 @@ describe "Trocla::Util" do
4
4
 
5
5
  { :random_str => 12, :salt => 8 }.each do |m,length|
6
6
  describe m do
7
- it "should be random" do
8
- Trocla::Util.send(m).should_not eql(Trocla::Util.send(m))
7
+ it "is random" do
8
+ expect(Trocla::Util.send(m)).not_to eq(Trocla::Util.send(m))
9
9
  end
10
10
 
11
- it "should default to length #{length}" do
12
- Trocla::Util.send(m).length.should == length
11
+ it "defaults to length #{length}" do
12
+ expect(Trocla::Util.send(m).length).to eq(length)
13
13
  end
14
14
 
15
- it "should be possible to change length" do
16
- Trocla::Util.send(m,8).length.should == 8
17
- Trocla::Util.send(m,32).length.should == 32
18
- Trocla::Util.send(m,1).length.should == 1
15
+ it "is possible to change length" do
16
+ expect(Trocla::Util.send(m,8).length).to eq(8)
17
+ expect(Trocla::Util.send(m,32).length).to eq(32)
18
+ expect(Trocla::Util.send(m,1).length).to eq(1)
19
19
  end
20
20
  end
21
21
  end
22
22
 
23
23
  describe :numeric_generator do
24
- it "should create random numeric password" do
25
- Trocla::Util.send(:random_str, 12, 'numeric' ).should =~ /^[0-9]{12}$/
24
+ 10.times.each do |i|
25
+ it "creates random numeric password #{i}" do
26
+ expect(Trocla::Util.random_str(12, 'numeric')).to match(/^[0-9]{12}$/)
27
+ end
28
+ end
29
+ end
30
+
31
+ describe :hexadecimal_generator do
32
+ 10.times.each do |i|
33
+ it "creates random hexadecimal password #{i}" do
34
+ expect(Trocla::Util.random_str(12, 'hexadecimal')).to match(/^[0-9a-f]{12}$/)
35
+ end
26
36
  end
27
37
  end
28
38
 
29
39
  describe :salt do
30
- it "should only contain characters and numbers" do
31
- Trocla::Util.salt =~ /^[a-z0-9]+$/i
40
+ 10.times.each do |i|
41
+ it "contains only characters and numbers #{i}" do
42
+ expect(Trocla::Util.salt).to match(/^[a-z0-9]+$/i)
43
+ end
32
44
  end
33
45
  end
34
46
  end
data/spec/trocla_spec.rb CHANGED
@@ -1,128 +1,161 @@
1
1
  require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
2
 
3
3
  describe "Trocla" do
4
-
4
+
5
5
  before(:each) do
6
6
  expect_any_instance_of(Trocla).to receive(:read_config).and_return(test_config)
7
7
  @trocla = Trocla.new
8
8
  end
9
-
9
+
10
10
  describe "password" do
11
- it "should generate random passwords by default" do
12
- @trocla.password('random1','plain').should_not eql(@trocla.password('random2','plain'))
11
+ it "generates random passwords by default" do
12
+ expect(@trocla.password('random1','plain')).not_to eq(@trocla.password('random2','plain'))
13
13
  end
14
14
 
15
- it "should generate passwords of length #{default_config['options']['length']}" do
16
- @trocla.password('random1','plain').length.should eql(default_config['options']['length'])
15
+ it "generates passwords of length #{default_config['options']['length']}" do
16
+ expect(@trocla.password('random1','plain').length).to eq(default_config['options']['length'])
17
17
  end
18
-
18
+
19
19
  Trocla::Formats.all.each do |format|
20
20
  describe "#{format} password format" do
21
- it "should return a password hashed in the #{format} format" do
22
- @trocla.password('some_test',format,format_options[format]).should_not be_empty
21
+ it "retursn a password hashed in the #{format} format" do
22
+ expect(@trocla.password('some_test',format,format_options[format])).not_to be_empty
23
23
  end
24
-
25
- it "should return the same hashed for the #{format} format on multiple invocations" do
26
- (round1=@trocla.password('some_test',format,format_options[format])).should_not be_empty
27
- @trocla.password('some_test',format,format_options[format]).should eql(round1)
24
+
25
+ it "returns the same hashed for the #{format} format on multiple invocations" do
26
+ expect(round1=@trocla.password('some_test',format,format_options[format])).not_to be_empty
27
+ expect(@trocla.password('some_test',format,format_options[format])).to eq(round1)
28
28
  end
29
-
30
- it "should also store the plain password by default" do
29
+
30
+ it "also stores the plain password by default" do
31
31
  pwd = @trocla.password('some_test','plain')
32
- pwd.should_not be_empty
33
- pwd.length.should eql(12)
32
+ expect(pwd).not_to be_empty
33
+ expect(pwd.length).to eq(16)
34
34
  end
35
35
  end
36
36
  end
37
-
37
+
38
38
  Trocla::Formats.all.reject{|f| f == 'plain' }.each do |format|
39
- it "should raise an exception if not a random password is asked but plain password is not present for format #{format}" do
40
- lambda{ @trocla.password('not_random',format, 'random' => false) }.should raise_error
39
+ it "raises an exception if not a random password is asked but plain password is not present for format #{format}" do
40
+ expect{@trocla.password('not_random',format, 'random' => false)}.to raise_error(/Password must be present as plaintext/)
41
+ end
42
+ end
43
+
44
+ describe 'with profiles' do
45
+ it 'raises an exception on unknown profile' do
46
+ expect{@trocla.password('no profile known','plain',
47
+ 'profiles' => 'unknown_profile') }.to raise_error(/No such profile unknown_profile defined/)
48
+ end
49
+
50
+ it 'takes a profile and merge its options' do
51
+ pwd = @trocla.password('some_test','plain', 'profiles' => 'rootpw')
52
+ expect(pwd).not_to be_empty
53
+ expect(pwd.length).to eq(32)
54
+ expect(pwd).to_not match(/[={}\[\]\?%\*()&!]+/)
55
+ end
56
+
57
+ it 'is possible to combine profiles but first profile wins' do
58
+ pwd = @trocla.password('some_test','plain', 'profiles' => ['rootpw','login'])
59
+ expect(pwd).not_to be_empty
60
+ expect(pwd.length).to eq(32)
61
+ expect(pwd).not_to match(/[={}\[\]\?%\*()&!]+/)
62
+ end
63
+ it 'is possible to combine profiles but first profile wins 2' do
64
+ pwd = @trocla.password('some_test','plain', 'profiles' => ['login','mysql'])
65
+ expect(pwd).not_to be_empty
66
+ expect(pwd.length).to eq(16)
67
+ expect(pwd).not_to match(/[={}\[\]\?%\*()&!]+/)
68
+ end
69
+ it 'is possible to combine profiles but first profile wins 3' do
70
+ pwd = @trocla.password('some_test','plain', 'profiles' => ['mysql','login'])
71
+ expect(pwd).not_to be_empty
72
+ expect(pwd.length).to eq(32)
73
+ expect(pwd).to match(/[+%\/@=\?_.,:]+/)
41
74
  end
42
75
  end
43
76
  end
44
-
77
+
45
78
  describe "set_password" do
46
- it "should reset hashed passwords on a new plain password" do
47
- @trocla.password('set_test','mysql').should_not be_empty
48
- @trocla.get_password('set_test','mysql').should_not be_nil
49
- (old_plain=@trocla.password('set_test','mysql')).should_not be_empty
50
-
51
- @trocla.set_password('set_test','plain','foobar').should_not eql(old_plain)
52
- @trocla.get_password('set_test','mysql').should be_nil
79
+ it "resets hashed passwords on a new plain password" do
80
+ expect(@trocla.password('set_test','mysql')).not_to be_empty
81
+ expect(@trocla.get_password('set_test','mysql')).not_to be_nil
82
+ expect(old_plain=@trocla.password('set_test','mysql')).not_to be_empty
83
+
84
+ expect(@trocla.set_password('set_test','plain','foobar')).not_to eq(old_plain)
85
+ expect(@trocla.get_password('set_test','mysql')).to be_nil
53
86
  end
54
-
55
- it "should otherwise only update the hash" do
56
- (mysql = @trocla.password('set_test2','mysql')).should_not be_empty
57
- (md5crypt = @trocla.password('set_test2','md5crypt')).should_not be_empty
58
- (plain = @trocla.get_password('set_test2','plain')).should_not be_empty
59
-
60
- (new_mysql = @trocla.set_password('set_test2','mysql','foo')).should_not eql(mysql)
61
- @trocla.get_password('set_test2','mysql').should eql(new_mysql)
62
- @trocla.get_password('set_test2','md5crypt').should eql(md5crypt)
63
- @trocla.get_password('set_test2','plain').should eql(plain)
87
+
88
+ it "otherwise updates only the hash" do
89
+ expect(mysql = @trocla.password('set_test2','mysql')).not_to be_empty
90
+ expect(md5crypt = @trocla.password('set_test2','md5crypt')).not_to be_empty
91
+ expect(plain = @trocla.get_password('set_test2','plain')).not_to be_empty
92
+
93
+ expect(new_mysql = @trocla.set_password('set_test2','mysql','foo')).not_to eql(mysql)
94
+ expect(@trocla.get_password('set_test2','mysql')).to eq(new_mysql)
95
+ expect(@trocla.get_password('set_test2','md5crypt')).to eq(md5crypt)
96
+ expect(@trocla.get_password('set_test2','plain')).to eq(plain)
64
97
  end
65
98
  end
66
-
99
+
67
100
  describe "reset_password" do
68
- it "should reset a password" do
101
+ it "resets a password" do
69
102
  plain1 = @trocla.password('reset_pwd','plain')
70
103
  plain2 = @trocla.reset_password('reset_pwd','plain')
71
-
72
- plain1.should_not eql(plain2)
104
+
105
+ expect(plain1).not_to eq(plain2)
73
106
  end
74
-
75
- it "should not reset other formats" do
76
- (mysql = @trocla.password('reset_pwd2','mysql')).should_not be_empty
77
- (md5crypt1 = @trocla.password('reset_pwd2','md5crypt')).should_not be_empty
78
-
79
- (md5crypt2 = @trocla.reset_password('reset_pwd2','md5crypt')).should_not be_empty
80
- md5crypt2.should_not eql(md5crypt1)
81
-
82
- @trocla.get_password('reset_pwd2','mysql').should eql(mysql)
107
+
108
+ it "does not reset other formats" do
109
+ expect(mysql = @trocla.password('reset_pwd2','mysql')).not_to be_empty
110
+ expect(md5crypt1 = @trocla.password('reset_pwd2','md5crypt')).not_to be_empty
111
+
112
+ expect(md5crypt2 = @trocla.reset_password('reset_pwd2','md5crypt')).not_to be_empty
113
+ expect(md5crypt2).not_to eq(md5crypt1)
114
+
115
+ expect(@trocla.get_password('reset_pwd2','mysql')).to eq(mysql)
83
116
  end
84
117
  end
85
-
118
+
86
119
  describe "delete_password" do
87
- it "should delete all passwords if no format is given" do
88
- @trocla.password('delete_test1','mysql').should_not be_nil
89
- @trocla.get_password('delete_test1','plain').should_not be_nil
90
-
120
+ it "deletes all passwords if no format is given" do
121
+ expect(@trocla.password('delete_test1','mysql')).not_to be_nil
122
+ expect(@trocla.get_password('delete_test1','plain')).not_to be_nil
123
+
91
124
  @trocla.delete_password('delete_test1')
92
- @trocla.get_password('delete_test1','plain').should be_nil
93
- @trocla.get_password('delete_test1','mysql').should be_nil
125
+ expect(@trocla.get_password('delete_test1','plain')).to be_nil
126
+ expect(@trocla.get_password('delete_test1','mysql')).to be_nil
94
127
  end
95
-
96
- it "should delete only a given format" do
97
- @trocla.password('delete_test2','mysql').should_not be_nil
98
- @trocla.get_password('delete_test2','plain').should_not be_nil
99
-
128
+
129
+ it "deletes only a given format" do
130
+ expect(@trocla.password('delete_test2','mysql')).not_to be_nil
131
+ expect(@trocla.get_password('delete_test2','plain')).not_to be_nil
132
+
100
133
  @trocla.delete_password('delete_test2','plain')
101
- @trocla.get_password('delete_test2','plain').should be_nil
102
- @trocla.get_password('delete_test2','mysql').should_not be_nil
134
+ expect(@trocla.get_password('delete_test2','plain')).to be_nil
135
+ expect(@trocla.get_password('delete_test2','mysql')).not_to be_nil
103
136
  end
104
-
105
- it "should delete only a given non-plain format" do
106
- @trocla.password('delete_test3','mysql').should_not be_nil
107
- @trocla.get_password('delete_test3','plain').should_not be_nil
108
-
137
+
138
+ it "deletes only a given non-plain format" do
139
+ expect(@trocla.password('delete_test3','mysql')).not_to be_nil
140
+ expect(@trocla.get_password('delete_test3','plain')).not_to be_nil
141
+
109
142
  @trocla.delete_password('delete_test3','mysql')
110
- @trocla.get_password('delete_test3','mysql').should be_nil
111
- @trocla.get_password('delete_test3','plain').should_not be_nil
143
+ expect(@trocla.get_password('delete_test3','mysql')).to be_nil
144
+ expect(@trocla.get_password('delete_test3','plain')).not_to be_nil
112
145
  end
113
146
  end
114
-
147
+
115
148
  def format_options
116
149
  @format_options ||= Hash.new({}).merge({
117
150
  'pgsql' => { 'username' => 'test' },
118
151
  'x509' => { 'CN' => 'test' },
119
152
  })
120
153
  end
121
-
154
+
122
155
  end
123
156
 
124
157
  describe "VERSION" do
125
- it "should return a version" do
126
- Trocla::VERSION::STRING.should_not be_empty
158
+ it "returns a version" do
159
+ expect(Trocla::VERSION::STRING).not_to be_empty
127
160
  end
128
161
  end