sshwrap 0.0.2 → 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.
- data/LICENSE +1 -1
- data/README.md +2 -1
- data/bin/sshwrap +1 -0
- data/lib/sshwrap/main.rb +44 -15
- data/lib/sshwrap/prompter.rb +15 -0
- data/lib/sshwrap/version.rb +1 -1
- data/sshwrap.gemspec +1 -1
- metadata +4 -3
data/LICENSE
CHANGED
data/README.md
CHANGED
@@ -1,7 +1,8 @@
|
|
1
1
|
# SSHwrap
|
2
2
|
|
3
3
|
This provides a wrapper for ssh that execute a command on multiple machines,
|
4
|
-
optionally in parallel, and handles any sudo prompts that
|
4
|
+
optionally in parallel, and handles any ssh and sudo password prompts that
|
5
|
+
result.
|
5
6
|
|
6
7
|
## Installation
|
7
8
|
|
data/bin/sshwrap
CHANGED
data/lib/sshwrap/main.rb
CHANGED
@@ -1,24 +1,53 @@
|
|
1
|
+
require 'etc'
|
2
|
+
require 'yaml'
|
1
3
|
require 'net/ssh'
|
2
4
|
require 'highline/import'
|
5
|
+
require 'sshwrap/prompter'
|
6
|
+
|
7
|
+
# Monkey patch our prompt method into Net::SSH
|
8
|
+
module Net::SSH
|
9
|
+
def KeyFactory.prompt(prompt, echo=true)
|
10
|
+
@prompter ||= SSHwrap::Prompter.new
|
11
|
+
@prompter.prompt(prompt + ' ', echo)
|
12
|
+
end
|
13
|
+
module Authentication::Methods
|
14
|
+
def KeyboardInteractive.prompt(prompt, echo=true)
|
15
|
+
@prompter ||= SSHwrap::Prompter.new
|
16
|
+
@prompter.prompt(prompt + ' ', echo)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
3
20
|
|
4
21
|
class SSHwrap::Main
|
5
22
|
def initialize(options={})
|
23
|
+
home = Dir.respond_to?(:home) ? Dir.home : ENV['HOME'] || ENV['LOGDIR']
|
24
|
+
conffile = "#{home}/.sshwrap.yaml"
|
25
|
+
if File.exist?(conffile)
|
26
|
+
conf = YAML.load_file(conffile)
|
27
|
+
else
|
28
|
+
conf = {}
|
29
|
+
end
|
30
|
+
|
6
31
|
@mutex = Mutex.new
|
7
32
|
@max_workers = options[:max_workers] || 1
|
8
33
|
@abort_on_failure = options[:abort_on_failure]
|
9
34
|
@user = options[:user] || Etc.getlogin
|
10
35
|
@ssh_key = options[:ssh_key]
|
11
36
|
@debug = options[:debug]
|
12
|
-
@
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
37
|
+
@prompter = SSHwrap::Prompter.new
|
38
|
+
@ssh_prompt = "Password for #{@user}: "
|
39
|
+
|
40
|
+
if conf['password_regexp']
|
41
|
+
@password_regexp = Regexp.new('(' + conf['password_regexp'] + ')')
|
42
|
+
elsif options[:password_regexp]
|
43
|
+
@password_regexp = options[:password_regexp]
|
44
|
+
else
|
45
|
+
# sudo on Mac OS X:
|
46
|
+
# Password:
|
47
|
+
# sudo on Red Hat, Debian, Ubuntu:
|
48
|
+
# [sudo] password for <user>:
|
49
|
+
@password_regexp = /(Password: |\[sudo\] password for .*: )/
|
20
50
|
end
|
21
|
-
@password
|
22
51
|
end
|
23
52
|
|
24
53
|
def ssh_execute(cmd, target)
|
@@ -31,9 +60,9 @@ class SSHwrap::Main
|
|
31
60
|
params[:keys] = [@ssh_key]
|
32
61
|
end
|
33
62
|
using_password = false
|
34
|
-
if @
|
63
|
+
if @prompter.passwords[@ssh_prompt]
|
35
64
|
using_password = true
|
36
|
-
params[:password] = @
|
65
|
+
params[:password] = @prompter.passwords[@ssh_prompt]
|
37
66
|
end
|
38
67
|
|
39
68
|
begin
|
@@ -63,9 +92,9 @@ class SSHwrap::Main
|
|
63
92
|
# if it's a password prompt, and interactively return data if so
|
64
93
|
# (see request_pty above).
|
65
94
|
channel.on_data do |ch_data, data|
|
66
|
-
|
67
|
-
|
68
|
-
channel.send_data "#{
|
95
|
+
if data =~ @password_regexp
|
96
|
+
prompt = $1
|
97
|
+
channel.send_data "#{@prompter.prompt(prompt)}\n"
|
69
98
|
else
|
70
99
|
stdout << data unless (data.nil? or data.empty?)
|
71
100
|
end
|
@@ -85,7 +114,7 @@ class SSHwrap::Main
|
|
85
114
|
end
|
86
115
|
rescue Net::SSH::AuthenticationFailed
|
87
116
|
if !using_password
|
88
|
-
|
117
|
+
@prompter.prompt(@ssh_prompt)
|
89
118
|
return ssh_execute(cmd, target)
|
90
119
|
else
|
91
120
|
stderr << "Authentication failed to #{target}"
|
@@ -0,0 +1,15 @@
|
|
1
|
+
class SSHwrap::Prompter
|
2
|
+
attr_reader :passwords
|
3
|
+
def initialize
|
4
|
+
@mutex = Mutex.new
|
5
|
+
@passwords = {}
|
6
|
+
end
|
7
|
+
def prompt(prompt, echo=false)
|
8
|
+
@mutex.synchronize do
|
9
|
+
if !@passwords[prompt]
|
10
|
+
@passwords[prompt] = ask(prompt) { |q| q.echo = echo }
|
11
|
+
end
|
12
|
+
end
|
13
|
+
@passwords[prompt]
|
14
|
+
end
|
15
|
+
end
|
data/lib/sshwrap/version.rb
CHANGED
data/sshwrap.gemspec
CHANGED
@@ -4,7 +4,7 @@ require File.expand_path('../lib/sshwrap/version', __FILE__)
|
|
4
4
|
Gem::Specification.new do |gem|
|
5
5
|
gem.authors = ['Jason Heiss']
|
6
6
|
gem.email = ['jheiss@aput.net']
|
7
|
-
gem.description = 'This provides a wrapper for ssh that execute a command on multiple machines, optionally in parallel, and handles any sudo prompts that result.'
|
7
|
+
gem.description = 'This provides a wrapper for ssh that execute a command on multiple machines, optionally in parallel, and handles any ssh and sudo password prompts that result.'
|
8
8
|
gem.summary = 'Perform batch SSH operations, handling sudo prompts'
|
9
9
|
gem.homepage = 'https://github.com/jheiss/sshwrap'
|
10
10
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sshwrap
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.3
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-03-
|
12
|
+
date: 2013-03-14 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: net-ssh
|
@@ -44,7 +44,7 @@ dependencies:
|
|
44
44
|
- !ruby/object:Gem::Version
|
45
45
|
version: '0'
|
46
46
|
description: This provides a wrapper for ssh that execute a command on multiple machines,
|
47
|
-
optionally in parallel, and handles any sudo prompts that result.
|
47
|
+
optionally in parallel, and handles any ssh and sudo password prompts that result.
|
48
48
|
email:
|
49
49
|
- jheiss@aput.net
|
50
50
|
executables:
|
@@ -61,6 +61,7 @@ files:
|
|
61
61
|
- bin/sshwrap
|
62
62
|
- lib/sshwrap.rb
|
63
63
|
- lib/sshwrap/main.rb
|
64
|
+
- lib/sshwrap/prompter.rb
|
64
65
|
- lib/sshwrap/version.rb
|
65
66
|
- sshwrap.gemspec
|
66
67
|
- test/test_options.rb
|