lita-ssh-run 0.0.1 → 0.0.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/README.md +13 -4
- data/lib/lita/handlers/ssh_run.rb +162 -45
- data/lita-ssh-run.gemspec +3 -2
- metadata +36 -22
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6668cf973bb770f5e4780e4158e3fb040bcaff6b
|
4
|
+
data.tar.gz: ceea91c7635db468810021111e925bafb7068886
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f696b54d60afebd72c8b4e0df86efaf4c7f11cae81a86c7968d82f84ce192c67c041e6998a79aaf4914c6b1a0bf0278d6fbce54b1bfc40bb4de019f979f898ec
|
7
|
+
data.tar.gz: b4d3c3df2b10daf7415b272539e09cc627579ce63812b8486e09ffeb2bc7a07ab0e66a61d9c1ff0db86b429166b1007f1d46f0ab27861d48ef96ee8494895ae2
|
data/README.md
CHANGED
@@ -1,13 +1,17 @@
|
|
1
1
|
# lita-ssh-run
|
2
2
|
|
3
|
-
This will allow you to run commands via ssh
|
3
|
+
This will allow you to run commands via ssh and powershell via winrm
|
4
|
+
|
4
5
|
Example:
|
5
6
|
`Lita, run uptime on 192.168.1.10`
|
7
|
+
`Lita, run Get-Service on 192.168.1.20`
|
6
8
|
|
7
|
-
Usernames and
|
8
|
-
|
9
|
+
Usernames, passwords, and OS type are stored in redis memory by chat userid and host passed.
|
10
|
+
|
11
|
+
If not found, it will prompt via private message on how to enter user, password, and OS:
|
9
12
|
Currently passwords are passed via plaintext in private message. I have requested to Slack to add an obfuscation format block for things like this.
|
10
13
|
|
14
|
+
**Tested on slack and hipchat**
|
11
15
|
## Installation
|
12
16
|
|
13
17
|
Add lita-ssh-run to your Lita instance's Gemfile:
|
@@ -16,7 +20,6 @@ Add lita-ssh-run to your Lita instance's Gemfile:
|
|
16
20
|
gem "lita-ssh-run"
|
17
21
|
```
|
18
22
|
|
19
|
-
|
20
23
|
## Configuration
|
21
24
|
|
22
25
|
None
|
@@ -29,6 +32,12 @@ None
|
|
29
32
|
|
30
33
|
`Lita, set password for 192.168.1.0 to PASSWORD`
|
31
34
|
|
35
|
+
`Lita, set OS for 192.168.1.0 to linux`
|
36
|
+
|
37
|
+
`Lita, set OS for 192.168.1.0 to windows`
|
38
|
+
|
39
|
+
`List, set port for 192.168.1.0 to 2222`
|
40
|
+
|
32
41
|
|
33
42
|
## License
|
34
43
|
|
@@ -1,73 +1,190 @@
|
|
1
1
|
module Lita
|
2
2
|
module Handlers
|
3
3
|
class SshRun < Handler
|
4
|
-
|
4
|
+
require 'net/ssh'
|
5
|
+
require 'winrm'
|
5
6
|
|
6
|
-
|
7
|
+
route(/^run\s+(.+)\s+on\s+(.+)/i,
|
8
|
+
:run_command,
|
9
|
+
command: true,
|
10
|
+
help: { "run <command> on <machine>" => "runs an ssh or powershell command on remote machine" })
|
7
11
|
|
8
|
-
|
12
|
+
route(/^set\s+(username|password)\s+for\s+(.+)\s+to\s+(.+)/i,
|
13
|
+
:set_user_pass,
|
14
|
+
command: true,
|
15
|
+
help: { "set <username or password> for <machineName>" =>
|
16
|
+
"sets a username or password for a machine you want to run commands on" })
|
9
17
|
|
10
|
-
|
18
|
+
route(/^set\s+(port)\s+for\s+(.+)\s+to\s+(.+)/i,
|
19
|
+
:set_server_port,
|
20
|
+
command: true,
|
21
|
+
help: { "set port for <machinename>" =>
|
22
|
+
"changes default port for machine connection (defaults are 22 for SSH and 5985 for winrm" })
|
11
23
|
|
12
|
-
|
24
|
+
route(/^set\s+(os)\s+for\s+(.+)\s+to\s+(.+)/i,
|
25
|
+
:set_server_os,
|
26
|
+
command: true,
|
27
|
+
help: { "set os for <machineName>" =>
|
28
|
+
"choices are 'windows' and 'linux'. This tells us to use ssh or winrm for the specified machine" })
|
13
29
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
30
|
+
route(/^clear\s+all\s+stored\s+(creds|credentials)/i,
|
31
|
+
:flush_redis,
|
32
|
+
command: true,
|
33
|
+
restrict_to: :admins,
|
34
|
+
help: { "clear all stored cred" =>
|
35
|
+
"blows away our redis data for lita-run-ssh" })
|
36
|
+
|
37
|
+
def run_command(response)
|
38
|
+
server = response.matches[0][1]
|
39
|
+
id_server_os = response.user.id + "_" + server + "_os"
|
40
|
+
os = redis.get(id_server_os)
|
41
|
+
get_os(response, server) unless['WINDOWS', 'LINUX'].include? os.to_s.upcase
|
42
|
+
if (os.to_s.upcase.eql? 'WINDOWS')
|
43
|
+
run_winrm(response)
|
44
|
+
elsif (os.to_s.upcase.eql? 'LINUX')
|
45
|
+
run_ssh(response)
|
46
|
+
else
|
47
|
+
response.reply("I was unable to find an OS for you on #{server}, please check you direct messages from me.")
|
48
|
+
end
|
49
|
+
end
|
22
50
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
51
|
+
def run_ssh(response)
|
52
|
+
cmd = response.matches[0][0]
|
53
|
+
server = response.matches[0][1]
|
54
|
+
id_server_port = response.user.id + "_" + server + "_port"
|
55
|
+
port = redis.get(id_server_port)
|
56
|
+
if (port.nil?)
|
57
|
+
port = 22
|
58
|
+
end
|
59
|
+
id_server_user = response.user.id + "_" + server + "_username"
|
60
|
+
id_server_pass = response.user.id + "_" + server + "_password"
|
61
|
+
usernm = redis.get(id_server_user)
|
62
|
+
passwd = redis.get(id_server_pass)
|
63
|
+
get_user_pass(response, server, "Username") unless usernm
|
64
|
+
get_user_pass(response, server, "Password") unless passwd
|
65
|
+
if usernm && passwd && port
|
66
|
+
Net::SSH.start(server, usernm, :port => port, :password => passwd, :timeout => 10) do |ssh |
|
67
|
+
output = ssh.exec!(cmd)
|
68
|
+
if !output
|
69
|
+
response.reply("Command was run, but it appears there was no output to stdout or stderr.")
|
70
|
+
else
|
71
|
+
response.reply("```" + output.encode('utf-8', :invalid => :replace, :undef => :replace, :replace => '_') + "```")
|
27
72
|
end
|
28
|
-
elsif usernm
|
29
|
-
response.reply_with_mention("I was unable to find a password for you on #{server}, please check you direct messages from me.")
|
30
|
-
elsif passwd
|
31
|
-
response.reply_with_mention("I was unable to find a username for you on #{server}, please check you direct messages from me.")
|
32
|
-
else
|
33
|
-
response.reply_with_mention("I was unable to find a username or password for you on #{server}, please check you direct messages from me.")
|
34
73
|
end
|
74
|
+
elsif usernm
|
75
|
+
response.reply_with_mention("I was unable to find a password for you on #{server}, please check you direct messages from me.")
|
76
|
+
elsif passwd
|
77
|
+
response.reply_with_mention("I was unable to find a username for you on #{server}, please check you direct messages from me.")
|
78
|
+
else
|
79
|
+
response.reply_with_mention("I was unable to find a username or password for you on #{server}, please check you direct messages from me.")
|
80
|
+
end
|
81
|
+
end
|
35
82
|
|
83
|
+
def run_winrm(response)
|
84
|
+
cmd = response.matches[0][0]
|
85
|
+
server = response.matches[0][1]
|
86
|
+
id_server_port = response.user.id + "_" + server + "_port"
|
87
|
+
port = redis.get(id_server_port)
|
88
|
+
if (port.nil?)
|
89
|
+
port = 5985
|
36
90
|
end
|
91
|
+
id_server_user = response.user.id + "_" + server + "_username"
|
92
|
+
id_server_pass = response.user.id + "_" + server + "_password"
|
93
|
+
usernm = redis.get(id_server_user)
|
94
|
+
passwd = redis.get(id_server_pass)
|
95
|
+
get_user_pass(response, server, "Username") unless usernm
|
96
|
+
get_user_pass(response, server, "Password") unless passwd
|
97
|
+
if usernm && passwd && port
|
98
|
+
endpoint = "http://#{server}:#{port}/wsman"
|
99
|
+
winrm = WinRM::WinRMWebService.new(endpoint, :negotiate, :user => usernm, :pass => passwd)
|
100
|
+
winrm.create_executor do |executor|
|
101
|
+
executor.run_powershell_script(cmd) do |stdout, stderr|
|
102
|
+
if stdout.to_s == '' && stderr.to_s == ''
|
103
|
+
response.reply("Command was run, but it appears there was no output to stdout or stderr.")
|
104
|
+
else
|
105
|
+
out = StringIO.new
|
106
|
+
out.puts stdout
|
107
|
+
response.reply(out.string)
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
elsif usernm
|
112
|
+
response.reply_with_mention("I was unable to find a password for you on #{server}, please check you direct messages from me.")
|
113
|
+
elsif passwd
|
114
|
+
response.reply_with_mention("I was unable to find a username for you on #{server}, please check you direct messages from me.")
|
115
|
+
else
|
116
|
+
response.reply_with_mention("I was unable to find a username or password for you on #{server}, please check you direct messages from me.")
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
def get_user_pass(response, server, * user_pass)
|
121
|
+
user_pass.each do |blah|
|
122
|
+
response.reply_privately("No #{blah.capitalize} found for you on #{server}\nPlease privately reply with:\n`Lita, set #{blah.capitalize} for #{server} to #{blah.upcase}`")
|
123
|
+
end
|
124
|
+
end
|
37
125
|
|
38
|
-
|
39
|
-
|
40
|
-
|
126
|
+
def get_os(response, server)
|
127
|
+
response.reply_privately("No os found for you on #{server}\nPlease privately reply with:\n`Lita, set os for #{server} to windows` or \n`Lita, set os for #{server} to linux`")
|
128
|
+
end
|
129
|
+
|
130
|
+
def set_user_pass(response)
|
131
|
+
request = response.matches[0][0]
|
132
|
+
server = response.matches[0][1]
|
133
|
+
value = response.matches[0][2]
|
134
|
+
id_server_user_pass = response.user.id + "_" + server + "_" + request.downcase
|
135
|
+
if request && server && value
|
136
|
+
redis.set(id_server_user_pass, value)
|
137
|
+
response.reply_privately("#{request.capitalize} set")
|
138
|
+
id_server_user = response.user.id + "_" + server + "_username"
|
139
|
+
id_server_pass = response.user.id + "_" + server + "_password"
|
140
|
+
if redis.get(id_server_user) && redis.get(id_server_pass)
|
141
|
+
response.reply("Username and Password now set, please rerun your request")
|
41
142
|
end
|
143
|
+
else
|
144
|
+
response.reply_privately("There seems to have been a problem setting that for you")
|
42
145
|
end
|
146
|
+
end
|
43
147
|
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
value = response.matches[0][2]
|
48
|
-
id_server_user_pass = response.user.id + "_" + server + "_" + request.downcase
|
148
|
+
def flush_redis(response)
|
149
|
+
redis.flushdb
|
150
|
+
end
|
49
151
|
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
152
|
+
def set_server_port(response)
|
153
|
+
request = response.matches[0][0]
|
154
|
+
server = response.matches[0][1]
|
155
|
+
value = response.matches[0][2]
|
156
|
+
id_server_port = response.user.id + "_" + server + "_port"
|
157
|
+
if request && server && value
|
158
|
+
redis.set(id_server_port, value)
|
159
|
+
if redis.get(id_server_port)
|
160
|
+
response.reply("Server Port now set to #{value}")
|
161
|
+
end
|
162
|
+
else
|
163
|
+
response.reply_privately("There seems to have been a problem setting that for you")
|
164
|
+
end
|
165
|
+
end
|
57
166
|
|
167
|
+
def set_server_os(response)
|
168
|
+
request = response.matches[0][0]
|
169
|
+
server = response.matches[0][1]
|
170
|
+
value = response.matches[0][2]
|
171
|
+
id_server_os = response.user.id + "_" + server + "_os"
|
172
|
+
if ['WINDOWS', 'LINUX'].include? value.to_s.upcase
|
173
|
+
if request && server && value
|
174
|
+
redis.set(id_server_os, value)
|
175
|
+
id_server_os = response.user.id + "_" + server + "_os"
|
176
|
+
if redis.get(id_server_os)
|
177
|
+
response.reply("Server os now set to #{value}.")
|
58
178
|
end
|
59
179
|
else
|
60
180
|
response.reply_privately("There seems to have been a problem setting that for you")
|
61
181
|
end
|
182
|
+
else
|
183
|
+
response.reply_privately("valid options for os are: windows, linux")
|
62
184
|
end
|
63
|
-
|
64
|
-
def flush_redis(response)
|
65
|
-
redis.flushdb
|
66
|
-
end
|
67
|
-
|
68
|
-
|
69
185
|
end
|
70
186
|
|
71
187
|
Lita.register_handler(SshRun)
|
188
|
+
end
|
72
189
|
end
|
73
|
-
end
|
190
|
+
end
|
data/lita-ssh-run.gemspec
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
Gem::Specification.new do |spec|
|
2
2
|
spec.name = "lita-ssh-run"
|
3
|
-
spec.version = "0.0.
|
3
|
+
spec.version = "0.0.3"
|
4
4
|
spec.authors = ["Dan Cash"]
|
5
5
|
spec.email = ["dancash04@gmail.com"]
|
6
|
-
spec.description = %q{Runs commands against remote server via ssh}
|
6
|
+
spec.description = %q{Runs commands against remote server via ssh or winrm}
|
7
7
|
spec.summary = %q{See description}
|
8
8
|
spec.homepage = "https://github.com/cashman04/lita-ssh-run"
|
9
9
|
spec.license = "MIT"
|
@@ -16,6 +16,7 @@ Gem::Specification.new do |spec|
|
|
16
16
|
|
17
17
|
spec.add_runtime_dependency "lita", ">= 4.1"
|
18
18
|
spec.add_runtime_dependency 'net-ssh'
|
19
|
+
spec.add_runtime_dependency 'winrm'
|
19
20
|
|
20
21
|
spec.add_development_dependency "bundler", "~> 1.3"
|
21
22
|
spec.add_development_dependency "rake"
|
metadata
CHANGED
@@ -1,128 +1,142 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: lita-ssh-run
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Dan Cash
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2016-06-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: lita
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- -
|
17
|
+
- - '>='
|
18
18
|
- !ruby/object:Gem::Version
|
19
19
|
version: '4.1'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- -
|
24
|
+
- - '>='
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '4.1'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: net-ssh
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- -
|
31
|
+
- - '>='
|
32
32
|
- !ruby/object:Gem::Version
|
33
33
|
version: '0'
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- -
|
38
|
+
- - '>='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: winrm
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - '>='
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - '>='
|
39
53
|
- !ruby/object:Gem::Version
|
40
54
|
version: '0'
|
41
55
|
- !ruby/object:Gem::Dependency
|
42
56
|
name: bundler
|
43
57
|
requirement: !ruby/object:Gem::Requirement
|
44
58
|
requirements:
|
45
|
-
- -
|
59
|
+
- - ~>
|
46
60
|
- !ruby/object:Gem::Version
|
47
61
|
version: '1.3'
|
48
62
|
type: :development
|
49
63
|
prerelease: false
|
50
64
|
version_requirements: !ruby/object:Gem::Requirement
|
51
65
|
requirements:
|
52
|
-
- -
|
66
|
+
- - ~>
|
53
67
|
- !ruby/object:Gem::Version
|
54
68
|
version: '1.3'
|
55
69
|
- !ruby/object:Gem::Dependency
|
56
70
|
name: rake
|
57
71
|
requirement: !ruby/object:Gem::Requirement
|
58
72
|
requirements:
|
59
|
-
- -
|
73
|
+
- - '>='
|
60
74
|
- !ruby/object:Gem::Version
|
61
75
|
version: '0'
|
62
76
|
type: :development
|
63
77
|
prerelease: false
|
64
78
|
version_requirements: !ruby/object:Gem::Requirement
|
65
79
|
requirements:
|
66
|
-
- -
|
80
|
+
- - '>='
|
67
81
|
- !ruby/object:Gem::Version
|
68
82
|
version: '0'
|
69
83
|
- !ruby/object:Gem::Dependency
|
70
84
|
name: rack-test
|
71
85
|
requirement: !ruby/object:Gem::Requirement
|
72
86
|
requirements:
|
73
|
-
- -
|
87
|
+
- - '>='
|
74
88
|
- !ruby/object:Gem::Version
|
75
89
|
version: '0'
|
76
90
|
type: :development
|
77
91
|
prerelease: false
|
78
92
|
version_requirements: !ruby/object:Gem::Requirement
|
79
93
|
requirements:
|
80
|
-
- -
|
94
|
+
- - '>='
|
81
95
|
- !ruby/object:Gem::Version
|
82
96
|
version: '0'
|
83
97
|
- !ruby/object:Gem::Dependency
|
84
98
|
name: rspec
|
85
99
|
requirement: !ruby/object:Gem::Requirement
|
86
100
|
requirements:
|
87
|
-
- -
|
101
|
+
- - '>='
|
88
102
|
- !ruby/object:Gem::Version
|
89
103
|
version: 3.0.0
|
90
104
|
type: :development
|
91
105
|
prerelease: false
|
92
106
|
version_requirements: !ruby/object:Gem::Requirement
|
93
107
|
requirements:
|
94
|
-
- -
|
108
|
+
- - '>='
|
95
109
|
- !ruby/object:Gem::Version
|
96
110
|
version: 3.0.0
|
97
111
|
- !ruby/object:Gem::Dependency
|
98
112
|
name: simplecov
|
99
113
|
requirement: !ruby/object:Gem::Requirement
|
100
114
|
requirements:
|
101
|
-
- -
|
115
|
+
- - '>='
|
102
116
|
- !ruby/object:Gem::Version
|
103
117
|
version: '0'
|
104
118
|
type: :development
|
105
119
|
prerelease: false
|
106
120
|
version_requirements: !ruby/object:Gem::Requirement
|
107
121
|
requirements:
|
108
|
-
- -
|
122
|
+
- - '>='
|
109
123
|
- !ruby/object:Gem::Version
|
110
124
|
version: '0'
|
111
125
|
- !ruby/object:Gem::Dependency
|
112
126
|
name: coveralls
|
113
127
|
requirement: !ruby/object:Gem::Requirement
|
114
128
|
requirements:
|
115
|
-
- -
|
129
|
+
- - '>='
|
116
130
|
- !ruby/object:Gem::Version
|
117
131
|
version: '0'
|
118
132
|
type: :development
|
119
133
|
prerelease: false
|
120
134
|
version_requirements: !ruby/object:Gem::Requirement
|
121
135
|
requirements:
|
122
|
-
- -
|
136
|
+
- - '>='
|
123
137
|
- !ruby/object:Gem::Version
|
124
138
|
version: '0'
|
125
|
-
description: Runs commands against remote server via ssh
|
139
|
+
description: Runs commands against remote server via ssh or winrm
|
126
140
|
email:
|
127
141
|
- dancash04@gmail.com
|
128
142
|
executables: []
|
@@ -150,17 +164,17 @@ require_paths:
|
|
150
164
|
- lib
|
151
165
|
required_ruby_version: !ruby/object:Gem::Requirement
|
152
166
|
requirements:
|
153
|
-
- -
|
167
|
+
- - '>='
|
154
168
|
- !ruby/object:Gem::Version
|
155
169
|
version: '0'
|
156
170
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
157
171
|
requirements:
|
158
|
-
- -
|
172
|
+
- - '>='
|
159
173
|
- !ruby/object:Gem::Version
|
160
174
|
version: '0'
|
161
175
|
requirements: []
|
162
176
|
rubyforge_project:
|
163
|
-
rubygems_version: 2.
|
177
|
+
rubygems_version: 2.0.14
|
164
178
|
signing_key:
|
165
179
|
specification_version: 4
|
166
180
|
summary: See description
|