trocla 0.4.0 → 0.5.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
2
  SHA256:
3
- metadata.gz: 18cb6a02ca556208840b6370287987e72fc18e01e199b7fe1b5b72c463a91ee4
4
- data.tar.gz: d2f8068ab15baf1a5cbbfd3370543ff03ad2f2c1baf564ba43f824589920fcf6
3
+ metadata.gz: 2d6d84b42cc62b4ab04eea0478d9e4801939c1d31accd0dba4a27e272f56dad2
4
+ data.tar.gz: 6a322a8ae343b6723476b53e9ff7158adaa8d1537bbb46fbc81ef5ebd5a6cff2
5
5
  SHA512:
6
- metadata.gz: a5829218248d2d9f7f4f3ddfc5bca4f35f8839871fd18074ede34f9281eae086a79c858987285da7839b5699961b417244fc5d86a696b355a8fd4c96d0145bf8
7
- data.tar.gz: fc4c6e7ce2cf53009ee3db4f8791b820dca9c696223567fac1367cc3e80b8558a2b5d430f6a255d0f7e07403f9be06ee3e895310971303dc571be6a82d908404
6
+ metadata.gz: 9bf44101c733c550f2ca6cd76e9a3788e8e2ac9f44576af255f6ea42271b0cb0cc6c004c6d66c9a4c49e5d74ab647e1cfc8f52bf1c0944176e5e529334effd11
7
+ data.tar.gz: d8e988c515297525975ca3b2339cfe81ba21444cf45c42637131d3f949871ab6a993f30b62ac2992d8388a2874bf8d4d43fcc9714383ac55fb22ad176f340dbc
@@ -0,0 +1,24 @@
1
+ ---
2
+ name: Ruby
3
+ on: [push, pull_request]
4
+ jobs:
5
+ spec:
6
+ runs-on: ubuntu-latest
7
+ steps:
8
+ - name: check out repository
9
+ uses: actions/checkout@v3
10
+ - name: set up Ruby
11
+ uses: ruby/setup-ruby@v1
12
+ with:
13
+ bundler-cache: true
14
+ ruby-version: ${{ matrix.ruby }}
15
+ - name: install dependencies
16
+ run: bundle install
17
+ - name: install wireguard
18
+ run: sudo apt install -y wireguard
19
+ - name: run rspec
20
+ run: bundle exec rake spec
21
+ strategy:
22
+ fail-fast: false
23
+ matrix:
24
+ ruby: [2.5, 2.7, 3.0, 3.1]
data/.rspec CHANGED
@@ -1 +1 @@
1
- --color
1
+ --color --format documentation
data/CHANGELOG.md CHANGED
@@ -1,5 +1,16 @@
1
1
  # Changelog
2
2
 
