trocla 0.5.1 → 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/trocla_spec.rb DELETED
@@ -1,291 +0,0 @@
1
- # -- encoding : utf-8 --
2
- require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
3
-
4
- describe "Trocla" do
5
-
6
- before(:each) do
7
- expect_any_instance_of(Trocla).to receive(:read_config).and_return(test_config)
8
- end
9
- context 'in normal usage with' do
10
- before(:each) do
11
- @trocla = Trocla.new
12
- @trocla.password('init','plain')
13
- end
14
-
15
- describe "password" do
16
- it "generates random passwords by default" do
17
- expect(@trocla.password('random1','plain')).not_to eq(@trocla.password('random2','plain'))
18
- end
19
-
20
- it "generates passwords of length #{default_config['options']['length']}" do
21
- expect(@trocla.password('random1','plain').length).to eq(default_config['options']['length'])
22
- end
23
-
24
- Trocla::Formats.all.each do |format|
25
- describe "#{format} password format" do
26
- it "retursn a password hashed in the #{format} format" do
27
- expect(@trocla.password('some_test',format,format_options[format])).not_to be_empty
28
- end
29
-
30
- it "returns the same hashed for the #{format} format on multiple invocations" do
31
- expect(round1=@trocla.password('some_test',format,format_options[format])).not_to be_empty
32
- expect(@trocla.password('some_test',format,format_options[format])).to eq(round1)
33
- end
34
-
35
- it "also stores the plain password by default" do
36
- pwd = @trocla.password('some_test','plain')
37
- expect(pwd).not_to be_empty
38
- expect(pwd.length).to eq(16)
39
- end
40
- end
41
- end
42
-
43
- Trocla::Formats.all.reject{|f| f == 'plain' }.each do |format|
44
- it "raises an exception if not a random password is asked but plain password is not present for format #{format}" do
45
- expect{@trocla.password('not_random',format, 'random' => false)}.to raise_error(/Password must be present as plaintext/)
46
- end
47
- end
48
-
49
- describe 'with profiles' do
50
- it 'raises an exception on unknown profile' do
51
- expect{@trocla.password('no profile known','plain',
52
- 'profiles' => 'unknown_profile') }.to raise_error(/No such profile unknown_profile defined/)
53
- end
54
-
55
- it 'takes a profile and merge its options' do
56
- pwd = @trocla.password('some_test','plain', 'profiles' => 'rootpw')
57
- expect(pwd).not_to be_empty
58
- expect(pwd.length).to eq(32)
59
- expect(pwd).to_not match(/[={}\[\]\?%\*()&!]+/)
60
- end
61
-
62
- it 'is possible to combine profiles but first profile wins' do
63
- pwd = @trocla.password('some_test1','plain', 'profiles' => ['rootpw','login'])
64
- expect(pwd).not_to be_empty
65
- expect(pwd.length).to eq(32)
66
- expect(pwd).not_to match(/[={}\[\]\?%\*()&!]+/)
67
- end
68
- it 'is possible to combine profiles but first profile wins 2' do
69
- pwd = @trocla.password('some_test2','plain', 'profiles' => ['login','mysql'])
70
- expect(pwd).not_to be_empty
71
- expect(pwd.length).to eq(16)
72
- expect(pwd).not_to match(/[={}\[\]\?%\*()&!]+/)
73
- end
74
- it 'is possible to combine profiles but first profile wins 3' do
75
- # mysql profile uses a 32 long random pwd with shell safe characters
76
- # and we want to use a fixed random str here https://github.com/duritong/trocla/issues/55
77
- allow(Trocla::Util).to receive(:random_str).with(32,'shellsafe') { "jmNi6+7dsUn@H?vfbXCq=ULEGPW,u:hu" }
78
- pwd = @trocla.password('some_test3','plain', 'profiles' => ['mysql','login'])
79
- expect(pwd).not_to be_empty
80
- expect(pwd.length).to eq(32)
81
- expect(pwd).to match(/[+%\/@=\?_.,:]+/)
82
- end
83
- end
84
- end
85
-
86
- describe "set_password" do
87
- it "resets hashed passwords on a new plain password" do
88
- expect(@trocla.password('set_test','mysql')).not_to be_empty
89
- expect(@trocla.get_password('set_test','mysql')).not_to be_nil
90
- expect(old_plain=@trocla.password('set_test','mysql')).not_to be_empty
91
-
92
- expect(@trocla.set_password('set_test','plain','foobar')).not_to eq(old_plain)
93
- expect(@trocla.get_password('set_test','mysql')).to be_nil
94
- end
95
-
96
- it "otherwise updates only the hash" do
97
- expect(mysql = @trocla.password('set_test2','mysql')).not_to be_empty
98
- expect(md5crypt = @trocla.password('set_test2','md5crypt')).not_to be_empty
99
- expect(plain = @trocla.get_password('set_test2','plain')).not_to be_empty
100
-
101
- expect(new_mysql = @trocla.set_password('set_test2','mysql','foo')).not_to eql(mysql)
102
- expect(@trocla.get_password('set_test2','mysql')).to eq(new_mysql)
103
- expect(@trocla.get_password('set_test2','md5crypt')).to eq(md5crypt)
104
- expect(@trocla.get_password('set_test2','plain')).to eq(plain)
105
- end
106
-
107
- it 'is able to set password with umlauts and other UTF-8 charcters' do
108
- expect(myumlaut = @trocla.set_password('set_test_umlaut','plain','Tütü')).to eql('Tütü')
109
- expect(@trocla.get_password('set_test_umlaut','plain','Tütü')).to eql('Tütü')
110
- end
111
- end
112
-
113
- describe "reset_password" do
114
- it "resets a password" do
115
- plain1 = @trocla.password('reset_pwd','plain')
116
- plain2 = @trocla.reset_password('reset_pwd','plain')
117
-
118
- expect(plain1).not_to eq(plain2)
119
- end
120
-
121
- it "does not reset other formats" do
122
- expect(mysql = @trocla.password('reset_pwd2','mysql')).not_to be_empty
123
- expect(md5crypt1 = @trocla.password('reset_pwd2','md5crypt')).not_to be_empty
124
-
125
- expect(md5crypt2 = @trocla.reset_password('reset_pwd2','md5crypt')).not_to be_empty
126
- expect(md5crypt2).not_to eq(md5crypt1)
127
-
128
- expect(@trocla.get_password('reset_pwd2','mysql')).to eq(mysql)
129
- end
130
- end
131
-
132
- describe "search_key" do
133
- it "search a specific key" do
134
- keys = ['search_key','search_key1','key_search','key_search2']
135
- keys.each do |k|
136
- @trocla.password(k,'plain')
137
- end
138
- expect(@trocla.search_key('search_key1').length).to eq(1)
139
- end
140
- it "ensure search regex is ok" do
141
- keys = ['search_key2','search_key3','key_search2','key_search4']
142
- keys.each do |k|
143
- @trocla.password(k,'plain')
144
- end
145
- expect(@trocla.search_key('key').length).to eq(4)
146
- expect(@trocla.search_key('^search').length).to eq(2)
147
- expect(@trocla.search_key('ch.*3').length).to eq(1)
148
- expect(@trocla.search_key('ch.*[3-4]$').length).to eq(2)
149
- expect(@trocla.search_key('ch.*1')).to be_nil
150
- end
151
- end
152
-
153
- describe "list_format" do
154
- it "list available formats for key" do
155
- formats = ['plain','mysql']
156
- formats.each do |f|
157
- @trocla.password('list_key',f)
158
- end
159
- expect(@trocla.available_format('list_key')).to eq(formats)
160
- end
161
- it "no return if key doesn't exist" do
162
- expect(@trocla.available_format('list_key1')).to be_nil
163
- end
164
- end
165
-
166
- describe "delete_password" do
167
- it "deletes all passwords if no format is given" do
168
- expect(@trocla.password('delete_test1','mysql')).not_to be_nil
169
- expect(@trocla.get_password('delete_test1','plain')).not_to be_nil
170
-
171
- @trocla.delete_password('delete_test1')
172
- expect(@trocla.get_password('delete_test1','plain')).to be_nil
173
- expect(@trocla.get_password('delete_test1','mysql')).to be_nil
174
- end
175
-
176
- it "deletes only a given format" do
177
- expect(@trocla.password('delete_test2','mysql')).not_to be_nil
178
- expect(@trocla.get_password('delete_test2','plain')).not_to be_nil
179
-
180
- @trocla.delete_password('delete_test2','plain')
181
- expect(@trocla.get_password('delete_test2','plain')).to be_nil
182
- expect(@trocla.get_password('delete_test2','mysql')).not_to be_nil
183
- end
184
-
185
- it "deletes only a given non-plain format" do
186
- expect(@trocla.password('delete_test3','mysql')).not_to be_nil
187
- expect(@trocla.get_password('delete_test3','plain')).not_to be_nil
188
-
189
- @trocla.delete_password('delete_test3','mysql')
190
- expect(@trocla.get_password('delete_test3','mysql')).to be_nil
191
- expect(@trocla.get_password('delete_test3','plain')).not_to be_nil
192
- end
193
- end
194
-
195
- context 'concurrent access' do
196
- context 'on expensive flagged formats' do
197
- before(:each) do
198
- expect(Trocla::Formats).to receive(:[]).with('sleep').at_least(:once).and_return(Trocla::Formats::Sleep)
199
- expect(Trocla::Formats::Sleep).to receive(:expensive?).at_least(:once).and_return(true)
200
- expect(Trocla::Formats).to receive(:available?).with('sleep').at_least(:once).and_return(true)
201
- end
202
- it 'should not overwrite a value if it takes longer' do
203
- t1 = Thread.new{ @trocla.password('threadpwd','sleep','sleep' => 4) }
204
- t2 = Thread.new{ @trocla.password('threadpwd','sleep','sleep' => 1) }
205
- pwd1 = t1.value
206
- pwd2 = t2.value
207
- real_value = @trocla.password('threadpwd','sleep')
208
- # as t2 finished first this should win
209
- expect(pwd1).to eql(pwd2)
210
- expect(real_value).to eql(pwd1)
211
- expect(real_value).to eql(pwd2)
212
- end
213
- end
214
- context 'on inexpensive flagged formats' do
215
- before(:each) do
216
- expect(Trocla::Formats).to receive(:[]).with('sleep').at_least(:once).and_return(Trocla::Formats::Sleep)
217
- expect(Trocla::Formats::Sleep).to receive(:expensive?).at_least(:once).and_return(false)
218
- expect(Trocla::Formats).to receive(:available?).with('sleep').at_least(:once).and_return(true)
219
- end
220
- it 'should not overwrite a value if it takes longer' do
221
- t1 = Thread.new{ @trocla.password('threadpwd_inexp','sleep','sleep' => 4) }
222
- t2 = Thread.new{ @trocla.password('threadpwd_inexp','sleep','sleep' => 1) }
223
- pwd1 = t1.value
224
- pwd2 = t2.value
225
- real_value = @trocla.password('threadpwd_inexp','sleep')
226
- # as t2 finished first but the format is inexpensive it gets overwritten
227
- expect(pwd1).not_to eql(pwd2)
228
- expect(real_value).to eql(pwd1)
229
- expect(real_value).not_to eql(pwd2)
230
- end
231
- end
232
- context 'real world example' do
233
- it 'should store the quicker one' do
234
- t1 = Thread.new{ @trocla.password('threadpwd_real','bcrypt','cost' => 17) }
235
- t2 = Thread.new{ @trocla.password('threadpwd_real','bcrypt') }
236
- pwd1 = t1.value
237
- pwd2 = t2.value
238
- real_value = @trocla.password('threadpwd_real','bcrypt')
239
- # t2 should still win but both should be the same
240
- expect(pwd1).to eql(pwd2)
241
- expect(real_value).to eql(pwd1)
242
- expect(real_value).to eql(pwd2)
243
- end
244
- it 'should store the quicker one test 2' do
245
- t1 = Thread.new{ @trocla.password('my_shiny_selfsigned_ca', 'x509', {
246
- 'CN' => 'This is my self-signed certificate',
247
- 'become_ca' => false,
248
- }) }
249
- t2 = Thread.new{ @trocla.password('my_shiny_selfsigned_ca', 'x509', {
250
- 'CN' => 'This is my self-signed certificate',
251
- 'become_ca' => false,
252
- }) }
253
- cert1 = t1.value
254
- cert2 = t2.value
255
- real_value = @trocla.password('my_shiny_selfsigned_ca','x509')
256
- # t2 should still win but both should be the same
257
- expect(cert1).to eql(cert2)
258
- expect(real_value).to eql(cert1)
259
- expect(real_value).to eql(cert2)
260
- end
261
- end
262
- end
263
-
264
- end
265
- context 'with .open' do
266
- it 'closes the connection with a block' do
267
- expect_any_instance_of(Trocla::Stores::Memory).to receive(:close)
268
- Trocla.open{|t|
269
- t.password('plain_open','plain')
270
- }
271
- end
272
- it 'keeps the connection without a block' do
273
- expect_any_instance_of(Trocla::Stores::Memory).not_to receive(:close)
274
- Trocla.open.password('plain_open','plain')
275
- end
276
- end
277
-
278
- def format_options
279
- @format_options ||= Hash.new({}).merge({
280
- 'pgsql' => { 'username' => 'test' },
281
- 'x509' => { 'CN' => 'test' },
282
- })
283
- end
284
-
285
- end
286
-
287
- describe "VERSION" do
288
- it "returns a version" do
289
- expect(Trocla::VERSION::STRING).not_to be_empty
290
- end
291
- end
data/trocla.gemspec DELETED
@@ -1,105 +0,0 @@
1
- # Generated by jeweler
2
- # DO NOT EDIT THIS FILE DIRECTLY
3
- # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
- # -*- encoding: utf-8 -*-
5
- # stub: trocla 0.5.1 ruby lib
6
-
7
- Gem::Specification.new do |s|
8
- s.name = "trocla".freeze
9
- s.version = "0.5.1"
10
-
11
- s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version=
12
- s.require_paths = ["lib".freeze]
13
- s.authors = ["mh".freeze]
14
- s.date = "2023-02-17"
15
- s.description = "Trocla helps you to generate random passwords and to store them in various formats (plain, MD5, bcrypt) for later retrival.".freeze
16
- s.email = "mh+trocla@immerda.ch".freeze
17
- s.executables = ["trocla".freeze]
18
- s.extra_rdoc_files = [
19
- "LICENSE.txt",
20
- "README.md"
21
- ]
22
- s.files = [
23
- ".document",
24
- ".github/workflows/ruby.yml",
25
- ".rspec",
26
- "CHANGELOG.md",
27
- "Gemfile",
28
- "LICENSE.txt",
29
- "README.md",
30
- "Rakefile",
31
- "bin/trocla",
32
- "ext/redhat/rubygem-trocla.spec",
33
- "lib/VERSION",
34
- "lib/trocla.rb",
35
- "lib/trocla/default_config.yaml",
36
- "lib/trocla/encryptions.rb",
37
- "lib/trocla/encryptions/none.rb",
38
- "lib/trocla/encryptions/ssl.rb",
39
- "lib/trocla/formats.rb",
40
- "lib/trocla/formats/bcrypt.rb",
41
- "lib/trocla/formats/md5crypt.rb",
42
- "lib/trocla/formats/mysql.rb",
43
- "lib/trocla/formats/pgsql.rb",
44
- "lib/trocla/formats/plain.rb",
45
- "lib/trocla/formats/sha1.rb",
46
- "lib/trocla/formats/sha256crypt.rb",
47
- "lib/trocla/formats/sha512crypt.rb",
48
- "lib/trocla/formats/ssha.rb",
49
- "lib/trocla/formats/sshkey.rb",
50
- "lib/trocla/formats/wireguard.rb",
51
- "lib/trocla/formats/x509.rb",
52
- "lib/trocla/store.rb",
53
- "lib/trocla/stores.rb",
54
- "lib/trocla/stores/memory.rb",
55
- "lib/trocla/stores/moneta.rb",
56
- "lib/trocla/stores/vault.rb",
57
- "lib/trocla/util.rb",
58
- "lib/trocla/version.rb",
59
- "spec/data/.keep",
60
- "spec/spec_helper.rb",
61
- "spec/trocla/encryptions/none_spec.rb",
62
- "spec/trocla/encryptions/ssl_spec.rb",
63
- "spec/trocla/formats/pgsql_spec.rb",
64
- "spec/trocla/formats/sshkey_spec.rb",
65
- "spec/trocla/formats/x509_spec.rb",
66
- "spec/trocla/store/memory_spec.rb",
67
- "spec/trocla/store/moneta_spec.rb",
68
- "spec/trocla/util_spec.rb",
69
- "spec/trocla_spec.rb",
70
- "trocla.gemspec"
71
- ]
72
- s.homepage = "https://tech.immerda.ch/2011/12/trocla-get-hashed-passwords-out-of-puppet-manifests/".freeze
73
- s.licenses = ["GPLv3".freeze]
74
- s.rubygems_version = "3.3.26".freeze
75
- s.summary = "Trocla a simple password generator and storage".freeze
76
-
77
- if s.respond_to? :specification_version then
78
- s.specification_version = 4
79
- end
80
-
81
- if s.respond_to? :add_runtime_dependency then
82
- s.add_runtime_dependency(%q<highline>.freeze, ["~> 2.0.0"])
83
- s.add_runtime_dependency(%q<moneta>.freeze, ["~> 1.0"])
84
- s.add_runtime_dependency(%q<bcrypt>.freeze, [">= 0"])
85
- s.add_runtime_dependency(%q<sshkey>.freeze, [">= 0"])
86
- s.add_development_dependency(%q<rake>.freeze, [">= 0"])
87
- s.add_development_dependency(%q<addressable>.freeze, [">= 0"])
88
- s.add_development_dependency(%q<jeweler>.freeze, ["~> 2.0"])
89
- s.add_development_dependency(%q<rdoc>.freeze, [">= 0"])
90
- s.add_development_dependency(%q<rspec>.freeze, [">= 0"])
91
- s.add_development_dependency(%q<rspec-pending_for>.freeze, [">= 0"])
92
- else
93
- s.add_dependency(%q<highline>.freeze, ["~> 2.0.0"])
94
- s.add_dependency(%q<moneta>.freeze, ["~> 1.0"])
95
- s.add_dependency(%q<bcrypt>.freeze, [">= 0"])
96
- s.add_dependency(%q<sshkey>.freeze, [">= 0"])
97
- s.add_dependency(%q<rake>.freeze, [">= 0"])
98
- s.add_dependency(%q<addressable>.freeze, [">= 0"])
99
- s.add_dependency(%q<jeweler>.freeze, ["~> 2.0"])
100
- s.add_dependency(%q<rdoc>.freeze, [">= 0"])
101
- s.add_dependency(%q<rspec>.freeze, [">= 0"])
102
- s.add_dependency(%q<rspec-pending_for>.freeze, [">= 0"])
103
- end
104
- end
105
-