sym 2.3.0 → 2.4.3
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +55 -2
- data/README.md +106 -70
- data/Rakefile +3 -2
- data/bin/sym.completion +6 -2
- data/lib/sym.rb +28 -15
- data/lib/sym/app.rb +1 -3
- data/lib/sym/app/args.rb +5 -1
- data/lib/sym/app/cli.rb +54 -6
- data/lib/sym/app/cli_slop.rb +35 -23
- data/lib/sym/app/commands/base_command.rb +12 -19
- data/lib/sym/app/commands/bash_completion.rb +19 -3
- data/lib/sym/app/commands/decrypt.rb +1 -1
- data/lib/sym/app/commands/encrypt.rb +1 -1
- data/lib/sym/app/commands/generate_key.rb +7 -3
- data/lib/sym/app/commands/keychain_add_key.rb +7 -2
- data/lib/sym/app/commands/open_editor.rb +1 -1
- data/lib/sym/app/commands/password_protect_key.rb +9 -4
- data/lib/sym/app/commands/print_key.rb +3 -3
- data/lib/sym/app/commands/show_examples.rb +25 -17
- data/lib/sym/app/commands/show_help.rb +2 -2
- data/lib/sym/app/keychain.rb +5 -0
- data/lib/sym/app/output/base.rb +3 -7
- data/lib/sym/app/output/file.rb +0 -1
- data/lib/sym/app/output/noop.rb +2 -1
- data/lib/sym/app/password/providers.rb +4 -0
- data/lib/sym/app/password/providers/memcached_provider.rb +1 -1
- data/lib/sym/app/private_key/base64_decoder.rb +1 -0
- data/lib/sym/app/private_key/decryptor.rb +1 -0
- data/lib/sym/app/private_key/detector.rb +45 -26
- data/lib/sym/app/private_key/handler.rb +20 -25
- data/lib/sym/app/private_key/key_source_check.rb +89 -0
- data/lib/sym/application.rb +115 -33
- data/lib/sym/configuration.rb +1 -0
- data/lib/sym/constants.rb +24 -0
- data/lib/sym/data/decoder.rb +2 -1
- data/lib/sym/data/wrapper_struct.rb +1 -1
- data/lib/sym/extensions/stdlib.rb +1 -0
- data/lib/sym/version.rb +1 -1
- data/sym.gemspec +1 -1
- metadata +5 -4
- data/lib/sym/encrypted_file.rb +0 -34
data/lib/sym/application.rb
CHANGED
@@ -2,62 +2,80 @@ require 'colored2'
|
|
2
2
|
require 'sym'
|
3
3
|
require 'sym/app'
|
4
4
|
require 'openssl'
|
5
|
+
require 'json'
|
5
6
|
|
6
7
|
module Sym
|
7
8
|
class Application
|
8
9
|
|
9
10
|
attr_accessor :opts,
|
10
|
-
:
|
11
|
+
:opts_original,
|
12
|
+
:opts,
|
13
|
+
:provided_options,
|
11
14
|
:args,
|
12
15
|
:action,
|
13
16
|
:key,
|
17
|
+
:key_source,
|
14
18
|
:input_handler,
|
15
19
|
:key_handler,
|
16
20
|
:result,
|
17
21
|
:password_cache
|
18
22
|
|
19
23
|
def initialize(opts)
|
20
|
-
self.
|
21
|
-
self.
|
22
|
-
self.args = ::Sym::App::Args.new(opts_hash)
|
24
|
+
self.opts_original = opts
|
25
|
+
self.opts = opts.is_a?(Hash) ? opts : opts.to_hash
|
23
26
|
|
27
|
+
process_negated_option(opts[:negate]) if opts[:negate]
|
28
|
+
self.args = ::Sym::App::Args.new(self.provided_options)
|
29
|
+
|
30
|
+
initialize_action
|
31
|
+
initialize_data_source
|
24
32
|
initialize_password_cache
|
25
33
|
initialize_input_handler
|
26
|
-
initialize_key_handler
|
27
|
-
initialize_action
|
28
34
|
end
|
29
35
|
|
30
|
-
def
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
+
def provided_options
|
37
|
+
provided_opts = self.opts.clone
|
38
|
+
provided_opts.delete_if { |k, v| !v }
|
39
|
+
provided_opts
|
40
|
+
end
|
41
|
+
|
42
|
+
def provided_safe_options
|
43
|
+
provided_options.map do |k, v|
|
44
|
+
k == :key && [44, 45].include?(v.size) ?
|
45
|
+
[k, '[reducted]'] :
|
46
|
+
[k, v]
|
47
|
+
end.to_h
|
48
|
+
end
|
49
|
+
|
50
|
+
def provided_flags
|
51
|
+
provided_flags = provided_options
|
52
|
+
provided_flags.delete_if { |k, v| ![false, true].include?(v) }
|
53
|
+
provided_flags.keys
|
54
|
+
end
|
55
|
+
|
56
|
+
def provided_value_options
|
57
|
+
provided = provided_safe_options
|
58
|
+
provided.delete_if { |k, v| [false, true].include?(v) }
|
59
|
+
provided
|
36
60
|
end
|
37
61
|
|
38
62
|
def execute!
|
39
|
-
|
40
|
-
log :debug, 'operation requires a key...'
|
41
|
-
self.key = Sym::App::PrivateKey::Handler.new(opts, input_handler, password_cache).key
|
42
|
-
unless self.key
|
43
|
-
log :error, 'Unable to determine the key, which appears to be required'
|
44
|
-
raise Sym::Errors::NoPrivateKeyFound, 'Private key is required'
|
45
|
-
end
|
46
|
-
end
|
47
|
-
log :info, "detected command [#{command.class.name}]"
|
63
|
+
initialize_key_source
|
48
64
|
unless command
|
49
|
-
raise Sym::Errors::InsufficientOptionsError,
|
65
|
+
raise Sym::Errors::InsufficientOptionsError,
|
66
|
+
" Can not determine what to do
|
67
|
+
from the options: \ n " +
|
68
|
+
" #{self.provided_options.inspect.green.bold}\n" +
|
69
|
+
"and flags #{self.provided_flags.to_s.green.bold}"
|
70
|
+
end
|
71
|
+
log :info, "command located is #{command.class.name.blue.bold}"
|
72
|
+
self.result = command.execute.tap do |result|
|
73
|
+
log :info, "result is #{result.nil? ? 'nil' : result[0..10].to_s.blue.bold }..." if opts[:trace]
|
50
74
|
end
|
51
|
-
self.result = command.execute
|
52
|
-
end
|
53
|
-
|
54
|
-
def log(*args)
|
55
|
-
Sym::App.log(*args, **opts)
|
56
75
|
end
|
57
76
|
|
58
77
|
def execute
|
59
78
|
execute!
|
60
|
-
|
61
79
|
rescue ::OpenSSL::Cipher::CipherError => e
|
62
80
|
{ reason: 'Invalid key provided',
|
63
81
|
exception: e }
|
@@ -67,8 +85,8 @@ module Sym
|
|
67
85
|
exception: e }
|
68
86
|
|
69
87
|
rescue TypeError => e
|
70
|
-
if e.message =~ /marshal/
|
71
|
-
{ reason:
|
88
|
+
if e.message =~ /marshal/m
|
89
|
+
{ reason: 'Corrupt source data or invalid/corrupt key provided',
|
72
90
|
exception: e }
|
73
91
|
else
|
74
92
|
{ exception: e }
|
@@ -84,10 +102,17 @@ module Sym
|
|
84
102
|
@command
|
85
103
|
end
|
86
104
|
|
105
|
+
def log(*args)
|
106
|
+
Sym::App.log(*args, **opts)
|
107
|
+
end
|
108
|
+
|
87
109
|
def editor
|
88
110
|
editors_to_try.find { |editor| File.exist?(editor) }
|
89
111
|
end
|
90
112
|
|
113
|
+
|
114
|
+
private
|
115
|
+
|
91
116
|
def editors_to_try
|
92
117
|
[
|
93
118
|
ENV['EDITOR'],
|
@@ -108,17 +133,74 @@ module Sym
|
|
108
133
|
end
|
109
134
|
|
110
135
|
def initialize_key_handler
|
111
|
-
self.key_handler = ::Sym::App::PrivateKey::Handler.new(
|
136
|
+
self.key_handler = ::Sym::App::PrivateKey::Handler.new(opts, input_handler, password_cache)
|
112
137
|
end
|
113
138
|
|
114
139
|
def initialize_password_cache
|
115
140
|
args = {}
|
116
|
-
args[:timeout] = opts[:
|
117
|
-
args[:enabled] = opts[:
|
141
|
+
args[:timeout] = (opts[:cache_timeout] || ENV['SYM_CACHE_TTL'] || Sym::Configuration.config.password_cache_timeout).to_i
|
142
|
+
args[:enabled] = opts[:cache_passwords]
|
118
143
|
args[:verbose] = opts[:verbose]
|
119
144
|
args[:provider] = opts[:cache_provider] if opts[:cache_provider]
|
120
145
|
|
121
146
|
self.password_cache = Sym::App::Password::Cache.instance.configure(args)
|
122
147
|
end
|
148
|
+
|
149
|
+
def process_negated_option(file)
|
150
|
+
opts.delete(:negate)
|
151
|
+
opts[:file] = file
|
152
|
+
extension = Sym.config.encrypted_file_extension
|
153
|
+
if file.end_with?('.enc')
|
154
|
+
opts[:decrypt] = true
|
155
|
+
opts[:output] = file.gsub(/\.#{extension}/, '')
|
156
|
+
opts.delete(:output) if opts[:output] == ''
|
157
|
+
else
|
158
|
+
opts[:encrypt] = true
|
159
|
+
opts[:output] = "#{file}.#{extension}"
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
def initialize_action
|
164
|
+
self.action = if opts[:encrypt] then
|
165
|
+
:encr
|
166
|
+
elsif opts[:decrypt]
|
167
|
+
:decr
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
# If we are encrypting or decrypting, and no data has been provided, check if we
|
172
|
+
# should read from STDIN
|
173
|
+
def initialize_data_source
|
174
|
+
if self.action && opts[:string].nil? && opts[:file].nil? && !(STDIN.tty?)
|
175
|
+
opts[:file] = '-'
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
# If no key is provided with command line options, check the default
|
180
|
+
# key location (which can be changed via Configuration class).
|
181
|
+
# In any case, attempt to initialize the key one way or another.
|
182
|
+
def initialize_key_source
|
183
|
+
detect_key_source
|
184
|
+
|
185
|
+
if args.require_key? && !self.key
|
186
|
+
log :error, 'Unable to determine the key, which appears to be required with current args'
|
187
|
+
raise Sym::Errors::NoPrivateKeyFound, 'Private key is required when ' + provided_flags.join(', ') << 'ing.'
|
188
|
+
end
|
189
|
+
log :debug, "initialize_key_source: detected key ends with [...#{(key ? key[-5..-1] : 'nil').bold.magenta}]"
|
190
|
+
log :debug, "opts: #{self.provided_value_options.to_s.green.bold}"
|
191
|
+
log :debug, "flags: #{self.provided_flags.to_s.green.bold}"
|
192
|
+
end
|
193
|
+
|
194
|
+
def detect_key_source
|
195
|
+
initialize_key_handler
|
196
|
+
self.key = self.key_handler.key
|
197
|
+
if self.key
|
198
|
+
self.key_source = key_handler.key_source
|
199
|
+
if key_source =~ /^default_file/
|
200
|
+
opts[:key] = self.key
|
201
|
+
end
|
202
|
+
log :info, "key was detected from source #{key_source.to_s.bold.green}"
|
203
|
+
end
|
204
|
+
end
|
123
205
|
end
|
124
206
|
end
|
data/lib/sym/configuration.rb
CHANGED
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'logger'
|
2
|
+
module Sym
|
3
|
+
module Constants
|
4
|
+
module Completion
|
5
|
+
FILE = '.sym.completion'.freeze
|
6
|
+
PATH = "#{ENV['HOME']}/#{FILE}".freeze
|
7
|
+
Config = {
|
8
|
+
file: File.expand_path('../../../bin/sym.completion', __FILE__),
|
9
|
+
script: "[[ -f '#{PATH}' ]] && source '#{PATH}'",
|
10
|
+
}.freeze
|
11
|
+
|
12
|
+
end
|
13
|
+
|
14
|
+
module Log
|
15
|
+
NIL = Logger.new(nil).freeze # empty logger
|
16
|
+
LOG = Logger.new(STDERR).freeze
|
17
|
+
end
|
18
|
+
|
19
|
+
ENV_ARGS_VARIABLE_NAME = 'SYM_ARGS'.freeze
|
20
|
+
SYM_KEY_FILE = "#{ENV['HOME']}/.sym.key"
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
|
data/lib/sym/data/decoder.rb
CHANGED
data/lib/sym/version.rb
CHANGED
data/sym.gemspec
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sym
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.3
|
4
|
+
version: 2.4.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Konstantin Gredeskoul
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-
|
11
|
+
date: 2017-03-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: colored2
|
@@ -274,15 +274,16 @@ files:
|
|
274
274
|
- lib/sym/app/private_key/decryptor.rb
|
275
275
|
- lib/sym/app/private_key/detector.rb
|
276
276
|
- lib/sym/app/private_key/handler.rb
|
277
|
+
- lib/sym/app/private_key/key_source_check.rb
|
277
278
|
- lib/sym/app/short_name.rb
|
278
279
|
- lib/sym/application.rb
|
279
280
|
- lib/sym/cipher_handler.rb
|
280
281
|
- lib/sym/configuration.rb
|
282
|
+
- lib/sym/constants.rb
|
281
283
|
- lib/sym/data.rb
|
282
284
|
- lib/sym/data/decoder.rb
|
283
285
|
- lib/sym/data/encoder.rb
|
284
286
|
- lib/sym/data/wrapper_struct.rb
|
285
|
-
- lib/sym/encrypted_file.rb
|
286
287
|
- lib/sym/errors.rb
|
287
288
|
- lib/sym/extensions/class_methods.rb
|
288
289
|
- lib/sym/extensions/instance_methods.rb
|
@@ -315,7 +316,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
315
316
|
version: '0'
|
316
317
|
requirements: []
|
317
318
|
rubyforge_project:
|
318
|
-
rubygems_version: 2.
|
319
|
+
rubygems_version: 2.5.2
|
319
320
|
signing_key:
|
320
321
|
specification_version: 4
|
321
322
|
summary: Super easy to use encryption library & a CLI with a strong aes-256-cbc cipher
|
data/lib/sym/encrypted_file.rb
DELETED
@@ -1,34 +0,0 @@
|
|
1
|
-
require 'sym'
|
2
|
-
require 'sym/application'
|
3
|
-
require 'sym/app/args'
|
4
|
-
|
5
|
-
module Sym
|
6
|
-
# This class provides a convenience wrapper for opening and reading
|
7
|
-
# encrypted files as they were regular files, and then possibly writing
|
8
|
-
# changes to them later.
|
9
|
-
|
10
|
-
class EncryptedFile
|
11
|
-
|
12
|
-
include Sym
|
13
|
-
|
14
|
-
attr_reader :application, :file, :key_id, :key_type, :app_args
|
15
|
-
|
16
|
-
def initialize(file:, key_id:, key_type:)
|
17
|
-
@file = file
|
18
|
-
@key_id = key_id
|
19
|
-
@key_type = key_type.to_sym
|
20
|
-
@app_args = { file: file, key_type => key_id, decrypt: true }
|
21
|
-
@application = Sym::Application.new(self.app_args)
|
22
|
-
end
|
23
|
-
|
24
|
-
def read
|
25
|
-
@content = application.execute! unless @content
|
26
|
-
@content
|
27
|
-
end
|
28
|
-
|
29
|
-
def write
|
30
|
-
Sym::Application.new(file: file, key_type => key_id, encrypt: true, output: file).execute
|
31
|
-
end
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|