Skip to content

Commit

Permalink
Merge branch 'release/1.3.0'
Browse files Browse the repository at this point in the history
* release/1.3.0:
  version bump
  Trivial rubocop fixes, spelling fixes
  Fixes to copy feature, Readme updated
  Add extensions to scripts then scripts run
  fixes in output
  • Loading branch information
vvchik committed Sep 17, 2015
2 parents 669c976 + 5b172f3 commit ebb167c
Show file tree
Hide file tree
Showing 5 changed files with 111 additions and 48 deletions.
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,10 @@
`0.6.0` Different authentication types for winrm
`0.7.0` different shells support (powershell, cmd, wql)
`0.8.0` WinRM timeout managed via config
`0.9.0` Fixes in quotes cleanup behavior, Fixes in quotes cleanup behavior, trivial rubocop fixes
`0.9.0` Fixes in quotes cleanup behaviour, Fixes in quotes cleanup behaviour, trivial rubocop fixes
`1.0.0` Public release, debugging depends on debugging level on job
`1.1.0` Added possibility to set port for winrm
`1.1.1` Sanitised passwords in debug mode
`1.2.0` Allow override feature and fix for [rundeck bug](https://github.com/rundeck/rundeck/issues/1421)
`1.3.0` Extension for copied script depends on context of script execution

33 changes: 28 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ Compatible with Rundeck 2.3.x+
## Features
Can run scripts, not only commands
Can run PowerShell, CMD and WQL not only CMD
Can avoid quoting problems (should be removed afrer core Rundeck fixes)
Can copy files to windows
Can avoid quoting problems (should be removed after core Rundeck fixes)
Can copy files to windows

### Installation

Expand All @@ -19,15 +19,15 @@ something like this: `apt-get install make ruby ruby-dev`
Install following gems:
`gem install winrm`
`gem install winrm-fs`

Download from the [releases page](https://github.com/vvchik/rd-winrm-plugin/releases).

Copy the `rd-winrm-plugin.zip` to the `libext/` directory for Rundeck.

Run `winrm quickconfig` as admin [Configuration the Remote Windows](https://technet.microsoft.com/en-us/magazine/ff700227.aspx) on Nodes

### Configuration
choose `WinRM Executivetor` as Default Node Executor
choose `WinRM Executor` as Default Node Executor
and `WinRM File Copier` as Default Node File Copier
Settings:
`Kerberos Realm` Put here fqdn of your realm in case your computer is part of AD domain
Expand All @@ -38,10 +38,33 @@ Settings:
`Shell` choose here powershell, cmd or wql
`WinRM timeout` put here time in seconds (useful for long running commands)

### Special Behavior
### Special Behaviour
`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

- If that parameter set to `hostname` you may use option variable with name `winrmhost` to set hostname
- If that parameter set to `user` you may use `winrmuser` and `winrmpass` to set username/pass
- If that parameter set to `all` you may use all these additional options
- If that parameter set to `none` these options in jobs will be ignored

### Limitations
- Scripts in c:/tmp with .sh extension will be renamed into .ps1, .bat or .wql
- Quotes behaviour can be strange (we trying to fix rundeck core strange behaviour, so our own also not perfect)
- WQL execution never been tested :)

### PR and reporting
PR is highly welcome, we using gitflow for our development process, so please, make them to develop branch.
If you have some issue please describe steps to reproduce it

### License and Authors
Copyright 2015 NetDocuments

Author: [Volodymyr Babchynskyy](https://github.com/vvchik)

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License
is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
either express or implied. See the License for the specific language governing permissions and limitations under the License.
26 changes: 20 additions & 6 deletions contents/winrmcp.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,13 @@
pass = ENV['RD_CONFIG_PASS'].dup
host = ENV['RD_NODE_HOSTNAME']
port = ENV['RD_CONFIG_WINRMPORT']
shell = ENV['RD_CONFIG_SHELL']
realm = ENV['RD_CONFIG_KRB5_REALM']
winrmtimeout = ENV['RD_CONFIG_WINRMTIMEOUT']
override = ENV['RD_CONFIG_ALLOWOVERRIDE']
host = ENV['RD_OPTION_WINRMHOST'] if ENV['RD_OPTION_WINRMHOST'] and (override == 'host' or override == 'all')
user = ENV['RD_OPTION_WINRMUSER'] if ENV['RD_OPTION_WINRMUSER'] and (override == 'user' or override == 'all')
pass = ENV['RD_OPTION_WINRMPASS'] if ENV['RD_OPTION_WINRMPASS'] and (override == 'user' or override == 'all')
host = ENV['RD_OPTION_WINRMHOST'] if ENV['RD_OPTION_WINRMHOST'] && (override == 'host' || override == 'all')
user = ENV['RD_OPTION_WINRMUSER'] if ENV['RD_OPTION_WINRMUSER'] && (override == 'user' || override == 'all')
pass = ENV['RD_OPTION_WINRMPASS'] if ENV['RD_OPTION_WINRMPASS'] && (override == 'user' || override == 'all')

file = ARGV[1]
dest = ARGV[2]
Expand All @@ -19,11 +20,24 @@
# Wrapper to fix: "not setting executing flags by rundeck for 2nd file in plugin"
# # https://github.com/rundeck/rundeck/issues/1421
# remove it after issue will be fixed
if File.exist?("#{ENV['RD_PLUGIN_BASE']}/winrmexe.rb") and not File.executable?("#{ENV['RD_PLUGIN_BASE']}/winrmexe.rb")
File.chmod(0764, "#{ENV['RD_PLUGIN_BASE']}/winrmexe.rb") # https://github.com/rundeck/rundeck/issues/1421
if File.exist?("#{ENV['RD_PLUGIN_BASE']}/winrmexe.rb") && !File.executable?("#{ENV['RD_PLUGIN_BASE']}/winrmexe.rb")
File.chmod(0764, "#{ENV['RD_PLUGIN_BASE']}/winrmexe.rb") # https://github.com/rundeck/rundeck/issues/1421
end

dest = dest.gsub(/\.sh/, '.ps1') if %r{/tmp/.*\.sh}.match(dest)
# Wrapper for avoid unix style file copying then scripts run
# - not accept chmod call
# - replace rm -f into rm -force
# - auto copying renames file from .sh into .ps1, .bat or .wql in tmp directory
if %r{/tmp/.*\.sh}.match(dest)
case shell
when 'powershell'
dest = dest.gsub(/\.sh/, '.ps1')
when 'cmd'
dest = dest.gsub(/\.sh/, '.bat')
when 'wql'
dest = dest.gsub(/\.sh/, '.wql')
end
end

case auth
when 'kerberos'
Expand Down
76 changes: 46 additions & 30 deletions contents/winrmexe.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,19 @@
command = ENV['RD_EXEC_COMMAND']
winrmtimeout = ENV['RD_CONFIG_WINRMTIMEOUT']
override = ENV['RD_CONFIG_ALLOWOVERRIDE']
host = ENV['RD_OPTION_WINRMHOST'] if ENV['RD_OPTION_WINRMHOST'] and (override == 'host' or override == 'all')
user = ENV['RD_OPTION_WINRMUSER'] if ENV['RD_OPTION_WINRMUSER'] and (override == 'user' or override == 'all')
pass = ENV['RD_OPTION_WINRMPASS'].dup if ENV['RD_OPTION_WINRMPASS'] and (override == 'user' or override == 'all')
host = ENV['RD_OPTION_WINRMHOST'] if ENV['RD_OPTION_WINRMHOST'] && (override == 'host' || override == 'all')
user = ENV['RD_OPTION_WINRMUSER'] if ENV['RD_OPTION_WINRMUSER'] && (override == 'user' || override == 'all')
pass = ENV['RD_OPTION_WINRMPASS'].dup if ENV['RD_OPTION_WINRMPASS'] && (override == 'user' || override == 'all')

endpoint = "http://#{host}:#{port}/wsman"
output = ''
ooutput = ''
eoutput = ''

# Wrapper to fix: "not setting executing flags by rundeck for 2nd file in plugin"
# # https://github.com/rundeck/rundeck/issues/1421
# remove it after issue will be fixed
if File.exist?("#{ENV['RD_PLUGIN_BASE']}/winrmcp.rb") and not File.executable?("#{ENV['RD_PLUGIN_BASE']}/winrmcp.rb")
File.chmod(0764, "#{ENV['RD_PLUGIN_BASE']}/winrmcp.rb")
if File.exist?("#{ENV['RD_PLUGIN_BASE']}/winrmcp.rb") && !File.executable?("#{ENV['RD_PLUGIN_BASE']}/winrmcp.rb")
File.chmod(0764, "#{ENV['RD_PLUGIN_BASE']}/winrmcp.rb")
end

# Wrapper ro avoid strange and undocumented behavior of rundeck
Expand All @@ -32,32 +33,44 @@
command = command.gsub(/ '"/, '"')
command = command.gsub(/"' /, '"')

# Wrapper for avoid unix style file copying in command run
# not accept chmod call
# replace rm -f into rm -force
# auto copying renames file from .sh into .ps1
# so in that case we should call file with ps1 extension
# TODO: add extension based on shell variable
# TODO: deleting based on shell variable
# Wrapper for avoid unix style file copying then scripts run
# - not accept chmod call
# - replace rm -f into rm -force
# - auto copying renames file from .sh into .ps1, .bat or .wql in tmp directory
exit 0 if command.include? 'chmod +x /tmp/'
command = command.gsub(%r{rm -f /tmp/}, 'rm -force /tmp/') if command.include? 'rm -f /tmp/'
command = command.gsub(/\.sh/, '.ps1') if %r{/tmp/.*\.sh}.match(command)

if command.include? 'rm -f /tmp/'
shell = 'powershell'
command = command.gsub(%r{rm -f /tmp/}, 'rm -force /tmp/')
end

if %r{/tmp/.*\.sh}.match(command)
case shell
when 'powershell'
command = command.gsub(/\.sh/, '.ps1')
when 'cmd'
command = command.gsub(/\.sh/, '.bat')
when 'wql'
command = command.gsub(/\.sh/, '.wql')
end
end

if ENV['RD_JOB_LOGLEVEL'] == 'DEBUG'
puts 'variables is:'
puts "realm is #{realm}"
puts "endpoint is #{endpoint}"
puts "user is #{user}"
puts "pass is ********"
# puts "pass is #{pass}" # uncomment it for full auth debugging
puts "command is #{ENV['RD_EXEC_COMMAND']}"
puts "newcommand is #{command}"

puts 'ENV'
puts 'variables:'
puts "realm => #{realm}"
puts "endpoint => #{endpoint}"
puts "user => #{user}"
puts 'pass => ********'
# puts "pass => #{pass}" # uncomment it for full auth debugging
puts "command => #{ENV['RD_EXEC_COMMAND']}"
puts "newcommand => #{command}"
puts ''

puts 'ENV:'
ENV.each do |k, v|
puts "#{k} => #{v}" if v != pass
puts "#{k} => ********" if v == pass or k == 'RD_CONFIG_PASS'
# puts "#{k} => #{v}" if v == pass # uncomment it for full auth debugging
puts "#{k} => ********" if v == pass || k == 'RD_CONFIG_PASS'
# puts "#{k} => #{v}" if v == pass # uncomment it for full auth debugging
end
end

Expand Down Expand Up @@ -91,11 +104,14 @@ def stderr_text(stderr)
when 'wql'
result = winrm.wql(command)
end

result[:data].each do |output_line|
output = "#{output}#{output_line[:stderr]}" if output_line.key?(:stderr)
STDOUT.print output_line[:stdout] if output_line.key?(:stdout)
eoutput = "#{eoutput}#{output_line[:stderr]}" if output_line.key?(:stderr)
ooutput = "#{ooutput}#{output_line[:stdout]}" if output_line.key?(:stdout)
end
STDERR.print stderr_text(output) if output != ''

STDERR.print stderr_text(eoutput) if eoutput != ''
STDOUT.print ooutput
exit result[:exitcode] if result[:exitcode] != 0

# winrm.powershell(command) do |stdout, stderr|
Expand Down
21 changes: 15 additions & 6 deletions plugin.yaml
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
name: rd-winrm-plugin
version: 1.2.0
version: 1.3.0
rundeckPluginVersion: 1.0
author: Volodymyr Babchynskyy
date: 15.09.2015
date: 17.09.2015
providers:
- name: WinRMexe
title: WinRM Executor
description: Executing Scripts or commands on remote windows computer
service: NodeExecutor
plugin-type: script
# script-interpreter: []
script-interpreter: ruby
script-file: winrmexe.rb
# script-args: ${config.realm} ${config.username} ${config.password} ${node.hostname} ${exec.command}
interpreter-args-quoted: true
Expand Down Expand Up @@ -76,7 +76,7 @@ providers:
required: true
scope: Instance
renderingOptions:
instance-scope-node-attribute: "interpreter"
instance-scope-node-attribute: "shell"
- name: winrmtimeout
title: WinRM timeout
description: "timeout in seconds default: 60"
Expand All @@ -85,12 +85,11 @@ providers:
scope: Instance
renderingOptions:
instance-scope-node-attribute: "winrmtimeout"

- name: WinRMcp
title: WinRM File Copier
service: FileCopier
plugin-type: script
# script-interpreter: [interpreter]
script-interpreter: ruby
script-file: winrmcp.rb
script-args: ${node.hostname} ${file-copy.file} ${file-copy.destination}
config:
Expand Down Expand Up @@ -147,6 +146,16 @@ providers:
scope: Instance
renderingOptions:
instance-scope-node-attribute: "winrmport"
- name: shell
title: Shell
description: "Windows interpreter. Should be same as in Executor"
type: Select
values: "cmd, powershell, wql"
default: 'powershell'
required: true
scope: Instance
renderingOptions:
instance-scope-node-attribute: "shell"
- name: winrmtimeout
title: WinRM timeout
description: "timeout in seconds default: 60"
Expand Down

0 comments on commit ebb167c

Please sign in to comment.