trocla 0.3.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 0fe321c3e5f61203499ad978f32fef9b9617bf54
4
- data.tar.gz: 276a6191e0342e7d26c185a06b383f357483b300
2
+ SHA256:
3
+ metadata.gz: 18cb6a02ca556208840b6370287987e72fc18e01e199b7fe1b5b72c463a91ee4
4
+ data.tar.gz: d2f8068ab15baf1a5cbbfd3370543ff03ad2f2c1baf564ba43f824589920fcf6
5
5
  SHA512:
6
- metadata.gz: cda445d5bab3d8b96a56990b2b9e447869a44e02bb4f28ca9d29ffce8578aa1e1cb4d5dedb7bec0e0102cc42416fed6361f1c9ea276c2b9fa2b1b7e1ab99698a
7
- data.tar.gz: a59f1905c9877eda6ff3614b84f50e6598c75be420ba78c4e324f0b5c6c72584efda35a711477c35571aeac804de4e8f6ff1a3de80e3f2f220a825ce0d52056d
6
+ metadata.gz: a5829218248d2d9f7f4f3ddfc5bca4f35f8839871fd18074ede34f9281eae086a79c858987285da7839b5699961b417244fc5d86a696b355a8fd4c96d0145bf8
7
+ data.tar.gz: fc4c6e7ce2cf53009ee3db4f8791b820dca9c696223567fac1367cc3e80b8558a2b5d430f6a255d0f7e07403f9be06ee3e895310971303dc571be6a82d908404
data/.travis.yml CHANGED
@@ -2,10 +2,5 @@ language: ruby
2
2
  sudo: false
3
3
  rvm:
4
4
  - jruby
5
- - jruby-18mode
6
- - jruby-19mode
7
- - 2.4.0
8
- - 2.2.0
9
- - 2.0.0
10
- - 1.9.3
11
- - 1.8.7
5
+ - 2.7.0
6
+ - 3.0.0
data/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # Changelog
2
2
 
