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 +4 -4
- data/.github/workflows/ruby.yml +24 -0
- data/.rspec +1 -1
- data/CHANGELOG.md +11 -0
- data/Gemfile +10 -9
- data/README.md +18 -2
- data/bin/trocla +42 -42
- data/lib/VERSION +1 -1
- data/lib/trocla/default_config.yaml +3 -4
- data/lib/trocla/encryptions/none.rb +0 -1
- data/lib/trocla/encryptions/ssl.rb +11 -11
- data/lib/trocla/encryptions.rb +12 -5
- data/lib/trocla/formats/bcrypt.rb +2 -2
- data/lib/trocla/formats/md5crypt.rb +2 -2
- data/lib/trocla/formats/mysql.rb +2 -2
- data/lib/trocla/formats/pgsql.rb +50 -3
- data/lib/trocla/formats/plain.rb +1 -3
- data/lib/trocla/formats/sha1.rb +1 -1
- data/lib/trocla/formats/sha256crypt.rb +2 -2
- data/lib/trocla/formats/sha512crypt.rb +2 -2
- data/lib/trocla/formats/ssha.rb +3 -3
- data/lib/trocla/formats/sshkey.rb +4 -8
- data/lib/trocla/formats/wireguard.rb +45 -0
- data/lib/trocla/formats/x509.rb +54 -46
- data/lib/trocla/formats.rb +15 -5
- data/lib/trocla/store.rb +16 -15
- data/lib/trocla/stores/memory.rb +17 -10
- data/lib/trocla/stores/moneta.rb +29 -19
- data/lib/trocla/stores/vault.rb +42 -14
- data/lib/trocla/stores.rb +3 -2
- data/lib/trocla/util.rb +28 -17
- data/lib/trocla/version.rb +7 -4
- data/lib/trocla.rb +47 -45
- data/spec/trocla/formats/pgsql_spec.rb +25 -0
- data/spec/trocla_spec.rb +3 -0
- data/trocla.gemspec +17 -13
- metadata +30 -14
- data/.travis.yml +0 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2d6d84b42cc62b4ab04eea0478d9e4801939c1d31accd0dba4a27e272f56dad2
|
4
|
+
data.tar.gz: 6a322a8ae343b6723476b53e9ff7158adaa8d1537bbb46fbc81ef5ebd5a6cff2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
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
|
7
|
-
gem
|
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
|
13
|
-
gem
|
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
|
19
|
-
gem
|
20
|
-
gem
|
21
|
-
gem
|
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.
|
169
|
-
|
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
|
-
[
|
49
|
+
[Trocla.new(options.delete(:config_file)).password(
|
51
50
|
options.delete(:trocla_key),
|
52
51
|
options.delete(:trocla_format),
|
53
|
-
options.merge(YAML.
|
54
|
-
)
|
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.
|
60
|
+
options.merge(YAML.safe_load(options.delete(:other_options).shift.to_s) || {})
|
62
61
|
)
|
63
|
-
[
|
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 [
|
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
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
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
|
-
[
|
90
|
+
['', 0]
|
91
91
|
end
|
92
92
|
|
93
93
|
def reset(options)
|
94
|
-
[
|
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.
|
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
|
-
[
|
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.
|
116
|
+
options.merge(YAML.safe_load(options.delete(:other_options).shift.to_s) || {})
|
117
117
|
)
|
118
|
-
[
|
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
|
-
[
|
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
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
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
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
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
@@ -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
|
-
|
24
|
+
public_key.n.num_bytes - 11
|
25
25
|
end
|
26
26
|
|
27
27
|
def private_key
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
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
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
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
|
-
|
data/lib/trocla/encryptions.rb
CHANGED
@@ -1,18 +1,24 @@
|
|
1
|
-
|
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(
|
14
|
+
def encrypt(_)
|
11
15
|
raise NoMethodError.new("#{self.class.name} needs to implement 'encrypt()'")
|
16
|
+
|
12
17
|
end
|
13
18
|
|
14
|
-
def decrypt(
|
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[
|
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.
|
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
|
-
|
3
|
+
def format(plain_password, options = {})
|
4
|
+
plain_password.crypt('$1$' << Trocla::Util.salt << '$')
|
5
5
|
end
|
6
6
|
end
|
data/lib/trocla/formats/mysql.rb
CHANGED
@@ -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
|
-
|
3
|
+
def format(plain_password, options = {})
|
4
|
+
'*' + Digest::SHA1.hexdigest(Digest::SHA1.digest(plain_password)).upcase
|
5
5
|
end
|
6
6
|
end
|
data/lib/trocla/formats/pgsql.rb
CHANGED
@@ -1,7 +1,54 @@
|
|
1
1
|
class Trocla::Formats::Pgsql < Trocla::Formats::Base
|
2
2
|
require 'digest/md5'
|
3
|
-
|
4
|
-
|
5
|
-
|
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
|
data/lib/trocla/formats/plain.rb
CHANGED
data/lib/trocla/formats/sha1.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# salted crypt
|
2
2
|
class Trocla::Formats::Sha256crypt < Trocla::Formats::Base
|
3
|
-
def format(plain_password,options={})
|
4
|
-
|
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
|
-
|
3
|
+
def format(plain_password, options = {})
|
4
|
+
plain_password.crypt('$6$' << Trocla::Util.salt << '$')
|
5
5
|
end
|
6
6
|
end
|
data/lib/trocla/formats/ssha.rb
CHANGED
@@ -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
|
-
|
7
|
-
|
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:
|
25
|
-
|
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
|