con_ssh 0.0.1
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 +7 -0
- data/.codeclimate.yml +21 -0
- data/.gitignore +50 -0
- data/.rubocop-custom.yml +1157 -0
- data/.ruby-version +1 -0
- data/README.md +3 -0
- data/Rakefile +8 -0
- data/TODO +0 -0
- data/bin/con +6 -0
- data/con_ssh.gemspec +18 -0
- data/gempush +5 -0
- data/lib/con_ssh/core_extensions.rb +24 -0
- data/lib/con_ssh.rb +173 -0
- data/test/con_ssh_test.rb +8 -0
- metadata +58 -0
data/.ruby-version
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
2.3.0
|
data/README.md
ADDED
data/Rakefile
ADDED
data/TODO
ADDED
|
File without changes
|
data/bin/con
ADDED
data/con_ssh.gemspec
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
Gem::Specification.new do |s|
|
|
2
|
+
s.name = "con_ssh"
|
|
3
|
+
s.version = "0.0.1"
|
|
4
|
+
s.authors = ["Tom Lobato"]
|
|
5
|
+
s.email = "lobato@bettercall.io"
|
|
6
|
+
# s.homepage = "http://sys-watchdog.bettercall.io/"
|
|
7
|
+
s.summary = "SSH cli wrapper."
|
|
8
|
+
s.description = "#{s.summary}."
|
|
9
|
+
s.licenses = ["MIT"]
|
|
10
|
+
s.platform = Gem::Platform::RUBY
|
|
11
|
+
|
|
12
|
+
s.files = `git ls-files`.split("\n")
|
|
13
|
+
s.test_files = `git ls-files -- test/*`.split("\n")
|
|
14
|
+
s.require_paths = ["lib"]
|
|
15
|
+
s.executables = %w(con)
|
|
16
|
+
s.required_ruby_version = '>= 2.3.0'
|
|
17
|
+
end
|
|
18
|
+
|
data/gempush
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
|
|
2
|
+
class String
|
|
3
|
+
def strip_text
|
|
4
|
+
split("\n")
|
|
5
|
+
.map{|l| l.trip}
|
|
6
|
+
.join("\n")
|
|
7
|
+
end
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
class Exception
|
|
11
|
+
def desc
|
|
12
|
+
"#{ message } #{ backtrace&.join "\n" }"
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def log_ex e
|
|
17
|
+
STDERR.puts e.desc
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def match_root_or_current_user stat
|
|
21
|
+
(stat.uid == 0 and stat.gid == 0) ||
|
|
22
|
+
(stat.uid == Process.uid and stat.gid == Process.gid)
|
|
23
|
+
end
|
|
24
|
+
|
data/lib/con_ssh.rb
ADDED
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
|
|
2
|
+
require 'ostruct'
|
|
3
|
+
require 'con_ssh/core_extensions'
|
|
4
|
+
|
|
5
|
+
class SSHCon
|
|
6
|
+
CONF_PATH = File.expand_path '~/.con'
|
|
7
|
+
CONF_LINE_FIELDS = %w(shortcut conn_desc host user port knock unknock)
|
|
8
|
+
DEFAULT_PORT = "22"
|
|
9
|
+
|
|
10
|
+
def initialize
|
|
11
|
+
@conn_confs = {}
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def run *args
|
|
15
|
+
# setup
|
|
16
|
+
if args[0] == 'setup'
|
|
17
|
+
warn "Ignoring arguments after #{args[0]}." if args.length > 1
|
|
18
|
+
install_sample_conf
|
|
19
|
+
|
|
20
|
+
# knock / unknock
|
|
21
|
+
elsif ['knock', 'unknock'].include? args[1]
|
|
22
|
+
warn "Ignoring arguments after #{args[1]}." if args.length > 2
|
|
23
|
+
parse_conf
|
|
24
|
+
conn_conf = @conn_confs[args[0]]
|
|
25
|
+
unless conn_confs
|
|
26
|
+
warn "Shorcut #{args[0]} not found. See #{CONF_PATH}."
|
|
27
|
+
exit 1
|
|
28
|
+
end
|
|
29
|
+
ports = conn_conf[args[1]]
|
|
30
|
+
if ports.nil? || ports.empty?
|
|
31
|
+
warn "#{conn_conf.conn_desc} has no #{args[1]} configuration."
|
|
32
|
+
exit 1
|
|
33
|
+
end
|
|
34
|
+
knock conn_conf.host, ports
|
|
35
|
+
|
|
36
|
+
# connect
|
|
37
|
+
elsif conn_conf = @conn_confs[args[0]]
|
|
38
|
+
warn "Ignoring arguments after #{args[0]}." if args.length > 1
|
|
39
|
+
parse_conf
|
|
40
|
+
ssh conn_conf
|
|
41
|
+
|
|
42
|
+
# help
|
|
43
|
+
elsif ['-h'].include? args[0]
|
|
44
|
+
warn "Ignoring arguments after #{args[0]}." if args.length > 1
|
|
45
|
+
print_help
|
|
46
|
+
|
|
47
|
+
# fail
|
|
48
|
+
else
|
|
49
|
+
warn "Invalid arguments."
|
|
50
|
+
print_help
|
|
51
|
+
exit 1
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
private
|
|
56
|
+
|
|
57
|
+
def ssh c
|
|
58
|
+
port = (c.port && c.port != DEFAULT_PORT) ? "-p #{ c.port } " : ''
|
|
59
|
+
user = c.user ? "#{ c.user }@" : ''
|
|
60
|
+
knock c.host, c.knock if c.knock
|
|
61
|
+
system "ssh #{port}#{user}#{c.host}"
|
|
62
|
+
knock c.host, c.unknock if c.unknock
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def knock host, ports
|
|
66
|
+
unless has_knock
|
|
67
|
+
msg = "Skipping knock!
|
|
68
|
+
The connection configuration has ports knock set but you don`t have 'knock' installed on your system.
|
|
69
|
+
Please install: 'apt-get install knockd', 'brew install knock', ...".strip_text
|
|
70
|
+
warn msg
|
|
71
|
+
return
|
|
72
|
+
end
|
|
73
|
+
run_cmd "knock #{ host } #{ ports.join ' ' }", false
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
# Conf
|
|
78
|
+
|
|
79
|
+
def parse_conf
|
|
80
|
+
unless File.exists? CONF_PATH
|
|
81
|
+
raise "#{CONF_PATH} not found. Install a sample with 'con setup'."
|
|
82
|
+
end
|
|
83
|
+
File.open(CONF_PATH).readlines.each do |line|
|
|
84
|
+
add_connection line.strip
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def add_connection line
|
|
89
|
+
return if skip_line? line
|
|
90
|
+
|
|
91
|
+
values = line.split /\s+/
|
|
92
|
+
|
|
93
|
+
conn_conf = OpenStruct.new
|
|
94
|
+
CONF_LINE_FIELDS.each_with_index do |field, idx|
|
|
95
|
+
conn_conf[field.to_sym] = values[idx]
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
unless valid? conn_conf
|
|
99
|
+
warn "WARNING: Invalid line, skipping: '#{line}'"
|
|
100
|
+
return
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
adjust_conn_conf conn_conf
|
|
104
|
+
|
|
105
|
+
if @conn_confs[conn_conf.shortcut]
|
|
106
|
+
warn "WARNING: Shorcut '#{conn_conf.shortcut} is duplicated, skipping line: '#{line}'"
|
|
107
|
+
return
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
@conn_confs[conn_conf.shortcut] = conn_conf
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
def valid? c
|
|
114
|
+
c.shortcut &&
|
|
115
|
+
c.conn_desc &&
|
|
116
|
+
c.host
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
def adjust_conn_conf c
|
|
120
|
+
c.knock = c.knock.split ',' if c.knock
|
|
121
|
+
c.unknock = c.unknock.split ',' if c.unknock
|
|
122
|
+
|
|
123
|
+
if c.host =~ /^(.*?)@(.*?)$/
|
|
124
|
+
c.host = $2
|
|
125
|
+
c.user ||= $1
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
def install_sample_conf
|
|
130
|
+
if File.exists? CONF_PATH
|
|
131
|
+
warn "#{CONF_PATH} already exists. Skipping install."
|
|
132
|
+
return false
|
|
133
|
+
end
|
|
134
|
+
sample_conf = "# #{ CONF_LINE_FIELDS.join ' ' }
|
|
135
|
+
# *connection_desc must have no spaces.
|
|
136
|
+
# *user, port, knock, unknock are optionals.
|
|
137
|
+
|
|
138
|
+
s1 server_1 123.234.35.456
|
|
139
|
+
s1r server_1r root@123.234.35.456
|
|
140
|
+
s3 server_3 123.234.35.456 username 2222 knock unknock"
|
|
141
|
+
File.write CONF_PATH, sample_conf.strip_text
|
|
142
|
+
true
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
# Util
|
|
147
|
+
|
|
148
|
+
def warn desc
|
|
149
|
+
$stderr.puts desc
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
def skip_line? line
|
|
153
|
+
line =~ /^\s*[$#]/
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
def has_knock
|
|
157
|
+
!`which knock`.strip.empty?
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
def print_help
|
|
161
|
+
puts "Usage: con <shortcut>|setup [knock|unknock]".strip_text
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
def run_cmd cmd, print = true
|
|
165
|
+
puts "run: #{cmd}" if print
|
|
166
|
+
output = `#{cmd} 2>&1`
|
|
167
|
+
exit_status = $?.to_i
|
|
168
|
+
unless exit_status == 0
|
|
169
|
+
warn "Non-zero output: #{output}"
|
|
170
|
+
end
|
|
171
|
+
[exit_status, output]
|
|
172
|
+
end
|
|
173
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: con_ssh
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.0.1
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Tom Lobato
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: bin
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 2017-06-23 00:00:00.000000000 Z
|
|
12
|
+
dependencies: []
|
|
13
|
+
description: SSH cli wrapper..
|
|
14
|
+
email: lobato@bettercall.io
|
|
15
|
+
executables:
|
|
16
|
+
- con
|
|
17
|
+
extensions: []
|
|
18
|
+
extra_rdoc_files: []
|
|
19
|
+
files:
|
|
20
|
+
- ".codeclimate.yml"
|
|
21
|
+
- ".gitignore"
|
|
22
|
+
- ".rubocop-custom.yml"
|
|
23
|
+
- ".ruby-version"
|
|
24
|
+
- README.md
|
|
25
|
+
- Rakefile
|
|
26
|
+
- TODO
|
|
27
|
+
- bin/con
|
|
28
|
+
- con_ssh.gemspec
|
|
29
|
+
- gempush
|
|
30
|
+
- lib/con_ssh.rb
|
|
31
|
+
- lib/con_ssh/core_extensions.rb
|
|
32
|
+
- test/con_ssh_test.rb
|
|
33
|
+
homepage:
|
|
34
|
+
licenses:
|
|
35
|
+
- MIT
|
|
36
|
+
metadata: {}
|
|
37
|
+
post_install_message:
|
|
38
|
+
rdoc_options: []
|
|
39
|
+
require_paths:
|
|
40
|
+
- lib
|
|
41
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
42
|
+
requirements:
|
|
43
|
+
- - ">="
|
|
44
|
+
- !ruby/object:Gem::Version
|
|
45
|
+
version: 2.3.0
|
|
46
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
47
|
+
requirements:
|
|
48
|
+
- - ">="
|
|
49
|
+
- !ruby/object:Gem::Version
|
|
50
|
+
version: '0'
|
|
51
|
+
requirements: []
|
|
52
|
+
rubyforge_project:
|
|
53
|
+
rubygems_version: 2.5.1
|
|
54
|
+
signing_key:
|
|
55
|
+
specification_version: 4
|
|
56
|
+
summary: SSH cli wrapper.
|
|
57
|
+
test_files:
|
|
58
|
+
- test/con_ssh_test.rb
|