From e855274dc8c5773e1385b261e9824633b44a1c18 Mon Sep 17 00:00:00 2001 From: Dag Wieers Date: Thu, 11 May 2017 01:10:33 +0200 Subject: [PATCH] win_psexec: Enable -nobanner option by default (#23422) * win_psexec: Enable -nobanner option by default PR also includes: - Option `nobanner:` to remove this flag - Improvements to Examples - Improvement to Return Value - Add types to all parameters now - Add (limited) integration tests * Move sysinternals into C:\Windows\Temp --- lib/ansible/modules/windows/win_psexec.ps1 | 34 ++++---- lib/ansible/modules/windows/win_psexec.py | 45 ++++++---- test/integration/targets/win_psexec/aliases | 1 + .../targets/win_psexec/tasks/main.yml | 83 +++++++++++++++++++ 4 files changed, 134 insertions(+), 29 deletions(-) create mode 100644 test/integration/targets/win_psexec/aliases create mode 100644 test/integration/targets/win_psexec/tasks/main.yml diff --git a/lib/ansible/modules/windows/win_psexec.ps1 b/lib/ansible/modules/windows/win_psexec.ps1 index 4d6206e949..2d51958c0e 100644 --- a/lib/ansible/modules/windows/win_psexec.ps1 +++ b/lib/ansible/modules/windows/win_psexec.ps1 @@ -23,21 +23,22 @@ $params = Parse-Args $args -$command = Get-AnsibleParam -obj $params -name "command" -failifempty $true -$executable = Get-AnsibleParam -obj $params -name "executable" -default "psexec.exe" -$hostnames = Get-AnsibleParam -obj $params -name "hostnames" -$username = Get-AnsibleParam -obj $params -name "username" -$password = Get-AnsibleParam -obj $params -name "password" +$command = Get-AnsibleParam -obj $params -name "command" -type "str" -failifempty $true +$executable = Get-AnsibleParam -obj $params -name "executable" -type "path" -default "psexec.exe" +$hostnames = Get-AnsibleParam -obj $params -name "hostnames" -type "list" +$username = Get-AnsibleParam -obj $params -name "username" -type "str" +$password = Get-AnsibleParam -obj $params -name "password" -type "str" $chdir = Get-AnsibleParam -obj $params -name "chdir" -type "path" $wait = Get-AnsibleParam -obj $params -name "wait" -type "bool" -default $true +$nobanner = Get-AnsibleParam -obj $params -name "nobanner" -type "bool" -default $true $noprofile = Get-AnsibleParam -obj $params -name "noprofile" -type "bool" -default $false $elevated = Get-AnsibleParam -obj $params -name "elevated" -type "bool" -default $false $limited = Get-AnsibleParam -obj $params -name "limited" -type "bool" -default $false $system = Get-AnsibleParam -obj $params -name "system" -type "bool" -default $false $interactive = Get-AnsibleParam -obj $params -name "interactive" -type "bool" -default $false -$priority = Get-AnsibleParam -obj $params -name "priority" -validateset "background","low","belownormal","abovenormal","high","realtime" -$timeout = Get-AnsibleParam -obj $params -name "timeout" -$extra_opts = Get-AnsibleParam -obj $params -name "extra_opts" -default @() +$priority = Get-AnsibleParam -obj $params -name "priority" -type "str" -validateset "background","low","belownormal","abovenormal","high","realtime" +$timeout = Get-AnsibleParam -obj $params -name "timeout" -type "int" +$extra_opts = Get-AnsibleParam -obj $params -name "extra_opts" -type "list" $result = @{ changed = $true @@ -87,9 +88,13 @@ $util_type = Add-Type -TypeDefinition $util_def $arguments = "" -# Supports running on local system if not hostname is specified -If ($hostnames -ne $null) { - $arguments = " \\" + $($hostnames | sort -Unique) -join ',' +If ($nobanner -eq $true) { + $arguments += " -nobanner" +} + +# Support running on local system if no hostname is specified +If ($hostnames) { + $arguments += " \\" + $($hostnames | sort -Unique) -join ',' } # Username is optional @@ -139,8 +144,10 @@ If ($timeout -ne $null) { } # Add additional advanced options -ForEach ($opt in $extra_opts) { - $arguments += " $opt" +If ($extra_opts) { + ForEach ($opt in $extra_opts) { + $arguments += " $opt" + } } $arguments += " -accepteula" @@ -153,7 +160,6 @@ $psi.RedirectStandardOutput = $true $psi.RedirectStandardError = $true $psi.UseShellExecute = $false -# TODO: psexec has a limit to the argument length of 260 (?) $result.psexec_command = "$executable$arguments $command" $start_datetime = [DateTime]::UtcNow diff --git a/lib/ansible/modules/windows/win_psexec.py b/lib/ansible/modules/windows/win_psexec.py index 08bc990224..9820035917 100644 --- a/lib/ansible/modules/windows/win_psexec.py +++ b/lib/ansible/modules/windows/win_psexec.py @@ -55,26 +55,37 @@ options: chdir: description: - Run the command from this (remote) directory. + nobanner: + description: + - Do not display the startup banner and copyright message. + default: 'yes' + choices: [ 'no', 'yes' ] + version_added: '2.4' noprofile: description: - Run the command without loading the account's profile. - default: False + default: 'no' + choices: [ 'no', 'yes' ] elevated: description: - Run the command with elevated privileges. - default: False + default: 'no' + choices: [ 'no', 'yes' ] interactive: description: - Run the program so that it interacts with the desktop on the remote system. - default: False + default: 'no' + choices: [ 'no', 'yes' ] limited: description: - Run the command as limited user (strips the Administrators group and allows only privileges assigned to the Users group). - default: False + default: 'no' + choices: [ 'no', 'yes' ] system: description: - Run the remote command in the System account. - default: False + default: 'no' + choices: [ 'no', 'yes' ] priority: description: - Used to run the command at a different priority. @@ -92,24 +103,28 @@ options: description: - Wait for the application to terminate. - Only use for non-interactive applications. - default: True + default: 'yes' + choices: [ 'no', 'yes' ] +notes: +- More information related to PsExec is available from + U(https://technet.microsoft.com/en-us/sysinternals/bb897553.aspx) requirements: [ psexec ] author: Dag Wieers (@dagwieers) ''' EXAMPLES = r''' -# Test the PsExec connection to the local system (target node) with your user -- win_psexec: +- name: Test the PsExec connection to the local system (target node) with your user + win_psexec: command: whoami.exe -# Run regedit.exe locally (on target node) as SYSTEM and interactively -- win_psexec: +- name: Run regedit.exe locally (on target node) as SYSTEM and interactively + win_psexec: command: regedit.exe interactive: yes system: yes -# Run the setup.exe installer on multiple servers using the Domain Administrator -- win_psexec: +- name: Run the setup.exe installer on multiple servers using the Domain Administrator + win_psexec: command: E:\setup.exe /i /IACCEPTEULA hostnames: - remote_server1 @@ -118,8 +133,8 @@ EXAMPLES = r''' password: some_password priority: high -# Run PsExec from custom location C:\Program Files\sysinternals\ -- win_psexec: +- name: Run PsExec from custom location C:\Program Files\sysinternals\ + win_psexec: command: netsh advfirewall set allprofiles state off executable: C:\Program Files\sysinternals\psexec.exe hostnames: [ remote_server ] @@ -132,7 +147,7 @@ cmd: description: The complete command line used by the module, including PsExec call and additional options. returned: always type: string - sample: psexec.exe \\remote_server -u DOMAIN\Administrator -p some_password E:\setup.exe + sample: psexec.exe -nobanner \\remote_server -u "DOMAIN\Administrator" -p "some_password" -accepteula E:\setup.exe rc: description: The return code for the command returned: always diff --git a/test/integration/targets/win_psexec/aliases b/test/integration/targets/win_psexec/aliases new file mode 100644 index 0000000000..c6d6198167 --- /dev/null +++ b/test/integration/targets/win_psexec/aliases @@ -0,0 +1 @@ +windows/ci/group3 diff --git a/test/integration/targets/win_psexec/tasks/main.yml b/test/integration/targets/win_psexec/tasks/main.yml new file mode 100644 index 0000000000..741e18602b --- /dev/null +++ b/test/integration/targets/win_psexec/tasks/main.yml @@ -0,0 +1,83 @@ +- name: Download PSTools + win_get_url: + url: https://download.sysinternals.com/files/PSTools.zip + dest: C:\Windows\Temp\PSTools.zip + force: no + +- name: Create sysinternals directory + win_file: + path: C:\Windows\Temp\sysinternals + state: directory + +- name: Unzip PSTools + win_unzip: + src: C:\Windows\Temp\PSTools.zip + dest: C:\Windows\Temp\sysinternals + +- name: Add sysinternals to PATH + win_path: + name: PATH + elements: C:\Windows\Temp\sysinternals + scope: machine + state: present + +- name: Run whoami + win_psexec: + command: whoami.exe + register: whoami + +- name: Test whoami + assert: + that: + - whoami.rc == 0 + - whoami.stdout == '' + # FIXME: Standard output does not work or is truncated + #- whoami.stdout == '{{ ansible_hostname|lower }}' + +- name: Run whoami as SYSTEM + win_psexec: + command: whoami.exe + system: yes + register: whoami_as_system + +- name: Test whoami as SYSTEM + assert: + that: + - whoami_as_system.rc == 0 + - whoami_as_system.stdout == 'nt authority\system' + +# FIXME: Behaviour is not consistent on all Windows systems +#- name: Run whoami as ELEVATED +# win_psexec: +# command: whoami.exe +# elevated: yes +# register: whoami_as_elevated +# +## Ensure we have basic facts +#- setup: +# +#- debug: +# msg: '{{ whoami_as_elevated.stdout|lower }} == {{ ansible_hostname|lower }}\{{ ansible_user_id|lower }}' +# +#- name: Test whoami +# assert: +# that: +# - whoami_as_elevated.rc == 0 +# - whoami_as_elevated.stdout|lower == '{{ ansible_hostname|lower }}\{{ ansible_user_id|lower }}' + +- name: Remove sysinternals from PATH + win_path: + name: PATH + elements: C:\Windows\Temp\sysinternals + scope: machine + state: absent + +- name: Remove sysinternals directory + win_file: + path: C:\Windows\Temp\sysinternals + state: absent + +- name: Remove sysinternals directory + win_file: + path: C:\Windows\Temp\PSTools.zip + state: absent