sym 2.8.1 → 3.0.0
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 +5 -5
- data/.circleci/config.yml +31 -30
- data/.envrc +7 -0
- data/.gitignore +1 -0
- data/.rubocop.yml +150 -928
- data/.travis.yml +16 -26
- data/CHANGELOG.md +220 -167
- data/Gemfile +1 -0
- data/LICENSE +2 -2
- data/README.adoc +670 -0
- data/Rakefile +10 -4
- data/bin/changelog +34 -0
- data/bin/sym.completion.bash +6 -4
- data/bin/sym.symit.bash +412 -187
- data/codecov.yml +29 -0
- data/design/sym-class-dependency-future-refactor.png +0 -0
- data/design/sym-class-dependency-vertical.png +0 -0
- data/design/sym-class-dependency.graffle +0 -0
- data/design/sym-class-dependency.png +0 -0
- data/design/sym-help.png +0 -0
- data/exe/keychain +1 -1
- data/exe/sym +5 -2
- data/lib/ruby_warnings.rb +7 -0
- data/lib/sym.rb +2 -8
- data/lib/sym/app.rb +1 -2
- data/lib/sym/app/args.rb +3 -2
- data/lib/sym/app/cli.rb +34 -21
- data/lib/sym/app/cli_slop.rb +9 -2
- 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/input/handler.rb +7 -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 +6 -11
- data/lib/sym/constants.rb +39 -23
- data/lib/sym/data/wrapper_struct.rb +20 -12
- data/lib/sym/errors.rb +13 -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 +54 -5
- data/sym.gemspec +36 -35
- metadata +102 -66
- data/.codeclimate.yml +0 -30
- data/README.md +0 -623
- data/lib/sym/app/password/providers/drb_provider.rb +0 -41
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/
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
data/design/sym-help.png
CHANGED
Binary file
|
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
@@ -14,24 +14,18 @@ Sym::Configuration.configure do |config|
|
|
14
14
|
config.compression_enabled = true
|
15
15
|
config.compression_level = Zlib::BEST_COMPRESSION
|
16
16
|
config.encrypted_file_extension = 'enc'
|
17
|
-
config.default_key_file = Sym::Constants
|
17
|
+
config.default_key_file = Sym::Constants.sym_key_file
|
18
18
|
|
19
19
|
config.password_cache_timeout = 300
|
20
20
|
|
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
@@ -18,7 +18,6 @@ module Sym
|
|
18
18
|
class << self
|
19
19
|
attr_accessor :exit_code
|
20
20
|
attr_accessor :stdin, :stdout, :stderr
|
21
|
-
|
22
21
|
end
|
23
22
|
|
24
23
|
self.exit_code = 0
|
@@ -66,7 +65,7 @@ module Sym
|
|
66
65
|
self.exit_code = 1
|
67
66
|
end
|
68
67
|
|
69
|
-
def self.
|
68
|
+
def self.osx?
|
70
69
|
Gem::Platform.local.os.eql?('darwin')
|
71
70
|
end
|
72
71
|
|
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
@@ -56,11 +56,10 @@ module Sym
|
|
56
56
|
# brings in #parse(Array[String] args)
|
57
57
|
include CLISlop
|
58
58
|
|
59
|
-
attr_accessor :opts, :application, :outputs, :stdin, :stdout, :stderr, :kernel
|
60
|
-
|
59
|
+
attr_accessor :opts, :application, :outputs, :stdin, :stdout, :stderr, :kernel, :args
|
61
60
|
|
62
61
|
def initialize(argv, stdin = STDIN, stdout = STDOUT, stderr = STDERR, kernel = nil)
|
63
|
-
|
62
|
+
self.args = argv
|
64
63
|
self.stdin = stdin
|
65
64
|
self.stdout = stdout
|
66
65
|
self.stderr = stderr
|
@@ -72,37 +71,46 @@ module Sym
|
|
72
71
|
|
73
72
|
begin
|
74
73
|
# Re-map any legacy options to the new options
|
75
|
-
self.opts = parse(
|
74
|
+
self.opts = parse(args)
|
75
|
+
|
76
|
+
if opts[:user_home]
|
77
|
+
Constants.user_home = opts[:user_home]
|
78
|
+
raise InvalidSymHomeDirectory, "#{opts[:user_home]} does not exist!" unless Dir.exist?(Constants.user_home)
|
79
|
+
end
|
80
|
+
|
81
|
+
# Deal with SYM_ARGS and -A
|
76
82
|
if opts[:sym_args]
|
77
|
-
|
78
|
-
|
83
|
+
if non_empty_array?(sym_args)
|
84
|
+
args << sym_args
|
85
|
+
args.flatten!
|
86
|
+
args.compact!
|
87
|
+
args.delete('-A')
|
88
|
+
args.delete('--sym-args')
|
89
|
+
self.opts = parse(args)
|
90
|
+
end
|
79
91
|
end
|
80
92
|
|
81
93
|
# Disable coloring if requested, or if piping STDOUT
|
82
94
|
if opts[:no_color] || !self.stdout.tty?
|
83
95
|
Colored2.disable! # reparse options without the colors to create new help msg
|
84
|
-
self.opts = parse(
|
96
|
+
self.opts = parse(args)
|
85
97
|
end
|
86
98
|
|
87
99
|
rescue StandardError => e
|
88
100
|
log :error, "#{e.message}" if opts
|
89
101
|
error exception: e
|
90
|
-
|
102
|
+
quit!(127) if stdin == STDIN
|
91
103
|
end
|
92
104
|
|
93
|
-
self.application = ::Sym::Application.new(opts, stdin, stdout, stderr, kernel)
|
105
|
+
self.application = ::Sym::Application.new(self.opts, stdin, stdout, stderr, kernel)
|
94
106
|
end
|
95
107
|
|
96
|
-
def
|
97
|
-
|
98
|
-
argv << env_args.split(' ')
|
99
|
-
argv.flatten!
|
100
|
-
argv.compact!
|
101
|
-
end
|
108
|
+
def quit!(code = 0)
|
109
|
+
exit(code)
|
102
110
|
end
|
103
111
|
|
104
112
|
def sym_args
|
105
|
-
ENV[
|
113
|
+
(ENV['SYM_ARGS']&.split(/\s+/) || [])
|
106
114
|
end
|
107
115
|
|
108
116
|
def execute!
|
@@ -132,15 +140,20 @@ module Sym
|
|
132
140
|
end
|
133
141
|
|
134
142
|
def opts_present
|
135
|
-
|
136
|
-
|
137
|
-
|
143
|
+
opts.to_hash.tap do |o|
|
144
|
+
o.keys.map { |k| opts[k] ? nil : k }.compact.each { |k| o.delete(k) }
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
def log(*args)
|
149
|
+
Sym::App.log(*args, **opts.to_hash)
|
138
150
|
end
|
139
151
|
|
152
|
+
|
140
153
|
private
|
141
154
|
|
142
|
-
def
|
143
|
-
|
155
|
+
def non_empty_array?(object)
|
156
|
+
object.is_a?(Array) && !object.empty?
|
144
157
|
end
|
145
158
|
|
146
159
|
def error(hash)
|
data/lib/sym/app/cli_slop.rb
CHANGED
@@ -55,7 +55,8 @@ 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
|
-
|
58
|
+
|
59
|
+
if Sym::App.osx?
|
59
60
|
o.string '-x', '--keychain', '[key-name] '.blue + 'write the key to OS-X Keychain'
|
60
61
|
end
|
61
62
|
|
@@ -67,7 +68,7 @@ module Sym
|
|
67
68
|
o.separator ' '
|
68
69
|
o.separator 'Password Cache:'.yellow
|
69
70
|
o.bool '-c', '--cache-passwords', ' enable password cache'
|
70
|
-
o.integer '-
|
71
|
+
o.integer '-z', '--cache-timeout', '[seconds]'.blue + ' expire passwords after'
|
71
72
|
o.string '-r', '--cache-provider', '[provider]'.blue + ' cache provider, one of ' + "#{Sym::App::Password::Providers.provider_list}"
|
72
73
|
|
73
74
|
o.separator ' '
|
@@ -89,8 +90,14 @@ module Sym
|
|
89
90
|
|
90
91
|
o.separator ' '
|
91
92
|
o.separator 'Utility:'.yellow
|
93
|
+
o.separator " The following flag helps with Sym installation by hooking to \n" +
|
94
|
+
" your #{'~/.bashrc'.bold.yellow}. If you are running Sym on an environment without \n" +
|
95
|
+
" user home available, you may need to force set user's home to any existing\n" +
|
96
|
+
" directory using the #{'--user-home'.bold.blue} flag.\n"
|
97
|
+
|
92
98
|
o.string '-B', '--bash-support', '[file]'.blue + ' append bash completion & utils to a file'+ "\n" +
|
93
99
|
' such as ~/.bash_profile or ~/.bashrc'
|
100
|
+
o.string '-u', '--user-home', '[DIR]'.blue + " Overrides #{'${HOME}'.green} ==> supports AWS Lambda\n"
|
94
101
|
|
95
102
|
o.separator ' '
|
96
103
|
o.separator 'Help & Examples:'.yellow
|
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
|
18
|
+
Sym::Constants.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
|
|
@@ -27,7 +27,13 @@ module Sym
|
|
27
27
|
end
|
28
28
|
|
29
29
|
def prompt(message, color)
|
30
|
-
|
30
|
+
unless STDIN.isatty && STDIN.tty?
|
31
|
+
raise Sym::Errors::CantReadPasswordNoTTY.new('key requires a password, however STDIN is not a TTY')
|
32
|
+
end
|
33
|
+
highline(message, color)
|
34
|
+
end
|
35
|
+
|
36
|
+
def highline(message, color)
|
31
37
|
HighLine.new(stdin, stderr).ask(message.bold) { |q| q.echo = '•'.send(color) }
|
32
38
|
end
|
33
39
|
|
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
|