train-winrm 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 +7 -0
- data/Gemfile +23 -0
- data/README.md +51 -0
- data/lib/train-winrm.rb +20 -0
- data/lib/train-winrm/connection.rb +213 -0
- data/lib/train-winrm/transport.rb +216 -0
- data/lib/train-winrm/version.rb +10 -0
- data/train-winrm.gemspec +45 -0
- metadata +94 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 12bed665790e51bd23cbe569c27f6a93c0300e8c
|
4
|
+
data.tar.gz: 599a6d141eb447d549ca3b511c15929401dea19d
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: b12889e4dc8845c34c911e3856213eee6a8993d1d1e93488bd838a0ff0421722cba9256641b3c23bda1a7df9982e5c0ed3fdd805ee787f161edf57e34129f5a6
|
7
|
+
data.tar.gz: 82873a1ed8096c63b6c56f8a8acf0981168429af31fcb63f421af272664d8822142f7fab0e7627d6aa413f1639201c84c8e91b076f1cd7cd551c88d0d38cef37
|
data/Gemfile
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
source 'https://rubygems.org'
|
4
|
+
|
5
|
+
# This is a Gemfile, which is used by bundler
|
6
|
+
# to ensure a coherent set of gems is installed.
|
7
|
+
# This file lists dependencies needed when outside
|
8
|
+
# of a gem (the gemspec lists deps for gem deployment)
|
9
|
+
|
10
|
+
# Bundler should refer to the gemspec for any dependencies.
|
11
|
+
gemspec
|
12
|
+
|
13
|
+
# Remaining group is only used for development.
|
14
|
+
group :development do
|
15
|
+
gem 'bundler'
|
16
|
+
gem 'byebug'
|
17
|
+
gem 'm'
|
18
|
+
gem 'minitest'
|
19
|
+
gem 'mocha'
|
20
|
+
gem 'pry'
|
21
|
+
gem 'rake'
|
22
|
+
gem 'rubocop', '= 0.49.1' # Need to keep in sync with main InSpec project, so config files will work
|
23
|
+
end
|
data/README.md
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
# train-winrm - Train Plugin for connecting to Windows via Remote Management
|
2
|
+
|
3
|
+
This plugin allows applications that rely on Train to communicate with the WinRM API. For example, you could use this to audit Windows Server 2016 machines.
|
4
|
+
|
5
|
+
TODO - details about underlying library
|
6
|
+
|
7
|
+
Train itself has no CLI, nor a sophisticated test harness. Chef InSpec does have such facilities, so installing Train plugins will require a Chef InSpec installation. You do not need to use or understand Chef InSpec.
|
8
|
+
|
9
|
+
Train plugins may be developed without a Chef InSpec installation.
|
10
|
+
|
11
|
+
## To Install this as a User
|
12
|
+
|
13
|
+
Train plugins are distributed as gems. You may choose to manage the gem yourself, but if you are an Chef InSpec user, Chef InSpec can handle it for you.
|
14
|
+
|
15
|
+
You will need Chef InSpec v2.3 or later.
|
16
|
+
|
17
|
+
Simply run:
|
18
|
+
|
19
|
+
```
|
20
|
+
$ inspec plugin install train-winrm
|
21
|
+
```
|
22
|
+
|
23
|
+
You can then run:
|
24
|
+
|
25
|
+
```
|
26
|
+
TODO - example
|
27
|
+
```
|
28
|
+
|
29
|
+
## Target Options for Train-WinRM
|
30
|
+
|
31
|
+
TODO
|
32
|
+
|
33
|
+
## Reporting Issues
|
34
|
+
|
35
|
+
Bugs, typos, limitations, and frustrations are welcome to be reported through the [GitHub issues page for the train-winrm project](https://github.com/inspec/train-winrm/issues).
|
36
|
+
|
37
|
+
You may also ask questions in the #inspec channel of the Chef Community Slack team. However, for an issue to get traction, please report it as a github issue.
|
38
|
+
|
39
|
+
## Development on this Plugin
|
40
|
+
|
41
|
+
### Development Process
|
42
|
+
|
43
|
+
If you wish to contribute to this plugin, please use the usual fork-branch-push-PR cycle. All functional changes need new tests, and bugfixes are expected to include a new test that demonstrates the bug.
|
44
|
+
|
45
|
+
### Reference Information
|
46
|
+
|
47
|
+
[Plugin Development](https://github.com/inspec/train/blob/master/docs/dev/plugins.md) is documented on the `train` project on GitHub.
|
48
|
+
|
49
|
+
### Testing changes against a Windows Machine
|
50
|
+
|
51
|
+
TODO
|
data/lib/train-winrm.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
# This file is known as the "entry point."
|
2
|
+
# This is the file Train will try to load if it
|
3
|
+
# thinks your plugin is needed.
|
4
|
+
|
5
|
+
# The *only* thing this file should do is setup the
|
6
|
+
# load path, then load plugin files.
|
7
|
+
|
8
|
+
# Next two lines simply add the path of the gem to the load path.
|
9
|
+
# This is not needed when being loaded as a gem; but when doing
|
10
|
+
# plugin development, you may need it. Either way, it's harmless.
|
11
|
+
libdir = File.dirname(__FILE__)
|
12
|
+
$LOAD_PATH.unshift(libdir) unless $LOAD_PATH.include?(libdir)
|
13
|
+
|
14
|
+
# It's traditonal to keep your gem version in a separate file, so CI can find it easier.
|
15
|
+
require 'train-winrm/version'
|
16
|
+
|
17
|
+
# A train plugin has three components: Transport, Connection, and (optionally) Platform.
|
18
|
+
# Transport acts as the glue.
|
19
|
+
require 'train-winrm/transport'
|
20
|
+
require 'train-winrm/connection'
|
@@ -0,0 +1,213 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
#
|
4
|
+
# Author:: Salim Afiune (<salim@afiunemaya.com.mx>)
|
5
|
+
# Author:: Matt Wrock (<matt@mattwrock.com>)
|
6
|
+
# Author:: Fletcher Nichol (<fnichol@nichol.ca>)
|
7
|
+
# Author:: Dominik Richter (<dominik.richter@gmail.com>)
|
8
|
+
# Author:: Christoph Hartmann (<chris@lollyrock.com>)
|
9
|
+
#
|
10
|
+
# Copyright (C) 2014, Salim Afiune
|
11
|
+
#
|
12
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
13
|
+
# you may not use this file except in compliance with the License.
|
14
|
+
# You may obtain a copy of the License at
|
15
|
+
#
|
16
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
17
|
+
#
|
18
|
+
# Unless required by applicable law or agreed to in writing, software
|
19
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
20
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
21
|
+
# See the License for the specific language governing permissions and
|
22
|
+
# limitations under the License.
|
23
|
+
|
24
|
+
# Most of the work of a Train plugin happens in this file.
|
25
|
+
# Connections derive from Train::Plugins::Transport::BaseConnection,
|
26
|
+
# and provide a variety of services. Later generations of the plugin
|
27
|
+
# API will likely separate out these responsibilities, but for now,
|
28
|
+
# some of the responsibilities include:
|
29
|
+
# * authentication to the target
|
30
|
+
# * platform / release /family detection
|
31
|
+
# * caching
|
32
|
+
# * API execution
|
33
|
+
# * marshalling to / from JSON
|
34
|
+
# You don't have to worry about most of this.
|
35
|
+
|
36
|
+
require 'train'
|
37
|
+
require 'train/plugins'
|
38
|
+
|
39
|
+
module TrainPlugins
|
40
|
+
module WinRM
|
41
|
+
# @author Fletcher Nichol <fnichol@nichol.ca>
|
42
|
+
class Connection < Train::Plugins::Transport::BaseConnection # rubocop:disable Metrics/ClassLength
|
43
|
+
attr_reader :hostname
|
44
|
+
def initialize(options)
|
45
|
+
super(options)
|
46
|
+
@hostname = @options.delete(:hostname)
|
47
|
+
@rdp_port = @options.delete(:rdp_port)
|
48
|
+
@connection_retries = @options.delete(:connection_retries)
|
49
|
+
@connection_retry_sleep = @options.delete(:connection_retry_sleep)
|
50
|
+
@max_wait_until_ready = @options.delete(:max_wait_until_ready)
|
51
|
+
@operation_timeout = @options.delete(:operation_timeout)
|
52
|
+
end
|
53
|
+
|
54
|
+
# (see Base::Connection#close)
|
55
|
+
def close
|
56
|
+
return if @session.nil?
|
57
|
+
session.close
|
58
|
+
ensure
|
59
|
+
@session = nil
|
60
|
+
end
|
61
|
+
|
62
|
+
# (see Base::Connection#login_command)
|
63
|
+
def login_command
|
64
|
+
case RbConfig::CONFIG['host_os']
|
65
|
+
when /darwin/
|
66
|
+
login_command_for_mac
|
67
|
+
when /mswin|msys|mingw|cygwin|bccwin|wince|emc/
|
68
|
+
login_command_for_windows
|
69
|
+
when /linux/
|
70
|
+
login_command_for_linux
|
71
|
+
else
|
72
|
+
fail ActionFailed,
|
73
|
+
"Remote login not supported in #{self.class} " \
|
74
|
+
"from host OS '#{RbConfig::CONFIG['host_os']}'."
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
# (see Base::Connection#upload)
|
79
|
+
def upload(locals, remote)
|
80
|
+
file_manager.upload(locals, remote)
|
81
|
+
end
|
82
|
+
|
83
|
+
def download(remotes, local)
|
84
|
+
Array(remotes).each do |remote|
|
85
|
+
file_manager.download(remote, local)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
# (see Base::Connection#wait_until_ready)
|
90
|
+
def wait_until_ready
|
91
|
+
delay = 3
|
92
|
+
session(
|
93
|
+
retry_limit: @max_wait_until_ready / delay,
|
94
|
+
retry_delay: delay,
|
95
|
+
)
|
96
|
+
run_command_via_connection(PING_COMMAND.dup)
|
97
|
+
end
|
98
|
+
|
99
|
+
def uri
|
100
|
+
"winrm://#{options[:user]}@#{options[:endpoint]}:#{@rdp_port}"
|
101
|
+
end
|
102
|
+
|
103
|
+
private
|
104
|
+
|
105
|
+
PING_COMMAND = "Write-Host '[WinRM] Established\n'".freeze
|
106
|
+
|
107
|
+
def file_via_connection(path)
|
108
|
+
Train::File::Remote::Windows.new(self, path)
|
109
|
+
end
|
110
|
+
|
111
|
+
def run_command_via_connection(command, &data_handler)
|
112
|
+
return if command.nil?
|
113
|
+
logger.debug("[WinRM] #{self} (#{command})")
|
114
|
+
out = ''
|
115
|
+
|
116
|
+
response = session.run(command) do |stdout, _|
|
117
|
+
yield(stdout) if data_handler && stdout
|
118
|
+
out << stdout if stdout
|
119
|
+
end
|
120
|
+
|
121
|
+
CommandResult.new(out, response.stderr, response.exitcode)
|
122
|
+
end
|
123
|
+
|
124
|
+
# Create a local RDP document and return it
|
125
|
+
#
|
126
|
+
# @param opts [Hash] configuration options
|
127
|
+
# @option opts [true,false] :mac whether or not the document is for a
|
128
|
+
# Mac system
|
129
|
+
# @api private
|
130
|
+
def rdp_doc(opts = {})
|
131
|
+
host = URI.parse(options[:endpoint]).host
|
132
|
+
content = [
|
133
|
+
"full address:s:#{host}:#{@rdp_port}",
|
134
|
+
'prompt for credentials:i:1',
|
135
|
+
"username:s:#{options[:user]}",
|
136
|
+
].join("\n")
|
137
|
+
|
138
|
+
content.prepend("drivestoredirect:s:*\n") if opts[:mac]
|
139
|
+
|
140
|
+
content
|
141
|
+
end
|
142
|
+
|
143
|
+
# @return [Winrm::FileManager] a file transporter
|
144
|
+
# @api private
|
145
|
+
def file_manager
|
146
|
+
@file_manager ||= begin
|
147
|
+
# Ensure @service is available:
|
148
|
+
wait_until_ready
|
149
|
+
WinRM::FS::FileManager.new(@service)
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
# Builds a `LoginCommand` for use by Linux-based platforms.
|
154
|
+
#
|
155
|
+
# TODO: determine whether or not `desktop` exists
|
156
|
+
#
|
157
|
+
# @return [LoginCommand] a login command
|
158
|
+
# @api private
|
159
|
+
def login_command_for_linux
|
160
|
+
args = %W(-u #{options[:user]})
|
161
|
+
args += %W(-p #{options[:pass]}) if options.key?(:pass)
|
162
|
+
args += %W(#{URI.parse(options[:endpoint]).host}:#{@rdp_port})
|
163
|
+
LoginCommand.new('rdesktop', args)
|
164
|
+
end
|
165
|
+
|
166
|
+
# Builds a `LoginCommand` for use by Mac-based platforms.
|
167
|
+
#
|
168
|
+
# @return [LoginCommand] a login command
|
169
|
+
# @api private
|
170
|
+
def login_command_for_mac
|
171
|
+
LoginCommand.new('open', rdp_doc(mac: true))
|
172
|
+
end
|
173
|
+
|
174
|
+
# Builds a `LoginCommand` for use by Windows-based platforms.
|
175
|
+
#
|
176
|
+
# @return [LoginCommand] a login command
|
177
|
+
# @api private
|
178
|
+
def login_command_for_windows
|
179
|
+
LoginCommand.new('mstsc', rdp_doc)
|
180
|
+
end
|
181
|
+
|
182
|
+
# Establishes a remote shell session, or establishes one when invoked
|
183
|
+
# the first time.
|
184
|
+
#
|
185
|
+
# @param retry_options [Hash] retry options for the initial connection
|
186
|
+
# @return [Winrm::CommandExecutor] the command executor session
|
187
|
+
# @api private
|
188
|
+
def session(retry_options = {})
|
189
|
+
@session ||= begin
|
190
|
+
opts = {
|
191
|
+
retry_limit: @connection_retries.to_i,
|
192
|
+
retry_delay: @connection_retry_sleep.to_i,
|
193
|
+
}.merge(retry_options)
|
194
|
+
|
195
|
+
opts[:operation_timeout] = @operation_timeout unless @operation_timeout.nil?
|
196
|
+
@service = ::WinRM::Connection.new(options.merge(opts))
|
197
|
+
@service.logger = logger
|
198
|
+
@service.shell(:powershell)
|
199
|
+
end
|
200
|
+
end
|
201
|
+
|
202
|
+
# String representation of object, reporting its connection details and
|
203
|
+
# configuration.
|
204
|
+
#
|
205
|
+
# @api private
|
206
|
+
def to_s
|
207
|
+
options_to_print = @options.clone
|
208
|
+
options_to_print[:password] = '<hidden>' if options_to_print.key?(:password)
|
209
|
+
"#{@username}@#{@hostname}<#{options_to_print.inspect}>"
|
210
|
+
end
|
211
|
+
end
|
212
|
+
end
|
213
|
+
end
|
@@ -0,0 +1,216 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
#
|
4
|
+
# Author:: Salim Afiune (<salim@afiunemaya.com.mx>)
|
5
|
+
# Author:: Matt Wrock (<matt@mattwrock.com>)
|
6
|
+
# Author:: Fletcher Nichol (<fnichol@nichol.ca>)
|
7
|
+
# Author:: Dominik Richter (<dominik.richter@gmail.com>)
|
8
|
+
# Author:: Christoph Hartmann (<chris@lollyrock.com>)
|
9
|
+
#
|
10
|
+
# Copyright (C) 2014, Salim Afiune
|
11
|
+
#
|
12
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
13
|
+
# you may not use this file except in compliance with the License.
|
14
|
+
# You may obtain a copy of the License at
|
15
|
+
#
|
16
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
17
|
+
#
|
18
|
+
# Unless required by applicable law or agreed to in writing, software
|
19
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
20
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
21
|
+
# See the License for the specific language governing permissions and
|
22
|
+
# limitations under the License.
|
23
|
+
|
24
|
+
require 'rbconfig'
|
25
|
+
require 'uri'
|
26
|
+
require 'train'
|
27
|
+
require 'train/errors'
|
28
|
+
require 'train/plugins'
|
29
|
+
|
30
|
+
# Train Plugins v1 are usually declared under the TrainPlugins namespace.
|
31
|
+
# Each plugin has three components: Transport, Connection, and (optionally) Platform.
|
32
|
+
# We'll only define the Transport here, but we'll refer to the others.
|
33
|
+
|
34
|
+
module TrainPlugins
|
35
|
+
module WinRM
|
36
|
+
# Wrapped exception for any internally raised WinRM-related errors.
|
37
|
+
#
|
38
|
+
# @author Fletcher Nichol <fnichol@nichol.ca>
|
39
|
+
class WinRMFailed < Train::TransportError; end
|
40
|
+
|
41
|
+
# A Transport which uses WinRM to execute commands and transfer files.
|
42
|
+
#
|
43
|
+
# @author Matt Wrock <matt@mattwrock.com>
|
44
|
+
# @author Salim Afiune <salim@afiunemaya.com.mx>
|
45
|
+
# @author Fletcher Nichol <fnichol@nichol.ca>
|
46
|
+
class Transport < Train.plugin(1) # rubocop:disable Metrics/ClassLength
|
47
|
+
name 'winrm'
|
48
|
+
|
49
|
+
require 'train-winrm/connection'
|
50
|
+
|
51
|
+
# ref: https://github.com/winrb/winrm#transports
|
52
|
+
SUPPORTED_WINRM_TRANSPORTS = %i(negotiate ssl plaintext kerberos).freeze
|
53
|
+
|
54
|
+
# common target configuration
|
55
|
+
option :host, required: true
|
56
|
+
option :port
|
57
|
+
option :user, default: 'administrator', required: true
|
58
|
+
option :password, nil
|
59
|
+
option :winrm_transport, default: :negotiate
|
60
|
+
option :winrm_disable_sspi, default: false
|
61
|
+
option :winrm_basic_auth_only, default: false
|
62
|
+
option :path, default: '/wsman'
|
63
|
+
option :ssl, default: false
|
64
|
+
option :self_signed, default: false
|
65
|
+
|
66
|
+
# additional winrm options
|
67
|
+
option :rdp_port, default: 3389
|
68
|
+
option :connection_retries, default: 5
|
69
|
+
option :connection_retry_sleep, default: 1
|
70
|
+
option :max_wait_until_ready, default: 600
|
71
|
+
option :ssl_peer_fingerprint, default: nil
|
72
|
+
option :kerberos_realm, default: nil
|
73
|
+
option :kerberos_service, default: nil
|
74
|
+
option :ca_trust_file, default: nil
|
75
|
+
# The amount of time in SECONDS for which each operation must get an ack
|
76
|
+
# from the winrm endpoint. Does not mean that the command has
|
77
|
+
# completed in this time, only that the server has ack'd the request.
|
78
|
+
option :operation_timeout, default: nil
|
79
|
+
|
80
|
+
def initialize(opts)
|
81
|
+
super(opts)
|
82
|
+
load_needed_dependencies!
|
83
|
+
end
|
84
|
+
|
85
|
+
# (see Base#connection)
|
86
|
+
def connection(state = nil, &block)
|
87
|
+
opts = merge_options(options, state || {})
|
88
|
+
validate_options(opts)
|
89
|
+
conn_opts = connection_options(opts)
|
90
|
+
|
91
|
+
if @connection && @connection_options == conn_opts
|
92
|
+
reuse_connection(&block)
|
93
|
+
else
|
94
|
+
create_new_connection(conn_opts, &block)
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
private
|
99
|
+
|
100
|
+
def validate_options(opts)
|
101
|
+
super(opts)
|
102
|
+
|
103
|
+
# set scheme and port based on ssl activation
|
104
|
+
scheme = opts[:ssl] ? 'https' : 'http'
|
105
|
+
port = opts[:port]
|
106
|
+
port = (opts[:ssl] ? 5986 : 5985) if port.nil?
|
107
|
+
winrm_transport = opts[:winrm_transport].to_sym
|
108
|
+
unless SUPPORTED_WINRM_TRANSPORTS.include?(winrm_transport)
|
109
|
+
fail Train::ClientError, "Unsupported transport type: #{winrm_transport.inspect}"
|
110
|
+
end
|
111
|
+
|
112
|
+
# remove leading '/'
|
113
|
+
path = (opts[:path] || '').sub(%r{^/+}, '')
|
114
|
+
|
115
|
+
opts[:endpoint] = "#{scheme}://#{opts[:host]}:#{port}/#{path}"
|
116
|
+
end
|
117
|
+
|
118
|
+
WINRM_FS_SPEC_VERSION = '~> 1.0'.freeze
|
119
|
+
|
120
|
+
# Builds the hash of options needed by the Connection object on
|
121
|
+
# construction.
|
122
|
+
#
|
123
|
+
# @param data [Hash] merged configuration and mutable state data
|
124
|
+
# @return [Hash] hash of connection options
|
125
|
+
# @api private
|
126
|
+
def connection_options(opts)
|
127
|
+
{
|
128
|
+
logger: logger,
|
129
|
+
transport: opts[:winrm_transport].to_sym,
|
130
|
+
disable_sspi: opts[:winrm_disable_sspi],
|
131
|
+
basic_auth_only: opts[:winrm_basic_auth_only],
|
132
|
+
hostname: opts[:host],
|
133
|
+
endpoint: opts[:endpoint],
|
134
|
+
user: opts[:user],
|
135
|
+
password: opts[:password],
|
136
|
+
rdp_port: opts[:rdp_port],
|
137
|
+
connection_retries: opts[:connection_retries],
|
138
|
+
connection_retry_sleep: opts[:connection_retry_sleep],
|
139
|
+
max_wait_until_ready: opts[:max_wait_until_ready],
|
140
|
+
no_ssl_peer_verification: opts[:self_signed],
|
141
|
+
realm: opts[:kerberos_realm],
|
142
|
+
service: opts[:kerberos_service],
|
143
|
+
ca_trust_file: opts[:ca_trust_file],
|
144
|
+
ssl_peer_fingerprint: opts[:ssl_peer_fingerprint],
|
145
|
+
}
|
146
|
+
end
|
147
|
+
|
148
|
+
# Creates a new WinRM Connection instance and save it for potential
|
149
|
+
# future reuse.
|
150
|
+
#
|
151
|
+
# @param options [Hash] conneciton options
|
152
|
+
# @return [WinRM::Connection] a WinRM Connection instance
|
153
|
+
# @api private
|
154
|
+
def create_new_connection(options, &block)
|
155
|
+
if @connection
|
156
|
+
logger.debug("[WinRM] shutting previous connection #{@connection}")
|
157
|
+
@connection.close
|
158
|
+
end
|
159
|
+
|
160
|
+
@connection_options = options
|
161
|
+
@connection = Connection.new(options, &block)
|
162
|
+
end
|
163
|
+
|
164
|
+
# (see Base#load_needed_dependencies!)
|
165
|
+
def load_needed_dependencies!
|
166
|
+
spec_version = WINRM_FS_SPEC_VERSION.dup
|
167
|
+
logger.debug('winrm-fs requested,' \
|
168
|
+
" loading WinRM::FS gem (#{spec_version})")
|
169
|
+
gem 'winrm-fs', spec_version
|
170
|
+
first_load = require 'winrm-fs'
|
171
|
+
load_winrm_transport!
|
172
|
+
|
173
|
+
if first_load
|
174
|
+
logger.debug('WinRM::FS library loaded')
|
175
|
+
else
|
176
|
+
logger.debug('WinRM::FS previously loaded')
|
177
|
+
end
|
178
|
+
rescue LoadError => e
|
179
|
+
logger.fatal(
|
180
|
+
"The `winrm-fs' gem is missing and must" \
|
181
|
+
' be installed or cannot be properly activated. Run' \
|
182
|
+
" `gem install winrm-fs --version '#{spec_version}'`" \
|
183
|
+
' or add the following to your Gemfile if you are using Bundler:' \
|
184
|
+
" `gem 'winrm-fs', '#{spec_version}'`.",
|
185
|
+
)
|
186
|
+
raise Train::UserError,
|
187
|
+
"Could not load or activate WinRM::FS (#{e.message})"
|
188
|
+
end
|
189
|
+
|
190
|
+
# Load WinRM::Transport code.
|
191
|
+
#
|
192
|
+
# @api private
|
193
|
+
def load_winrm_transport!
|
194
|
+
silence_warnings { require 'winrm-fs' }
|
195
|
+
end
|
196
|
+
|
197
|
+
# Return the last saved WinRM connection instance.
|
198
|
+
#
|
199
|
+
# @return [Winrm::Connection] a WinRM Connection instance
|
200
|
+
# @api private
|
201
|
+
def reuse_connection
|
202
|
+
logger.debug("[WinRM] reusing existing connection #{@connection}")
|
203
|
+
yield @connection if block_given?
|
204
|
+
@connection
|
205
|
+
end
|
206
|
+
|
207
|
+
def silence_warnings
|
208
|
+
old_verbose = $VERBOSE
|
209
|
+
$VERBOSE = nil
|
210
|
+
yield
|
211
|
+
ensure
|
212
|
+
$VERBOSE = old_verbose
|
213
|
+
end
|
214
|
+
end
|
215
|
+
end
|
216
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
# This file exists simply to record the version number of the plugin.
|
2
|
+
# It is kept in a separate file, so that your gemspec can load it and
|
3
|
+
# learn the current version without loading the whole plugin. Also,
|
4
|
+
# many CI servers can update this file when "version bumping".
|
5
|
+
|
6
|
+
module TrainPlugins
|
7
|
+
module WinRM
|
8
|
+
VERSION = '0.1.0'.freeze
|
9
|
+
end
|
10
|
+
end
|
data/train-winrm.gemspec
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
# As plugins are usually packaged and distributed as a RubyGem,
|
2
|
+
# we have to provide a .gemspec file, which controls the gembuild
|
3
|
+
# and publish process. This is a fairly generic gemspec.
|
4
|
+
|
5
|
+
# It is traditional in a gemspec to dynamically load the current version
|
6
|
+
# from a file in the source tree. The next three lines make that happen.
|
7
|
+
lib = File.expand_path('../lib', __FILE__)
|
8
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
9
|
+
require 'train-winrm/version'
|
10
|
+
|
11
|
+
Gem::Specification.new do |spec|
|
12
|
+
# Importantly, all Train plugins must be prefixed with `train-`
|
13
|
+
spec.name = 'train-winrm'
|
14
|
+
|
15
|
+
# It is polite to namespace your plugin under InspecPlugins::YourPluginInCamelCase
|
16
|
+
spec.version = TrainPlugins::WinRM::VERSION
|
17
|
+
spec.authors = ['Chef InSpec Team']
|
18
|
+
spec.email = ['inspec@chef.io']
|
19
|
+
spec.summary = 'Windows WinRM API Transport for Train'
|
20
|
+
spec.description = 'Allows applictaions using Train to speak to Windows using Remote Management; handles authentication, cacheing, and SDK dependency management.'
|
21
|
+
spec.homepage = 'https://github.com/inspec/train-winrm'
|
22
|
+
spec.license = 'Apache-2.0'
|
23
|
+
|
24
|
+
# Though complicated-looking, this is pretty standard for a gemspec.
|
25
|
+
# It just filters what will actually be packaged in the gem (leaving
|
26
|
+
# out tests, etc)
|
27
|
+
spec.files = %w{
|
28
|
+
README.md train-winrm.gemspec Gemfile
|
29
|
+
} + Dir.glob(
|
30
|
+
'lib/**/*', File::FNM_DOTMATCH
|
31
|
+
).reject { |f| File.directory?(f) }
|
32
|
+
spec.require_paths = ['lib']
|
33
|
+
|
34
|
+
# If you rely on any other gems, list them here with any constraints.
|
35
|
+
# This is how `inspec plugin install` is able to manage your dependencies.
|
36
|
+
|
37
|
+
# If you only need certain gems during development or testing, list
|
38
|
+
# them in Gemfile, not here.
|
39
|
+
|
40
|
+
# Do not list inspec as a dependency of a train plugin.
|
41
|
+
|
42
|
+
spec.add_dependency 'train', '~> 2.0'
|
43
|
+
spec.add_dependency 'winrm', '~> 2.0'
|
44
|
+
spec.add_dependency 'winrm-fs', '~> 1.0'
|
45
|
+
end
|
metadata
ADDED
@@ -0,0 +1,94 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: train-winrm
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Chef InSpec Team
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2019-05-09 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: train
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '2.0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '2.0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: winrm
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '2.0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '2.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: winrm-fs
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '1.0'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '1.0'
|
55
|
+
description: Allows applictaions using Train to speak to Windows using Remote Management;
|
56
|
+
handles authentication, cacheing, and SDK dependency management.
|
57
|
+
email:
|
58
|
+
- inspec@chef.io
|
59
|
+
executables: []
|
60
|
+
extensions: []
|
61
|
+
extra_rdoc_files: []
|
62
|
+
files:
|
63
|
+
- Gemfile
|
64
|
+
- README.md
|
65
|
+
- lib/train-winrm.rb
|
66
|
+
- lib/train-winrm/connection.rb
|
67
|
+
- lib/train-winrm/transport.rb
|
68
|
+
- lib/train-winrm/version.rb
|
69
|
+
- train-winrm.gemspec
|
70
|
+
homepage: https://github.com/inspec/train-winrm
|
71
|
+
licenses:
|
72
|
+
- Apache-2.0
|
73
|
+
metadata: {}
|
74
|
+
post_install_message:
|
75
|
+
rdoc_options: []
|
76
|
+
require_paths:
|
77
|
+
- lib
|
78
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
84
|
+
requirements:
|
85
|
+
- - ">="
|
86
|
+
- !ruby/object:Gem::Version
|
87
|
+
version: '0'
|
88
|
+
requirements: []
|
89
|
+
rubyforge_project:
|
90
|
+
rubygems_version: 2.6.14.3
|
91
|
+
signing_key:
|
92
|
+
specification_version: 4
|
93
|
+
summary: Windows WinRM API Transport for Train
|
94
|
+
test_files: []
|