diff --git a/CHANGELOG.md b/CHANGELOG.md index 0069e98..9cfec98 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,16 @@ ## Changelog +### [1.6.0.1](https://github.com/stoned/rd-winrm-plugin/releases/tag/1.6.0.1) +- Use Gem winrm 2.x which permit non-administrator session, see +https://github.com/WinRb/WinRM/issues/194 +- Use Gem winrm-fs 1.x +- Allow WinRM transport protocol to be specified (HTTP/HTTPS) so +HTTPS can be selected without using 'ssl' authentication type. +- Allow empty defaut user and password at the project level, or +above, so only "overriding" in job options can be use instead +- Mention in README the installation of Gem rubyntlm so NTLM +authentification can be used, via authentication type 'negotiate'. + ### [1.6.0](https://github.com/NetDocuments/rd-winrm-plugin/releases/tag/1.6.0) Enables basic auth (GH-34) diff --git a/README.md b/README.md index e681863..89707cb 100644 --- a/README.md +++ b/README.md @@ -18,8 +18,9 @@ Ubuntu: `apt-get install make ruby ruby-dev` CentOS/RHEL: `yum install make ruby ruby-devel` Install following gems: -`gem install winrm -v 1.8.1` -`gem install winrm-fs -v 0.4.3` +`gem install winrm -v 2.1.2` +`gem install winrm-fs -v 1.0.1` +`gem install rubyntlm` Download from the [releases page](https://github.com/NetDocuments/rd-winrm-plugin/releases). @@ -44,6 +45,7 @@ Settings: `Username` Put here username for negotiate, plaintext or ssl auth `Password` Put here password for negotiate, plaintext or ssl auth `Auth type` choose here negotiate, kerberos, plaintext or ssl +`WinRM transport protocol` set protocol for winrm transport (Default: http) `WinRM port` set port for winrm (Default: 5985/5986 for http/https) `Shell` choose here powershell, cmd or wql `WinRM timeout` put here time in seconds (useful for long running commands) diff --git a/contents/winrmcp.rb b/contents/winrmcp.rb index 7cada4a..0309093 100755 --- a/contents/winrmcp.rb +++ b/contents/winrmcp.rb @@ -1,11 +1,20 @@ #!/usr/bin/ruby -gem 'winrm-fs', '= 0.4.3' +gem 'winrm-fs', '= 1.0.1' require 'winrm-fs' auth = ENV['RD_CONFIG_AUTHTYPE'] -user = ENV['RD_CONFIG_USER'].dup # for some reason these strings is frozen, so we duplicate it -pass = ENV['RD_CONFIG_PASS'].dup +if ENV['RD_CONFIG_USER'] # allow empy (default) password (override used) + user = ENV['RD_CONFIG_USER'].dup # for some reason this string is frozen, so we duplicate it +else + user ='' +end +if ENV['RD_CONFIG_PASS'] # allow empy (default) password (override used) + pass = ENV['RD_CONFIG_PASS'].dup # for some reason this string is frozen, so we duplicate it +else + pass = '' +end host = ENV['RD_NODE_HOSTNAME'] port = ENV['RD_CONFIG_WINRMPORT'] +transport = ENV['RD_CONFIG_WINRMTRANSPORT'] shell = ENV['RD_CONFIG_SHELL'] realm = ENV['RD_CONFIG_KRB5_REALM'] override = ENV['RD_CONFIG_ALLOWOVERRIDE'] @@ -18,7 +27,7 @@ if auth == 'ssl' endpoint = "https://#{host}:#{port}/wsman" else - endpoint = "http://#{host}:#{port}/wsman" + endpoint = "#{transport}://#{host}:#{port}/wsman" end # Wrapper to fix: "not setting executing flags by rundeck for 2nd file in plugin" @@ -43,20 +52,35 @@ end end +connections_opts = { + endpoint: endpoint +} + +connections_opts[:operation_timeout] = ENV['RD_CONFIG_WINRMTIMEOUT'].to_i if ENV['RD_CONFIG_WINRMTIMEOUT'] + case auth when 'negotiate' - winrm = WinRM::WinRMWebService.new(endpoint, :negotiate, user: user, pass: pass) + connections_opts[:transport] = :negotiate + connections_opts[:user] = user + connections_opts[:password] = pass when 'kerberos' - winrm = WinRM::WinRMWebService.new(endpoint, :kerberos, realm: realm) + connections_opts[:transport] = :kerberos + connections_opts[:realm] = realm when 'plaintext' - winrm = WinRM::WinRMWebService.new(endpoint, :plaintext, user: user, pass: pass, disable_sspi: true) + connections_opts[:transport] = :plaintext + connections_opts[:user] = user + connections_opts[:password] = pass + connections_opts[:disable_sspi] = true when 'ssl' - winrm = WinRM::WinRMWebService.new(endpoint, :ssl, user: user, pass: pass, disable_sspi: true) + connections_opts[:transport] = :ssl + connections_opts[:user] = user + connections_opts[:password] = pass + connections_opts[:disable_sspi] = true else - fail "Invalid authtype '#{auth}' specified, expected: kerberos, plaintext, ssl." + fail "Invalid authtype '#{auth}' specified, expected: negotiate, kerberos, plaintext, ssl." end -winrm.set_timeout(ENV['RD_CONFIG_WINRMTIMEOUT'].to_i) if ENV['RD_CONFIG_WINRMTIMEOUT'] +winrm = WinRM::Connection.new(connections_opts) file_manager = WinRM::FS::FileManager.new(winrm) diff --git a/contents/winrmexe.rb b/contents/winrmexe.rb index 92a9670..0559baf 100755 --- a/contents/winrmexe.rb +++ b/contents/winrmexe.rb @@ -1,11 +1,20 @@ #!/usr/bin/ruby -gem 'winrm', '= 1.8.1' +gem 'winrm', '= 2.1.2' require 'winrm' auth = ENV['RD_CONFIG_AUTHTYPE'] -user = ENV['RD_CONFIG_USER'].dup # for some reason these strings is frozen, so we duplicate it -pass = ENV['RD_CONFIG_PASS'].dup +if ENV['RD_CONFIG_USER'] # allow empy (default) password (override used) + user = ENV['RD_CONFIG_USER'].dup # for some reason this string is frozen, so we duplicate it +else + user ='' +end +if ENV['RD_CONFIG_PASS'] # allow empy (default) password (override used) + pass = ENV['RD_CONFIG_PASS'].dup # for some reason this string is frozen, so we duplicate it +else + pass = '' +end host = ENV['RD_NODE_HOSTNAME'] port = ENV['RD_CONFIG_WINRMPORT'] +transport = ENV['RD_CONFIG_WINRMTRANSPORT'] shell = ENV['RD_CONFIG_SHELL'] realm = ENV['RD_CONFIG_KRB5_REALM'] command = ENV['RD_EXEC_COMMAND'] @@ -17,10 +26,8 @@ if auth == 'ssl' endpoint = "https://#{host}:#{port}/wsman" else - endpoint = "http://#{host}:#{port}/wsman" + endpoint = "#{transport}://#{host}:#{port}/wsman" end -ooutput = '' -eoutput = '' # Wrapper to fix: "not setting executing flags by rundeck for 2nd file in plugin" # # https://github.com/rundeck/rundeck/issues/1421 @@ -91,55 +98,52 @@ def stderr_text(stderr) end end +connections_opts = { + endpoint: endpoint +} + +connections_opts[:operation_timeout] = ENV['RD_CONFIG_WINRMTIMEOUT'].to_i if ENV['RD_CONFIG_WINRMTIMEOUT'] + case auth when 'negotiate' - winrm = WinRM::WinRMWebService.new(endpoint, :negotiate, user: user, pass: pass) + connections_opts[:transport] = :negotiate + connections_opts[:user] = user + connections_opts[:password] = pass when 'kerberos' - winrm = WinRM::WinRMWebService.new(endpoint, :kerberos, realm: realm) + connections_opts[:transport] = :kerberos + connections_opts[:realm] = realm when 'plaintext' - winrm = WinRM::WinRMWebService.new(endpoint, :plaintext, user: user, pass: pass, disable_sspi: true) + connections_opts[:transport] = :plaintext + connections_opts[:user] = user + connections_opts[:password] = pass + connections_opts[:disable_sspi] = true when 'ssl' - winrm = WinRM::WinRMWebService.new(endpoint, :ssl, user: user, pass: pass, disable_sspi: true) + connections_opts[:transport] = :ssl + connections_opts[:user] = user + connections_opts[:password] = pass + connections_opts[:disable_sspi] = true else - fail "Invalid authtype '#{auth}' specified, expected: kerberos, plaintext, ssl." + fail "Invalid authtype '#{auth}' specified, expected: negotiate, kerberos, plaintext, ssl." end -winrm.set_timeout(ENV['RD_CONFIG_WINRMTIMEOUT'].to_i) if ENV['RD_CONFIG_WINRMTIMEOUT'] +winrm = WinRM::Connection.new(connections_opts) +shell_session = nil case shell when 'powershell' - result = winrm.create_executor().run_powershell_script(command) + shell_session = winrm.shell(:powershell) + result = shell_session.run(command) when 'cmd' - result = winrm.create_executor().run_cmd(command) + shell_session = winrm.shell(:cmd) + result = shell_session.run(command) when 'wql' - result = winrm.wql(command) + result = winrm.run_wql(command) end -result[:data].each do |output_line| - eoutput = "#{eoutput}#{output_line[:stderr]}" if output_line.key?(:stderr) - ooutput = "#{ooutput}#{output_line[:stdout]}" if output_line.key?(:stdout) +if shell_session != nil + STDERR.print stderr_text(result.stderr) if result.stderr != '' + STDOUT.print result.stdout + exit result.exitcode if result.exitcode !=0 +else # WQL + STDOUT.print result end - -STDERR.print stderr_text(eoutput) if eoutput != '' -STDOUT.print ooutput -exit result[:exitcode] if result[:exitcode] != 0 - -# winrm.powershell(command) do |stdout, stderr| -# STDOUT.print stdout -# STDERR.print stderr -# end - -# result = winrm.cmd(command) -# if result[:exitcode] != 0 -# result[:data].each do |output_line| -# if output_line.has_key?(:stderr) -# STDOUT.print output_line[:stderr] -# end -# end -# else -# result[:data].each do |output_line| -# if output_line.has_key?(:stdout) -# STDOUT.print output_line[:stdout] -# end -# end -# end diff --git a/plugin.yaml b/plugin.yaml index 5eb4e82..d786f30 100644 --- a/plugin.yaml +++ b/plugin.yaml @@ -58,6 +58,16 @@ providers: scope: Instance renderingOptions: instance-scope-node-attribute: "allowoverride" + - name: winrmtransport + title: WinRM transport protocol + description: "WinRM transport protocol (Default: http or https when ssl is selected for Authentication type)" + type: Select + default: "http" + values: "http, https" + required: true + scope: Instance + renderingOptions: + instance-scope-node-attribute: "winrmtransport" - name: winrmport title: WinRM port description: "WinRM port (Default: 5985/5986 for http/https)" @@ -137,6 +147,16 @@ providers: scope: Instance renderingOptions: instance-scope-node-attribute: "allowoverride" + - name: winrmtransport + title: WinRM transport protocol + description: "WinRM transport protocol (Default: http or https when ssl is selected for Authentication type)" + type: Select + default: "http" + values: "http, https" + required: true + scope: Instance + renderingOptions: + instance-scope-node-attribute: "winrmtransport" - name: winrmport title: WinRM port description: "WinRM port (Default: 5985/5986 for http/https)"