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 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
@@ -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
@@ -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: []