Fixing winrm connection for v2
This commit is contained in:
parent
946c37fd88
commit
3aede800c5
7 changed files with 125 additions and 125 deletions
|
@ -48,7 +48,7 @@ class ConnectionInformation:
|
|||
self.remote_addr = None
|
||||
self.remote_user = None
|
||||
self.password = passwords.get('conn_pass','')
|
||||
self.port = 22
|
||||
self.port = None
|
||||
self.private_key_file = C.DEFAULT_PRIVATE_KEY_FILE
|
||||
self.timeout = C.DEFAULT_TIMEOUT
|
||||
|
||||
|
|
|
@ -56,22 +56,12 @@ class ActionBase:
|
|||
|
||||
def get_shell(self):
|
||||
|
||||
# FIXME: no more inject, get this from the host variables?
|
||||
#default_shell = getattr(self._connection, 'default_shell', '')
|
||||
#shell_type = inject.get('ansible_shell_type')
|
||||
#if not shell_type:
|
||||
# if default_shell:
|
||||
# shell_type = default_shell
|
||||
# else:
|
||||
# shell_type = os.path.basename(C.DEFAULT_EXECUTABLE)
|
||||
|
||||
shell_type = getattr(self._connection, 'default_shell', '')
|
||||
if not shell_type:
|
||||
shell_type = os.path.basename(C.DEFAULT_EXECUTABLE)
|
||||
|
||||
shell_plugin = shell_loader.get(shell_type)
|
||||
if shell_plugin is None:
|
||||
shell_plugin = shell_loader.get('sh')
|
||||
if hasattr(self._connection, '_shell'):
|
||||
shell_plugin = getattr(self._connection, '_shell', '')
|
||||
else:
|
||||
shell_plugin = shell_loader.get(os.path.basename(C.DEFAULT_EXECUTABLE))
|
||||
if shell_plugin is None:
|
||||
shell_plugin = shell_loader.get('sh')
|
||||
|
||||
return shell_plugin
|
||||
|
||||
|
|
|
@ -141,7 +141,8 @@ class Connection(ConnectionBase):
|
|||
if not HAVE_PARAMIKO:
|
||||
raise AnsibleError("paramiko is not installed")
|
||||
|
||||
self._display.vvv("ESTABLISH CONNECTION FOR USER: %s on PORT %s TO %s" % (self._connection_info.remote_user, self._connection_info.port, self._connection_info.remote_addr), host=self._connection_info.remote_addr)
|
||||
port = self._connection_info.port or 22
|
||||
self._display.vvv("ESTABLISH CONNECTION FOR USER: %s on PORT %s TO %s" % (self._connection_info.remote_user, port, self._connection_info.remote_addr), host=self._connection_info.remote_addr)
|
||||
|
||||
ssh = paramiko.SSHClient()
|
||||
|
||||
|
@ -170,7 +171,7 @@ class Connection(ConnectionBase):
|
|||
key_filename=key_filename,
|
||||
password=self._connection_info.password,
|
||||
timeout=self._connection_info.timeout,
|
||||
port=self._connection_info.port
|
||||
port=port,
|
||||
)
|
||||
except Exception, e:
|
||||
msg = str(e)
|
||||
|
@ -178,7 +179,7 @@ class Connection(ConnectionBase):
|
|||
raise AnsibleError("paramiko version issue, please upgrade paramiko on the machine running ansible")
|
||||
elif "Private key file is encrypted" in msg:
|
||||
msg = 'ssh %s@%s:%s : %s\nTo connect as a different user, use -u <username>.' % (
|
||||
self._connection_info.remote_user, self._connection_info.remote_addr, self._connection_info.port, msg)
|
||||
self._connection_info.remote_user, self._connection_info.remote_addr, port, msg)
|
||||
raise AnsibleConnectionFailure(msg)
|
||||
else:
|
||||
raise AnsibleConnectionFailure(msg)
|
||||
|
|
|
@ -39,7 +39,7 @@ from ansible.plugins.connections import ConnectionBase
|
|||
class Connection(ConnectionBase):
|
||||
''' ssh based connections '''
|
||||
|
||||
def __init__(self, connection_info, *args, **kwargs):
|
||||
def __init__(self, *args, **kwargs):
|
||||
# SSH connection specific init stuff
|
||||
self.HASHED_KEY_MAGIC = "|1|"
|
||||
self._has_pipelining = True
|
||||
|
@ -50,7 +50,7 @@ class Connection(ConnectionBase):
|
|||
self._cp_dir = '/tmp'
|
||||
#fcntl.lockf(self.runner.process_lockfile, fcntl.LOCK_UN)
|
||||
|
||||
super(Connection, self).__init__(connection_info, *args, **kwargs)
|
||||
super(Connection, self).__init__(*args, **kwargs)
|
||||
|
||||
@property
|
||||
def transport(self):
|
||||
|
|
|
@ -23,17 +23,13 @@ import re
|
|||
import shlex
|
||||
import traceback
|
||||
import urlparse
|
||||
from ansible import errors
|
||||
from ansible import utils
|
||||
from ansible.callbacks import vvv, vvvv, verbose
|
||||
from ansible.runner.shell_plugins import powershell
|
||||
|
||||
try:
|
||||
from winrm import Response
|
||||
from winrm.exceptions import WinRMTransportError
|
||||
from winrm.protocol import Protocol
|
||||
except ImportError:
|
||||
raise errors.AnsibleError("winrm is not installed")
|
||||
raise AnsibleError("winrm is not installed")
|
||||
|
||||
HAVE_KERBEROS = False
|
||||
try:
|
||||
|
@ -42,10 +38,12 @@ try:
|
|||
except ImportError:
|
||||
pass
|
||||
|
||||
def vvvvv(msg, host=None):
|
||||
verbose(msg, host=host, caplevel=4)
|
||||
from ansible import constants as C
|
||||
from ansible.errors import AnsibleError, AnsibleConnectionFailure, AnsibleFileNotFound
|
||||
from ansible.plugins.connections import ConnectionBase
|
||||
from ansible.plugins import shell_loader
|
||||
|
||||
class Connection(object):
|
||||
class Connection(ConnectionBase):
|
||||
'''WinRM connections over HTTP/HTTPS.'''
|
||||
|
||||
transport_schemes = {
|
||||
|
@ -53,69 +51,79 @@ class Connection(object):
|
|||
'https': [('kerberos', 'https'), ('plaintext', 'https')],
|
||||
}
|
||||
|
||||
def __init__(self, runner, host, port, user, password, *args, **kwargs):
|
||||
self.runner = runner
|
||||
self.host = host
|
||||
self.port = port
|
||||
self.user = user
|
||||
self.password = password
|
||||
self.has_pipelining = False
|
||||
self.default_shell = 'powershell'
|
||||
self.default_suffixes = ['.ps1', '']
|
||||
self.protocol = None
|
||||
self.shell_id = None
|
||||
self.delegate = None
|
||||
def __init__(self, *args, **kwargs):
|
||||
|
||||
# Add runas support
|
||||
#self.become_methods_supported=['runas']
|
||||
self.has_pipelining = False
|
||||
self.default_suffixes = ['.ps1', '']
|
||||
self.protocol = None
|
||||
self.shell_id = None
|
||||
self.delegate = None
|
||||
|
||||
self._shell = shell_loader.get('powershell')
|
||||
|
||||
# TODO: Add runas support
|
||||
self.become_methods_supported=[]
|
||||
|
||||
super(Connection, self).__init__(*args, **kwargs)
|
||||
|
||||
@property
|
||||
def transport(self):
|
||||
''' used to identify this connection object from other classes '''
|
||||
return 'winrm'
|
||||
|
||||
def _winrm_connect(self):
|
||||
'''
|
||||
Establish a WinRM connection over HTTP/HTTPS.
|
||||
'''
|
||||
port = self.port or 5986
|
||||
vvv("ESTABLISH WINRM CONNECTION FOR USER: %s on PORT %s TO %s" % \
|
||||
(self.user, port, self.host), host=self.host)
|
||||
netloc = '%s:%d' % (self.host, port)
|
||||
port = self._connection_info.port or 5986
|
||||
self._display.vvv("ESTABLISH WINRM CONNECTION FOR USER: %s on PORT %s TO %s" % \
|
||||
(self._connection_info.remote_user, port, self._connection_info.remote_addr), host=self._connection_info.remote_addr)
|
||||
netloc = '%s:%d' % (self._connection_info.remote_addr, port)
|
||||
exc = None
|
||||
for transport, scheme in self.transport_schemes['http' if port == 5985 else 'https']:
|
||||
if transport == 'kerberos' and (not HAVE_KERBEROS or not '@' in self.user):
|
||||
if transport == 'kerberos' and (not HAVE_KERBEROS or not '@' in self._connection_info.remote_user):
|
||||
continue
|
||||
|
||||
if transport == 'kerberos':
|
||||
realm = self.user.split('@', 1)[1].strip() or None
|
||||
realm = self._connection_info.remote_user.split('@', 1)[1].strip() or None
|
||||
else:
|
||||
realm = None
|
||||
|
||||
endpoint = urlparse.urlunsplit((scheme, netloc, '/wsman', '', ''))
|
||||
vvvv('WINRM CONNECT: transport=%s endpoint=%s' % (transport, endpoint),
|
||||
host=self.host)
|
||||
protocol = Protocol(endpoint, transport=transport,
|
||||
username=self.user, password=self.password,
|
||||
realm=realm)
|
||||
|
||||
self._display.vvvvv('WINRM CONNECT: transport=%s endpoint=%s' % (transport, endpoint), host=self._connection_info.remote_addr)
|
||||
protocol = Protocol(
|
||||
endpoint,
|
||||
transport=transport,
|
||||
username=self._connection_info.remote_user,
|
||||
password=self._connection_info.password,
|
||||
realm=realm
|
||||
)
|
||||
|
||||
try:
|
||||
protocol.send_message('')
|
||||
return protocol
|
||||
except WinRMTransportError, exc:
|
||||
err_msg = str(exc)
|
||||
if re.search(r'Operation\s+?timed\s+?out', err_msg, re.I):
|
||||
raise errors.AnsibleError("the connection attempt timed out")
|
||||
raise AnsibleError("the connection attempt timed out")
|
||||
m = re.search(r'Code\s+?(\d{3})', err_msg)
|
||||
if m:
|
||||
code = int(m.groups()[0])
|
||||
if code == 401:
|
||||
raise errors.AnsibleError("the username/password specified for this server was incorrect")
|
||||
raise AnsibleError("the username/password specified for this server was incorrect")
|
||||
elif code == 411:
|
||||
return protocol
|
||||
vvvv('WINRM CONNECTION ERROR: %s' % err_msg, host=self.host)
|
||||
self._display.vvvvv('WINRM CONNECTION ERROR: %s' % err_msg, host=self._connection_info.remote_addr)
|
||||
continue
|
||||
if exc:
|
||||
raise errors.AnsibleError(str(exc))
|
||||
raise AnsibleError(str(exc))
|
||||
|
||||
def _winrm_exec(self, command, args=(), from_exec=False):
|
||||
if from_exec:
|
||||
vvvv("WINRM EXEC %r %r" % (command, args), host=self.host)
|
||||
self._display.vvvvv("WINRM EXEC %r %r" % (command, args), host=self._connection_info.remote_addr)
|
||||
else:
|
||||
vvvvv("WINRM EXEC %r %r" % (command, args), host=self.host)
|
||||
self._display.vvvvvv("WINRM EXEC %r %r" % (command, args), host=self._connection_info.remote_addr)
|
||||
if not self.protocol:
|
||||
self.protocol = self._winrm_connect()
|
||||
if not self.shell_id:
|
||||
|
@ -125,49 +133,46 @@ class Connection(object):
|
|||
command_id = self.protocol.run_command(self.shell_id, command, args)
|
||||
response = Response(self.protocol.get_command_output(self.shell_id, command_id))
|
||||
if from_exec:
|
||||
vvvv('WINRM RESULT %r' % response, host=self.host)
|
||||
self._display.vvvvv('WINRM RESULT %r' % response, host=self._connection_info.remote_addr)
|
||||
else:
|
||||
vvvvv('WINRM RESULT %r' % response, host=self.host)
|
||||
vvvvv('WINRM STDOUT %s' % response.std_out, host=self.host)
|
||||
vvvvv('WINRM STDERR %s' % response.std_err, host=self.host)
|
||||
self._display.vvvvvv('WINRM RESULT %r' % response, host=self._connection_info.remote_addr)
|
||||
self._display.vvvvvv('WINRM STDOUT %s' % response.std_out, host=self._connection_info.remote_addr)
|
||||
self._display.vvvvvv('WINRM STDERR %s' % response.std_err, host=self._connection_info.remote_addr)
|
||||
return response
|
||||
finally:
|
||||
if command_id:
|
||||
self.protocol.cleanup_command(self.shell_id, command_id)
|
||||
|
||||
def connect(self):
|
||||
def _connect(self):
|
||||
if not self.protocol:
|
||||
self.protocol = self._winrm_connect()
|
||||
return self
|
||||
|
||||
def exec_command(self, cmd, tmp_path, become_user=None, sudoable=False, executable=None, in_data=None):
|
||||
|
||||
if sudoable and self.runner.become and self.runner.become_method not in self.become_methods_supported:
|
||||
raise errors.AnsibleError("Internal Error: this module does not support running commands via %s" % self.runner.become_method)
|
||||
def exec_command(self, cmd, tmp_path, executable='/bin/sh', in_data=None):
|
||||
|
||||
cmd = cmd.encode('utf-8')
|
||||
cmd_parts = shlex.split(cmd, posix=False)
|
||||
if '-EncodedCommand' in cmd_parts:
|
||||
encoded_cmd = cmd_parts[cmd_parts.index('-EncodedCommand') + 1]
|
||||
decoded_cmd = base64.b64decode(encoded_cmd)
|
||||
vvv("EXEC %s" % decoded_cmd, host=self.host)
|
||||
self._display.vvv("EXEC %s" % decoded_cmd, host=self._connection_info.remote_addr)
|
||||
else:
|
||||
vvv("EXEC %s" % cmd, host=self.host)
|
||||
self._display.vvv("EXEC %s" % cmd, host=self._connection_info.remote_addr)
|
||||
# For script/raw support.
|
||||
if cmd_parts and cmd_parts[0].lower().endswith('.ps1'):
|
||||
script = powershell._build_file_cmd(cmd_parts, quote_args=False)
|
||||
cmd_parts = powershell._encode_script(script, as_list=True)
|
||||
script = self._shell._build_file_cmd(cmd_parts, quote_args=False)
|
||||
cmd_parts = self._shell._encode_script(script, as_list=True)
|
||||
try:
|
||||
result = self._winrm_exec(cmd_parts[0], cmd_parts[1:], from_exec=True)
|
||||
except Exception, e:
|
||||
traceback.print_exc()
|
||||
raise errors.AnsibleError("failed to exec cmd %s" % cmd)
|
||||
raise AnsibleError("failed to exec cmd %s" % cmd)
|
||||
return (result.status_code, '', result.std_out.encode('utf-8'), result.std_err.encode('utf-8'))
|
||||
|
||||
def put_file(self, in_path, out_path):
|
||||
vvv("PUT %s TO %s" % (in_path, out_path), host=self.host)
|
||||
self._display.vvv("PUT %s TO %s" % (in_path, out_path), host=self._connection_info.remote_addr)
|
||||
if not os.path.exists(in_path):
|
||||
raise errors.AnsibleFileNotFound("file or module does not exist: %s" % in_path)
|
||||
raise AnsibleFileNotFound("file or module does not exist: %s" % in_path)
|
||||
with open(in_path) as in_file:
|
||||
in_size = os.path.getsize(in_path)
|
||||
script_template = '''
|
||||
|
@ -179,8 +184,8 @@ class Connection(object):
|
|||
[void]$s.Close();
|
||||
'''
|
||||
# Determine max size of data we can pass per command.
|
||||
script = script_template % (powershell._escape(out_path), in_size, '', in_size)
|
||||
cmd = powershell._encode_script(script)
|
||||
script = script_template % (self._shell._escape(out_path), in_size, '', in_size)
|
||||
cmd = self._shell._encode_script(script)
|
||||
# Encode script with no data, subtract its length from 8190 (max
|
||||
# windows command length), divide by 2.67 (UTF16LE base64 command
|
||||
# encoding), then by 1.35 again (data base64 encoding).
|
||||
|
@ -192,19 +197,19 @@ class Connection(object):
|
|||
if out_data.lower().startswith('#!powershell') and not out_path.lower().endswith('.ps1'):
|
||||
out_path = out_path + '.ps1'
|
||||
b64_data = base64.b64encode(out_data)
|
||||
script = script_template % (powershell._escape(out_path), offset, b64_data, in_size)
|
||||
vvvv("WINRM PUT %s to %s (offset=%d size=%d)" % (in_path, out_path, offset, len(out_data)), host=self.host)
|
||||
cmd_parts = powershell._encode_script(script, as_list=True)
|
||||
script = script_template % (self._shell._escape(out_path), offset, b64_data, in_size)
|
||||
self._display.vvvvv("WINRM PUT %s to %s (offset=%d size=%d)" % (in_path, out_path, offset, len(out_data)), host=self._connection_info.remote_addr)
|
||||
cmd_parts = self._shell._encode_script(script, as_list=True)
|
||||
result = self._winrm_exec(cmd_parts[0], cmd_parts[1:])
|
||||
if result.status_code != 0:
|
||||
raise IOError(result.std_err.encode('utf-8'))
|
||||
except Exception:
|
||||
traceback.print_exc()
|
||||
raise errors.AnsibleError("failed to transfer file to %s" % out_path)
|
||||
raise AnsibleError("failed to transfer file to %s" % out_path)
|
||||
|
||||
def fetch_file(self, in_path, out_path):
|
||||
out_path = out_path.replace('\\', '/')
|
||||
vvv("FETCH %s TO %s" % (in_path, out_path), host=self.host)
|
||||
self._display.vvv("FETCH %s TO %s" % (in_path, out_path), host=self._connection_info.remote_addr)
|
||||
buffer_size = 2**19 # 0.5MB chunks
|
||||
if not os.path.exists(os.path.dirname(out_path)):
|
||||
os.makedirs(os.path.dirname(out_path))
|
||||
|
@ -233,9 +238,9 @@ class Connection(object):
|
|||
Write-Error "%(path)s does not exist";
|
||||
Exit 1;
|
||||
}
|
||||
''' % dict(buffer_size=buffer_size, path=powershell._escape(in_path), offset=offset)
|
||||
vvvv("WINRM FETCH %s to %s (offset=%d)" % (in_path, out_path, offset), host=self.host)
|
||||
cmd_parts = powershell._encode_script(script, as_list=True)
|
||||
''' % dict(buffer_size=buffer_size, path=self._shell._escape(in_path), offset=offset)
|
||||
self._display.vvvvv("WINRM FETCH %s to %s (offset=%d)" % (in_path, out_path, offset), host=self._connection_info.remote_addr)
|
||||
cmd_parts = self._shell._encode_script(script, as_list=True)
|
||||
result = self._winrm_exec(cmd_parts[0], cmd_parts[1:])
|
||||
if result.status_code != 0:
|
||||
raise IOError(result.std_err.encode('utf-8'))
|
||||
|
@ -259,7 +264,7 @@ class Connection(object):
|
|||
offset += len(data)
|
||||
except Exception:
|
||||
traceback.print_exc()
|
||||
raise errors.AnsibleError("failed to transfer file to %s" % out_path)
|
||||
raise AnsibleError("failed to transfer file to %s" % out_path)
|
||||
finally:
|
||||
if out_file:
|
||||
out_file.close()
|
||||
|
|
|
@ -32,33 +32,6 @@ _powershell_version = os.environ.get('POWERSHELL_VERSION', None)
|
|||
if _powershell_version:
|
||||
_common_args = ['PowerShell', '-Version', _powershell_version] + _common_args[1:]
|
||||
|
||||
def _escape(value, include_vars=False):
|
||||
'''Return value escaped for use in PowerShell command.'''
|
||||
# http://www.techotopia.com/index.php/Windows_PowerShell_1.0_String_Quoting_and_Escape_Sequences
|
||||
# http://stackoverflow.com/questions/764360/a-list-of-string-replacements-in-python
|
||||
subs = [('\n', '`n'), ('\r', '`r'), ('\t', '`t'), ('\a', '`a'),
|
||||
('\b', '`b'), ('\f', '`f'), ('\v', '`v'), ('"', '`"'),
|
||||
('\'', '`\''), ('`', '``'), ('\x00', '`0')]
|
||||
if include_vars:
|
||||
subs.append(('$', '`$'))
|
||||
pattern = '|'.join('(%s)' % re.escape(p) for p, s in subs)
|
||||
substs = [s for p, s in subs]
|
||||
replace = lambda m: substs[m.lastindex - 1]
|
||||
return re.sub(pattern, replace, value)
|
||||
|
||||
def _encode_script(script, as_list=False):
|
||||
'''Convert a PowerShell script to a single base64-encoded command.'''
|
||||
script = '\n'.join([x.strip() for x in script.splitlines() if x.strip()])
|
||||
encoded_script = base64.b64encode(script.encode('utf-16-le'))
|
||||
cmd_parts = _common_args + ['-EncodedCommand', encoded_script]
|
||||
if as_list:
|
||||
return cmd_parts
|
||||
return ' '.join(cmd_parts)
|
||||
|
||||
def _build_file_cmd(cmd_parts):
|
||||
'''Build command line to run a file, given list of file name plus args.'''
|
||||
return ' '.join(_common_args + ['-ExecutionPolicy', 'Unrestricted', '-File'] + ['"%s"' % x for x in cmd_parts])
|
||||
|
||||
class ShellModule(object):
|
||||
|
||||
def env_prefix(self, **kwargs):
|
||||
|
@ -75,19 +48,19 @@ class ShellModule(object):
|
|||
return ''
|
||||
|
||||
def remove(self, path, recurse=False):
|
||||
path = _escape(path)
|
||||
path = self._escape(path)
|
||||
if recurse:
|
||||
return _encode_script('''Remove-Item "%s" -Force -Recurse;''' % path)
|
||||
return self._encode_script('''Remove-Item "%s" -Force -Recurse;''' % path)
|
||||
else:
|
||||
return _encode_script('''Remove-Item "%s" -Force;''' % path)
|
||||
return self._encode_script('''Remove-Item "%s" -Force;''' % path)
|
||||
|
||||
def mkdtemp(self, basefile, system=False, mode=None):
|
||||
basefile = _escape(basefile)
|
||||
basefile = self._escape(basefile)
|
||||
# FIXME: Support system temp path!
|
||||
return _encode_script('''(New-Item -Type Directory -Path $env:temp -Name "%s").FullName | Write-Host -Separator '';''' % basefile)
|
||||
return self._encode_script('''(New-Item -Type Directory -Path $env:temp -Name "%s").FullName | Write-Host -Separator '';''' % basefile)
|
||||
|
||||
def md5(self, path):
|
||||
path = _escape(path)
|
||||
path = self._escape(path)
|
||||
script = '''
|
||||
If (Test-Path -PathType Leaf "%(path)s")
|
||||
{
|
||||
|
@ -105,15 +78,43 @@ class ShellModule(object):
|
|||
Write-Host "1";
|
||||
}
|
||||
''' % dict(path=path)
|
||||
return _encode_script(script)
|
||||
return self._encode_script(script)
|
||||
|
||||
def build_module_command(self, env_string, shebang, cmd, rm_tmp=None):
|
||||
cmd = cmd.encode('utf-8')
|
||||
cmd_parts = shlex.split(cmd, posix=False)
|
||||
if not cmd_parts[0].lower().endswith('.ps1'):
|
||||
cmd_parts[0] = '%s.ps1' % cmd_parts[0]
|
||||
script = _build_file_cmd(cmd_parts)
|
||||
script = self._build_file_cmd(cmd_parts)
|
||||
if rm_tmp:
|
||||
rm_tmp = _escape(rm_tmp)
|
||||
rm_tmp = self._escape(rm_tmp)
|
||||
script = '%s; Remove-Item "%s" -Force -Recurse;' % (script, rm_tmp)
|
||||
return _encode_script(script)
|
||||
return self._encode_script(script)
|
||||
|
||||
def _escape(self, value, include_vars=False):
|
||||
'''Return value escaped for use in PowerShell command.'''
|
||||
# http://www.techotopia.com/index.php/Windows_PowerShell_1.0_String_Quoting_and_Escape_Sequences
|
||||
# http://stackoverflow.com/questions/764360/a-list-of-string-replacements-in-python
|
||||
subs = [('\n', '`n'), ('\r', '`r'), ('\t', '`t'), ('\a', '`a'),
|
||||
('\b', '`b'), ('\f', '`f'), ('\v', '`v'), ('"', '`"'),
|
||||
('\'', '`\''), ('`', '``'), ('\x00', '`0')]
|
||||
if include_vars:
|
||||
subs.append(('$', '`$'))
|
||||
pattern = '|'.join('(%s)' % re.escape(p) for p, s in subs)
|
||||
substs = [s for p, s in subs]
|
||||
replace = lambda m: substs[m.lastindex - 1]
|
||||
return re.sub(pattern, replace, value)
|
||||
|
||||
def _encode_script(self, script, as_list=False):
|
||||
'''Convert a PowerShell script to a single base64-encoded command.'''
|
||||
script = '\n'.join([x.strip() for x in script.splitlines() if x.strip()])
|
||||
encoded_script = base64.b64encode(script.encode('utf-16-le'))
|
||||
cmd_parts = _common_args + ['-EncodedCommand', encoded_script]
|
||||
if as_list:
|
||||
return cmd_parts
|
||||
return ' '.join(cmd_parts)
|
||||
|
||||
def _build_file_cmd(self, cmd_parts):
|
||||
'''Build command line to run a file, given list of file name plus args.'''
|
||||
return ' '.join(_common_args + ['-ExecutionPolicy', 'Unrestricted', '-File'] + ['"%s"' % x for x in cmd_parts])
|
||||
|
||||
|
|
|
@ -73,6 +73,9 @@ class Display:
|
|||
def vvvvv(self, msg, host=None):
|
||||
return self.verbose(msg, host=host, caplevel=4)
|
||||
|
||||
def vvvvvv(self, msg, host=None):
|
||||
return self.verbose(msg, host=host, caplevel=5)
|
||||
|
||||
def verbose(self, msg, host=None, caplevel=2):
|
||||
# FIXME: this needs to be implemented
|
||||
#msg = utils.sanitize_output(msg)
|
||||
|
|
Loading…
Reference in a new issue