3
+ ## to 0.5.0
4
+
5
+ * moved from travis ci to github actions (#73) - Thank you [Georg-g](https://github.com/geor-g)
6
+ * Support expire in vault (#71) - Thank you [Steffy Fort](https://github.com/fe80)
7
+ * Syntax improvements (#70) - Thank you [Steffy Fort](https://github.com/fe80)
8
+ * Add SCRAM-SHA-256 postgres support (#69) - Thank you [Steffy Fort](https://github.com/fe80)
9
+ * Support destroying and entry to properly clean up in vault (#68) - Thank you [Steffy Fort](https://github.com/fe80)
10
+ * Support search with vault backend (#67) - Thank you [Steffy Fort](https://github.com/fe80)
11
+ * Add wireguard format (#65) - Thank you [Jonas Genannt](https://github.com/hggh)
12
+ * Expand search path for sample config - Thank you [Anarcat](https://github.com/anarcat)
13
+
3
14
  ## to 0.4.0
4
15
 
5
16
  * Add vault backend (#61) - Thank you [Steffy Fort](https://github.com/fe80)
data/Gemfile CHANGED
@@ -1,23 +1,24 @@
1
- source "http://rubygems.org"
1
+ source 'http://rubygems.org'
2
2
  # Add dependencies required to use your gem here.
3
3
  # Example:
4
4
  # gem "activesupport", ">= 2.3.5"
5
5
 
6
- gem "moneta", "~> 1.4.0"
7
- gem "highline", "~> 2.0.0"
6
+ gem 'highline', '~> 2.0.0'
7
+ gem 'moneta', '~> 1.4.0'
8
8
 
9
9
  if defined?(RUBY_ENGINE) && (RUBY_ENGINE == 'jruby')
10
10
  gem 'jruby-openssl'
11
11
  end
12
- gem "bcrypt"
13
- gem "sshkey"
12
+ gem 'bcrypt'
13
+ gem 'openssl'
14
+ gem 'sshkey'
14
15
 
15
16
  # Add dependencies to develop your gem here.
16
17
  # Include everything needed to run rake, tests, features, etc.
17
18
  group :development do
18
- gem "rspec"
19
- gem "rdoc"
20
- gem "jeweler"
21
- gem "addressable"
19
+ gem 'addressable'
20
+ gem 'jeweler'
21
+ gem 'rdoc'
22
+ gem 'rspec'
22
23
  gem 'rspec-pending_for'
23
24
  end
data/README.md CHANGED
@@ -165,8 +165,9 @@ options to work properly. These are documented here:
165
165
 
166
166
  ### pgsql
167
167
 
168
- Password hashes for PostgreSQL servers. Requires the option `username` to be set
169
- to the username to which the password will be assigned.
168
+ Password hashes for PostgreSQL servers. Since postgesql 10 you can use the sha256 hash, you have two options:
169
+ * Create a ssh256 hash password with option `encode: sha256` (default value)
170
+ * Create a md5 hash, the username is require for the salt key, with option `encode: md5` and `username: your_user`
170
171
 
171
172
  ### bcrypt
172
173
 
@@ -232,6 +233,17 @@ Output render options are:
232
233
  pubonly If set to true the sshkey format will return only the ssh public key
233
234
  privonly If set to true the sshkey format will return only the ssh private key
234
235
 
236
+ ### wireguard
237
+
238
+ This format generate a keypair for WireGuard.
239
+
240
+ The format requires the wg binary from WireGuard userland utilities.
241
+
242
+ Output render options are:
243
+
244
+ pubonly If set to true the wireguard format will return only the public key
245
+ privonly If set to true the wireguard format will return only the private key
246
+
235
247
  ## Installation
236
248
 
237
249
  * Debian has trocla within its sid-release: `apt-get install trocla`
@@ -290,6 +302,8 @@ We expect storage backends to implement support for the `expires` option, so tha
290
302
 
291
303
  New backends should be tested using the provided shared example.
292
304
 
305
+ > **WARNING**: Vault backend use metadatas. It's set if an option is define. `expire` is automaticly change to `delete_version_after`, and you can use an interger or [format string](https://www.vaultproject.io/api-docs/secret/kv/kv-v2#parameters)
306
+
293
307
  #### Moneta backends
294
308
 
295
309
  Trocla uses moneta as its default storage backend and hence can store your passwords in any of moneta's supported backends. By default it uses the yaml backend, which is configured as followed:
@@ -341,6 +355,8 @@ store_options:
341
355
  :address: https://vault.local
342
356
  ```
343
357
 
358
+ With Vault when you delete a key, you don't delete all key content. The metadatas, like history, are still here and the endpoint are not delete. If you prefere to destroy all key content you can add `:destroy: true` in the `store_options:` hash.
359
+
344
360
  ### Backend encryption
345
361
 
346
362
  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
@@ -43,25 +43,25 @@ OptionParser.new do |opts|
43
43
  options[:ask_password] = false
44
44
  options[:password] = pass
45
45
  end
46
-
47
46
  end.parse!
48
47
 
49
48
  def create(options)
50
- [ Trocla.new(options.delete(:config_file)).password(
49
+ [Trocla.new(options.delete(:config_file)).password(
51
50
  options.delete(:trocla_key),
52
51
  options.delete(:trocla_format),
53
- options.merge(YAML.load(options.delete(:other_options).shift.to_s)||{})
54
- ) , 0 ]
52
+ options.merge(YAML.safe_load(options.delete(:other_options).shift.to_s) || {})
53
+ ), 0]
55
54
  end
56
55
 
57
56
  def get(options)
58
57
  res = Trocla.new(options.delete(:config_file)).get_password(
59
58
  options.delete(:trocla_key),
60
59
  options.delete(:trocla_format),
61
- options.merge(YAML.load(options.delete(:other_options).shift.to_s)||{})
60
+ options.merge(YAML.safe_load(options.delete(:other_options).shift.to_s) || {})
62
61
  )
63
- [ res, res.nil? ? 1 : 0 ]
62
+ [res, res.nil? ? 1 : 0]
64
63
  end
64
+
65
65
  def set(options)
66
66
  if options.delete(:ask_password)
67
67
  require 'highline/import'
@@ -69,7 +69,7 @@ def set(options)
69
69
  pwd2 = ask('Repeat password: ') { |q| q.echo = 'x' }.to_s
70
70
  unless password == pwd2
71
71
  STDERR.puts 'Passwords did not match, exiting!'
72
- return [ nil, 1 ]
72
+ return [nil, 1]
73
73
  end
74
74
  else
75
75
  password = options.delete(:password) || STDIN.read.chomp
@@ -78,24 +78,24 @@ def set(options)
78
78
  no_format = options.delete('no_format')
79
79
  trocla = Trocla.new(options.delete(:config_file))
80
80
  value = if no_format
81
- password
82
- else
83
- trocla.formats(format).format(password, (YAML.load(options.delete(:other_options).shift.to_s)||{}))
84
- end
81
+ password
82
+ else
83
+ trocla.formats(format).format(password, (YAML.safe_load(options.delete(:other_options).shift.to_s) || {}))
84
+ end
85
85
  trocla.set_password(
86
86
  options.delete(:trocla_key),
87
87
  format,
88
88
  value
89
89
  )
90
- [ '', 0 ]
90
+ ['', 0]
91
91
  end
92
92
 
93
93
  def reset(options)
94
- [ Trocla.new(options.delete(:config_file)).reset_password(
94
+ [Trocla.new(options.delete(:config_file)).reset_password(
95
95
  options.delete(:trocla_key),
96
96
  options.delete(:trocla_format),
97
- options.merge(YAML.load(options.delete(:other_options).shift.to_s)||{})
98
- ), 0 ]
97
+ options.merge(YAML.safe_load(options.delete(:other_options).shift.to_s) || {})
98
+ ), 0]
99
99
  end
100
100
 
101
101
  def delete(options)
@@ -103,19 +103,19 @@ def delete(options)
103
103
  options.delete(:trocla_key),
104
104
  options.delete(:trocla_format)
105
105
  )
106
- [ res, res.nil? ? 1 : 0 ]
106
+ [res, res.nil? ? 1 : 0]
107
107
  end
108
108
 
109
109
  def formats(options)
110
- key = (options.delete(:trocla_key) || '' )
110
+ key = (options.delete(:trocla_key) || '')
111
111
  if key.empty?
112
112
  "Available formats: #{Trocla::Formats.all.join(', ')}"
113
113
  else
114
114
  res = Trocla.new(options.delete(:config_file)).available_format(
115
115
  key,
116
- options.merge(YAML.load(options.delete(:other_options).shift.to_s)||{})
116
+ options.merge(YAML.safe_load(options.delete(:other_options).shift.to_s) || {})
117
117
  )
118
- [ res.nil? ? res : res.join(', '), res.nil? ? 1 : 0 ]
118
+ [res.nil? ? res : res.join(', '), res.nil? ? 1 : 0]
119
119
  end
120
120
  end
121
121
 
@@ -123,7 +123,7 @@ def search(options)
123
123
  res = Trocla.new(options.delete(:config_file)).search_key(
124
124
  options.delete(:trocla_key)
125
125
  )
126
- [ res.nil? ? res : res.join("\n"), res.nil? ? 1 : 0 ]
126
+ [res.nil? ? res : res.join("\n"), res.nil? ? 1 : 0]
127
127
  end
128
128
 
129
129
  def check_format(format_name)
@@ -136,30 +136,30 @@ def check_format(format_name)
136
136
  end
137
137
  end
138
138
 
139
- actions=['create','get','set','reset','delete','formats','search']
139
+ actions = ['create', 'get', 'set', 'reset', 'delete', 'formats', 'search']
140
140
 
141
141
  if (action=ARGV.shift) && actions.include?(action)
142
- options[:trocla_key] = ARGV.shift
143
- options[:trocla_format] = ARGV.shift
144
- options[:other_options] = ARGV
145
- check_format(options[:trocla_format]) unless ['delete','formats','search'].include?(action)
146
- begin
147
- result, excode = send(action,options)
148
- if result
149
- puts result.is_a?(String) ? result : result.inspect
150
- end
151
- rescue Exception => e
152
- unless e.message == 'exit'
153
- STDERR.puts "Action failed with the following message: #{e.message}"
154
- STDERR.puts '(See full trace by running task with --trace)'
155
- end
156
- raise e if options[:trace]
157
- exit 1
142
+ options[:trocla_key] = ARGV.shift
143
+ options[:trocla_format] = ARGV.shift
144
+ options[:other_options] = ARGV
145
+ check_format(options[:trocla_format]) unless ['delete','formats','search'].include?(action)
146
+ begin
147
+ result, excode = send(action, options)
148
+ if result
149
+ puts result.is_a?(String) ? result : result.inspect
158
150
  end
159
- exit excode.nil? ? 0 : excode
160
- else
161
- STDERR.puts "Please supply one of the following actions: #{actions.join(', ')}"
162
- STDERR.puts "Use #{$0} --help to get a list of options for these actions"
151
+ rescue Exception => e
152
+ unless e.message == 'exit'
153
+ STDERR.puts "Action failed with the following message: #{e.message}"
154
+ STDERR.puts '(See full trace by running task with --trace)'
155
+ end
156
+ raise e if options[:trace]
157
+
163
158
  exit 1
159
+ end
160
+ exit excode.nil? ? 0 : excode
161
+ else
162
+ STDERR.puts "Please supply one of the following actions: #{actions.join(', ')}"
163
+ STDERR.puts "Use #{$0} --help to get a list of options for these actions"
164
+ exit 1
164
165
  end
165
-
data/lib/VERSION CHANGED
@@ -1,4 +1,4 @@
1
1
  major:0
2
- minor:4
2
+ minor:5
3
3
  patch:0
4
4
  build:
@@ -7,9 +7,9 @@ store_options:
7
7
 
8
8
  encryption: :none
9
9
  options:
10
- random: true
11
- length: 16
12
- charset: default
10
+ random: true
11
+ length: 16
12
+ charset: default
13
13
 
14
14
  profiles:
15
15
  rootpw:
@@ -44,4 +44,3 @@ profiles:
44
44
  days: 2
45
45
  # 1 day
46
46
  expires: 86400
47
-
@@ -7,4 +7,3 @@ class Trocla::Encryptions::None < Trocla::Encryptions::Base
7
7
  value
8
8
  end
9
9
  end
10
-
@@ -5,7 +5,7 @@ class Trocla::Encryptions::Ssl < Trocla::Encryptions::Base
5
5
  def encrypt(value)
6
6
  ciphertext = ''
7
7
  value.scan(/.{0,#{chunksize}}/m).each do |chunk|
8
- ciphertext += Base64.encode64(public_key.public_encrypt(chunk)).gsub("\n",'')+"\n" if chunk
8
+ ciphertext += Base64.encode64(public_key.public_encrypt(chunk)).gsub("\n", '') + "\n" if chunk
9
9
  end
10
10
  ciphertext
11
11
  end
@@ -21,21 +21,21 @@ class Trocla::Encryptions::Ssl < Trocla::Encryptions::Base
21
21
  private
22
22
 
23
23
  def chunksize
24
- public_key.n.num_bytes - 11
24
+ public_key.n.num_bytes - 11
25
25
  end
26
26
 
27
27
  def private_key
28
- @private_key ||= begin
29
- file = require_option(:private_key)
30
- OpenSSL::PKey::RSA.new(File.read(file), nil)
31
- end
28
+ @private_key ||= begin
29
+ file = require_option(:private_key)
30
+ OpenSSL::PKey::RSA.new(File.read(file), nil)
31
+ end
32
32
  end
33
33
 
34
34
  def public_key
35
- @public_key ||= begin
36
- file = require_option(:public_key)
37
- OpenSSL::PKey::RSA.new(File.read(file), nil)
38
- end
35
+ @public_key ||= begin
36
+ file = require_option(:public_key)
37
+ OpenSSL::PKey::RSA.new(File.read(file), nil)
38
+ end
39
39
  end
40
40
 
41
41
  def option(key)
@@ -45,7 +45,7 @@ class Trocla::Encryptions::Ssl < Trocla::Encryptions::Base
45
45
  def require_option(key)
46
46
  val = option(key)
47
47
  raise "Config error: 'ssl_options' => :#{key} is not defined" if val.nil?
48
+
48
49
  val
49
50
  end
50
51
  end
51
-
@@ -1,18 +1,24 @@
1
- class Trocla::Encryptions
1
+ # frozen_string_literal: true
2
2
 
3
+ # Trocla::Encryptions
4
+ class Trocla::Encryptions
5
+ # Base
3
6
  class Base
4
7
  attr_reader :trocla, :config
8
+
5
9
  def initialize(config, trocla)
6
10
  @trocla = trocla
7
11
  @config = config
8
12
  end
9
13
 
10
- def encrypt(value)
14
+ def encrypt(_)
11
15
  raise NoMethodError.new("#{self.class.name} needs to implement 'encrypt()'")
16
+
12
17
  end
13
18
 
14
- def decrypt(value)
19
+ def decrypt(_)
15
20
  raise NoMethodError.new("#{self.class.name} needs to implement 'decrypt()'")
21
+
16
22
  end
17
23
  end
18
24
 
@@ -22,7 +28,7 @@ class Trocla::Encryptions
22
28
  end
23
29
 
24
30
  def all
25
- Dir[ path '*' ].collect do |enc|
31
+ Dir[path '*'].collect do |enc|
26
32
  File.basename(enc, '.rb').downcase
27
33
  end
28
34
  end
@@ -32,10 +38,11 @@ class Trocla::Encryptions
32
38
  end
33
39
 
34
40
  private
41
+
35
42
  def encryptions
36
43
  @@encryptions ||= Hash.new do |hash, encryption|
37
44
  encryption = encryption.to_s.downcase
38
- if File.exists?( path encryption )
45
+ if File.exist?(path encryption)
39
46
  require "trocla/encryptions/#{encryption}"
40
47
  class_name = "Trocla::Encryptions::#{encryption.capitalize}"
41
48
  hash[encryption] = (eval class_name)
@@ -1,7 +1,7 @@
1
1
  class Trocla::Formats::Bcrypt < Trocla::Formats::Base
2
2
  expensive true
3
3
  require 'bcrypt'
4
- def format(plain_password,options={})
5
- BCrypt::Password.create(plain_password, :cost => options['cost']||BCrypt::Engine.cost).to_s
4
+ def format(plain_password, options = {})
5
+ BCrypt::Password.create(plain_password, :cost => options['cost'] || BCrypt::Engine.cost).to_s
6
6
  end
7
7
  end
@@ -1,6 +1,6 @@
1
1
  # salted crypt
2
2
  class Trocla::Formats::Md5crypt < Trocla::Formats::Base
3
- def format(plain_password,options={})
4
- plain_password.crypt('$1$' << Trocla::Util.salt << '$')
3
+ def format(plain_password, options = {})
4
+ plain_password.crypt('$1$' << Trocla::Util.salt << '$')
5
5
  end
6
6
  end
@@ -1,6 +1,6 @@
1
1
  class Trocla::Formats::Mysql < Trocla::Formats::Base
2
2
  require 'digest/sha1'
3
- def format(plain_password,options={})
4
- "*" + Digest::SHA1.hexdigest(Digest::SHA1.digest(plain_password)).upcase
3
+ def format(plain_password, options = {})
4
+ '*' + Digest::SHA1.hexdigest(Digest::SHA1.digest(plain_password)).upcase
5
5
  end
6
6
  end
@@ -1,7 +1,54 @@
1
1
  class Trocla::Formats::Pgsql < Trocla::Formats::Base
2
2
  require 'digest/md5'
3
- def format(plain_password,options={})
4
- raise "You need pass the username as an option to use this format" unless options['username']
5
- "md5" + Digest::MD5.hexdigest(plain_password + options['username'])
3
+ require 'openssl'
4
+ require 'base64'
5
+ def format(plain_password, options = {})
6
+ encode = (options['encode'] || 'sha256')
7
+ case encode
8
+ when 'md5'
9
+ raise 'You need pass the username as an option to use this format' unless options['username']
10
+
11
+ 'md5' + Digest::MD5.hexdigest(plain_password + options['username'])
12
+ when 'sha256'
13
+ pg_sha256(plain_password)
14
+ else
15
+ raise 'Unkmow encode %s for pgsql password' % [encode]
16
+ end
17
+ end
18
+
19
+ private
20
+
21
+ def pg_sha256(password)
22
+ salt = OpenSSL::Random.random_bytes(16)
23
+ digest = digest_key(password, salt)
24
+ 'SCRAM-SHA-256$%s:%s$%s:%s' % [
25
+ '4096',
26
+ Base64.strict_encode64(salt),
27
+ Base64.strict_encode64(client_key(digest)),
28
+ Base64.strict_encode64(server_key(digest))
29
+ ]
30
+ end
31
+
32
+ def digest_key(password, salt)
33
+ OpenSSL::KDF.pbkdf2_hmac(
34
+ password,
35
+ salt: salt,
36
+ iterations: 4096,
37
+ length: 32,
38
+ hash: OpenSSL::Digest::SHA256.new
39
+ )
40
+ end
41
+
42
+ def client_key(digest_key)
43
+ hmac = OpenSSL::HMAC.new(digest_key, OpenSSL::Digest::SHA256.new)
44
+ hmac << 'Client Key'
45
+ hmac.digest
46
+ OpenSSL::Digest.new('SHA256').digest hmac.digest
47
+ end
48
+
49
+ def server_key(digest_key)
50
+ hmac = OpenSSL::HMAC.new(digest_key, OpenSSL::Digest::SHA256.new)
51
+ hmac << 'Server Key'
52
+ hmac.digest
6
53
  end
7
54
  end
@@ -1,7 +1,5 @@
1
1
  class Trocla::Formats::Plain < Trocla::Formats::Base
2
-
3
- def format(plain_password,options={})
2
+ def format(plain_password, options = {})
4
3
  plain_password
5
4
  end
6
-
7
5
  end
@@ -1,7 +1,7 @@
1
1
  class Trocla::Formats::Sha1 < Trocla::Formats::Base
2
2
  require 'digest/sha1'
3
3
  require 'base64'
4
- def format(plain_password,options={})
4
+ def format(plain_password, options = {})
5
5
  '{SHA}' + Base64.encode64(Digest::SHA1.digest(plain_password))
6
6
  end
7
7
  end
@@ -1,6 +1,6 @@
1
1
  # salted crypt
2
2
  class Trocla::Formats::Sha256crypt < Trocla::Formats::Base
3
- def format(plain_password,options={})
4
- plain_password.crypt('$5$' << Trocla::Util.salt << '$')
3
+ def format(plain_password, options = {})
4
+ plain_password.crypt('$5$' << Trocla::Util.salt << '$')
5
5
  end
6
6
  end
@@ -1,6 +1,6 @@
1
1
  # salted crypt
2
2
  class Trocla::Formats::Sha512crypt < Trocla::Formats::Base
3
- def format(plain_password,options={})
4
- plain_password.crypt('$6$' << Trocla::Util.salt << '$')
3
+ def format(plain_password, options = {})
4
+ plain_password.crypt('$6$' << Trocla::Util.salt << '$')
5
5
  end
6
6
  end
@@ -2,8 +2,8 @@
2
2
  require 'base64'
3
3
  require 'digest'
4
4
  class Trocla::Formats::Ssha < Trocla::Formats::Base
5
- def format(plain_password,options={})
6
- salt = options['salt'] || Trocla::Util.salt(16)
7
- "{SSHA}"+Base64.encode64("#{Digest::SHA1.digest("#{plain_password}#{salt}")}#{salt}").chomp
5
+ def format(plain_password, options = {})
6
+ salt = options['salt'] || Trocla::Util.salt(16)
7
+ '{SSHA}' + Base64.encode64("#{Digest::SHA1.digest("#{plain_password}#{salt}")}#{salt}").chomp
8
8
  end
9
9
  end
@@ -1,11 +1,9 @@
1
1
  require 'sshkey'
2
2
 
3
3
  class Trocla::Formats::Sshkey < Trocla::Formats::Base
4
-
5
4
  expensive true
6
5
 
7
6
  def format(plain_password,options={})
8
-
9
7
  if plain_password.match(/-----BEGIN RSA PRIVATE KEY-----.*-----END RSA PRIVATE KEY/m)
10
8
  # Import, validate ssh key
11
9
  begin
@@ -21,9 +19,8 @@ class Trocla::Formats::Sshkey < Trocla::Formats::Base
21
19
 
22
20
  begin
23
21
  sshkey = ::SSHKey.generate(
24
- type: type,
25
- bits: bits,
26
- comment: options['comment'],
22
+ type: type, bits: bits,
23
+ comment: options['comment'],
27
24
  passphrase: options['passphrase']
28
25
  )
29
26
  rescue Exception => e
@@ -33,14 +30,13 @@ class Trocla::Formats::Sshkey < Trocla::Formats::Base
33
30
  sshkey.private_key + sshkey.ssh_public_key
34
31
  end
35
32
 
36
- def render(output,render_options={})
33
+ def render(output, render_options = {})
37
34
  if render_options['privonly']
38
35
  ::SSHKey.new(output).private_key
39
36
  elsif render_options['pubonly']
40
37
  ::SSHKey.new(output).ssh_public_key
41
38
  else
42
- super(output,render_options)
39
+ super(output, render_options)
43
40
  end
44
41
  end
45
-
46
42
  end
@@ -0,0 +1,45 @@
1
+ require 'open3'
2
+ require 'yaml'
3
+
4
+ class Trocla::Formats::Wireguard < Trocla::Formats::Base
5
+ expensive true
6
+
7
+ def format(plain_password, options={})
8
+ return YAML.safe_load(plain_password) if plain_password.match(/---/)
9
+
10
+ wg_priv = nil
11
+ wg_pub = nil
12
+ begin
13
+ Open3.popen3('wg genkey') do |_stdin, stdout, _stderr, _waiter|
14
+ wg_priv = stdout.read.chomp
15
+ end
16
+ rescue SystemCallError => e
17
+ raise 'trocla wireguard: wg binary not found' if e.message =~ /No such file or directory/
18
+
19
+ raise "trocla wireguard: #{e.message}"
20
+ end
21
+
22
+ begin
23
+ Open3.popen3('wg pubkey') do |stdin, stdout, _stderr, _waiter|
24
+ stdin.write(wg_priv)
25
+ stdin.close
26
+
27
+ wg_pub = stdout.read.chomp
28
+ end
29
+ rescue SystemCallError => e
30
+ raise "trocla wireguard: #{e.message}"
31
+ end
32
+ YAML.dump({ 'wg_priv' => wg_priv, 'wg_pub' => wg_pub })
33
+ end
34
+
35
+ def render(output, render_options = {})
36
+ data = YAML.safe_load(output)
37
+ if render_options['privonly']
38
+ data['wg_priv']
39
+ elsif render_options['pubonly']
40
+ data['wg_pub']
41
+ else
42
+ 'pub: ' + data['wg_pub'] + "\npriv: " + data['wg_priv']
43
+ end
44
+ end
45
+ end