train-winrm 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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: []
|