Remove incidental_win_psexec (#71953)
* Explicit coverage to remove incidental_win_psexec * rc=1 failed * ci_complete ci_coverage * Test rc!=0 without failed and until * ci_complete ci_coverage * Remove incidental_win_psexec * Reduce delay * ci_complete ci_coverage
This commit is contained in:
parent
7c1dd1c7fb
commit
5d811fc551
7 changed files with 41 additions and 408 deletions
|
@ -1,2 +0,0 @@
|
||||||
shippable/windows/incidental
|
|
||||||
windows
|
|
|
@ -1,2 +0,0 @@
|
||||||
dependencies:
|
|
||||||
- setup_remote_tmp_dir
|
|
|
@ -1,80 +0,0 @@
|
||||||
# Would use [] but this has troubles with PATH and trying to find the executable so just resort to keeping a space
|
|
||||||
- name: record special path for tests
|
|
||||||
set_fact:
|
|
||||||
testing_dir: '{{ remote_tmp_dir }}\ansible win_psexec'
|
|
||||||
|
|
||||||
- name: create special path testing dir
|
|
||||||
win_file:
|
|
||||||
path: '{{ testing_dir }}'
|
|
||||||
state: directory
|
|
||||||
|
|
||||||
- name: Download PsExec
|
|
||||||
win_get_url:
|
|
||||||
url: https://ansible-ci-files.s3.amazonaws.com/test/integration/targets/win_psexec/PsExec.exe
|
|
||||||
dest: '{{ testing_dir }}\PsExec.exe'
|
|
||||||
|
|
||||||
- name: Get the existing PATH env var
|
|
||||||
win_shell: '$env:PATH'
|
|
||||||
register: system_path
|
|
||||||
changed_when: False
|
|
||||||
|
|
||||||
- name: Run whoami
|
|
||||||
win_psexec:
|
|
||||||
command: whoami.exe
|
|
||||||
nobanner: true
|
|
||||||
register: whoami
|
|
||||||
environment:
|
|
||||||
PATH: '{{ testing_dir }};{{ system_path.stdout | trim }}'
|
|
||||||
|
|
||||||
- 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
|
|
||||||
nobanner: true
|
|
||||||
executable: '{{ testing_dir }}\PsExec.exe'
|
|
||||||
register: whoami_as_system
|
|
||||||
# Seems to be a bug with PsExec where the stdout can be empty, just retry the task to make this test a bit more stable
|
|
||||||
until: whoami_as_system.rc == 0 and whoami_as_system.stdout == 'nt authority\system'
|
|
||||||
retries: 3
|
|
||||||
delay: 2
|
|
||||||
|
|
||||||
# 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: Run command with multiple arguments
|
|
||||||
win_psexec:
|
|
||||||
command: powershell.exe -NonInteractive "exit 1"
|
|
||||||
ignore_errors: yes
|
|
||||||
register: whoami_multiple_args
|
|
||||||
environment:
|
|
||||||
PATH: '{{ testing_dir }};{{ system_path.stdout | trim }}'
|
|
||||||
|
|
||||||
- name: Test command with multiple argumetns
|
|
||||||
assert:
|
|
||||||
that:
|
|
||||||
- whoami_multiple_args.rc == 1
|
|
||||||
- whoami_multiple_args.psexec_command == "psexec.exe -accepteula powershell.exe -NonInteractive \"exit 1\""
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
# Copyright: (c) 2017, Ansible Project
|
||||||
|
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||||
|
|
||||||
|
from __future__ import (absolute_import, division, print_function)
|
||||||
|
__metaclass__ = type
|
||||||
|
|
||||||
|
from ansible.plugins.action import ActionBase
|
||||||
|
|
||||||
|
|
||||||
|
class ActionModule(ActionBase):
|
||||||
|
|
||||||
|
def run(self, tmp=None, task_vars=None):
|
||||||
|
del tmp # tmp no longer has any effect
|
||||||
|
|
||||||
|
try:
|
||||||
|
self._task.args['_raw_params'] = self._task.args.pop('cmd')
|
||||||
|
except KeyError:
|
||||||
|
pass
|
||||||
|
shell_action = self._shared_loader_obj.action_loader.get('ansible.legacy.shell',
|
||||||
|
task=self._task,
|
||||||
|
connection=self._connection,
|
||||||
|
play_context=self._play_context,
|
||||||
|
loader=self._loader,
|
||||||
|
templar=self._templar,
|
||||||
|
shared_loader_obj=self._shared_loader_obj)
|
||||||
|
result = shell_action.run(task_vars=task_vars)
|
||||||
|
result.pop('failed', None)
|
||||||
|
return result
|
|
@ -69,3 +69,16 @@
|
||||||
retries: 5
|
retries: 5
|
||||||
delay: 0.5
|
delay: 0.5
|
||||||
failed_when: changed_when_attempts.attempts > 6
|
failed_when: changed_when_attempts.attempts > 6
|
||||||
|
|
||||||
|
# Test until on module that doesn't return failed, but does return rc
|
||||||
|
- name: create counter file
|
||||||
|
copy:
|
||||||
|
dest: "{{ output_dir }}/until_counter"
|
||||||
|
content: 3
|
||||||
|
|
||||||
|
- shell_no_failed:
|
||||||
|
cmd: |
|
||||||
|
COUNTER=$(cat "{{ output_dir }}/until_counter"); NEW=$(expr $COUNTER - 1); echo $NEW > "{{ output_dir }}/until_counter"; exit $COUNTER
|
||||||
|
register: counter
|
||||||
|
delay: 0.5
|
||||||
|
until: counter.rc == 0
|
||||||
|
|
|
@ -1,152 +0,0 @@
|
||||||
#!powershell
|
|
||||||
|
|
||||||
# Copyright: (c) 2017, Dag Wieers (@dagwieers) <dag@wieers.com>
|
|
||||||
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
|
||||||
|
|
||||||
#AnsibleRequires -CSharpUtil Ansible.Basic
|
|
||||||
#Requires -Module Ansible.ModuleUtils.ArgvParser
|
|
||||||
#Requires -Module Ansible.ModuleUtils.CommandUtil
|
|
||||||
|
|
||||||
# See also: https://technet.microsoft.com/en-us/sysinternals/pxexec.aspx
|
|
||||||
|
|
||||||
$spec = @{
|
|
||||||
options = @{
|
|
||||||
command = @{ type='str'; required=$true }
|
|
||||||
executable = @{ type='path'; default='psexec.exe' }
|
|
||||||
hostnames = @{ type='list' }
|
|
||||||
username = @{ type='str' }
|
|
||||||
password = @{ type='str'; no_log=$true }
|
|
||||||
chdir = @{ type='path' }
|
|
||||||
wait = @{ type='bool'; default=$true }
|
|
||||||
nobanner = @{ type='bool'; default=$false }
|
|
||||||
noprofile = @{ type='bool'; default=$false }
|
|
||||||
elevated = @{ type='bool'; default=$false }
|
|
||||||
limited = @{ type='bool'; default=$false }
|
|
||||||
system = @{ type='bool'; default=$false }
|
|
||||||
interactive = @{ type='bool'; default=$false }
|
|
||||||
session = @{ type='int' }
|
|
||||||
priority = @{ type='str'; choices=@( 'background', 'low', 'belownormal', 'abovenormal', 'high', 'realtime' ) }
|
|
||||||
timeout = @{ type='int' }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$module = [Ansible.Basic.AnsibleModule]::Create($args, $spec)
|
|
||||||
|
|
||||||
$command = $module.Params.command
|
|
||||||
$executable = $module.Params.executable
|
|
||||||
$hostnames = $module.Params.hostnames
|
|
||||||
$username = $module.Params.username
|
|
||||||
$password = $module.Params.password
|
|
||||||
$chdir = $module.Params.chdir
|
|
||||||
$wait = $module.Params.wait
|
|
||||||
$nobanner = $module.Params.nobanner
|
|
||||||
$noprofile = $module.Params.noprofile
|
|
||||||
$elevated = $module.Params.elevated
|
|
||||||
$limited = $module.Params.limited
|
|
||||||
$system = $module.Params.system
|
|
||||||
$interactive = $module.Params.interactive
|
|
||||||
$session = $module.Params.session
|
|
||||||
$priority = $module.Params.Priority
|
|
||||||
$timeout = $module.Params.timeout
|
|
||||||
|
|
||||||
$module.Result.changed = $true
|
|
||||||
|
|
||||||
If (-Not (Get-Command $executable -ErrorAction SilentlyContinue)) {
|
|
||||||
$module.FailJson("Executable '$executable' was not found.")
|
|
||||||
}
|
|
||||||
|
|
||||||
$arguments = [System.Collections.Generic.List`1[String]]@($executable)
|
|
||||||
|
|
||||||
If ($nobanner -eq $true) {
|
|
||||||
$arguments.Add("-nobanner")
|
|
||||||
}
|
|
||||||
|
|
||||||
# Support running on local system if no hostname is specified
|
|
||||||
If ($hostnames) {
|
|
||||||
$hostname_argument = ($hostnames | sort -Unique) -join ','
|
|
||||||
$arguments.Add("\\$hostname_argument")
|
|
||||||
}
|
|
||||||
|
|
||||||
# Username is optional
|
|
||||||
If ($null -ne $username) {
|
|
||||||
$arguments.Add("-u")
|
|
||||||
$arguments.Add($username)
|
|
||||||
}
|
|
||||||
|
|
||||||
# Password is optional
|
|
||||||
If ($null -ne $password) {
|
|
||||||
$arguments.Add("-p")
|
|
||||||
$arguments.Add($password)
|
|
||||||
}
|
|
||||||
|
|
||||||
If ($null -ne $chdir) {
|
|
||||||
$arguments.Add("-w")
|
|
||||||
$arguments.Add($chdir)
|
|
||||||
}
|
|
||||||
|
|
||||||
If ($wait -eq $false) {
|
|
||||||
$arguments.Add("-d")
|
|
||||||
}
|
|
||||||
|
|
||||||
If ($noprofile -eq $true) {
|
|
||||||
$arguments.Add("-e")
|
|
||||||
}
|
|
||||||
|
|
||||||
If ($elevated -eq $true) {
|
|
||||||
$arguments.Add("-h")
|
|
||||||
}
|
|
||||||
|
|
||||||
If ($system -eq $true) {
|
|
||||||
$arguments.Add("-s")
|
|
||||||
}
|
|
||||||
|
|
||||||
If ($interactive -eq $true) {
|
|
||||||
$arguments.Add("-i")
|
|
||||||
If ($null -ne $session) {
|
|
||||||
$arguments.Add($session)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
If ($limited -eq $true) {
|
|
||||||
$arguments.Add("-l")
|
|
||||||
}
|
|
||||||
|
|
||||||
If ($null -ne $priority) {
|
|
||||||
$arguments.Add("-$priority")
|
|
||||||
}
|
|
||||||
|
|
||||||
If ($null -ne $timeout) {
|
|
||||||
$arguments.Add("-n")
|
|
||||||
$arguments.Add($timeout)
|
|
||||||
}
|
|
||||||
|
|
||||||
$arguments.Add("-accepteula")
|
|
||||||
|
|
||||||
$argument_string = Argv-ToString -arguments $arguments
|
|
||||||
|
|
||||||
# Add the command at the end of the argument string, we don't want to escape
|
|
||||||
# that as psexec doesn't expect it to be one arg
|
|
||||||
$argument_string += " $command"
|
|
||||||
|
|
||||||
$start_datetime = [DateTime]::UtcNow
|
|
||||||
$module.Result.psexec_command = $argument_string
|
|
||||||
|
|
||||||
$command_result = Run-Command -command $argument_string
|
|
||||||
|
|
||||||
$end_datetime = [DateTime]::UtcNow
|
|
||||||
|
|
||||||
$module.Result.stdout = $command_result.stdout
|
|
||||||
$module.Result.stderr = $command_result.stderr
|
|
||||||
|
|
||||||
If ($wait -eq $true) {
|
|
||||||
$module.Result.rc = $command_result.rc
|
|
||||||
} else {
|
|
||||||
$module.Result.rc = 0
|
|
||||||
$module.Result.pid = $command_result.rc
|
|
||||||
}
|
|
||||||
|
|
||||||
$module.Result.start = $start_datetime.ToString("yyyy-MM-dd hh:mm:ss.ffffff")
|
|
||||||
$module.Result.end = $end_datetime.ToString("yyyy-MM-dd hh:mm:ss.ffffff")
|
|
||||||
$module.Result.delta = $($end_datetime - $start_datetime).ToString("h\:mm\:ss\.ffffff")
|
|
||||||
|
|
||||||
$module.ExitJson()
|
|
|
@ -1,172 +0,0 @@
|
||||||
#!/usr/bin/python
|
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
|
|
||||||
# Copyright: 2017, Dag Wieers (@dagwieers) <dag@wieers.com>
|
|
||||||
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
|
||||||
|
|
||||||
ANSIBLE_METADATA = {'metadata_version': '1.1',
|
|
||||||
'status': ['preview'],
|
|
||||||
'supported_by': 'community'}
|
|
||||||
|
|
||||||
DOCUMENTATION = r'''
|
|
||||||
---
|
|
||||||
module: win_psexec
|
|
||||||
version_added: '2.3'
|
|
||||||
short_description: Runs commands (remotely) as another (privileged) user
|
|
||||||
description:
|
|
||||||
- Run commands (remotely) through the PsExec service.
|
|
||||||
- Run commands as another (domain) user (with elevated privileges).
|
|
||||||
requirements:
|
|
||||||
- Microsoft PsExec
|
|
||||||
options:
|
|
||||||
command:
|
|
||||||
description:
|
|
||||||
- The command line to run through PsExec (limited to 260 characters).
|
|
||||||
type: str
|
|
||||||
required: yes
|
|
||||||
executable:
|
|
||||||
description:
|
|
||||||
- The location of the PsExec utility (in case it is not located in your PATH).
|
|
||||||
type: path
|
|
||||||
default: psexec.exe
|
|
||||||
hostnames:
|
|
||||||
description:
|
|
||||||
- The hostnames to run the command.
|
|
||||||
- If not provided, the command is run locally.
|
|
||||||
type: list
|
|
||||||
username:
|
|
||||||
description:
|
|
||||||
- The (remote) user to run the command as.
|
|
||||||
- If not provided, the current user is used.
|
|
||||||
type: str
|
|
||||||
password:
|
|
||||||
description:
|
|
||||||
- The password for the (remote) user to run the command as.
|
|
||||||
- This is mandatory in order authenticate yourself.
|
|
||||||
type: str
|
|
||||||
chdir:
|
|
||||||
description:
|
|
||||||
- Run the command from this (remote) directory.
|
|
||||||
type: path
|
|
||||||
nobanner:
|
|
||||||
description:
|
|
||||||
- Do not display the startup banner and copyright message.
|
|
||||||
- This only works for specific versions of the PsExec binary.
|
|
||||||
type: bool
|
|
||||||
default: no
|
|
||||||
version_added: '2.4'
|
|
||||||
noprofile:
|
|
||||||
description:
|
|
||||||
- Run the command without loading the account's profile.
|
|
||||||
type: bool
|
|
||||||
default: no
|
|
||||||
elevated:
|
|
||||||
description:
|
|
||||||
- Run the command with elevated privileges.
|
|
||||||
type: bool
|
|
||||||
default: no
|
|
||||||
interactive:
|
|
||||||
description:
|
|
||||||
- Run the program so that it interacts with the desktop on the remote system.
|
|
||||||
type: bool
|
|
||||||
default: no
|
|
||||||
session:
|
|
||||||
description:
|
|
||||||
- Specifies the session ID to use.
|
|
||||||
- This parameter works in conjunction with I(interactive).
|
|
||||||
- It has no effect when I(interactive) is set to C(no).
|
|
||||||
type: int
|
|
||||||
version_added: '2.7'
|
|
||||||
limited:
|
|
||||||
description:
|
|
||||||
- Run the command as limited user (strips the Administrators group and allows only privileges assigned to the Users group).
|
|
||||||
type: bool
|
|
||||||
default: no
|
|
||||||
system:
|
|
||||||
description:
|
|
||||||
- Run the remote command in the System account.
|
|
||||||
type: bool
|
|
||||||
default: no
|
|
||||||
priority:
|
|
||||||
description:
|
|
||||||
- Used to run the command at a different priority.
|
|
||||||
choices: [ abovenormal, background, belownormal, high, low, realtime ]
|
|
||||||
timeout:
|
|
||||||
description:
|
|
||||||
- The connection timeout in seconds
|
|
||||||
type: int
|
|
||||||
wait:
|
|
||||||
description:
|
|
||||||
- Wait for the application to terminate.
|
|
||||||
- Only use for non-interactive applications.
|
|
||||||
type: bool
|
|
||||||
default: yes
|
|
||||||
notes:
|
|
||||||
- More information related to Microsoft PsExec is available from
|
|
||||||
U(https://technet.microsoft.com/en-us/sysinternals/bb897553.aspx)
|
|
||||||
seealso:
|
|
||||||
- module: psexec
|
|
||||||
- module: raw
|
|
||||||
- module: win_command
|
|
||||||
- module: win_shell
|
|
||||||
author:
|
|
||||||
- Dag Wieers (@dagwieers)
|
|
||||||
'''
|
|
||||||
|
|
||||||
EXAMPLES = r'''
|
|
||||||
- name: Test the PsExec connection to the local system (target node) with your user
|
|
||||||
win_psexec:
|
|
||||||
command: whoami.exe
|
|
||||||
|
|
||||||
- name: Run regedit.exe locally (on target node) as SYSTEM and interactively
|
|
||||||
win_psexec:
|
|
||||||
command: regedit.exe
|
|
||||||
interactive: yes
|
|
||||||
system: yes
|
|
||||||
|
|
||||||
- name: Run the setup.exe installer on multiple servers using the Domain Administrator
|
|
||||||
win_psexec:
|
|
||||||
command: E:\setup.exe /i /IACCEPTEULA
|
|
||||||
hostnames:
|
|
||||||
- remote_server1
|
|
||||||
- remote_server2
|
|
||||||
username: DOMAIN\Administrator
|
|
||||||
password: some_password
|
|
||||||
priority: high
|
|
||||||
|
|
||||||
- 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 ]
|
|
||||||
password: some_password
|
|
||||||
priority: low
|
|
||||||
'''
|
|
||||||
|
|
||||||
RETURN = r'''
|
|
||||||
cmd:
|
|
||||||
description: The complete command line used by the module, including PsExec call and additional options.
|
|
||||||
returned: always
|
|
||||||
type: str
|
|
||||||
sample: psexec.exe -nobanner \\remote_server -u "DOMAIN\Administrator" -p "some_password" -accepteula E:\setup.exe
|
|
||||||
pid:
|
|
||||||
description: The PID of the async process created by PsExec.
|
|
||||||
returned: when C(wait=False)
|
|
||||||
type: int
|
|
||||||
sample: 1532
|
|
||||||
rc:
|
|
||||||
description: The return code for the command.
|
|
||||||
returned: always
|
|
||||||
type: int
|
|
||||||
sample: 0
|
|
||||||
stdout:
|
|
||||||
description: The standard output from the command.
|
|
||||||
returned: always
|
|
||||||
type: str
|
|
||||||
sample: Success.
|
|
||||||
stderr:
|
|
||||||
description: The error output from the command.
|
|
||||||
returned: always
|
|
||||||
type: str
|
|
||||||
sample: Error 15 running E:\setup.exe
|
|
||||||
'''
|
|
Loading…
Reference in a new issue