├── .rubocop.yml ├── CHANGELOG.md ├── README.md ├── contents ├── winrmcp.rb └── winrmexe.rb ├── plugin.yaml └── LICENSE.txt /.rubocop.yml: -------------------------------------------------------------------------------- 1 | Metrics/LineLength: 2 | Max: 120 3 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## Changelog 2 | ### [1.7.0](https://github.com/NetDocuments/rd-winrm-plugin/releases/tag/1.7.0) 3 | - Update winrm and winrm-rf gems 4 | - Rewrite of connection portion of script to support new features of these gems 5 | - Add basic error handling to improve user friendliness of output 6 | - Removed non functioning quote bug fix, Rundeck's documentation is an adequate fix until bug is resolved internally 7 | - Added grouping to UI elements of plugin 8 | 9 | ### [1.6.2](https://github.com/NetDocuments/rd-winrm-plugin/releases/tag/1.6.2) 10 | - Use Gem winrm 2.x which permit non-administrator session, see 11 | https://github.com/WinRb/WinRM/issues/194 12 | - Use Gem winrm-fs 1.x 13 | - Allow WinRM transport protocol to be specified (HTTP/HTTPS) so 14 | HTTPS can be selected without using 'ssl' authentication type. 15 | - Allow empty defaut user and password at the project level, or 16 | above, so only "overriding" in job options can be use instead 17 | 18 | ### [1.6.0](https://github.com/NetDocuments/rd-winrm-plugin/releases/tag/1.6.0) 19 | Enables basic auth (GH-34) 20 | 21 | ### [1.5.1](https://github.com/NetDocuments/rd-winrm-plugin/releases/tag/1.5.1) 22 | Add NTLM/Negotiate authentication type for WinRM File Copier 23 | 24 | ### [1.5.0](https://github.com/NetDocuments/rd-winrm-plugin/releases/tag/1.5.0) 25 | Add NTLM/Negotiate authentication type [#19](https://github.com/NetDocuments/rd-winrm-plugin/issues/19) 26 | Add check for required winrm/winrm-fs gem versions [#29](https://github.com/NetDocuments/rd-winrm-plugin/issues/29) 27 | 28 | ### [1.4.1](https://github.com/NetDocuments/rd-winrm-plugin/releases/tag/1.4.1) 29 | Fix HTTPS with self-signed cert [#23](https://github.com/netdocuments/rd-winrm-plugin/issues/23) 30 | Added support https for ssl connections [#25](https://github.com/NetDocuments/rd-winrm-plugin/pull/25) 31 | 32 | ### [1.4.0](https://github.com/NetDocuments/rd-winrm-plugin/releases/tag/1.4.0) 33 | Fix credential leakage [#22](https://github.com/netdocuments/rd-winrm-plugin/issues/22) 34 | Change shell executions to use non deprecated methods [#24](https://github.com/netdocuments/rd-winrm-plugin/issues/24) 35 | 36 | ### [1.3.2](https://github.com/NetDocuments/rd-winrm-plugin/releases/tag/1.3.2) 37 | Fix for error output in case it is not in XML format 38 | 39 | ### [1.3.1](https://github.com/NetDocuments/rd-winrm-plugin/releases/tag/1.3.1) 40 | Fixes in readme, fix for #3 (WinRM timeout defaults) and #2 (can't modify frozen string) 41 | 42 | ### [1.3.0](https://github.com/NetDocuments/rd-winrm-plugin/releases/tag/1.3.0) 43 | Extension for copied script depends on context of script execution 44 | 45 | ### [1.2.0](https://github.com/NetDocuments/rd-winrm-plugin/releases/tag/1.2.0) 46 | Allow override feature and fix for [rundeck bug](https://github.com/rundeck/rundeck/issues/1421) 47 | 48 | ### [1.1.1](https://github.com/NetDocuments/rd-winrm-plugin/releases/tag/1.1.1) 49 | Sanitised passwords in debug mode 50 | 51 | ### [1.1.0](https://github.com/NetDocuments/rd-winrm-plugin/releases/tag/1.1.0) 52 | Added possibility to set port for winrm 53 | 54 | ### [1.0.0](https://github.com/NetDocuments/rd-winrm-plugin/releases/tag/1.0.0) 55 | Public release, debugging depends on debugging level on job 56 | 57 | ### 0.9.0 58 | Fixes in quotes cleanup behaviour, Fixes in quotes cleanup behaviour, trivial rubocop fixes 59 | 60 | ### 0.8.0 61 | WinRM timeout managed via config 62 | 63 | ### 0.7.0 64 | different shells support (powershell, cmd, wql) 65 | 66 | ### 0.6.0 67 | Different authentication types for winrm 68 | 69 | ### 0.5.0 70 | convert XML output into readable strings, Password as secure string, cleanup 71 | 72 | ### 0.4.0 73 | fix for unix style file manipulation in rundeck on windows, added timeout for log running command 74 | 75 | ### 0.3.0 76 | fix for strange rundeck behaviour with quotes 77 | 78 | ### 0.2.0 79 | added file copy feature 80 | 81 | ### 0.1.0 82 | initial commit 83 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Rd-WinRM-plugin 2 | 3 | **_No support_** 4 | 5 | _We are no longer using rundeck. Merge requests and bug reports still welcome. We won't be able to provide support to any issues you may encounter._ 6 | 7 | --- 8 | 9 | This is a [Rundeck Node Execution plugin](http://rundeck.org/docs/plugins-user-guide/node-execution-plugins) that uses WinRM to connect to Windows and execute commands. It uses the [WinRM for Ruby](https://github.com/WinRb/WinRM)Library to provide the WinRM implementation. 10 | 11 | Compatible with Rundeck 2.9.x+ 12 | 13 | ## Features 14 | Can run scripts or commands. 15 | Supports PowerShell, CMD and WQL shells 16 | Can copy files to Windows 17 | 18 | ### Installation 19 | 20 | Install Ruby: 21 | Ubuntu: `apt-get install make ruby ruby-dev` 22 | CentOS/RHEL: `yum install make ruby ruby-devel` 23 | 24 | Install following gems: 25 | `gem install winrm -v 2.2.3` 26 | `gem install winrm-fs -v 1.0.2` 27 | `gem install rubyntlm -v 0.6.2` 28 | 29 | Download from the [releases page](https://github.com/NetDocuments/rd-winrm-plugin/releases). 30 | 31 | Copy the `rd-winrm-plugin.zip` to the `libext/` directory for Rundeck. It must be named like `rd-winrm-plugin-x.x.x.zip`. There is no need to restart rundeck. 32 | 33 | ```bash 34 | RD_WINRM='1.7.0' 35 | curl -L https://github.com/NetDocuments/rd-winrm-plugin/archive/$RD_WINRM.zip -o /var/lib/rundeck/libext/rd-winrm-plugin-$RD_WINRM.zip 36 | ``` 37 | 38 | Before rundeck can run commands on windows nodes, [configure winrm](https://technet.microsoft.com/en-us/magazine/ff700227.aspx) from an administrative powershell window 39 | 40 | winrm quickconfig 41 | 42 | ### Configuration 43 | Choose `WinRM Executor` as Default Node Executor 44 | and `WinRM File Copier` as Default Node File Copier 45 | 46 | Settings: 47 | `Kerberos Realm` Put here fqdn of your realm in case your computer is part of AD domain 48 | `Username` Put here username for negotiate, plaintext or ssl auth 49 | `Password` Put here password for negotiate, plaintext or ssl auth 50 | `Auth type` Choose here negotiate, kerberos, plaintext or ssl 51 | `NOSSL` Choose to disable SSL Validation 52 | `Allow override` Allow override of variables from job options 53 | `WinRM transport protocol` Set protocol for winrm transport (Default: http) 54 | `WinRM port` Set port for winrm (Default: 5985/5986 for http/https) 55 | `Shell` Choose here powershell, cmd or wql 56 | `WinRM timeout` Put here timeout in seconds (useful for long running commands) 57 | 58 | ![](http://cl.ly/1S1D2C070Z1T/Screenshot%202016-01-05%2016.51.53.png) 59 | 60 | ### Special Behaviour 61 | `Allow Override` parameter gives possibility to set hostname, username and password in job options, not in project. It can be used in case you need to quickly change hostnames (with dropdown list for example) or set username/pass on job level 62 | 63 | - If that parameter set to `hostname` you may use option variable with name `winrmhost` to set hostname 64 | - If that parameter set to `user` you may use `winrmuser` and `winrmpass` to set username/pass 65 | - If that parameter set to `all` you may use all these additional options 66 | - If that parameter set to `none` these options in jobs will be ignored 67 | 68 | ### Limitations 69 | - Scripts in c:/tmp with .sh extension will be renamed into .ps1, .bat or .wql 70 | - Quotes behaviour can be strange, [Rundeck bug](https://github.com/rundeck/rundeck/issues/602) 71 | 72 | ### Troubleshooting 73 | You may have some errors like ```WinRM::WinRMAuthorizationError```. 74 | You can run the following commands on the server to try to solve the problem: 75 | 76 | ``` 77 | winrm set winrm/config/client/auth @{Basic="true"} 78 | winrm set winrm/config/service/auth @{Basic="true"} 79 | winrm set winrm/config/service @{AllowUnencrypted="true"} 80 | ``` 81 | You can read more about that on issue [#29](https://github.com/WinRb/WinRM/issues/29) on ruby WinRM page 82 | 83 | ### PR and reporting 84 | PR is highly welcome, we using gitflow for our development process, so please, make them to develop branch. 85 | If you have some issue please describe steps to reproduce it 86 | 87 | ### License and Authors 88 | Copyright 2015 NetVoyage Corporation (NetDocuments) 89 | 90 | Author: [Volodymyr Babchynskyy](https://github.com/vvchik) 91 | 92 | Licensed under the Apache License, Version 2.0 (the "License"); 93 | you may not use this file except in compliance with the License. You may obtain a copy of the License at 94 | 95 | http://www.apache.org/licenses/LICENSE-2.0 96 | 97 | Unless required by applicable law or agreed to in writing, software distributed under the License 98 | is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, 99 | either express or implied. See the License for the specific language governing permissions and limitations under the License. 100 | -------------------------------------------------------------------------------- /contents/winrmcp.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/ruby 2 | gem 'winrm-fs', '= 1.0.2' 3 | require 'winrm-fs' 4 | auth = ENV['RD_CONFIG_AUTHTYPE'] 5 | nossl = ENV['RD_CONFIG_NOSSL'] == 'true' ? true : false 6 | if ENV['RD_CONFIG_USER'] # allow empty (default) user (override used) 7 | user = ENV['RD_CONFIG_USER'].dup # for some reason this string is frozen, so we duplicate it 8 | else 9 | user ='' 10 | end 11 | if ENV['RD_CONFIG_PASS'] # allow empty (default) password (override used) 12 | pass = ENV['RD_CONFIG_PASS'].dup # for some reason this string is frozen, so we duplicate it 13 | else 14 | pass = '' 15 | end 16 | host = ENV['RD_NODE_HOSTNAME'] 17 | port = ENV['RD_CONFIG_WINRMPORT'] 18 | transport = ENV['RD_CONFIG_WINRMTRANSPORT'] 19 | shell = ENV['RD_CONFIG_SHELL'] 20 | realm = ENV['RD_CONFIG_KRB5_REALM'] 21 | override = ENV['RD_CONFIG_ALLOWOVERRIDE'] 22 | if ENV['RD_CONFIG_WINRMTIMEOUT'] 23 | timeout = ENV['RD_CONFIG_WINRMTIMEOUT'].to_i 24 | else 25 | timeout = 60 26 | end 27 | host = ENV['RD_OPTION_WINRMHOST'] if ENV['RD_OPTION_WINRMHOST'] && (override == 'host' || override == 'all') 28 | user = ENV['RD_OPTION_WINRMUSER'].dup if ENV['RD_OPTION_WINRMUSER'] && (override == 'user' || override == 'all') 29 | pass = ENV['RD_OPTION_WINRMPASS'].dup if ENV['RD_OPTION_WINRMPASS'] && (override == 'user' || override == 'all') 30 | 31 | file = ARGV[1] 32 | dest = ARGV[2] 33 | if auth == 'ssl' 34 | endpoint = "https://#{host}:#{port}/wsman" 35 | else 36 | endpoint = "#{transport}://#{host}:#{port}/wsman" 37 | end 38 | 39 | # Wrapper to fix: "not setting executing flags by rundeck for 2nd file in plugin" 40 | # # https://github.com/rundeck/rundeck/issues/1421 41 | # remove it after issue will be fixed 42 | if File.exist?("#{ENV['RD_PLUGIN_BASE']}/winrmexe.rb") && !File.executable?("#{ENV['RD_PLUGIN_BASE']}/winrmexe.rb") 43 | File.chmod(0764, "#{ENV['RD_PLUGIN_BASE']}/winrmexe.rb") # https://github.com/rundeck/rundeck/issues/1421 44 | end 45 | #--- 46 | 47 | # Wrapper for avoid unix style file copying then scripts run 48 | # - not accept chmod call 49 | # - replace rm -f into rm -force 50 | # - auto copying renames file from .sh into .ps1, .bat or .wql in tmp directory 51 | if %r{/tmp/.*\.sh}.match(dest) 52 | case shell 53 | when 'powershell' 54 | dest = dest.gsub(/\.sh/, '.ps1') 55 | when 'cmd' 56 | dest = dest.gsub(/\.sh/, '.bat') 57 | when 'wql' 58 | dest = dest.gsub(/\.sh/, '.wql') 59 | end 60 | end 61 | #--- 62 | 63 | # Build connection options 64 | connections_opts = { 65 | endpoint: endpoint 66 | } 67 | 68 | connections_opts[:operation_timeout] = timeout 69 | 70 | case auth 71 | when 'negotiate' 72 | connections_opts[:transport] = :negotiate 73 | connections_opts[:user] = user 74 | connections_opts[:password] = pass 75 | when 'kerberos' 76 | connections_opts[:transport] = :kerberos 77 | connections_opts[:realm] = realm 78 | when 'plaintext' 79 | connections_opts[:transport] = :plaintext 80 | connections_opts[:user] = user 81 | connections_opts[:password] = pass 82 | connections_opts[:disable_sspi] = true 83 | when 'ssl' 84 | connections_opts[:transport] = :ssl 85 | connections_opts[:user] = user 86 | connections_opts[:password] = pass 87 | connections_opts[:disable_sspi] = true 88 | connections_opts[:no_ssl_peer_verification] = nossl 89 | else 90 | fail "Invalid authtype '#{auth}' specified, expected: negotiate, kerberos, plaintext, ssl." 91 | end 92 | #--- 93 | 94 | # Create session 95 | winrm = WinRM::Connection.new(connections_opts) 96 | file_manager = WinRM::FS::FileManager.new(winrm) 97 | #--- 98 | 99 | ## Upload file to host 100 | begin 101 | file_manager.upload(file, dest) 102 | rescue HTTPClient::ConnectTimeoutError => e #Capture Timeout on FileCopy (Server Offline) 103 | if ENV['RD_JOB_LOGLEVEL'] == 'DEBUG' 104 | STDERR.print "FileCopy failed due to Timeout:\n" 105 | STDERR.print "Exception Class: #{ e.class.name }\n" 106 | STDERR.print "Exception Message: #{ e.message }\n" 107 | STDERR.print "Exception Backtrace: #{ e.backtrace }\n" 108 | exit 1 109 | else 110 | STDERR.print "FileCopy failed due to Timeout: #{ e.class.name }--#{ e.message }\n" 111 | exit 1 112 | end 113 | rescue WinRM::WinRMAuthorizationError => e #Capture WinRM Access error (Bad WinRM config) 114 | if ENV['RD_JOB_LOGLEVEL'] == 'DEBUG' 115 | STDERR.print "FileCopy failed due to WinRM Access failure:\n" 116 | STDERR.print "Exception Class: #{ e.class.name }\n" 117 | STDERR.print "Exception Message: #{ e.message }\n" 118 | STDERR.print "Exception Backtrace: #{ e.backtrace }\n" 119 | exit 1 120 | else 121 | STDERR.print "FileCopy failed due to WinRM Access failure: #{ e.class.name }--#{ e.message }\n" 122 | exit 1 123 | end 124 | rescue => e 125 | if ENV['RD_JOB_LOGLEVEL'] == 'DEBUG' 126 | STDERR.print "FileCopy failed due to unhandled exception\n" 127 | STDERR.print "Exception Class: #{ e.class.name }\n" 128 | STDERR.print "Exception Message: #{ e.message }\n" 129 | STDERR.print "Exception Backtrace: #{ e.backtrace }\n" 130 | exit 1 131 | else 132 | STDERR.print "FileCopy failed due to unhandled exception: #{ e.class.name }--#{ e.message }\n" 133 | exit 1 134 | end 135 | end 136 | #--- 137 | -------------------------------------------------------------------------------- /contents/winrmexe.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/ruby 2 | gem 'winrm', '= 2.2.3' 3 | require 'winrm' 4 | auth = ENV['RD_CONFIG_AUTHTYPE'] 5 | nossl = ENV['RD_CONFIG_NOSSL'] == 'true' ? true : false 6 | if ENV['RD_CONFIG_USER'] # allow empty (default) user (override used) 7 | user = ENV['RD_CONFIG_USER'].dup # for some reason this string is frozen, so we duplicate it 8 | else 9 | user ='' 10 | end 11 | if ENV['RD_CONFIG_PASS'] # allow empty (default) password (override used) 12 | pass = ENV['RD_CONFIG_PASS'].dup # for some reason this string is frozen, so we duplicate it 13 | else 14 | pass = '' 15 | end 16 | host = ENV['RD_NODE_HOSTNAME'] 17 | port = ENV['RD_CONFIG_WINRMPORT'] 18 | transport = ENV['RD_CONFIG_WINRMTRANSPORT'] 19 | shell = ENV['RD_CONFIG_SHELL'] 20 | realm = ENV['RD_CONFIG_KRB5_REALM'] 21 | command = ENV['RD_EXEC_COMMAND'] 22 | override = ENV['RD_CONFIG_ALLOWOVERRIDE'] 23 | if ENV['RD_CONFIG_WINRMTIMEOUT'] 24 | timeout = ENV['RD_CONFIG_WINRMTIMEOUT'].to_i 25 | else 26 | timeout = 60 27 | end 28 | host = ENV['RD_OPTION_WINRMHOST'] if ENV['RD_OPTION_WINRMHOST'] && (override == 'host' || override == 'all') 29 | user = ENV['RD_OPTION_WINRMUSER'].dup if ENV['RD_OPTION_WINRMUSER'] && (override == 'user' || override == 'all') 30 | pass = ENV['RD_OPTION_WINRMPASS'].dup if ENV['RD_OPTION_WINRMPASS'] && (override == 'user' || override == 'all') 31 | 32 | if auth == 'ssl' 33 | endpoint = "https://#{host}:#{port}/wsman" 34 | else 35 | endpoint = "#{transport}://#{host}:#{port}/wsman" 36 | end 37 | 38 | # Wrapper to fix: "not setting executing flags by rundeck for 2nd file in plugin" 39 | # # https://github.com/rundeck/rundeck/issues/1421 40 | # remove it after issue will be fixed 41 | if File.exist?("#{ENV['RD_PLUGIN_BASE']}/winrmcp.rb") && !File.executable?("#{ENV['RD_PLUGIN_BASE']}/winrmcp.rb") 42 | File.chmod(0764, "#{ENV['RD_PLUGIN_BASE']}/winrmcp.rb") 43 | end 44 | #--- 45 | 46 | # Wrapper for avoid unix style file copying then scripts run 47 | # - not accept chmod call 48 | # - replace rm -f into rm -force 49 | # - auto copying renames file from .sh into .ps1, .bat or .wql in tmp directory 50 | exit 0 if command.include? 'chmod +x /tmp/' 51 | 52 | if command.include? 'rm -f /tmp/' 53 | shell = 'powershell' 54 | command = command.gsub(%r{rm -f /tmp/}, 'rm -force /tmp/') 55 | end 56 | 57 | if %r{/tmp/.*\.sh}.match(command) 58 | case shell 59 | when 'powershell' 60 | command = command.gsub(/\.sh/, '.ps1') 61 | when 'cmd' 62 | command = command.gsub(/\.sh/, '.bat') 63 | when 'wql' 64 | command = command.gsub(/\.sh/, '.wql') 65 | end 66 | end 67 | #--- 68 | 69 | # Output DEBUG messages 70 | if ENV['RD_JOB_LOGLEVEL'] == 'DEBUG' 71 | puts 'variables:' 72 | puts "realm => #{realm}" 73 | puts "endpoint => #{endpoint}" 74 | puts "user => #{user}" 75 | puts 'pass => ********' 76 | puts "timeout => #{timeout}" 77 | # puts "pass => #{pass}" # uncomment it for full auth debugging 78 | puts "command => #{ENV['RD_EXEC_COMMAND']}" 79 | puts "newcommand => #{command}" 80 | puts '' 81 | 82 | puts 'ENV:' 83 | ENV.each do |k, v| 84 | puts "#{k} => #{v}" if v != pass && k != 'RD_CONFIG_PASS' 85 | puts "#{k} => ********" if v == pass || k == 'RD_CONFIG_PASS' 86 | # puts "#{k} => #{v}" if v == pass # uncomment it for full auth debugging 87 | end 88 | end 89 | 90 | def stderr_text(stderr) 91 | doc = REXML::Document.new(stderr) 92 | begin 93 | text = doc.root.get_elements('//S').map(&:text).join 94 | text.gsub(/_x(\h\h\h\h)_/) do 95 | code = Regexp.last_match[1] 96 | code.hex.chr 97 | end 98 | rescue 99 | return stderr 100 | end 101 | end 102 | 103 | # Build connection options 104 | connections_opts = { 105 | endpoint: endpoint 106 | } 107 | 108 | connections_opts[:operation_timeout] = timeout 109 | 110 | case auth 111 | when 'negotiate' 112 | connections_opts[:transport] = :negotiate 113 | connections_opts[:user] = user 114 | connections_opts[:password] = pass 115 | when 'kerberos' 116 | connections_opts[:transport] = :kerberos 117 | connections_opts[:realm] = realm 118 | when 'plaintext' 119 | connections_opts[:transport] = :plaintext 120 | connections_opts[:user] = user 121 | connections_opts[:password] = pass 122 | connections_opts[:disable_sspi] = true 123 | when 'ssl' 124 | connections_opts[:transport] = :ssl 125 | connections_opts[:user] = user 126 | connections_opts[:password] = pass 127 | connections_opts[:disable_sspi] = true 128 | connections_opts[:no_ssl_peer_verification] = nossl 129 | else 130 | fail "Invalid authtype '#{auth}' specified, expected: negotiate, kerberos, plaintext, ssl." 131 | end 132 | #--- 133 | 134 | # Create and connect session 135 | winrm = WinRM::Connection.new(connections_opts) 136 | shell_session = nil 137 | case shell 138 | when 'powershell' 139 | begin 140 | shell_session = winrm.shell(:powershell) 141 | result = shell_session.run(command) 142 | rescue => e 143 | shell_session = nil 144 | if ENV['RD_JOB_LOGLEVEL'] == 'DEBUG' 145 | STDERR.print "ScriptExecution failed due unhandled exception:\n" 146 | STDERR.print "Exception Class: #{ e.class.name }\n" 147 | STDERR.print "Exception Message: #{ e.message }\n" 148 | STDERR.print "Exception Backtrace: #{ e.backtrace }\n" 149 | exit 1 150 | else 151 | STDERR.print "ScriptExecution failed due unhandled exception: #{ e.class.name }--#{ e.message }\n" 152 | exit 1 153 | end 154 | end 155 | when 'cmd' 156 | begin 157 | shell_session = winrm.shell(:cmd) 158 | result = shell_session.run(command) 159 | rescue => e 160 | shell_session = nil 161 | if ENV['RD_JOB_LOGLEVEL'] == 'DEBUG' 162 | STDERR.print "ScriptExecution failed due unhandled exception:\n" 163 | STDERR.print "Exception Class: #{ e.class.name }\n" 164 | STDERR.print "Exception Message: #{ e.message }\n" 165 | STDERR.print "Exception Backtrace: #{ e.backtrace }\n" 166 | exit 1 167 | else 168 | STDERR.print "ScriptExecution failed due unhandled exception: #{ e.class.name }--#{ e.message }\n" 169 | exit 1 170 | end 171 | end 172 | when 'wql' 173 | result = winrm.run_wql(command) 174 | end 175 | #--- 176 | 177 | # Organise output for return to Rundeck 178 | if shell_session != nil 179 | STDERR.print stderr_text(result.stderr) if result.stderr != '' 180 | STDOUT.print result.stdout 181 | exit result.exitcode if result.exitcode !=0 182 | else # WQL 183 | STDOUT.print result 184 | end 185 | #--- 186 | -------------------------------------------------------------------------------- /plugin.yaml: -------------------------------------------------------------------------------- 1 | name: rd-winrm-plugin 2 | version: 1.7.0 3 | rundeckPluginVersion: 1.2 4 | author: Volodymyr Babchynskyy 5 | date: 26.10.2015 6 | providers: 7 | - name: WinRMexe 8 | title: WinRM Executor 9 | description: Executing Scripts or Commands on remote Windows computer 10 | service: NodeExecutor 11 | plugin-type: script 12 | script-interpreter: ruby 13 | script-file: winrmexe.rb 14 | config: 15 | - name: krb5_realm 16 | title: Kerberos Realm 17 | type: String 18 | required: false 19 | description: "Kerberos Realm FQDN in capital letters" 20 | scope: Instance 21 | renderingOptions: 22 | groupName: Authentication 23 | instance-scope-node-attribute: "rd-winrm-krb5_realm" 24 | - name: user 25 | title: Username 26 | description: "Username in DOMAIN\\name format" 27 | type: String 28 | required: false 29 | scope: Instance 30 | renderingOptions: 31 | groupName: Authentication 32 | instance-scope-node-attribute: "rd-winrm-user" 33 | - name: pass 34 | title: Password 35 | description: "Password" 36 | type: String 37 | required: false 38 | scope: Instance 39 | renderingOptions: 40 | displayType: PASSWORD 41 | groupName: Authentication 42 | instance-scope-node-attribute: "rd-winrm-password" 43 | - name: authtype 44 | title: Authentication Type 45 | description: "Authentication Type" 46 | type: Select 47 | values: "negotiate, ssl, kerberos, plaintext" 48 | default: "plaintext" 49 | required: true 50 | scope: Instance 51 | renderingOptions: 52 | groupName: Authentication 53 | instance-scope-node-attribute: "rd-winrm-authtype" 54 | - name: nossl 55 | title: No SSL Verification 56 | description: "When set to true ssl certificate validation is not performed" 57 | type: Select 58 | values: "true, false" 59 | default: "false" 60 | required: true 61 | scope: Instance 62 | renderingOptions: 63 | groupName: Connection 64 | instance-scope-node-attribute: "rd-winrm-nossl" 65 | - name: allowoverride 66 | title: Allow Override 67 | description: "Gives possibility to override hostname, username (and password) in job options" 68 | type: Select 69 | values: "none, host, user, all" 70 | default: "none" 71 | required: true 72 | scope: Instance 73 | renderingOptions: 74 | groupName: Connection 75 | instance-scope-node-attribute: "rd-winrm-allowoverride" 76 | - name: winrmtransport 77 | title: WinRM Transport Protocol 78 | description: "WinRM transport protocol (Default: http or https when ssl is selected for Authentication type)" 79 | type: Select 80 | default: "http" 81 | values: "http, https" 82 | required: true 83 | scope: Instance 84 | renderingOptions: 85 | groupName: Connection 86 | instance-scope-node-attribute: "rd-winrm-transport" 87 | - name: winrmport 88 | title: WinRM Port 89 | description: "WinRM port (Default: 5985/5986 for http/https)" 90 | type: String 91 | default: "5985" 92 | required: true 93 | scope: Instance 94 | renderingOptions: 95 | groupName: Connection 96 | instance-scope-node-attribute: "rd-winrm-port" 97 | - name: shell 98 | title: Shell 99 | description: "Windows Shell interpreter" 100 | type: Select 101 | values: "cmd, powershell, wql" 102 | default: 'powershell' 103 | required: true 104 | scope: Instance 105 | renderingOptions: 106 | groupName: Connection 107 | instance-scope-node-attribute: "rd-winrm-shell" 108 | - name: winrmtimeout 109 | title: WinRM Timeout 110 | description: "Timeout in seconds default: 60" 111 | type: Integer 112 | required: false 113 | scope: Instance 114 | renderingOptions: 115 | groupName: Connection 116 | instance-scope-node-attribute: "rd-winrm-timeout" 117 | - name: WinRMcp 118 | title: WinRM File Copier 119 | description: Copying files to remote Windows computer 120 | service: FileCopier 121 | plugin-type: script 122 | script-interpreter: ruby 123 | script-file: winrmcp.rb 124 | script-args: ${node.hostname} ${file-copy.file} ${file-copy.destination} 125 | config: 126 | - name: krb5_realm 127 | title: Kerberos Realm 128 | type: String 129 | required: false 130 | description: "Kerberos Realm FQDN in capital letters" 131 | scope: Instance 132 | renderingOptions: 133 | groupName: Authentication 134 | instance-scope-node-attribute: "rd-winrm-krb5_realm" 135 | - name: user 136 | title: Username 137 | description: "Username in DOMAIN\\name format" 138 | type: String 139 | required: false 140 | scope: Instance 141 | renderingOptions: 142 | groupName: Authentication 143 | instance-scope-node-attribute: "rd-winrm-user" 144 | - name: pass 145 | title: Password 146 | description: "Password" 147 | type: String 148 | required: false 149 | scope: Instance 150 | renderingOptions: 151 | displayType: PASSWORD 152 | groupName: Authentication 153 | instance-scope-node-attribute: "rd-winrm-password" 154 | - name: authtype 155 | title: Authentication Type 156 | description: "Authentication Type" 157 | type: Select 158 | values: "negotiate, ssl, kerberos, plaintext" 159 | default: "plaintext" 160 | required: true 161 | scope: Instance 162 | renderingOptions: 163 | groupName: Authentication 164 | instance-scope-node-attribute: "rd-winrm-authtype" 165 | - name: nossl 166 | title: No SSL Verification 167 | description: "When set to true ssl certificate validation is not performed" 168 | type: Select 169 | values: "true, false" 170 | default: "false" 171 | required: true 172 | scope: Instance 173 | renderingOptions: 174 | groupName: Connection 175 | instance-scope-node-attribute: "rd-winrm-nossl" 176 | - name: allowoverride 177 | title: Allow Override 178 | description: "Gives possibility to override hostname, username (and password) in job options" 179 | type: Select 180 | values: "none, host, user, all" 181 | default: "none" 182 | required: true 183 | scope: Instance 184 | renderingOptions: 185 | groupName: Connection 186 | instance-scope-node-attribute: "rd-winrm-allowoverride" 187 | - name: winrmtransport 188 | title: WinRM Transport Protocol 189 | description: "WinRM transport protocol (Default: http or https when ssl is selected for Authentication type)" 190 | type: Select 191 | default: "http" 192 | values: "http, https" 193 | required: true 194 | scope: Instance 195 | renderingOptions: 196 | groupName: Connection 197 | instance-scope-node-attribute: "rd-winrm-transport" 198 | - name: winrmport 199 | title: WinRM Port 200 | description: "WinRM port (Default: 5985/5986 for http/https)" 201 | type: String 202 | default: "5985" 203 | required: true 204 | scope: Instance 205 | renderingOptions: 206 | groupName: Connection 207 | instance-scope-node-attribute: "rd-winrm-port" 208 | - name: shell 209 | title: Shell 210 | description: "Windows Shell interpreter" 211 | type: Select 212 | values: "cmd, powershell, wql" 213 | default: 'powershell' 214 | required: true 215 | scope: Instance 216 | renderingOptions: 217 | groupName: Connection 218 | instance-scope-node-attribute: "rd-winrm-shell" 219 | - name: winrmtimeout 220 | title: WinRM Timeout 221 | description: "Timeout in seconds default: 60" 222 | type: Integer 223 | required: false 224 | scope: Instance 225 | renderingOptions: 226 | groupName: Connection 227 | instance-scope-node-attribute: "rd-winrm-timeout" 228 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright 2015 NetVoyage Corporation (NetDocuments) 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | --------------------------------------------------------------------------------