sshkit-sudo 0.0.5 → 0.1.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 +4 -4
- data/README.md +44 -0
- data/lib/sshkit/sudo.rb +6 -3
- data/lib/sshkit/sudo/backends/abstract.rb +26 -0
- data/lib/sshkit/sudo/backends/netssh.rb +57 -0
- data/lib/sshkit/sudo/interaction_handler.rb +61 -0
- data/lib/sshkit/sudo/version.rb +1 -1
- data/sshkit-sudo.gemspec +1 -1
- metadata +6 -6
- data/lib/sshkit/sudo/backends_ext/local.rb +0 -11
- data/lib/sshkit/sudo/backends_ext/netssh.rb +0 -88
- data/lib/sshkit/sudo/backends_ext/printer.rb +0 -13
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 584ff1236a17ccb0e7a8d86879c20507500d27cc
|
4
|
+
data.tar.gz: 6ff19bcecb8f204277a21447d1a6723252b68a7e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 94eb893a96ad4aa5e66f776629e24e50d2ce02e4940ff4dddbf7eec0bd139110d0f2368e014aa9aff6ddf246b217112669bad7bcb04a98683a5d35b9d43572ff
|
7
|
+
data.tar.gz: af0359eb6962017f05967396c10f844a03e5fde4abd0a56ae12f721cf70e554d004dbf78c8ef03006ea820459c5e17d6c77ad09864df2395833f2aefd0379dc4
|
data/README.md
CHANGED
@@ -75,6 +75,50 @@ namespace :prov do
|
|
75
75
|
end
|
76
76
|
```
|
77
77
|
|
78
|
+
### Configuration
|
79
|
+
Available in sshkit-sudo 0.1.0 and later.
|
80
|
+
|
81
|
+
#### Same password across servers
|
82
|
+
If you are using a same password across all servers, you can skip inputting the password for the second server or after
|
83
|
+
by using `use_same_password!` method in your `deploy.rb` as follows:
|
84
|
+
```ruby
|
85
|
+
class SSHKit::Sudo::InteractionHandler
|
86
|
+
use_same_password!
|
87
|
+
end
|
88
|
+
```
|
89
|
+
|
90
|
+
#### Password prompt and wrong password matchers
|
91
|
+
You can set your own matchers in your `deploy.rb` as follows:
|
92
|
+
```ruby
|
93
|
+
class SSHKit::Sudo::InteractionHandler
|
94
|
+
password_prompt_regexp /[Pp]assword.*:/
|
95
|
+
wrong_password_regexp /Sorry.*\stry\sagain/
|
96
|
+
end
|
97
|
+
```
|
98
|
+
|
99
|
+
#### Making your own handler
|
100
|
+
You can write your own handler in your `deploy.rb` as follows:
|
101
|
+
```ruby
|
102
|
+
class SSHKit::Sudo::InteractionHandler
|
103
|
+
def on_data(command, stream_name, data, channel)
|
104
|
+
if data =~ wrong_password
|
105
|
+
SSHKit::Sudo.password_cache[password_cache_key(command.host)] = nil
|
106
|
+
end
|
107
|
+
if data =~ password_prompt
|
108
|
+
key = password_cache_key(command.host)
|
109
|
+
pass = SSHKit::Sudo.password_cache[key]
|
110
|
+
unless pass
|
111
|
+
print data
|
112
|
+
pass = $stdin.noecho(&:gets)
|
113
|
+
puts ''
|
114
|
+
SSHKit::Sudo.password_cache[key] = pass
|
115
|
+
end
|
116
|
+
channel.send_data(pass)
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
```
|
121
|
+
|
78
122
|
## Contributing
|
79
123
|
|
80
124
|
1. Fork it ( https://github.com/[my-github-username]/sshkit-sudo/fork )
|
data/lib/sshkit/sudo.rb
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
require "sshkit/sudo/version"
|
2
2
|
require 'sshkit'
|
3
|
-
require
|
4
|
-
require
|
5
|
-
require
|
3
|
+
require 'sshkit/sudo/interaction_handler'
|
4
|
+
require 'sshkit/sudo/backends/abstract'
|
5
|
+
require 'sshkit/sudo/backends/netssh'
|
6
6
|
|
7
7
|
module SSHKit
|
8
8
|
module Sudo
|
@@ -10,4 +10,7 @@ module SSHKit
|
|
10
10
|
@password_cache ||= {}
|
11
11
|
end
|
12
12
|
end
|
13
|
+
|
14
|
+
Backend::Abstract.send(:include, ::SSHKit::Sudo::Backend::Abstract)
|
15
|
+
Backend::Netssh.send(:include, ::SSHKit::Sudo::Backend::Netssh)
|
13
16
|
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module SSHKit
|
2
|
+
module Sudo
|
3
|
+
module Backend
|
4
|
+
module Abstract
|
5
|
+
def sudo(*args)
|
6
|
+
execute!(:sudo, *args)
|
7
|
+
end
|
8
|
+
|
9
|
+
def execute!(*args)
|
10
|
+
options = args.extract_options!
|
11
|
+
options[:interaction_handler] ||= SSHKit::Sudo::InteractionHandler.new
|
12
|
+
create_command_and_execute!(args, options).success?
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
def execute_command!(*args)
|
17
|
+
execute_command(*args)
|
18
|
+
end
|
19
|
+
|
20
|
+
def create_command_and_execute!(args, options)
|
21
|
+
command(args, options).tap { |cmd| execute_command!(cmd) }
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
module SSHKit
|
2
|
+
module Sudo
|
3
|
+
module Backend
|
4
|
+
module Netssh
|
5
|
+
private
|
6
|
+
def execute_command!(cmd)
|
7
|
+
output.log_command_start(cmd)
|
8
|
+
cmd.started = true
|
9
|
+
exit_status = nil
|
10
|
+
with_ssh do |ssh|
|
11
|
+
ssh.open_channel do |chan|
|
12
|
+
chan.request_pty
|
13
|
+
chan.exec cmd.to_command do |_ch, _success|
|
14
|
+
chan.on_data do |ch, data|
|
15
|
+
cmd.on_stdout(ch, data)
|
16
|
+
output.log_command_data(cmd, :stdout, data)
|
17
|
+
end
|
18
|
+
chan.on_extended_data do |ch, _type, data|
|
19
|
+
cmd.on_stderr(ch, data)
|
20
|
+
output.log_command_data(cmd, :stderr, data)
|
21
|
+
end
|
22
|
+
chan.on_request("exit-status") do |_ch, data|
|
23
|
+
exit_status = data.read_long
|
24
|
+
end
|
25
|
+
#chan.on_request("exit-signal") do |ch, data|
|
26
|
+
# # TODO: This gets called if the program is killed by a signal
|
27
|
+
# # might also be a worthwhile thing to report
|
28
|
+
# exit_signal = data.read_string.to_i
|
29
|
+
# warn ">>> " + exit_signal.inspect
|
30
|
+
# output.log_command_killed(cmd, exit_signal)
|
31
|
+
#end
|
32
|
+
chan.on_open_failed do |_ch|
|
33
|
+
# TODO: What do do here?
|
34
|
+
# I think we should raise something
|
35
|
+
end
|
36
|
+
chan.on_process do |_ch|
|
37
|
+
# TODO: I don't know if this is useful
|
38
|
+
end
|
39
|
+
chan.on_eof do |_ch|
|
40
|
+
# TODO: chan sends EOF before the exit status has been
|
41
|
+
# writtend
|
42
|
+
end
|
43
|
+
end
|
44
|
+
chan.wait
|
45
|
+
end
|
46
|
+
ssh.loop
|
47
|
+
end
|
48
|
+
# Set exit_status and log the result upon completion
|
49
|
+
if exit_status
|
50
|
+
cmd.exit_status = exit_status
|
51
|
+
output.log_command_exit(cmd)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
module SSHKit
|
2
|
+
module Sudo
|
3
|
+
class DefaultInteractionHandler
|
4
|
+
def wrong_password; self.class.wrong_password; end
|
5
|
+
def password_prompt; self.class.password_prompt; end
|
6
|
+
|
7
|
+
def on_data(command, stream_name, data, channel)
|
8
|
+
if data =~ wrong_password
|
9
|
+
puts data if defined?(Airbrussh) and
|
10
|
+
Airbrussh.configuration.command_output != :stdout and
|
11
|
+
data !~ password_prompt
|
12
|
+
SSHKit::Sudo.password_cache[password_cache_key(command.host)] = nil
|
13
|
+
end
|
14
|
+
if data =~ password_prompt
|
15
|
+
key = password_cache_key(command.host)
|
16
|
+
pass = SSHKit::Sudo.password_cache[key]
|
17
|
+
unless pass
|
18
|
+
print data
|
19
|
+
pass = $stdin.noecho(&:gets)
|
20
|
+
puts ''
|
21
|
+
SSHKit::Sudo.password_cache[key] = pass
|
22
|
+
end
|
23
|
+
channel.send_data(pass)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def password_cache_key(host)
|
28
|
+
"#{host.user}@#{host.hostname}"
|
29
|
+
end
|
30
|
+
|
31
|
+
class << self
|
32
|
+
def wrong_password
|
33
|
+
@wrong_password ||= /Sorry.*\stry\sagain/
|
34
|
+
end
|
35
|
+
|
36
|
+
def password_prompt
|
37
|
+
@password_prompt ||= /[Pp]assword.*:/
|
38
|
+
end
|
39
|
+
|
40
|
+
def wrong_password_regexp(regexp)
|
41
|
+
@wrong_password = regexp
|
42
|
+
end
|
43
|
+
|
44
|
+
def password_prompt_regexp(regexp)
|
45
|
+
@password_prompt = regexp
|
46
|
+
end
|
47
|
+
|
48
|
+
def use_same_password!
|
49
|
+
class_eval <<-METHOD, __FILE__, __LINE__ + 1
|
50
|
+
def password_cache_key(host)
|
51
|
+
'0'
|
52
|
+
end
|
53
|
+
METHOD
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
class InteractionHandler < DefaultInteractionHandler
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
data/lib/sshkit/sudo/version.rb
CHANGED
data/sshkit-sudo.gemspec
CHANGED
@@ -20,7 +20,7 @@ Gem::Specification.new do |spec|
|
|
20
20
|
|
21
21
|
spec.required_ruby_version = ">= 1.9.3"
|
22
22
|
|
23
|
-
spec.add_dependency "sshkit", "
|
23
|
+
spec.add_dependency "sshkit", "~> 1.8"
|
24
24
|
spec.add_development_dependency "bundler", "~> 1.7"
|
25
25
|
spec.add_development_dependency "rake", "~> 10.0"
|
26
26
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sshkit-sudo
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Kentaro Imai
|
@@ -14,14 +14,14 @@ dependencies:
|
|
14
14
|
name: sshkit
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - "
|
17
|
+
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
19
|
version: '1.8'
|
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: '1.8'
|
27
27
|
- !ruby/object:Gem::Dependency
|
@@ -65,9 +65,9 @@ files:
|
|
65
65
|
- README.md
|
66
66
|
- Rakefile
|
67
67
|
- lib/sshkit/sudo.rb
|
68
|
-
- lib/sshkit/sudo/
|
69
|
-
- lib/sshkit/sudo/
|
70
|
-
- lib/sshkit/sudo/
|
68
|
+
- lib/sshkit/sudo/backends/abstract.rb
|
69
|
+
- lib/sshkit/sudo/backends/netssh.rb
|
70
|
+
- lib/sshkit/sudo/interaction_handler.rb
|
71
71
|
- lib/sshkit/sudo/version.rb
|
72
72
|
- sshkit-sudo.gemspec
|
73
73
|
homepage: ''
|
@@ -1,88 +0,0 @@
|
|
1
|
-
require 'io/console'
|
2
|
-
|
3
|
-
module SSHKit
|
4
|
-
module Backend
|
5
|
-
|
6
|
-
class Netssh < Printer
|
7
|
-
def sudo(*args)
|
8
|
-
_execute!(:sudo, *args).success?
|
9
|
-
end
|
10
|
-
|
11
|
-
def execute!(*args)
|
12
|
-
_execute!(*args).success?
|
13
|
-
end
|
14
|
-
|
15
|
-
private
|
16
|
-
|
17
|
-
def _execute!(*args)
|
18
|
-
command(*args).tap do |cmd|
|
19
|
-
output << cmd
|
20
|
-
cmd.started = true
|
21
|
-
exit_status = nil
|
22
|
-
with_ssh do |ssh|
|
23
|
-
ssh.open_channel do |chan|
|
24
|
-
chan.request_pty
|
25
|
-
chan.exec cmd.to_command do |ch, success|
|
26
|
-
chan.on_data do |ch, data|
|
27
|
-
cmd.stdout = data
|
28
|
-
cmd.full_stdout += data
|
29
|
-
output << cmd
|
30
|
-
if data =~ /Sorry.*\stry\sagain/
|
31
|
-
SSHKit::Sudo.password_cache[password_cache_key(cmd.host)] = nil
|
32
|
-
end
|
33
|
-
if data =~ /[Pp]assword.*:/
|
34
|
-
key = password_cache_key(cmd.host)
|
35
|
-
pass = SSHKit::Sudo.password_cache[key]
|
36
|
-
unless pass
|
37
|
-
pass = $stdin.noecho(&:gets)
|
38
|
-
SSHKit::Sudo.password_cache[key] = pass
|
39
|
-
end
|
40
|
-
ch.send_data(pass)
|
41
|
-
end
|
42
|
-
end
|
43
|
-
chan.on_extended_data do |ch, type, data|
|
44
|
-
cmd.stderr = data
|
45
|
-
cmd.full_stderr += data
|
46
|
-
output << cmd
|
47
|
-
end
|
48
|
-
chan.on_request("exit-status") do |ch, data|
|
49
|
-
exit_status = data.read_long
|
50
|
-
end
|
51
|
-
#chan.on_request("exit-signal") do |ch, data|
|
52
|
-
# # TODO: This gets called if the program is killed by a signal
|
53
|
-
# # might also be a worthwhile thing to report
|
54
|
-
# exit_signal = data.read_string.to_i
|
55
|
-
# warn ">>> " + exit_signal.inspect
|
56
|
-
# output << cmd
|
57
|
-
#end
|
58
|
-
chan.on_open_failed do |ch|
|
59
|
-
# TODO: What do do here?
|
60
|
-
# I think we should raise something
|
61
|
-
end
|
62
|
-
chan.on_process do |ch|
|
63
|
-
# TODO: I don't know if this is useful
|
64
|
-
end
|
65
|
-
chan.on_eof do |ch|
|
66
|
-
# TODO: chan sends EOF before the exit status has been
|
67
|
-
# writtend
|
68
|
-
end
|
69
|
-
end
|
70
|
-
chan.wait
|
71
|
-
end
|
72
|
-
ssh.loop
|
73
|
-
end
|
74
|
-
# Set exit_status and log the result upon completion
|
75
|
-
if exit_status
|
76
|
-
cmd.exit_status = exit_status
|
77
|
-
output << cmd
|
78
|
-
end
|
79
|
-
end
|
80
|
-
end
|
81
|
-
|
82
|
-
def password_cache_key(host)
|
83
|
-
"#{host.user}@#{host.hostname}"
|
84
|
-
end
|
85
|
-
end
|
86
|
-
end
|
87
|
-
|
88
|
-
end
|