trocla 0.1.2 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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