sym 2.8.5 → 2.10.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.circleci/config.yml +19 -12
- data/.envrc +7 -0
- data/.gitignore +1 -0
- data/.rubocop.yml +150 -928
- data/.travis.yml +16 -28
- data/CHANGELOG.md +201 -174
- data/Gemfile +1 -0
- data/README.adoc +650 -0
- data/Rakefile +6 -2
- data/codecov.yml +29 -0
- data/exe/keychain +1 -1
- data/exe/sym +5 -2
- data/lib/ruby_warnings.rb +7 -0
- data/lib/sym.rb +1 -7
- data/lib/sym/app.rb +1 -1
- data/lib/sym/app/args.rb +3 -2
- data/lib/sym/app/cli.rb +1 -2
- data/lib/sym/app/cli_slop.rb +1 -1
- data/lib/sym/app/commands.rb +1 -1
- data/lib/sym/app/commands/base_command.rb +1 -1
- data/lib/sym/app/commands/bash_completion.rb +2 -2
- data/lib/sym/app/commands/open_editor.rb +1 -1
- data/lib/sym/app/commands/password_protect_key.rb +4 -4
- data/lib/sym/app/commands/show_examples.rb +1 -1
- data/lib/sym/app/keychain.rb +15 -9
- data/lib/sym/app/output/noop.rb +2 -1
- data/lib/sym/app/password/cache.rb +1 -1
- data/lib/sym/app/password/providers.rb +2 -3
- data/lib/sym/app/private_key/decryptor.rb +2 -2
- data/lib/sym/app/private_key/detector.rb +4 -7
- data/lib/sym/application.rb +5 -10
- data/lib/sym/constants.rb +4 -4
- data/lib/sym/data/wrapper_struct.rb +20 -12
- data/lib/sym/errors.rb +11 -2
- data/lib/sym/extensions/instance_methods.rb +7 -8
- data/lib/sym/extensions/stdlib.rb +0 -1
- data/lib/sym/extensions/with_retry.rb +1 -1
- data/lib/sym/extensions/with_timeout.rb +1 -1
- data/lib/sym/version.rb +30 -5
- data/sym.gemspec +35 -35
- metadata +86 -68
- data/README.md +0 -620
- data/lib/sym/app/password/providers/drb_provider.rb +0 -41
data/Rakefile
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'bundler/gem_tasks'
|
2
2
|
require 'rspec/core/rake_task'
|
3
|
+
require 'rubocop/rake_task'
|
3
4
|
require 'yard'
|
4
5
|
require 'timeout'
|
5
6
|
|
@@ -25,14 +26,17 @@ task :build => :permissions
|
|
25
26
|
|
26
27
|
YARD::Rake::YardocTask.new(:doc) do |t|
|
27
28
|
t.files = %w(lib/**/*.rb exe/*.rb - README.md LICENSE)
|
28
|
-
t.options.unshift('--title','"Sym – Symmetric Key Encryption for Your Data"')
|
29
|
-
t.after = ->
|
29
|
+
t.options.unshift('--title', '"Sym – Symmetric Key Encryption for Your Data"')
|
30
|
+
t.after = -> { exec('open doc/index.html') }
|
30
31
|
end
|
31
32
|
|
32
33
|
RSpec::Core::RakeTask.new(:spec)
|
33
34
|
|
35
|
+
RuboCop::RakeTask.new
|
36
|
+
|
34
37
|
task :default => :spec
|
35
38
|
|
36
39
|
|
37
40
|
|
38
41
|
|
42
|
+
|
data/codecov.yml
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
codecov:
|
2
|
+
require_ci_to_pass: no
|
3
|
+
|
4
|
+
notify:
|
5
|
+
wait_for_ci: yes
|
6
|
+
|
7
|
+
parsers:
|
8
|
+
v1:
|
9
|
+
include_full_missed_files: true # To use with Ruby so we see files that have NO tests written
|
10
|
+
|
11
|
+
coverage:
|
12
|
+
range: 50..75
|
13
|
+
round: down
|
14
|
+
precision: 1
|
15
|
+
status:
|
16
|
+
project:
|
17
|
+
default: off
|
18
|
+
sym:
|
19
|
+
target: 70%
|
20
|
+
threshold: 10%
|
21
|
+
informational: true
|
22
|
+
if_not_found: success
|
23
|
+
if_ci_failed: error
|
24
|
+
paths:
|
25
|
+
- lib/
|
26
|
+
flags:
|
27
|
+
sym:
|
28
|
+
paths:
|
29
|
+
- lib/
|
data/exe/keychain
CHANGED
data/exe/sym
CHANGED
@@ -1,4 +1,7 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
|
+
# vim: ft=ruby
|
3
|
+
|
4
|
+
require_relative '../lib/ruby_warnings'
|
2
5
|
|
3
6
|
lib_path = File.expand_path(File.dirname(__FILE__) + '/../lib')
|
4
7
|
$LOAD_PATH << lib_path if File.exist?(lib_path) && !$LOAD_PATH.include?(lib_path)
|
@@ -6,12 +9,12 @@ $LOAD_PATH << lib_path if File.exist?(lib_path) && !$LOAD_PATH.include?(lib_path
|
|
6
9
|
require 'sym'
|
7
10
|
require 'sym/app'
|
8
11
|
|
9
|
-
#ARGV.any?{ |a| a =~ /^-/ } ?
|
12
|
+
# ARGV.any?{ |a| a =~ /^-/ } ?
|
10
13
|
begin
|
11
14
|
exit ::Sym::App::CLI.new(ARGV.dup).execute
|
12
15
|
rescue Interrupt => e
|
13
16
|
STDERR.flush
|
14
|
-
|
17
|
+
warn "Interrupt, #{e.message}, exiting."
|
15
18
|
STDERR.flush
|
16
19
|
exit 1
|
17
20
|
end
|
data/lib/sym.rb
CHANGED
@@ -21,17 +21,11 @@ Sym::Configuration.configure do |config|
|
|
21
21
|
# When nil is selected, providers are auto-detected.
|
22
22
|
config.password_cache_default_provider = nil
|
23
23
|
config.password_cache_arguments = {
|
24
|
-
drb: {
|
25
|
-
opts: {
|
26
|
-
uri: 'druby://127.0.0.1:24924'
|
27
|
-
}
|
28
|
-
},
|
29
24
|
memcached: {
|
30
25
|
args: %w(127.0.0.1:11211),
|
31
26
|
opts: { namespace: 'sym',
|
32
27
|
compress: true,
|
33
|
-
expires_in: config.password_cache_timeout
|
34
|
-
}
|
28
|
+
expires_in: config.password_cache_timeout}
|
35
29
|
|
36
30
|
}
|
37
31
|
}
|
data/lib/sym/app.rb
CHANGED
data/lib/sym/app/args.rb
CHANGED
@@ -12,7 +12,7 @@ module Sym
|
|
12
12
|
|
13
13
|
def initialize(opts)
|
14
14
|
self.opts = opts
|
15
|
-
self.selected_options = opts.keys.
|
15
|
+
self.selected_options = opts.keys.select { |k| opts[k] }
|
16
16
|
end
|
17
17
|
|
18
18
|
def specify_key?
|
@@ -33,10 +33,11 @@ module Sym
|
|
33
33
|
end
|
34
34
|
|
35
35
|
def provided_options
|
36
|
-
opts.to_hash.keys.
|
36
|
+
opts.to_hash.keys.select { |k| opts[k] }
|
37
37
|
end
|
38
38
|
|
39
39
|
private
|
40
|
+
|
40
41
|
def do?(list)
|
41
42
|
!(list & selected_options).empty?
|
42
43
|
end
|
data/lib/sym/app/cli.rb
CHANGED
@@ -60,7 +60,6 @@ module Sym
|
|
60
60
|
|
61
61
|
|
62
62
|
def initialize(argv, stdin = STDIN, stdout = STDOUT, stderr = STDERR, kernel = nil)
|
63
|
-
|
64
63
|
self.stdin = stdin
|
65
64
|
self.stdout = stdout
|
66
65
|
self.stderr = stderr
|
@@ -140,7 +139,7 @@ module Sym
|
|
140
139
|
private
|
141
140
|
|
142
141
|
def log(*args)
|
143
|
-
Sym::App.log(*args, **
|
142
|
+
Sym::App.log(*args, **opts.to_hash)
|
144
143
|
end
|
145
144
|
|
146
145
|
def error(hash)
|
data/lib/sym/app/cli_slop.rb
CHANGED
@@ -55,7 +55,7 @@ module Sym
|
|
55
55
|
o.separator 'Create a new private key:'.yellow
|
56
56
|
o.bool '-g', '--generate', ' generate a new private key'
|
57
57
|
o.bool '-p', '--password', ' encrypt the key with a password'
|
58
|
-
if Sym::App.
|
58
|
+
if Sym::App.osx?
|
59
59
|
o.string '-x', '--keychain', '[key-name] '.blue + 'write the key to OS-X Keychain'
|
60
60
|
end
|
61
61
|
|
data/lib/sym/app/commands.rb
CHANGED
@@ -37,7 +37,7 @@ module Sym
|
|
37
37
|
# Sort commands based on the #dependencies array, which itself is sorted
|
38
38
|
# based on command dependencies.
|
39
39
|
def sorted_commands
|
40
|
-
@sorted_commands ||= self.commands.to_a.sort_by{|klass| dependencies.index(klass.short_name) }
|
40
|
+
@sorted_commands ||= self.commands.to_a.sort_by{ |klass| dependencies.index(klass.short_name) }
|
41
41
|
@sorted_commands
|
42
42
|
end
|
43
43
|
|
@@ -15,7 +15,7 @@ module Sym
|
|
15
15
|
file = opts[:bash_support]
|
16
16
|
|
17
17
|
out = ''
|
18
|
-
Sym::Constants::Bash::
|
18
|
+
Sym::Constants::Bash::CONFIG.each_pair do |key, config|
|
19
19
|
script_name = key.to_s
|
20
20
|
|
21
21
|
# This removes the old version of this file.
|
@@ -43,7 +43,7 @@ module Sym
|
|
43
43
|
out << "\nPlease reload your terminal session to activate bash completion\n"
|
44
44
|
out << "and other installed BASH utilities.\n"
|
45
45
|
out << "\nAlternatively, just type #{"source #{file}".bold.green} to reload BASH.\n"
|
46
|
-
out << "Also — go ahead and try running #{
|
46
|
+
out << "Also — go ahead and try running #{'sym -h'.bold.blue} and #{'symit -h'.bold.blue}.\n"
|
47
47
|
end
|
48
48
|
|
49
49
|
private
|
@@ -48,7 +48,7 @@ module Sym
|
|
48
48
|
end
|
49
49
|
|
50
50
|
def timestamp
|
51
|
-
@timestamp ||= Time.now.to_a.select { |d| d.is_a?(
|
51
|
+
@timestamp ||= Time.now.to_a.select { |d| d.is_a?(Integer) }.map { |d| '%02d' % d }[0..-3].reverse.join
|
52
52
|
end
|
53
53
|
|
54
54
|
def process(code)
|
@@ -16,10 +16,10 @@ module Sym
|
|
16
16
|
the_key = self.key
|
17
17
|
|
18
18
|
if opts[:password]
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
19
|
+
encrypted_key, password = encrypt_with_password(the_key)
|
20
|
+
add_password_to_the_cache(encrypted_key, password)
|
21
|
+
the_key = encrypted_key
|
22
|
+
end
|
23
23
|
|
24
24
|
add_to_keychain_if_needed(the_key)
|
25
25
|
|
@@ -56,7 +56,7 @@ Diff:
|
|
56
56
|
# (c) 2016 Konstantin Gredeskoul. All rights reserved.'.green.bold)
|
57
57
|
|
58
58
|
|
59
|
-
if Sym::App.
|
59
|
+
if Sym::App.osx?
|
60
60
|
output << example(comment: 'generate a new password-encrypted key, save it to your Keychain:',
|
61
61
|
command: 'sym -gpcx staging.key')
|
62
62
|
|
data/lib/sym/app/keychain.rb
CHANGED
@@ -39,11 +39,13 @@ module Sym
|
|
39
39
|
self.key_name = key_name
|
40
40
|
self.opts = opts
|
41
41
|
self.class.validate!
|
42
|
-
stderr_off
|
42
|
+
opts[:trace] ? stderr_on : stderr_off
|
43
43
|
end
|
44
44
|
|
45
45
|
def add(password)
|
46
|
-
|
46
|
+
delete rescue nil
|
47
|
+
sleep 0.1
|
48
|
+
execute command(:add, " -T /usr/bin/security -w '#{password}' ")
|
47
49
|
end
|
48
50
|
|
49
51
|
def find
|
@@ -56,10 +58,14 @@ module Sym
|
|
56
58
|
|
57
59
|
def execute(command)
|
58
60
|
command += ' 2>/dev/null' if stderr_disabled
|
59
|
-
puts "> #{command.yellow
|
61
|
+
puts "> #{command.yellow}" if opts[:verbose]
|
60
62
|
output = `#{command}`
|
61
63
|
result = $?
|
62
|
-
|
64
|
+
unless result.success?
|
65
|
+
warn "> ERROR running command:\n> $ #{output.red}" if !stderr_disabled && opts[:verbose]
|
66
|
+
raise Sym::Errors::KeyChainCommandError.new("Command error: #{result}, command: #{command}")
|
67
|
+
end
|
68
|
+
|
63
69
|
output.chomp
|
64
70
|
rescue Errno::ENOENT => e
|
65
71
|
raise Sym::Errors::KeyChainCommandError.new("Command error: #{e.message}, command: #{command}")
|
@@ -80,16 +86,16 @@ module Sym
|
|
80
86
|
out << extras if extras
|
81
87
|
out = out.join
|
82
88
|
# Do not actually ever run these commands on non MacOSX
|
83
|
-
out = "echo Run this –\"#{out}\", on #{Sym::App.this_os}?\nAre you sure?" unless Sym::App.
|
89
|
+
out = "echo Run this –\"#{out}\", on #{Sym::App.this_os}?\nAre you sure?" unless Sym::App.osx?
|
84
90
|
out
|
85
91
|
end
|
86
92
|
|
87
93
|
def base_command(action)
|
88
94
|
[
|
89
|
-
"security #{action}-#{self.class.sub_section} ",
|
90
|
-
"-a
|
91
|
-
"-D
|
92
|
-
"-s
|
95
|
+
"/usr/bin/security #{action}-#{self.class.sub_section} ",
|
96
|
+
"-a #{self.class.user} ",
|
97
|
+
"-D #{self.class.kind} ",
|
98
|
+
"-s #{self.key_name} "
|
93
99
|
]
|
94
100
|
end
|
95
101
|
end
|
data/lib/sym/app/output/noop.rb
CHANGED
@@ -36,7 +36,7 @@ module Sym
|
|
36
36
|
self.enabled = opts[:enabled]
|
37
37
|
self.verbose = opts[:verbose]
|
38
38
|
self.timeout = opts[:timeout] || ::Sym::Configuration.config.password_cache_timeout
|
39
|
-
self.provider = Providers.provider(opts[:provider], opts[:provider_opts] || {})
|
39
|
+
self.provider = Providers.provider(opts[:provider], **(opts[:provider_opts] || {}))
|
40
40
|
self.enabled = false unless self.provider
|
41
41
|
self
|
42
42
|
end
|
@@ -15,7 +15,7 @@ module Sym
|
|
15
15
|
self.providers << provider_class
|
16
16
|
end
|
17
17
|
|
18
|
-
# Detect first instance
|
18
|
+
# Detect first instance tht is "alive?" and return it.
|
19
19
|
def detect
|
20
20
|
self.detected ||= self.providers.inject(nil) do |instance, provider_class|
|
21
21
|
instance || (p = provider_class.new; p.alive? ? p : nil)
|
@@ -38,7 +38,7 @@ module Sym
|
|
38
38
|
|
39
39
|
def provider_from_argument(p, **opts, &block)
|
40
40
|
case p
|
41
|
-
|
41
|
+
when String, Symbol
|
42
42
|
provider_class_name = "#{p.to_s.capitalize}Provider"
|
43
43
|
Sym::App::Password::Providers.const_defined?(provider_class_name) ?
|
44
44
|
Sym::App::Password::Providers.const_get(provider_class_name).new(**opts, &block) :
|
@@ -53,4 +53,3 @@ end
|
|
53
53
|
|
54
54
|
# Order is important — they are tried in this order for auto detect
|
55
55
|
require 'sym/app/password/providers/memcached_provider'
|
56
|
-
require 'sym/app/password/providers/drb_provider'
|
@@ -31,10 +31,10 @@ module Sym
|
|
31
31
|
rescue ::OpenSSL::Cipher::CipherError => e
|
32
32
|
input_handler.puts 'Invalid password. Please try again.'
|
33
33
|
|
34
|
-
if (
|
34
|
+
if (retries += 1) < 3
|
35
35
|
retry
|
36
36
|
else
|
37
|
-
raise(Sym::Errors::
|
37
|
+
raise(Sym::Errors::WrongPasswordForKey.new('Invalid password.'))
|
38
38
|
end
|
39
39
|
end
|
40
40
|
else
|
@@ -23,11 +23,10 @@ module Sym
|
|
23
23
|
# procs on a given string.
|
24
24
|
def read!
|
25
25
|
KeySourceCheck::CHECKS.each do |source_check|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
end
|
26
|
+
next unless result = source_check.detect(self) rescue nil
|
27
|
+
if key_ = normalize_key(result.key)
|
28
|
+
key_source_ = result.to_s
|
29
|
+
return key_, key_source_
|
31
30
|
end
|
32
31
|
end
|
33
32
|
nil
|
@@ -51,8 +50,6 @@ module Sym
|
|
51
50
|
rescue
|
52
51
|
nil
|
53
52
|
end
|
54
|
-
else
|
55
|
-
nil
|
56
53
|
end
|
57
54
|
end
|
58
55
|
end
|
data/lib/sym/application.rb
CHANGED
@@ -32,7 +32,6 @@ module Sym
|
|
32
32
|
:stdin, :stdout, :stderr, :kernel
|
33
33
|
|
34
34
|
def initialize(opts, stdin = STDIN, stdout = STDOUT, stderr = STDERR, kernel = nil)
|
35
|
-
|
36
35
|
self.stdin = stdin
|
37
36
|
self.stdout = stdout
|
38
37
|
self.stderr = stderr
|
@@ -115,12 +114,8 @@ module Sym
|
|
115
114
|
end
|
116
115
|
|
117
116
|
def process_output(result)
|
118
|
-
unless result.is_a?(Hash)
|
119
|
-
|
120
|
-
result
|
121
|
-
else
|
122
|
-
result
|
123
|
-
end
|
117
|
+
self.output.call(result) unless result.is_a?(Hash)
|
118
|
+
result
|
124
119
|
end
|
125
120
|
|
126
121
|
private
|
@@ -182,7 +177,7 @@ module Sym
|
|
182
177
|
args[:verbose] = opts[:verbose]
|
183
178
|
args[:provider] = opts[:cache_provider] if opts[:cache_provider]
|
184
179
|
|
185
|
-
self.password_cache = Sym::App::Password::Cache.instance.configure(args)
|
180
|
+
self.password_cache = Sym::App::Password::Cache.instance.configure(**args)
|
186
181
|
end
|
187
182
|
|
188
183
|
def process_edit_option
|
@@ -207,7 +202,7 @@ module Sym
|
|
207
202
|
end
|
208
203
|
|
209
204
|
def initialize_action
|
210
|
-
self.action = if opts[:encrypt]
|
205
|
+
self.action = if opts[:encrypt]
|
211
206
|
:encr
|
212
207
|
elsif opts[:decrypt]
|
213
208
|
:decr
|
@@ -217,7 +212,7 @@ module Sym
|
|
217
212
|
# If we are encrypting or decrypting, and no data has been provided, check if we
|
218
213
|
# should read from STDIN
|
219
214
|
def initialize_data_source
|
220
|
-
if self.action && opts[:string].nil? && opts[:file].nil? && !
|
215
|
+
if self.action && opts[:string].nil? && opts[:file].nil? && !self.stdin.tty?
|
221
216
|
opts[:file] = '-'
|
222
217
|
end
|
223
218
|
end
|
data/lib/sym/constants.rb
CHANGED
@@ -5,12 +5,12 @@ module Sym
|
|
5
5
|
|
6
6
|
BASH_FILES = Dir.glob("#{File.expand_path('../../../bin', __FILE__)}/sym.*.bash").freeze
|
7
7
|
|
8
|
-
|
8
|
+
CONFIG = {}
|
9
9
|
|
10
10
|
class << self
|
11
11
|
def register_bash_files!
|
12
12
|
BASH_FILES.each do |bash_file|
|
13
|
-
register_bash_extension bash_file,
|
13
|
+
register_bash_extension bash_file, CONFIG
|
14
14
|
end
|
15
15
|
end
|
16
16
|
|
@@ -21,7 +21,7 @@ module Sym
|
|
21
21
|
home_file = "#{Dir.home}/.#{source_file}"
|
22
22
|
|
23
23
|
hash[source_file.gsub(/sym\./, '').gsub(/\.bash/, '').to_sym] = {
|
24
|
-
|
24
|
+
dest: home_file,
|
25
25
|
source: bash_file,
|
26
26
|
script: "[[ -f #{home_file} ]] && source #{home_file}"
|
27
27
|
}
|
@@ -37,7 +37,7 @@ module Sym
|
|
37
37
|
end
|
38
38
|
|
39
39
|
ENV_ARGS_VARIABLE_NAME = 'SYM_ARGS'.freeze
|
40
|
-
SYM_KEY_FILE = "#{
|
40
|
+
SYM_KEY_FILE = "#{Dir.home}/.sym.key".freeze
|
41
41
|
|
42
42
|
end
|
43
43
|
end
|