train-winrm 0.2.6 → 0.2.11
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/lib/train-winrm.rb +1 -1
- data/lib/train-winrm/connection.rb +40 -7
- data/lib/train-winrm/transport.rb +30 -16
- data/lib/train-winrm/version.rb +1 -1
- metadata +16 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e0ec8bfbda71e6a294ed4ca66e9e86ca9fe26c52f766b26a14a42435119d9d3e
|
4
|
+
data.tar.gz: cfaeaa2c5294859943d47691d0b43754fec79c6ab34a33c6fd9b9a8662cb3740
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 55e4978c8bcbc83858317ddcd4eaa467eaa37a19219b0e4e4a8f8875021bebbcccc68eabb3197634277dc66a23feb3f53024008ec9409141988ec7552686e193
|
7
|
+
data.tar.gz: a677486b1dcfb590028654948bc9ec9684d718586116caa7f5086028f5feccf747cb6da470ea1e6240ae50eaf31b12a137a01a6cc6e26209631538d6ca49afe6
|
data/lib/train-winrm.rb
CHANGED
@@ -11,7 +11,7 @@
|
|
11
11
|
libdir = File.dirname(__FILE__)
|
12
12
|
$LOAD_PATH.unshift(libdir) unless $LOAD_PATH.include?(libdir)
|
13
13
|
|
14
|
-
# It's
|
14
|
+
# It's traditional to keep your gem version in a separate file, so CI can find it easier.
|
15
15
|
require_relative "train-winrm/version"
|
16
16
|
|
17
17
|
# A train plugin has three components: Transport, Connection, and (optionally) Platform.
|
@@ -1,5 +1,3 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
1
|
#
|
4
2
|
# Author:: Salim Afiune (<salim@afiunemaya.com.mx>)
|
5
3
|
# Author:: Matt Wrock (<matt@mattwrock.com>)
|
@@ -35,6 +33,8 @@
|
|
35
33
|
|
36
34
|
require "train"
|
37
35
|
require "train/plugins"
|
36
|
+
# This module may need to directly require WinRM to reference its exception classes
|
37
|
+
require "winrm" unless defined?(WinRM)
|
38
38
|
|
39
39
|
module TrainPlugins
|
40
40
|
module WinRM
|
@@ -49,6 +49,7 @@ module TrainPlugins
|
|
49
49
|
@connection_retry_sleep = @options.delete(:connection_retry_sleep)
|
50
50
|
@max_wait_until_ready = @options.delete(:max_wait_until_ready)
|
51
51
|
@operation_timeout = @options.delete(:operation_timeout)
|
52
|
+
@shell_type = @options.delete(:winrm_shell_type)
|
52
53
|
end
|
53
54
|
|
54
55
|
# (see Base::Connection#close)
|
@@ -109,15 +110,47 @@ module TrainPlugins
|
|
109
110
|
Train::File::Remote::Windows.new(self, path)
|
110
111
|
end
|
111
112
|
|
112
|
-
def run_command_via_connection(command, &data_handler)
|
113
|
+
def run_command_via_connection(command, opts = {}, &data_handler)
|
113
114
|
return if command.nil?
|
114
115
|
|
115
116
|
logger.debug("[WinRM] #{self} (#{command})")
|
116
117
|
out = ""
|
118
|
+
response = nil
|
119
|
+
timeout = opts[:timeout]&.to_i
|
120
|
+
|
121
|
+
# Run the command in a thread, to support timing out the command
|
122
|
+
thr = Thread.new do
|
123
|
+
# Surface any exceptions in this thread back to this method
|
124
|
+
Thread.current.report_on_exception = false
|
125
|
+
Thread.current.abort_on_exception = true
|
126
|
+
begin
|
127
|
+
response = session.run(command) do |stdout, _|
|
128
|
+
yield(stdout) if data_handler && stdout
|
129
|
+
out << stdout if stdout
|
130
|
+
end
|
131
|
+
rescue ::WinRM::WinRMHTTPTransportError => e
|
132
|
+
# If this command hits timeout, there is also a potential race in the HTTP transport
|
133
|
+
# where decryption is attempted on an empty message.
|
134
|
+
raise e unless timeout && e.to_s == "Could not decrypt NTLM message. ()."
|
135
|
+
rescue RuntimeError => e
|
136
|
+
# Ref: https://github.com/WinRb/WinRM/issues/315
|
137
|
+
# If this command hits timeout, calling close with the command currently running causes
|
138
|
+
# a RuntimeError error in WinRM's cleanup code. This specific error can be ignored.
|
139
|
+
# The command will be terminated and further commands can be sent on the connection.
|
140
|
+
raise e unless timeout && e.to_s == "opts[:shell_id] is required"
|
141
|
+
end
|
142
|
+
end
|
117
143
|
|
118
|
-
|
119
|
-
|
120
|
-
|
144
|
+
if timeout
|
145
|
+
res = thr.join(timeout)
|
146
|
+
unless res
|
147
|
+
msg = "PowerShell command '(#{command})' reached timeout (#{timeout}s)"
|
148
|
+
logger.info("[WinRM] #{msg}")
|
149
|
+
close
|
150
|
+
raise Train::CommandTimeoutReached.new msg
|
151
|
+
end
|
152
|
+
else
|
153
|
+
thr.join
|
121
154
|
end
|
122
155
|
|
123
156
|
CommandResult.new(out, response.stderr, response.exitcode)
|
@@ -197,7 +230,7 @@ module TrainPlugins
|
|
197
230
|
opts[:operation_timeout] = @operation_timeout unless @operation_timeout.nil?
|
198
231
|
@service = ::WinRM::Connection.new(options.merge(opts))
|
199
232
|
@service.logger = logger
|
200
|
-
@service.shell(
|
233
|
+
@service.shell(@shell_type)
|
201
234
|
end
|
202
235
|
end
|
203
236
|
|
@@ -1,5 +1,3 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
1
|
#
|
4
2
|
# Author:: Salim Afiune (<salim@afiunemaya.com.mx>)
|
5
3
|
# Author:: Matt Wrock (<matt@mattwrock.com>)
|
@@ -21,8 +19,6 @@
|
|
21
19
|
# See the License for the specific language governing permissions and
|
22
20
|
# limitations under the License.
|
23
21
|
|
24
|
-
require "rbconfig"
|
25
|
-
require "uri"
|
26
22
|
require "train"
|
27
23
|
require "train/errors"
|
28
24
|
require "train/plugins"
|
@@ -50,6 +46,7 @@ module TrainPlugins
|
|
50
46
|
|
51
47
|
# ref: https://github.com/winrb/winrm#transports
|
52
48
|
SUPPORTED_WINRM_TRANSPORTS = %i{negotiate ssl plaintext kerberos}.freeze
|
49
|
+
SUPPORTED_WINRM_SHELL_TYPES = %i{powershell elevated cmd}.freeze
|
53
50
|
|
54
51
|
# common target configuration
|
55
52
|
option :host, required: true
|
@@ -76,6 +73,7 @@ module TrainPlugins
|
|
76
73
|
# from the winrm endpoint. Does not mean that the command has
|
77
74
|
# completed in this time, only that the server has ack'd the request.
|
78
75
|
option :operation_timeout, default: nil
|
76
|
+
option :winrm_shell_type , default: "powershell"
|
79
77
|
|
80
78
|
def initialize(opts)
|
81
79
|
super(opts)
|
@@ -109,6 +107,11 @@ module TrainPlugins
|
|
109
107
|
raise Train::ClientError, "Unsupported transport type: #{winrm_transport.inspect}"
|
110
108
|
end
|
111
109
|
|
110
|
+
winrm_shell_type = opts[:winrm_shell_type].to_sym
|
111
|
+
unless SUPPORTED_WINRM_SHELL_TYPES.include?(winrm_shell_type)
|
112
|
+
raise Train::ClientError, "Unsupported winrm shell type: #{winrm_shell_type.inspect}"
|
113
|
+
end
|
114
|
+
|
112
115
|
# remove leading '/'
|
113
116
|
path = (opts[:path] || "").sub(%r{^/+}, "")
|
114
117
|
|
@@ -116,6 +119,7 @@ module TrainPlugins
|
|
116
119
|
end
|
117
120
|
|
118
121
|
WINRM_FS_SPEC_VERSION = "~> 1.0".freeze
|
122
|
+
WINRM_ELEVATED_SPEC_VERSION = "~> 1.2.2".freeze
|
119
123
|
|
120
124
|
# Builds the hash of options needed by the Connection object on
|
121
125
|
# construction.
|
@@ -142,13 +146,14 @@ module TrainPlugins
|
|
142
146
|
service: opts[:kerberos_service],
|
143
147
|
ca_trust_file: opts[:ca_trust_file],
|
144
148
|
ssl_peer_fingerprint: opts[:ssl_peer_fingerprint],
|
149
|
+
winrm_shell_type: opts[:winrm_shell_type],
|
145
150
|
}
|
146
151
|
end
|
147
152
|
|
148
153
|
# Creates a new WinRM Connection instance and save it for potential
|
149
154
|
# future reuse.
|
150
155
|
#
|
151
|
-
# @param options [Hash]
|
156
|
+
# @param options [Hash] connection options
|
152
157
|
# @return [WinRM::Connection] a WinRM Connection instance
|
153
158
|
# @api private
|
154
159
|
def create_new_connection(options, &block)
|
@@ -166,32 +171,41 @@ module TrainPlugins
|
|
166
171
|
spec_version = WINRM_FS_SPEC_VERSION.dup
|
167
172
|
logger.debug("winrm-fs requested," \
|
168
173
|
" loading WinRM::FS gem (#{spec_version})")
|
169
|
-
|
170
|
-
|
171
|
-
|
174
|
+
load_dependency("winrm-fs", spec_version)
|
175
|
+
|
176
|
+
spec_version = WINRM_ELEVATED_SPEC_VERSION.dup
|
177
|
+
logger.debug("winrm-elevated requested," \
|
178
|
+
" loading WinRM-elevated gem (#{spec_version})")
|
179
|
+
load_dependency("winrm-elevated", spec_version)
|
180
|
+
end
|
181
|
+
|
182
|
+
def load_dependency(gem_name, spec_version)
|
183
|
+
gem gem_name, spec_version
|
184
|
+
first_load = require gem_name
|
185
|
+
load_winrm_transport!(gem_name)
|
172
186
|
|
173
187
|
if first_load
|
174
|
-
logger.debug("
|
188
|
+
logger.debug("#{gem_name} library loaded")
|
175
189
|
else
|
176
|
-
logger.debug("
|
190
|
+
logger.debug("#{gem_name} previously loaded")
|
177
191
|
end
|
178
192
|
rescue LoadError => e
|
179
193
|
logger.fatal(
|
180
|
-
"The
|
194
|
+
"The `#{gem_name}' gem is missing and must" \
|
181
195
|
" be installed or cannot be properly activated. Run" \
|
182
|
-
" `gem install
|
196
|
+
" `gem install #{gem_name} --version '#{spec_version}'`" \
|
183
197
|
" or add the following to your Gemfile if you are using Bundler:" \
|
184
|
-
" `gem '
|
198
|
+
" `gem '#{gem_name}', '#{spec_version}'`."
|
185
199
|
)
|
186
200
|
raise Train::UserError,
|
187
|
-
"Could not load or activate
|
201
|
+
"Could not load or activate #{gem_name} (#{e.message})"
|
188
202
|
end
|
189
203
|
|
190
204
|
# Load WinRM::Transport code.
|
191
205
|
#
|
192
206
|
# @api private
|
193
|
-
def load_winrm_transport!
|
194
|
-
silence_warnings { require
|
207
|
+
def load_winrm_transport!(gem_name)
|
208
|
+
silence_warnings { require gem_name }
|
195
209
|
end
|
196
210
|
|
197
211
|
# Return the last saved WinRM connection instance.
|
data/lib/train-winrm/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: train-winrm
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.11
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Chef InSpec Team
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2020-09-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: winrm
|
@@ -24,6 +24,20 @@ dependencies:
|
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '2.0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: winrm-elevated
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 1.2.2
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 1.2.2
|
27
41
|
- !ruby/object:Gem::Dependency
|
28
42
|
name: winrm-fs
|
29
43
|
requirement: !ruby/object:Gem::Requirement
|