3
+ ## to 0.4.0
4
+
5
+ * Add vault backend (#61) - Thank you [Steffy Fort](https://github.com/fe80)
6
+ * Add sshkey format similar to the OpenSSL - Thank you [Raphaël Rondeau](https://github.com/rrondeau)
7
+ * format/x509 allow to render 'publickeyonly' (#62) - Thank you [Thomas Weißschuh](https://github.com/t-8ch)
8
+ * Add a method to search for keys and list all formats of a key (#49) - Thank you - [Steffy Fort](https://github.com/fe80)
9
+ * Proper return code on cli (#57) - Thank you [Steffy Fort](https://github.com/fe80)
10
+ * expand search path for sample config file to fix autopkgtest (#64) - Thank you [anarcat](https://github.com/anarcat)
11
+ * drop support for ruby < 2.7 & update dependencies
12
+ * skip self-signed cert verification test on newer openssl version (#63)
13
+ * Fix reseting passwords when using SSL encryption (#52)
14
+
3
15
  ## to 0.3.0
4
16
 
5
17
  * Add open method to be able to immediately close a trocla store after using it - thanks martinpfeiffer
data/Gemfile CHANGED
@@ -3,48 +3,21 @@ source "http://rubygems.org"
3
3
  # Example:
4
4
  # gem "activesupport", ">= 2.3.5"
5
5
 
6
- if RUBY_VERSION.to_f <= 2.2
7
- gem 'rack', '< 2.0'
8
- end
9
-
10
- if RUBY_VERSION.to_f < 2.1
11
- gem 'nokogiri', '< 1.7'
12
- end
13
-
14
- if RUBY_VERSION.to_f > 1.8
15
- gem "moneta"
16
- gem "highline"
17
- else
18
- gem "moneta", "~> 0.7.20"
19
- gem "highline", "~> 1.6.2"
20
- gem 'rake', '< 11'
21
- gem 'git', '< 1.3'
22
- end
6
+ gem "moneta", "~> 1.4.0"
7
+ gem "highline", "~> 2.0.0"
23
8
 
24
9
  if defined?(RUBY_ENGINE) && (RUBY_ENGINE == 'jruby')
25
10
  gem 'jruby-openssl'
26
11
  end
27
12
  gem "bcrypt"
13
+ gem "sshkey"
28
14
 
29
15
  # Add dependencies to develop your gem here.
30
16
  # Include everything needed to run rake, tests, features, etc.
31
17
  group :development do
32
- if RUBY_VERSION.to_f > 1.8
33
- gem "rspec"
34
- gem "rdoc"
35
- if RUBY_VERSION.to_f < 2.2
36
- gem 'jeweler', '< 2.2'
37
- else
38
- gem "jeweler"
39
- end
40
- if RUBY_VERSION.to_f < 2.0
41
- gem 'public_suffix', '~> 1.4.6'
42
- end
43
- else
44
- gem "rspec", "~> 2.4"
45
- gem "rdoc", "~> 3.8"
46
- gem "jeweler", "~> 1.6"
47
- gem "addressable", "~> 2.3.8"
48
- end
18
+ gem "rspec"
19
+ gem "rdoc"
20
+ gem "jeweler"
21
+ gem "addressable"
49
22
  gem 'rspec-pending_for'
50
23
  end
data/README.md CHANGED
@@ -24,7 +24,7 @@ retrieve (by deleting) the plain password and send it to the user. Puppet
24
24
  will still simply retrieve the hashed password that is stored in trocla,
25
25
  while the plain password is not anymore stored on the server.
26
26
 
27
- Be default trocla uses moneta to store the passwords and can use any kind of
27
+ By default trocla uses moneta to store the passwords and can use any kind of
28
28
  key/value based storage supported by moneta for trocla. By default it uses a
29
29
  simple yaml file.
30
30
  However, since version 0.2.0 trocla also supports a pluggable storage backend
@@ -212,8 +212,25 @@ Additional options are:
212
212
 
213
213
  Output render options are:
214
214
 
215
- certonly If set to true the x509 format will return only the certificate
216
- keyonly If set to true the x509 format will return only the private key
215
+ certonly If set to true the x509 format will return only the certificate
216
+ keyonly If set to true the x509 format will return only the private key
217
+ publickeyonly If set to true the x509 format will return only the public key
218
+
219
+ ### sshkey
220
+
221
+ This format generate a ssh keypair
222
+
223
+ Additional options are:
224
+
225
+ type The ssh key type (rsa, dsa). Default: rsa
226
+ bits Specifies the number of bits in the key to create. Default: 2048
227
+ comment Specifies a comment.
228
+ passphrase Specifies a passphrase.
229
+
230
+ Output render options are:
231
+
232
+ pubonly If set to true the sshkey format will return only the ssh public key
233
+ privonly If set to true the sshkey format will return only the ssh private key
217
234
 
218
235
  ## Installation
219
236
 
@@ -256,6 +273,7 @@ Such a store is a simple class that implements Trocla::Store and at the moment t
256
273
 
257
274
  * Moneta - the default store using [moneta](https://rubygems.org/gems/moneta) to delegate storing the values
258
275
  * Memory - simple inmemory backend. Mainly used for testing.
276
+ * Vault - modern secrets storage by HashiCorp, require the ruby gem [vault](https://github.com/hashicorp/vault-ruby)
259
277
 
260
278
  The backend is chosen based on the `store` configuration option. If it is a symbol, we expect it to be a store that we ship with trocla. Otherwise, we assume it to be a fully qualified ruby class name, that inherits from Trocla::Store. If trocla should load an additional library to be able to find your custom store class, you can set `store_require` to whatever should be passed to a ruby require statement.
261
279
 
@@ -298,6 +316,31 @@ store_options:
298
316
 
299
317
  These examples are by no way complete, moneta has much more to offer. Please have a look at [moneta's documentation](https://github.com/minad/moneta/blob/master/README.md) for further information.
300
318
 
319
+ #### Vault backend
320
+
321
+ [Vault](https://www.vaultproject.io/) is a modern secret storage supported by HashiCorp, which works with a REST API. You can create multiple storage engine.
322
+
323
+ To use vault with trocla you need to create a kv (key/value) storage engine on the vault side. Trocla can use [v1](https://www.vaultproject.io/docs/secrets/kv/kv-v1) and [v2](https://www.vaultproject.io/docs/secrets/kv/kv-v2) API endpoints, but it's recommended to use the v2 (native hash object, history, acl...).
324
+
325
+ You need to install the `vault` gem to be able to use the vault backend, which is not included in the default dependencies for trocla.
326
+
327
+ With vault storage, the terminology changes:
328
+ * `mount`, this is the name of your kv engine
329
+ * `key`, this is the biggest change. As usual with trocla, the key is a simple string. With the vault kv engine, the key map to a path, so you can have a key like `my/path/key` for structured your data
330
+ * `secret`, is the data content of your key. This is a simple hash with key (format) and value (the secret content of your format)
331
+
332
+ The trocla mapping works the same way as with a moneta or file backend.
333
+
334
+ The `store_options` are a dynamic argument for initializer [Vault::Client](https://github.com/hashicorp/vault-ruby/blob/master/lib/vault/client.rb) class (except `:mount`, used to defined the kv name). You can define only one kv mount.
335
+
336
+ ```YAML
337
+ store: :vault
338
+ store_options:
339
+ :mount: kv
340
+ :token: s.Tok3n
341
+ :address: https://vault.local
342
+ ```
343
+
301
344
  ### Backend encryption
302
345
 
303
346
  By default trocla does not encrypt anything it stores. You might want to let Trocla encrypt all your passwords, at the moment the only supported way is SSL.
data/bin/trocla CHANGED
@@ -99,14 +99,31 @@ def reset(options)
99
99
  end
100
100
 
101
101
  def delete(options)
102
- [ Trocla.new(options.delete(:config_file)).delete_password(
102
+ res = Trocla.new(options.delete(:config_file)).delete_password(
103
103
  options.delete(:trocla_key),
104
104
  options.delete(:trocla_format)
105
- ), 0 ]
105
+ )
106
+ [ res, res.nil? ? 1 : 0 ]
106
107
  end
107
108
 
108
109
  def formats(options)
109
- "Available formats: #{Trocla::Formats.all.join(', ')}"
110
+ key = (options.delete(:trocla_key) || '' )
111
+ if key.empty?
112
+ "Available formats: #{Trocla::Formats.all.join(', ')}"
113
+ else
114
+ res = Trocla.new(options.delete(:config_file)).available_format(
115
+ key,
116
+ options.merge(YAML.load(options.delete(:other_options).shift.to_s)||{})
117
+ )
118
+ [ res.nil? ? res : res.join(', '), res.nil? ? 1 : 0 ]
119
+ end
120
+ end
121
+
122
+ def search(options)
123
+ res = Trocla.new(options.delete(:config_file)).search_key(
124
+ options.delete(:trocla_key)
125
+ )
126
+ [ res.nil? ? res : res.join("\n"), res.nil? ? 1 : 0 ]
110
127
  end
111
128
 
112
129
  def check_format(format_name)
@@ -119,13 +136,13 @@ def check_format(format_name)
119
136
  end
120
137
  end
121
138
 
122
- actions=['create','get','set','reset','delete', 'formats' ]
139
+ actions=['create','get','set','reset','delete','formats','search']
123
140
 
124
141
  if (action=ARGV.shift) && actions.include?(action)
125
142
  options[:trocla_key] = ARGV.shift
126
143
  options[:trocla_format] = ARGV.shift
127
144
  options[:other_options] = ARGV
128
- check_format(options[:trocla_format]) unless ['delete','formats'].include?(action)
145
+ check_format(options[:trocla_format]) unless ['delete','formats','search'].include?(action)
129
146
  begin
130
147
  result, excode = send(action,options)
131
148
  if result
data/lib/VERSION CHANGED
@@ -1,4 +1,4 @@
1
1
  major:0
2
- minor:3
2
+ minor:4
3
3
  patch:0
4
4
  build:
data/lib/trocla.rb CHANGED
@@ -62,7 +62,7 @@ class Trocla
62
62
  end
63
63
 
64
64
  def reset_password(key,format,options={})
65
- set_password(key,format,nil,options)
65
+ delete_password(key,format)
66
66
  password(key,format,options)
67
67
  end
68
68
 
@@ -82,6 +82,14 @@ class Trocla
82
82
  render(format,password,options)
83
83
  end
84
84
 
85
+ def available_format(key, options={})
86
+ render(false,store.formats(key),options)
87
+ end
88
+
89
+ def search_key(key, options={})
90
+ render(false,store.search(key),options)
91
+ end
92
+
85
93
  def formats(format)
86
94
  (@format_cache||={})[format] ||= Trocla::Formats[format].new(self)
87
95
  end
@@ -0,0 +1,46 @@
1
+ require 'sshkey'
2
+
3
+ class Trocla::Formats::Sshkey < Trocla::Formats::Base
4
+
5
+ expensive true
6
+
7
+ def format(plain_password,options={})
8
+
9
+ if plain_password.match(/-----BEGIN RSA PRIVATE KEY-----.*-----END RSA PRIVATE KEY/m)
10
+ # Import, validate ssh key
11
+ begin
12
+ sshkey = ::SSHKey.new(plain_password)
13
+ rescue Exception => e
14
+ raise "SSH key import failed: #{e.message}"
15
+ end
16
+ return sshkey.private_key + sshkey.ssh_public_key
17
+ end
18
+
19
+ type = options['type'] || 'rsa'
20
+ bits = options['bits'] || 2048
21
+
22
+ begin
23
+ sshkey = ::SSHKey.generate(
24
+ type: type,
25
+ bits: bits,
26
+ comment: options['comment'],
27
+ passphrase: options['passphrase']
28
+ )
29
+ rescue Exception => e
30
+ raise "SSH key creation failed: #{e.message}"
31
+ end
32
+
33
+ sshkey.private_key + sshkey.ssh_public_key
34
+ end
35
+
36
+ def render(output,render_options={})
37
+ if render_options['privonly']
38
+ ::SSHKey.new(output).private_key
39
+ elsif render_options['pubonly']
40
+ ::SSHKey.new(output).ssh_public_key
41
+ else
42
+ super(output,render_options)
43
+ end
44
+ end
45
+
46
+ end
@@ -97,6 +97,8 @@ class Trocla::Formats::X509 < Trocla::Formats::Base
97
97
  OpenSSL::PKey::RSA.new(output).to_pem
98
98
  elsif render_options['certonly']
99
99
  OpenSSL::X509::Certificate.new(output).to_pem
100
+ elsif render_options['publickeyonly']
101
+ OpenSSL::PKey::RSA.new(output).public_key.to_pem
100
102
  else
101
103
  super(output,render_options)
102
104
  end
data/lib/trocla/store.rb CHANGED
@@ -50,6 +50,16 @@ class Trocla::Store
50
50
  format.nil? ? (delete_all(key)||{}) : delete_format(key,format)
51
51
  end
52
52
 
53
+ # returns all formats for a key
54
+ def formats(key)
55
+ raise 'not implemented'
56
+ end
57
+
58
+ # def searches for a key
59
+ def search(key)
60
+ raise 'not implemented'
61
+ end
62
+
53
63
  private
54
64
  # sets a new plain value
55
65
  # *must* invalidate all
@@ -19,6 +19,15 @@ class Trocla::Stores::Memory < Trocla::Store
19
19
  set_expires(key,options['expires'])
20
20
  end
21
21
 
22
+ def formats(key)
23
+ memory[key].empty? ? nil : memory[key].keys
24
+ end
25
+
26
+ def search(key)
27
+ r = memory.keys.grep(/#{key}/)
28
+ r.empty? ? nil : r
29
+ end
30
+
22
31
  private
23
32
  def set_plain(key,value,options)
24
33
  memory[key] = { 'plain' => value }
@@ -18,6 +18,17 @@ class Trocla::Stores::Moneta < Trocla::Store
18
18
  moneta.fetch(key, {})[format]
19
19
  end
20
20
 
21
+ def formats(key)
22
+ r = moneta.fetch(key)
23
+ r.nil? ? nil : r.keys
24
+ end
25
+
26
+ def search(key)
27
+ raise 'The search option is not available for any adapter other than Sequel or YAML' unless store_config['adapter'] == :Sequel || store_config['adapter'] == :YAML
28
+ r = search_keys(key)
29
+ r.empty? ? nil : r
30
+ end
31
+
21
32
  private
22
33
  def set_plain(key,value,options)
23
34
  h = { 'plain' => value }
@@ -55,4 +66,19 @@ class Trocla::Stores::Moneta < Trocla::Store
55
66
  end
56
67
  res
57
68
  end
69
+ def search_keys(key)
70
+ _moneta = Moneta.new(store_config['adapter'], (store_config['adapter_options']||{}).merge({ :expires => false }))
71
+ a = []
72
+ if store_config['adapter'] == :Sequel
73
+ keys = _moneta.adapter.backend[:trocla].select_order_map {from_base64(:k)}
74
+ elsif store_config['adapter'] == :YAML
75
+ keys = _moneta.adapter.backend.transaction(true) { _moneta.adapter.backend.roots }
76
+ end
77
+ _moneta.close
78
+ regexp = Regexp.new("#{key}")
79
+ keys.each do |k|
80
+ a << k if regexp.match(k)
81
+ end
82
+ a
83
+ end
58
84
  end
@@ -0,0 +1,50 @@
1
+ # the default vault based store
2
+ class Trocla::Stores::Vault < Trocla::Store
3
+ attr_reader :vault, :mount
4
+ def initialize(config,trocla)
5
+ super(config,trocla)
6
+ require 'vault'
7
+ @mount = (config.delete(:mount) || 'kv')
8
+ # load expire support by default
9
+ @vault = Vault::Client.new(config)
10
+ end
11
+
12
+ def close
13
+ end
14
+
15
+ def get(key,format)
16
+ read(key)[format.to_sym]
17
+ end
18
+
19
+ def formats(key)
20
+ read(key).keys
21
+ end
22
+
23
+ private
24
+ def read(key)
25
+ k = vault.kv(mount).read(key)
26
+ k.nil? ? {} : k.data
27
+ end
28
+
29
+ def write(key, value)
30
+ vault.kv(mount).write(key, value)
31
+ end
32
+
33
+ def set_plain(key,value,options)
34
+ set_format(key,'plain',value,options)
35
+ end
36
+
37
+ def set_format(key,format,value,options)
38
+ write(key, read(key).merge({format.to_sym => value}))
39
+ end
40
+
41
+ def delete_all(key)
42
+ vault.kv(mount).delete(key)
43
+ end
44
+
45
+ def delete_format(key,format)
46
+ old = read(key)
47
+ write(key, old.reject { |k,v| k == format.to_sym })
48
+ old[format.to_sym]
49
+ end
50
+ end
data/spec/spec_helper.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
2
2
  $LOAD_PATH.unshift(File.dirname(__FILE__))
3
+ require 'jruby' if Object.const_defined?(:RUBY_ENGINE) and RUBY_ENGINE == 'jruby'
3
4
  require 'rspec'
4
5
  require 'rspec/pending_for'
5
6
  require 'yaml'
@@ -35,6 +36,11 @@ RSpec.shared_examples "encryption_basics" do
35
36
  expect(@trocla.get_password('some_pass', 'plain')).to eql('super secret')
36
37
  end
37
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
+
38
44
  end
39
45
  describe 'deleting' do
40
46
  it "plain" do
@@ -225,7 +231,13 @@ RSpec.shared_examples 'store_validation' do |store|
225
231
  end
226
232
 
227
233
  def default_config
228
- @default_config ||= YAML.load(File.read(File.expand_path(base_dir+'/lib/trocla/default_config.yaml')))
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.exists?(p) }
239
+ YAML.load(File.read(config_path))
240
+ end
229
241
  end
230
242
 
231
243
  def test_config
@@ -0,0 +1,52 @@
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
@@ -44,7 +44,9 @@ describe "Trocla::Format::X509" do
44
44
  expect(cert.public_key.n.num_bytes * 8).to eq(4096)
45
45
  expect((Date.parse(cert.not_after.localtime.to_s) - Date.today).to_i).to eq(365)
46
46
  # it's a self signed cert and NOT a CA
47
- expect(verify(cert,cert)).to be false
47
+ # Change of behavior on openssl side: https://github.com/openssl/openssl/issues/15146
48
+ validates_self_even_if_no_ca = Gem::Version.new(%x{openssl version}.split(' ')[1]) > Gem::Version.new('1.1.1g')
49
+ expect(verify(cert,cert)).to be validates_self_even_if_no_ca
48
50
 
49
51
  v = cert.extensions.find{|e| e.oid == 'basicConstraints' }.value
50
52
  expect(v).to eq('CA:FALSE')
@@ -136,6 +138,11 @@ describe "Trocla::Format::X509" do
136
138
  expect(cert_str).not_to match(/-----BEGIN CERTIFICATE-----/)
137
139
  expect(cert_str).to match(/-----BEGIN RSA PRIVATE KEY-----/)
138
140
  end
141
+ it 'supports fetching only the publickey' do
142
+ pkey_str = @trocla.password('mycert', 'x509', cert_options.merge('render' => {'publickeyonly' => true }))
143
+ expect(pkey_str).not_to match(/-----BEGIN CERTIFICATE-----/)
144
+ expect(pkey_str).to match(/-----BEGIN PUBLIC KEY-----/)
145
+ end
139
146
  it 'supports fetching only the cert' do
140
147
  cert_str = @trocla.password('mycert', 'x509', cert_options.merge('render' => {'certonly' => true }))
141
148
  expect(cert_str).to match(/-----BEGIN CERTIFICATE-----/)
data/spec/trocla_spec.rb CHANGED
@@ -1,3 +1,4 @@
1
+ # -- encoding : utf-8 --
1
2
  require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
3
 
3
4
  describe "Trocla" do
@@ -99,6 +100,11 @@ describe "Trocla" do
99
100
  expect(@trocla.get_password('set_test2','md5crypt')).to eq(md5crypt)
100
101
  expect(@trocla.get_password('set_test2','plain')).to eq(plain)
101
102
  end
103
+
104
+ it 'is able to set password with umlauts and other UTF-8 charcters' do
105
+ expect(myumlaut = @trocla.set_password('set_test_umlaut','plain','Tütü')).to eql('Tütü')
106
+ expect(@trocla.get_password('set_test_umlaut','plain','Tütü')).to eql('Tütü')
107
+ end
102
108
  end
103
109
 
104
110
  describe "reset_password" do
@@ -120,6 +126,40 @@ describe "Trocla" do
120
126
  end
121
127
  end
122
128
 
129
+ describe "search_key" do
130
+ it "search a specific key" do
131
+ keys = ['search_key','search_key1','key_search','key_search2']
132
+ keys.each do |k|
133
+ @trocla.password(k,'plain')
134
+ end
135
+ expect(@trocla.search_key('search_key1').length).to eq(1)
136
+ end
137
+ it "ensure search regex is ok" do
138
+ keys = ['search_key2','search_key3','key_search2','key_search4']
139
+ keys.each do |k|
140
+ @trocla.password(k,'plain')
141
+ end
142
+ expect(@trocla.search_key('key').length).to eq(4)
143
+ expect(@trocla.search_key('^search').length).to eq(2)
144
+ expect(@trocla.search_key('ch.*3').length).to eq(1)
145
+ expect(@trocla.search_key('ch.*[3-4]$').length).to eq(2)
146
+ expect(@trocla.search_key('ch.*1')).to be_nil
147
+ end
148
+ end
149
+
150
+ describe "list_format" do
151
+ it "list available formats for key" do
152
+ formats = ['plain','mysql']
153
+ formats.each do |f|
154
+ @trocla.password('list_key',f)
155
+ end
156
+ expect(@trocla.available_format('list_key')).to eq(formats)
157
+ end
158
+ it "no return if key doesn't exist" do
159
+ expect(@trocla.available_format('list_key1')).to be_nil
160
+ end
161
+ end
162
+
123
163
  describe "delete_password" do
124
164
  it "deletes all passwords if no format is given" do
125
165
  expect(@trocla.password('delete_test1','mysql')).not_to be_nil
data/trocla.gemspec CHANGED
@@ -2,16 +2,16 @@
2
2
  # DO NOT EDIT THIS FILE DIRECTLY
3
3
  # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
4
  # -*- encoding: utf-8 -*-
5
- # stub: trocla 0.3.0 ruby lib
5
+ # stub: trocla 0.4.0 ruby lib
6
6
 
7
7
  Gem::Specification.new do |s|
8
8
  s.name = "trocla".freeze
9
- s.version = "0.3.0"
9
+ s.version = "0.4.0"
10
10
 
11
11
  s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version=
12
12
  s.require_paths = ["lib".freeze]
13
13
  s.authors = ["mh".freeze]
14
- s.date = "2017-08-04"
14
+ s.date = "2021-05-11"
15
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
16
  s.email = "mh+trocla@immerda.ch".freeze
17
17
  s.executables = ["trocla".freeze]
@@ -46,17 +46,20 @@ Gem::Specification.new do |s|
46
46
  "lib/trocla/formats/sha256crypt.rb",
47
47
  "lib/trocla/formats/sha512crypt.rb",
48
48
  "lib/trocla/formats/ssha.rb",
49
+ "lib/trocla/formats/sshkey.rb",
49
50
  "lib/trocla/formats/x509.rb",
50
51
  "lib/trocla/store.rb",
51
52
  "lib/trocla/stores.rb",
52
53
  "lib/trocla/stores/memory.rb",
53
54
  "lib/trocla/stores/moneta.rb",
55
+ "lib/trocla/stores/vault.rb",
54
56
  "lib/trocla/util.rb",
55
57
  "lib/trocla/version.rb",
56
58
  "spec/data/.keep",
57
59
  "spec/spec_helper.rb",
58
60
  "spec/trocla/encryptions/none_spec.rb",
59
61
  "spec/trocla/encryptions/ssl_spec.rb",
62
+ "spec/trocla/formats/sshkey_spec.rb",
60
63
  "spec/trocla/formats/x509_spec.rb",
61
64
  "spec/trocla/store/memory_spec.rb",
62
65
  "spec/trocla/store/moneta_spec.rb",
@@ -66,36 +69,32 @@ Gem::Specification.new do |s|
66
69
  ]
67
70
  s.homepage = "https://tech.immerda.ch/2011/12/trocla-get-hashed-passwords-out-of-puppet-manifests/".freeze
68
71
  s.licenses = ["GPLv3".freeze]
69
- s.rubygems_version = "2.6.11".freeze
72
+ s.rubygems_version = "3.1.2".freeze
70
73
  s.summary = "Trocla a simple password generator and storage".freeze
71
74
 
72
75
  if s.respond_to? :specification_version then
73
76
  s.specification_version = 4
77
+ end
74
78
 
75
- if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
76
- s.add_runtime_dependency(%q<moneta>.freeze, [">= 0"])
77
- s.add_runtime_dependency(%q<highline>.freeze, [">= 0"])
78
- s.add_runtime_dependency(%q<bcrypt>.freeze, [">= 0"])
79
- s.add_development_dependency(%q<rspec>.freeze, [">= 0"])
80
- s.add_development_dependency(%q<rdoc>.freeze, [">= 0"])
81
- s.add_development_dependency(%q<jeweler>.freeze, [">= 0"])
82
- s.add_development_dependency(%q<rspec-pending_for>.freeze, [">= 0"])
83
- else
84
- s.add_dependency(%q<moneta>.freeze, [">= 0"])
85
- s.add_dependency(%q<highline>.freeze, [">= 0"])
86
- s.add_dependency(%q<bcrypt>.freeze, [">= 0"])
87
- s.add_dependency(%q<rspec>.freeze, [">= 0"])
88
- s.add_dependency(%q<rdoc>.freeze, [">= 0"])
89
- s.add_dependency(%q<jeweler>.freeze, [">= 0"])
90
- s.add_dependency(%q<rspec-pending_for>.freeze, [">= 0"])
91
- end
79
+ if s.respond_to? :add_runtime_dependency then
80
+ s.add_runtime_dependency(%q<moneta>.freeze, ["~> 1.4.0"])
81
+ s.add_runtime_dependency(%q<highline>.freeze, ["~> 2.0.0"])
82
+ s.add_runtime_dependency(%q<bcrypt>.freeze, [">= 0"])
83
+ s.add_runtime_dependency(%q<sshkey>.freeze, [">= 0"])
84
+ s.add_development_dependency(%q<rspec>.freeze, [">= 0"])
85
+ s.add_development_dependency(%q<rdoc>.freeze, [">= 0"])
86
+ s.add_development_dependency(%q<jeweler>.freeze, [">= 0"])
87
+ s.add_development_dependency(%q<addressable>.freeze, [">= 0"])
88
+ s.add_development_dependency(%q<rspec-pending_for>.freeze, [">= 0"])
92
89
  else
93
- s.add_dependency(%q<moneta>.freeze, [">= 0"])
94
- s.add_dependency(%q<highline>.freeze, [">= 0"])
90
+ s.add_dependency(%q<moneta>.freeze, ["~> 1.4.0"])
91
+ s.add_dependency(%q<highline>.freeze, ["~> 2.0.0"])
95
92
  s.add_dependency(%q<bcrypt>.freeze, [">= 0"])
93
+ s.add_dependency(%q<sshkey>.freeze, [">= 0"])
96
94
  s.add_dependency(%q<rspec>.freeze, [">= 0"])
97
95
  s.add_dependency(%q<rdoc>.freeze, [">= 0"])
98
96
  s.add_dependency(%q<jeweler>.freeze, [">= 0"])
97
+ s.add_dependency(%q<addressable>.freeze, [">= 0"])
99
98
  s.add_dependency(%q<rspec-pending_for>.freeze, [">= 0"])
100
99
  end
101
100
  end
metadata CHANGED
@@ -1,31 +1,45 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: trocla
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - mh
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-08-04 00:00:00.000000000 Z
11
+ date: 2021-05-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: moneta
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - ">="
17
+ - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '0'
19
+ version: 1.4.0
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - ">="
24
+ - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '0'
26
+ version: 1.4.0
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: highline
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: 2.0.0
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: 2.0.0
41
+ - !ruby/object:Gem::Dependency
42
+ name: bcrypt
29
43
  requirement: !ruby/object:Gem::Requirement
30
44
  requirements:
31
45
  - - ">="
@@ -39,7 +53,7 @@ dependencies:
39
53
  - !ruby/object:Gem::Version
40
54
  version: '0'
41
55
  - !ruby/object:Gem::Dependency
42
- name: bcrypt
56
+ name: sshkey
43
57
  requirement: !ruby/object:Gem::Requirement
44
58
  requirements:
45
59
  - - ">="
@@ -94,6 +108,20 @@ dependencies:
94
108
  - - ">="
95
109
  - !ruby/object:Gem::Version
96
110
  version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: addressable
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
97
125
  - !ruby/object:Gem::Dependency
98
126
  name: rspec-pending_for
99
127
  requirement: !ruby/object:Gem::Requirement
@@ -144,17 +172,20 @@ files:
144
172
  - lib/trocla/formats/sha256crypt.rb
145
173
  - lib/trocla/formats/sha512crypt.rb
146
174
  - lib/trocla/formats/ssha.rb
175
+ - lib/trocla/formats/sshkey.rb
147
176
  - lib/trocla/formats/x509.rb
148
177
  - lib/trocla/store.rb
149
178
  - lib/trocla/stores.rb
150
179
  - lib/trocla/stores/memory.rb
151
180
  - lib/trocla/stores/moneta.rb
181
+ - lib/trocla/stores/vault.rb
152
182
  - lib/trocla/util.rb
153
183
  - lib/trocla/version.rb
154
184
  - spec/data/.keep
155
185
  - spec/spec_helper.rb
156
186
  - spec/trocla/encryptions/none_spec.rb
157
187
  - spec/trocla/encryptions/ssl_spec.rb
188
+ - spec/trocla/formats/sshkey_spec.rb
158
189
  - spec/trocla/formats/x509_spec.rb
159
190
  - spec/trocla/store/memory_spec.rb
160
191
  - spec/trocla/store/moneta_spec.rb
@@ -165,7 +196,7 @@ homepage: https://tech.immerda.ch/2011/12/trocla-get-hashed-passwords-out-of-pup
165
196
  licenses:
166
197
  - GPLv3
167
198
  metadata: {}
168
- post_install_message:
199
+ post_install_message:
169
200
  rdoc_options: []
170
201
  require_paths:
171
202
  - lib
@@ -180,9 +211,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
180
211
  - !ruby/object:Gem::Version
181
212
  version: '0'
182
213
  requirements: []
183
- rubyforge_project:
184
- rubygems_version: 2.6.11
185
- signing_key:
214
+ rubygems_version: 3.1.2
215
+ signing_key:
186
216
  specification_version: 4
187
217
  summary: Trocla a simple password generator and storage
188
218
  test_files: []