Example #1
0
 def _winrm_connect(self):
     '''
     Establish a WinRM connection over HTTP/HTTPS.
     '''
     display.vvv("ESTABLISH WINRM CONNECTION FOR USER: %s on PORT %s TO %s" %
         (self._winrm_user, self._winrm_port, self._winrm_host), host=self._winrm_host)
     netloc = '%s:%d' % (self._winrm_host, self._winrm_port)
     endpoint = urlunsplit((self._winrm_scheme, netloc, self._winrm_path, '', ''))
     errors = []
     for transport in self._winrm_transport:
         if transport == 'kerberos' and not HAVE_KERBEROS:
             errors.append('kerberos: the python kerberos library is not installed')
             continue
         display.vvvvv('WINRM CONNECT: transport=%s endpoint=%s' % (transport, endpoint), host=self._winrm_host)
         try:
             protocol = Protocol(endpoint, transport=transport, **self._winrm_kwargs)
             protocol.send_message('')
             return protocol
         except Exception as e:
             err_msg = (str(e) or repr(e)).strip()
             if re.search(r'Operation\s+?timed\s+?out', err_msg, re.I):
                 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:
                     err_msg = 'the username/password specified for this server was incorrect'
                 elif code == 411:
                     return protocol
             errors.append('%s: %s' % (transport, err_msg))
             display.vvvvv('WINRM CONNECTION ERROR: %s\n%s' % (err_msg, traceback.format_exc()), host=self._winrm_host)
     if errors:
         raise AnsibleError(', '.join(errors))
     else:
         raise AnsibleError('No transport found for WinRM connection')
Example #2
0
 def __init__(self, target, auth, transport='plaintext'):
     username, password = auth
     self.url = self._build_url(target, transport)
     self.protocol = Protocol(self.url,
                              transport=transport,
                              username=username,
                              password=password)
Example #3
0
 def _winrm_connect(self):
     '''
     Establish a WinRM connection over HTTP/HTTPS.
     '''
     display.vvv("ESTABLISH WINRM CONNECTION FOR USER: %s on PORT %s TO %s" %
         (self._winrm_user, self._winrm_port, self._winrm_host), host=self._winrm_host)
     netloc = '%s:%d' % (self._winrm_host, self._winrm_port)
     endpoint = urlunsplit((self._winrm_scheme, netloc, self._winrm_path, '', ''))
     errors = []
     for transport in self._winrm_transport:
         if transport == 'kerberos' and not HAVE_KERBEROS:
             errors.append('kerberos: the python kerberos library is not installed')
             continue
         display.vvvvv('WINRM CONNECT: transport=%s endpoint=%s' % (transport, endpoint), host=self._winrm_host)
         try:
             protocol = Protocol(endpoint, transport=transport, **self._winrm_kwargs)
             protocol.send_message('')
             return protocol
         except Exception as e:
             err_msg = (str(e) or repr(e)).strip()
             if re.search(r'Operation\s+?timed\s+?out', err_msg, re.I):
                 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:
                     err_msg = 'the username/password specified for this server was incorrect'
                 elif code == 411:
                     return protocol
             errors.append('%s: %s' % (transport, err_msg))
             display.vvvvv('WINRM CONNECTION ERROR: %s\n%s' % (err_msg, traceback.format_exc()), host=self._winrm_host)
     if errors:
         raise AnsibleError(', '.join(errors))
     else:
         raise AnsibleError('No transport found for WinRM connection')
Example #4
0
 def __init__(self, target, auth, **kwargs):
     username, password = auth
     self.url = self._build_url(target, kwargs.get('transport',
                                                   'plaintext'))
     self.protocol = Protocol(self.url,
                              username=username,
                              password=password,
                              **kwargs)
Example #5
0
class WINRM(object):
    """
    WINRM Module to connect to windows host
    """
    def __init__(self, host_ip, usr, pwd):
        """
        - **parameters**, **types**, **return** and **return types**::
            :param os_type : windows/linux
            :param host_ip: ip address of the Windows host
            :param usr: username of the Windows Host
            :param pwd: Password of the Windows Host
            :type os_type: string
            :type host_ip: string
            :type u_name: string
            :type pwd: string
        """
        self.os_type = 'windows'
        self.host_ip = host_ip
        self.usr = usr
        self.pwd = pwd
        self.shell_id = None
        self.host_win_ip = None
        self.conn = None

    def connect(self):
        """
            Method to connect to a Windows machine.
        """
        try:
            self.host_win_ip = "http://" + self.host_ip + ":5985/wsman"
            self.conn = Protocol(endpoint=self.host_win_ip,
                                 transport="ntlm",
                                 username=self.usr,
                                 password=self.pwd,
                                 server_cert_validation="ignore")
            logger.warn("Connecting Windows ...")
            self.shell_id = self.conn.open_shell()
            logger.warn(self.shell_id)
            logger.warn('Connected to Windows.')
        except Exception as error:
            msg_exception_error = "Exception raised: %s " % error
            raise (msg_exception_error)

    def run_cmd(self, cmd):
        """
            Generic Method for passing command and run it on windows machine and return output.
             - **parameters**, **types**, **return** and **return types**::
                 :param cmd: Command to be executed on windows machine.
                 :return stdout,stderr,status_code : output,errormessage and statuscode of output.
                 :rtype stdout,stderr,status_code: tuple
        """
        if 'shell_id' in dir(self):
            #checking for the shell_id created in winrm object
            command_id = self.conn.run_command(self.shell_id, cmd)
            std_out, std_err, status_code = self.conn.get_command_output(
                self.shell_id, command_id)
            #runs the command and returns output,error,statuscode
            return std_out, std_err, status_code
Example #6
0
    def _winrm_connect(self):
        '''
        Establish a WinRM connection over HTTP/HTTPS.
        '''
        display.vvv("ESTABLISH WINRM CONNECTION FOR USER: %s on PORT %s TO %s" %
                    (self._winrm_user, self._winrm_port, self._winrm_host), host=self._winrm_host)

        winrm_host = self._winrm_host
        if HAS_IPADDRESS:
            display.vvvv("checking if winrm_host %s is an IPv6 address" % winrm_host)
            try:
                ipaddress.IPv6Address(winrm_host)
            except ipaddress.AddressValueError:
                pass
            else:
                winrm_host = "[%s]" % winrm_host

        netloc = '%s:%d' % (winrm_host, self._winrm_port)
        endpoint = urlunsplit((self._winrm_scheme, netloc, self._winrm_path, '', ''))
        errors = []
        for transport in self._winrm_transport:
            if transport == 'kerberos':
                if not HAVE_KERBEROS:
                    errors.append('kerberos: the python kerberos library is not installed')
                    continue
                if self._kerb_managed:
                    self._kerb_auth(self._winrm_user, self._winrm_pass)
            display.vvvvv('WINRM CONNECT: transport=%s endpoint=%s' % (transport, endpoint), host=self._winrm_host)
            try:
                winrm_kwargs = self._winrm_kwargs.copy()
                if self._winrm_connection_timeout:
                    winrm_kwargs['operation_timeout_sec'] = self._winrm_connection_timeout
                    winrm_kwargs['read_timeout_sec'] = self._winrm_connection_timeout + 1
                protocol = Protocol(endpoint, transport=transport, **winrm_kwargs)

                # open the shell from connect so we know we're able to talk to the server
                if not self.shell_id:
                    self.shell_id = protocol.open_shell(codepage=65001)  # UTF-8
                    display.vvvvv('WINRM OPEN SHELL: %s' % self.shell_id, host=self._winrm_host)

                return protocol
            except Exception as e:
                err_msg = to_text(e).strip()
                if re.search(to_text(r'Operation\s+?timed\s+?out'), err_msg, re.I):
                    raise AnsibleError('the connection attempt timed out')
                m = re.search(to_text(r'Code\s+?(\d{3})'), err_msg)
                if m:
                    code = int(m.groups()[0])
                    if code == 401:
                        err_msg = 'the specified credentials were rejected by the server'
                    elif code == 411:
                        return protocol
                errors.append(u'%s: %s' % (transport, err_msg))
                display.vvvvv(u'WINRM CONNECTION ERROR: %s\n%s' % (err_msg, to_text(traceback.format_exc())), host=self._winrm_host)
        if errors:
            raise AnsibleConnectionFailure(', '.join(map(to_native, errors)))
        else:
            raise AnsibleError('No transport found for WinRM connection')
Example #7
0
    def _winrm_connect(self):
        '''
        Establish a WinRM connection over HTTP/HTTPS.
        '''
        display.vvv("ESTABLISH WINRM CONNECTION FOR USER: %s on PORT %s TO %s" %
                    (self._winrm_user, self._winrm_port, self._winrm_host), host=self._winrm_host)

        winrm_host = self._winrm_host
        if HAS_IPADDRESS:
            display.debug("checking if winrm_host %s is an IPv6 address" % winrm_host)
            try:
                ipaddress.IPv6Address(winrm_host)
            except ipaddress.AddressValueError:
                pass
            else:
                winrm_host = "[%s]" % winrm_host

        netloc = '%s:%d' % (winrm_host, self._winrm_port)
        endpoint = urlunsplit((self._winrm_scheme, netloc, self._winrm_path, '', ''))
        errors = []
        for transport in self._winrm_transport:
            if transport == 'kerberos':
                if not HAVE_KERBEROS:
                    errors.append('kerberos: the python kerberos library is not installed')
                    continue
                if self._kerb_managed:
                    self._kerb_auth(self._winrm_user, self._winrm_pass)
            display.vvvvv('WINRM CONNECT: transport=%s endpoint=%s' % (transport, endpoint), host=self._winrm_host)
            try:
                winrm_kwargs = self._winrm_kwargs.copy()
                if self._winrm_connection_timeout:
                    winrm_kwargs['operation_timeout_sec'] = self._winrm_connection_timeout
                    winrm_kwargs['read_timeout_sec'] = self._winrm_connection_timeout + 1
                protocol = Protocol(endpoint, transport=transport, **winrm_kwargs)

                # open the shell from connect so we know we're able to talk to the server
                if not self.shell_id:
                    self.shell_id = protocol.open_shell(codepage=65001)  # UTF-8
                    display.vvvvv('WINRM OPEN SHELL: %s' % self.shell_id, host=self._winrm_host)

                return protocol
            except Exception as e:
                err_msg = to_text(e).strip()
                if re.search(to_text(r'Operation\s+?timed\s+?out'), err_msg, re.I):
                    raise AnsibleError('the connection attempt timed out')
                m = re.search(to_text(r'Code\s+?(\d{3})'), err_msg)
                if m:
                    code = int(m.groups()[0])
                    if code == 401:
                        err_msg = 'the specified credentials were rejected by the server'
                    elif code == 411:
                        return protocol
                errors.append(u'%s: %s' % (transport, err_msg))
                display.vvvvv(u'WINRM CONNECTION ERROR: %s\n%s' % (err_msg, to_text(traceback.format_exc())), host=self._winrm_host)
        if errors:
            raise AnsibleConnectionFailure(', '.join(map(to_native, errors)))
        else:
            raise AnsibleError('No transport found for WinRM connection')
    def run(self, scripturl, scriptarguments):
        scriptpath = "c:\\samanamon"
        #scripturl="http://%s/%s" % (self.nagiosaddress, scriptname)
        scriptname = scripturl.split('/')[-1]
        if self.cleanup:
            script = '''
 if (-Not (Test-Path %(scriptpath)s)) { mkdir %(scriptpath)s | Out-Null}
 "Environment prepared." | Out-Host
 Invoke-WebRequest -Uri %(scripturl)s -OutFile "%(scriptpath)s\\%(scriptname)s"
 if (-Not (Test-Path %(scriptpath)s\\%(scriptname)s)) { 
   "File not downloaded" | Out-Host; 
   Remove-Item -Recurse -Force %(scriptpath)s
   exit 1 
 }
 "Downloaded Script." | Out-Host
 %(scriptpath)s\\%(scriptname)s %(scriptarguments)s| Out-Host
 "Done executing script" | Out-Host
 del %(scriptpath)s\\%(scriptname)s
 Remove-Item -Recurse -Force %(scriptpath)s
 "Done cleanup" | Out-Host''' % { 'scripturl': scripturl, 
      'scriptpath': scriptpath, 
      'scriptname': scriptname,
      'scriptarguments': scriptarguments,
      'hostaddress': self.hostaddress
      }
        else:
            script = '''
 %(scriptpath)s\\%(scriptname)s %(scriptarguments)s| Out-Host
 "Done executing script" | Out-Host''' % {
            'scriptpath': scriptpath, 
            'scriptname': scriptname,
            'scriptarguments': scriptarguments
            }

        shell_id = None
        command_id = None
        p = None
        error = 0
        std_out = ''
        std_err = ''
        try:
            p = Protocol(
                endpoint='http://%s:5985/wsman' % self.hostaddress,
                transport='ntlm',
                username=self.username,
                password=self.password)
            shell_id = p.open_shell()
            encoded_ps = b64encode(script.encode('utf_16_le')).decode('ascii')
            command_id = p.run_command(shell_id, 'powershell', ['-encodedcommand {0}'.format(encoded_ps), ])
            std_out, std_err, status_code = p.get_command_output(shell_id, command_id)
            self.check_error(std_err)
            p.cleanup_command(shell_id, command_id)
            p.close_shell(shell_id)

        except Exception as e:
          raise CheckWinRMExceptionUNKNOWN("Unable to get data from Server (%s) %s." % (type(e).__name__, str(e)))

        if status_code != 0:
            raise CheckWinRMExceptionUNKNOWN(std_err)
        return "%s\n%s" % (std_out, "")
Example #9
0
    def getLastTaskResult(self, taskname):
        script = """
$task = Get-ScheduledTaskInfo -TaskName %s
$task.LastTaskResult
""" % taskname

        shell_id = None
        command_id = None
        p = None
        error = False
        try:
            p = Protocol(endpoint='https://' + self.hostname + ':5986/wsman',
                         transport='ntlm',
                         username=self.username,
                         password=self.password,
                         server_cert_validation='ignore')
            shell_id = p.open_shell()
            encoded_ps = b64encode(script.encode('utf_16_le')).decode('ascii')
            command_id = p.run_command(shell_id, 'powershell', [
                '-encodedcommand {0}'.format(encoded_ps),
            ])
            std_out, std_err, status_code = p.get_command_output(
                shell_id, command_id)
            lasttaskresult = std_out.rstrip()
        except Exception as e:
            print("UNKNOWN - Unable to get data from server (%s) %s." %
                  (str(e), type(e).__name__))
            error = True
        finally:
            p.cleanup_command(shell_id, command_id)
            p.close_shell(shell_id)
        if error: exit(3)
        return lasttaskresult
    def run(self):
        # use win remote management to run powershell script

        # set command text, tell windows which module to import and run in this case
        script = "Import-Module -Name 'C:\\Users\\trota\\Source\\PowerShell\\Modules\\yo.psm1'; &WriteYo(' with var')"

        # must use utf16 little endian on windows
        # see run_ps in pywinrm __init__.py https://github.com/diyan/pywinrm/blob/master/winrm/__init__.py
        encoded_ps = b64encode(script.encode('utf_16_le')).decode('ascii')
        encoded_ps_command = 'powershell -encodedcommand {0}'.format(
            encoded_ps)

        print("")
        print("encoded ps command: ", encoded_ps_command)
        print("")

        # connect
        p = Protocol(
            endpoint='https://CCWL-2909.chsamerica.com:5986/wsman',
            transport='ntlm',
            username=r'chs\trota',
            password='******',
            # secure connection validation - see http://www.hurryupandwait.io/blog/understanding-and-troubleshooting-winrm-connection-and-authentication-a-thrill-seekers-guide-to-adventure
            # TODO: configure SSL properly for production/public spaces
            server_cert_validation='ignore'
            #server_cert_validation='validate'
        )
        shell_id = p.open_shell()
        command_id = p.run_command(shell_id, encoded_ps_command)
        std_out, std_err, status_code = p.get_command_output(
            shell_id, command_id)
        p.cleanup_command(shell_id, command_id)
        p.close_shell(shell_id)
Example #11
0
    def run(self,
            host,
            password,
            command,
            params,
            username='******',
            port=5732,
            secure=True):
        proto = 'https' if secure else 'http'
        p = Protocol(
            endpoint='%s://%s:%i/wsman' % (proto, host, port),  # RFC 2732?
            transport='ntlm',
            username=username,
            password=password,
            server_cert_validation='ignore')
        shell_id = p.open_shell()

        # run the command
        command_id = p.run_command(shell_id, command, params)
        std_out, std_err, status_code = p.get_command_output(
            shell_id, command_id)
        p.cleanup_command(shell_id, command_id)

        p.close_shell(shell_id)
        return {'stdout': std_out, 'stderr': std_err}
Example #12
0
def main():
    args = parse_args()
    endpoint = '{}://{}:{}/{}'.format(
        'http' if args.use_http else 'https',
        args.host,
        args.port,
        args.endpoint
    )
    username = args.user
    if '\\' not in username or '@' not in username:
        username = '******'.format(args.host.split('.')[0], username)

    if args.shell:
        command = args.command[0]
        arguments = args.command[1:]
    else:
        command = 'powershell'
        encoded_command = ' '.join(args.command)
        encoded_command = base64.b64encode(encoded_command.encode('utf-16-le'))
        arguments = ['-EncodedCommand', encoded_command]

    proto = Protocol(endpoint, 'ntlm', username, args.password, server_cert_validation='ignore')
    shell_id = proto.open_shell()
    command_id = proto.run_command(shell_id, command, arguments)
    std_out, std_err, status_code = proto.get_command_output(shell_id, command_id)
    sys.stdout.write(std_out.decode('utf-8'))
    # sys.stderr.write(std_err.decode('utf-8'))
    proto.cleanup_command(shell_id, command_id)
    proto.close_shell(shell_id)
    return status_code
Example #13
0
def run_command(command, target):

    p = Protocol(endpoint='https://' + target + ':5986/wsman',
                 transport='kerberos')

    # We do not want printed info about kerberos ticket
    stdout_orig = sys.stdout
    f = open('/dev/null', 'w')
    sys.stdout = f

    try:
        shell_id = p.open_shell()
        command_id = p.run_command(shell_id, 'powershell', [command])
        std_out, std_err, status_code = p.get_command_output(
            shell_id, command_id)
        p.cleanup_command(shell_id, command_id)
        p.close_shell(shell_id)

        sys.stdout = stdout_orig

        print std_out

        if std_err:
            sys.exit(std_err)

    except kerberos.GSSError as e:
        print >> sys.stderr, "kerberos GSSError:", e
        sys.exit(2)
    except:
        print >> sys.stderr, (
            "Unexpected error during remote ps command execution :",
            sys.exc_info()[0], sys.exc_info()[1])
        sys.exit(2)
Example #14
0
    def _winrm_connect(self):
        '''
        Establish a WinRM connection over HTTP/HTTPS.
        '''
        display.vvv(
            "ESTABLISH WINRM CONNECTION FOR USER: %s on PORT %s TO %s" %
            (self._winrm_user, self._winrm_port, self._winrm_host),
            host=self._winrm_host)
        netloc = '%s:%d' % (self._winrm_host, self._winrm_port)
        endpoint = urlunsplit(
            (self._winrm_scheme, netloc, self._winrm_path, '', ''))
        errors = []
        for transport in self._winrm_transport:
            if transport == 'kerberos' and not HAVE_KERBEROS:
                errors.append(
                    'kerberos: the python kerberos library is not installed')
                continue
            display.vvvvv('WINRM CONNECT: transport=%s endpoint=%s' %
                          (transport, endpoint),
                          host=self._winrm_host)
            try:
                protocol = Protocol(endpoint,
                                    transport=transport,
                                    **self._winrm_kwargs)
                # send keepalive message to ensure we're awake
                # TODO: is this necessary?
                # protocol.send_message(xmltodict.unparse(rq))
                if not self.shell_id:
                    self.shell_id = protocol.open_shell(
                        codepage=65001)  # UTF-8
                    display.vvvvv('WINRM OPEN SHELL: %s' % self.shell_id,
                                  host=self._winrm_host)

                return protocol
            except Exception as e:
                err_msg = to_unicode(e).strip()
                if re.search(to_unicode(r'Operation\s+?timed\s+?out'), err_msg,
                             re.I):
                    raise AnsibleError('the connection attempt timed out')
                m = re.search(to_unicode(r'Code\s+?(\d{3})'), err_msg)
                if m:
                    code = int(m.groups()[0])
                    if code == 401:
                        err_msg = 'the username/password specified for this server was incorrect'
                    elif code == 411:
                        return protocol
                errors.append(u'%s: %s' % (transport, err_msg))
                display.vvvvv(u'WINRM CONNECTION ERROR: %s\n%s' %
                              (err_msg, to_unicode(traceback.format_exc())),
                              host=self._winrm_host)
        if errors:
            raise AnsibleConnectionFailure(', '.join(map(to_str, errors)))
        else:
            raise AnsibleError('No transport found for WinRM connection')
Example #15
0
    def _winrm_connect(self):
        '''
        Establish a WinRM connection over HTTP/HTTPS.
        '''
        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._connection_info.remote_user):
                continue

            if transport == 'kerberos':
                realm = self._connection_info.remote_user.split(
                    '@', 1)[1].strip() or None
            else:
                realm = None

            endpoint = parse.urlunsplit((scheme, netloc, '/wsman', '', ''))

            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 as exc:
                err_msg = str(exc)
                if re.search(r'Operation\s+?timed\s+?out', err_msg, re.I):
                    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 AnsibleError(
                            "the username/password specified for this server was incorrect"
                        )
                    elif code == 411:
                        return protocol
                self._display.vvvvv('WINRM CONNECTION ERROR: %s' % err_msg,
                                    host=self._connection_info.remote_addr)
                continue
        if exc:
            raise AnsibleError(str(exc))
    def connect(self):
        inventory = Inventory()

        if inventory.has_option(self.hostname, 'address'):
            address = inventory.get(self.hostname, 'address')
        else:
            address = self.hostname
        logger.debug('Using address ' + address)

        if inventory.has_option(self.hostname, 'scheme'):
            scheme = inventory.get(self.hostname, 'scheme')
        else:
            scheme = 'http'
        logger.debug('Using url scheme ' + scheme)

        if inventory.has_option(self.hostname, 'port'):
            port = inventory.get(self.hostname, 'port')
        else:
            if scheme == 'http':
                port = '5985'
            elif scheme == 'https':
                port = '5986'
            else:
                raise('Invalid WinRM scheme: ' + scheme)
        logger.debug('Using port ' + port)

        if not inventory.has_option(self.hostname, 'username'):
            raise RuntimeError('Host ' + self.hostname + ' has not specified option: username')
        username = inventory.get(self.hostname, 'username')

        if inventory.has_option(self.hostname, 'kerberos_realm'):
            username = username + '@' + inventory.get(self.hostname, 'kerberos_realm')
        logger.debug('Using username ' + username)

        if inventory.has_option(self.hostname, 'kerberos_delegation'):
            kerberos_delegation = inventory.get(self.hostname, 'kerberos_delegation')
        else:
            kerberos_delegation = False

        if inventory.has_option(self.hostname, 'kerberos_hostname_override'):
            kerberos_hostname_override = inventory.get(self.hostname, 'kerberos_hostname_override')
        else:
            kerberos_hostname_override = None
        self.protocol = Protocol(
            endpoint=scheme + '://' + address + ':' + port + '/wsman',
            transport='kerberos',
            username=username,
            kerberos_delegation=kerberos_delegation,
            kerberos_hostname_override=kerberos_hostname_override)

        try:
            self.shell_id = self.protocol.open_shell()
        except Exception as e:
            logger.warning(str(e))
Example #17
0
 def connect(self, output, server):
     self.output = output
     self.datastore = os.path.join(self.output, server['server'])
     os.makedirs(self.datastore)
     # session = winrm.Session(server['url'],
     #                         auth=(server['user'], server['password']),
     #                         transport='ntlm')
     self.protocol = Protocol(endpoint='http://{}:5985/wsman'.format(
         server['url']),
                              transport='ntlm',
                              username=server['user'],
                              password=server['password'])
Example #18
0
 def init_winrm_connection(self, host, port, username, password):
     endpoint = 'https://%s:%s/wsman' % (host, port)
     try:
         self.winrm = Protocol(endpoint=endpoint,
                               transport='ntlm',
                               username=username,
                               password=password,
                               server_cert_validation='ignore')
         return True
     except Exception as ex:
         print "\t=> WinRM : Authentication failed on server: %s cause: %s" % (
             host, str(ex))
         return False
Example #19
0
    def _winrm_connect(self):
        '''
        Establish a WinRM connection over HTTP/HTTPS.
        '''

        # get winrm-specific connection vars
        host_vars = self.runner.inventory._hosts_cache[self.delegate].get_variables()

        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)
        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):
                continue
            if transport == 'kerberos':
                realm = self.user.split('@', 1)[1].strip() or None
            else:
                realm = None
            endpoint = urlparse.urlunsplit((scheme, netloc, '/wsman', '', ''))

            self._winrm_kwargs = dict(username=self.user, password=self.password, realm=realm)
            argspec = inspect.getargspec(Protocol.__init__)
            for arg in argspec.args:
                if arg in ('self', 'endpoint', 'transport', 'username', 'password', 'realm'):
                    continue
                if 'ansible_winrm_%s' % arg in host_vars:
                    self._winrm_kwargs[arg] = host_vars['ansible_winrm_%s' % arg]

            vvvv('WINRM CONNECT: transport=%s endpoint=%s' % (transport, endpoint),
                 host=self.host)

            protocol = Protocol(endpoint, transport=transport, **self._winrm_kwargs)

            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")
                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")
                    elif code == 411:
                        return protocol
                vvvv('WINRM CONNECTION ERROR: %s' % err_msg, host=self.host)
                continue
    def connect(self):
        inventory = Inventory()

        if inventory.has_option(self.hostname, 'address'):
            address = inventory.get(self.hostname, 'address')
        else:
            address = self.hostname
        logger.debug('Using address ' + address)

        if inventory.has_option(self.hostname, 'scheme'):
            scheme = inventory.get(self.hostname, 'scheme')
        else:
            scheme = 'http'
        logger.debug('Using url scheme ' + scheme)

        if inventory.has_option(self.hostname, 'port'):
            port = inventory.get(self.hostname, 'port')
        else:
            if scheme == 'http':
                port = '5985'
            elif scheme == 'https':
                port = '5986'
            else:
                raise ('Invalid WinRM scheme: ' + scheme)
        logger.debug('Using port ' + port)

        if not inventory.has_option(self.hostname, 'username'):
            raise RuntimeError('Host ' + self.hostname +
                               ' has not specified option: username')
        username = inventory.get(self.hostname, 'username')
        if inventory.has_option(self.hostname, 'domain'):
            username = inventory.get(self.hostname, 'domain') + '\\' + username
        logger.debug('Using username ' + username)

        if not inventory.has_option(self.hostname, 'password'):
            raise RuntimeError('Host ' + self.hostname +
                               ' has not specified option: password')
        password = inventory.get(self.hostname, 'password')

        self.protocol = Protocol(endpoint=scheme + '://' + address + ':' +
                                 port + '/wsman',
                                 transport='plaintext',
                                 username=username,
                                 password=password)

        try:
            self.shell_id = self.protocol.open_shell()
        except Exception as e:
            logger.warning(str(e))
Example #21
0
 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)
     cache_key = '%s:%s@%s:%d' % (self.user, hashlib.md5(
         self.password).hexdigest(), self.host, port)
     if cache_key in _winrm_cache:
         vvvv('WINRM REUSE EXISTING CONNECTION: %s' % cache_key,
              host=self.host)
         return _winrm_cache[cache_key]
     transport_schemes = [('plaintext', 'https'),
                          ('plaintext', 'http')]  # FIXME: ssl/kerberos
     if port == 5985:
         transport_schemes = reversed(transport_schemes)
     exc = None
     for transport, scheme in transport_schemes:
         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)
         try:
             protocol.send_message('')
             _winrm_cache[cache_key] = protocol
             return protocol
         except WinRMTransportError, exc:
             err_msg = str(exc.args[0])
             if re.search(r'Operation\s+?timed\s+?out', err_msg, re.I):
                 raise errors.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"
                     )
                 elif code == 411:
                     _winrm_cache[cache_key] = protocol
                     return protocol
             vvvv('WINRM CONNECTION ERROR: %s' % err_msg, host=self.host)
             continue
Example #22
0
    def getRemoteConnection(self, timeout=4):
        '''
        create a remote connection
        :return: remote connection
        '''
        p = Protocol(endpoint='https://' + self.ip + ':5986/wsman',
                     transport='basic',
                     username=self.remoteAdminUser,
                     password=self.passwd,
                     server_cert_validation='ignore',
                     read_timeout_sec=timeout + 5,
                     operation_timeout_sec=timeout)
        shell_id = p.open_shell()

        return p, shell_id
Example #23
0
def check_creds(host, username, password, domain):
    has_access = False
    try:
        username = '******' % (domain, username)
        url = 'http://%s:5985/wsman' % host
        wsman = Protocol(endpoint=url,
                         transport='ntlm',
                         username=username,
                         password=password)
        shell_id = wsman.open_shell()
        wsman.close_shell(shell_id)
        has_access = True
    except:
        has_access = False
    return has_access
Example #24
0
def run_command(server_name, command_line):
    """
      Execute remote command and return the output.
      Remark: No handing of any kind of exeception. Kerberos ticket should be intiated.
      Args:
        server_name(string): Name of the host to connect.
        command_line(string): Command to execute.
      Returns:
        Standard output, Standard error, Status
  """
    host_name = "http://" + server_name + ":5985/wsman"
    win_connect = Protocol(endpoint=host_name, transport='kerberos')
    shell_id = win_connect.open_shell()
    command_id = win_connect.run_command(shell_id, command_line)
    return win_connect.get_command_output(shell_id, command_id)
def run_powershell_with_codepage_936(target, username, password, script):
    """
    run remote command with WinRM

    [Chinese characters are not displayed properly #288](https://github.com/diyan/pywinrm/issues/288)
    [Code Page Identifiers](https://docs.microsoft.com/en-us/windows/win32/intl/code-page-identifiers)

    codepage use 936, gb2312, ANSI/OEM Simplified Chinese (PRC, Singapore); Chinese Simplified (GB2312)

    :param target: hostname or ip address
    :type target: str
    :param username:
    :type username: str
    :param password:
    :type password: str
    :param script: powershell commands or scripts
    :type script: str | unicode
    :return: status_code, std_out
    :rtype: tuple
    """
    script = to_unicode_or_bust(script)
    encoded_ps = b64encode(script.encode('utf_16_le')).decode("ascii")

    p = Protocol(
        endpoint='http://{}:5985/wsman'.format(target),
        transport='ntlm',
        username=username,
        password=password,
        read_timeout_sec=10,
        operation_timeout_sec=5,
    )

    try:
        shell_id = p.open_shell(codepage=936)
    except requests.exceptions.ConnectionError as e:
        return 1, "requests failed.", str(e)

    try:
        command_id = p.run_command(shell_id, 'powershell.exe',
                                   ['-EncodedCommand', encoded_ps])
        try:
            std_out, std_err, status_code = p.get_command_output(
                shell_id, command_id)
        finally:
            p.cleanup_command(shell_id, command_id)
    finally:
        p.close_shell(shell_id)

    # print(std_out.decode('utf-8'))
    # print(std_err.decode('utf-8'))
    # print(status_code)

    return status_code, std_out, std_err
 def connect(self, host, username, password):
     client = Protocol(endpoint="http://{0}:5985/wsman".format(host),
                       transport="ntlm",
                       username=username,
                       password=password,
                       read_timeout_sec=30)
     return client
Example #27
0
def get_pywinrm_session(ip, port, username, password):
    '''Get an insecure pywinrm session.

    :params ip, username, password: Windows host's WinRM details.
    :param port: the port where the WinRM service is listening in host.
    '''
    transport_protocols = {
        'http': ('plaintext', 'http'),
        'https': ('ssl', 'https')
    }
    transport, protocol = transport_protocols['http' if port ==
                                              5985 else 'https']
    session = winrm.Session("%(protocol)s://%(ip)s:%(port)s/wsman" % {
        "ip": ip,
        "port": port,
        "protocol": protocol
    },
                            auth=(username, password),
                            transport=transport)
    session.protocol = Protocol(session.url,
                                transport=transport,
                                username=username,
                                password=password,
                                server_cert_validation='ignore')
    return session
Example #28
0
 def __init__(self, target, auth, transport='plaintext',
              timeout=None):
     username, password = auth
     self.url = self._build_url(target, transport)
     self.protocol = Protocol(self.url, transport=transport,
                              username=username, password=password,
                              timeout=timeout)
Example #29
0
    def _winrm_connect(self):
        '''
        Establish a WinRM connection over HTTP/HTTPS.
        '''
        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._connection_info.remote_user):
                continue

            if transport == 'kerberos':
                realm = self._connection_info.remote_user.split('@', 1)[1].strip() or None
            else:
                realm = None

            endpoint = parse.urlunsplit((scheme, netloc, '/wsman', '', ''))

            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 as exc:
                err_msg = str(exc)
                if re.search(r'Operation\s+?timed\s+?out', err_msg, re.I):
                    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 AnsibleError("the username/password specified for this server was incorrect")
                    elif code == 411:
                        return protocol
                self._display.vvvvv('WINRM CONNECTION ERROR: %s' % err_msg, host=self._connection_info.remote_addr)
                continue
        if exc:
            raise AnsibleError(str(exc))
Example #30
0
def main(computer, username, password, command):
    p = Protocol(endpoint='https://{}:5986/wsman'.format(computer),
                 transport='ntlm',
                 username=username,
                 password=password,
                 server_cert_validation='ignore')

    shell_id = p.open_shell()
    #command_id = p.run_command(shell_id, 'query', ['user'])
    command_id = p.run_command(shell_id, command, [])
    std_out, std_err, status_code = p.get_command_output(shell_id, command_id)
    p.cleanup_command(shell_id, command_id)
    p.close_shell(shell_id)
Example #31
0
def auto_ss():
    from winrm.protocol import Protocol

    p = Protocol(endpoint='http://172.30.200.149:5985/wsman',
                 transport='basic',
                 username=r'chry',
                 password='******',
                 server_cert_validation='ignore')
    shell_id = p.open_shell()
    command_id = p.run_command(shell_id, 'ipconfig', ['/all'])
    std_out, std_err, status_code = p.get_command_output(shell_id, command_id)
    p.cleanup_command(shell_id, command_id)
    p.close_shell(shell_id)
Example #32
0
def build_connection(host,
                     username='',
                     password='',
                     transport='ntlm',
                     useSSL=False):
    if (useSSL):
        p = Protocol(endpoint='https://' + host + ':5986/wsman',
                     username=username,
                     password=password,
                     transport=transport,
                     server_cert_validation='ignore')
    else:
        p = Protocol(endpoint='http://' + host + ':5985/wsman',
                     username=username,
                     password=password,
                     transport=transport)
    return p
Example #33
0
 def connect(self,host,username,password):
     client = Protocol(endpoint="http://{0}:5985/wsman".format(host),transport="ntlm",username=username,password=password,read_timeout_sec=30)
     try:
         smbclient.register_session(self.host, username=self.username, password=self.password, connection_timeout=30)
     except Exception as e:
         self.error = str(e)
         return None
     return client
Example #34
0
def test_set_timeout_as_sec():
    protocol = Protocol('endpoint',
                        username='******',
                        password='******',
                        read_timeout_sec='30',
                        operation_timeout_sec='29')
    assert protocol.read_timeout_sec == 30
    assert protocol.operation_timeout_sec == 29
Example #35
0
class Session(object):
    #TODO implement context manager methods
    def __init__(self, target, auth, transport='plaintext'):
        username, password = auth
        self.url = self._build_url(target, transport)
        self.protocol = Protocol(self.url, transport=transport, username=username, password=password)

    def run_cmd(self, command, args=()):
        #TODO optimize perf. Do not call open/close shell every time
        shell_id = self.protocol.open_shell()
        command_id = self.protocol.run_command(shell_id, command, args)
        rs = Response(self.protocol.get_command_output(shell_id, command_id))
        self.protocol.cleanup_command(shell_id, command_id)
        self.protocol.close_shell(shell_id)
        return rs

    @staticmethod
    def _build_url(target, transport):
        match = re.match(
            '(?i)^((?P<scheme>http[s]?)://)?(?P<host>[0-9a-z-_]+)(:(?P<port>\d+))?(?P<path>(/)?(wsman)?)?', target)
        scheme = match.group('scheme')
        if not scheme:
            scheme = 'https' if transport == 'ssl' else 'http'  # TODO do we have anything other than HTTP/HTTPS
        host = match.group('host')
        port = match.group('port')
        if not port:
            port = 5986 if transport == 'ssl' else 5985
        path = match.group('path')
        if not path:
            path = 'wsman'
        return '{0}://{1}:{2}/{3}'.format(scheme, host, port, path.lstrip('/'))
Example #36
0
def winrm_cmd(cmd):

    p = Protocol(endpoint='https://192.168.183.186:5986/wsman',
                 transport='basic',
                 username=r'Administrator',
                 password='******',
                 server_cert_validation='ignore')
    shell_id = p.open_shell()
    command_id = p.run_command(shell_id, cmd)
    std_out, std_err, status_code = p.get_command_output(shell_id, command_id)
    p.cleanup_command(shell_id, command_id)
    p.close_shell(shell_id)

    return std_out
Example #37
0
 def _winrm_connect(self):
     '''
     Establish a WinRM connection over HTTP/HTTPS.
     '''
     if _winrm_hacks:
         port = _winrm_hacks.get_port(self)
     else:
         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)
     cache_key = '%s:%s@%s:%d' % (self.user, hashlib.md5(self.password).hexdigest(), self.host, port)
     if cache_key in _winrm_cache:
         vvvv('WINRM REUSE EXISTING CONNECTION: %s' % cache_key, host=self.host)
         return _winrm_cache[cache_key]
     transport_schemes = [('plaintext', 'https'), ('plaintext', 'http')] # FIXME: ssl/kerberos
     if port == 5985:
         transport_schemes = reversed(transport_schemes)
     exc = None
     for transport, scheme in transport_schemes:
         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)
         try:
             protocol.send_message('')
             _winrm_cache[cache_key] = protocol
             return protocol
         except WinRMTransportError, exc:
             err_msg = str(exc.args[0])
             if re.search(r'Operation\s+?timed\s+?out', err_msg, re.I):
                 raise
             m = re.search(r'Code\s+?(\d{3})', err_msg)
             if m:
                 code = int(m.groups()[0])
                 if code == 411:
                     _winrm_cache[cache_key] = protocol
                     return protocol
             vvvv('WINRM CONNECTION ERROR: %s' % err_msg, host=self.host)
             continue
Example #38
0
    def _winrm_connect(self):
        '''
        Establish a WinRM connection over HTTP/HTTPS.
        '''
        display.vvv("ESTABLISH WINRM CONNECTION FOR USER: %s on PORT %s TO %s" %
            (self._winrm_user, self._winrm_port, self._winrm_host), host=self._winrm_host)
        netloc = '%s:%d' % (self._winrm_host, self._winrm_port)
        endpoint = urlunsplit((self._winrm_scheme, netloc, self._winrm_path, '', ''))
        errors = []
        for transport in self._winrm_transport:
            if transport == 'kerberos' and not HAVE_KERBEROS:
                errors.append('kerberos: the python kerberos library is not installed')
                continue
            display.vvvvv('WINRM CONNECT: transport=%s endpoint=%s' % (transport, endpoint), host=self._winrm_host)
            try:
                protocol = Protocol(endpoint, transport=transport, **self._winrm_kwargs)
                # send keepalive message to ensure we're awake
                # TODO: is this necessary?
                # protocol.send_message(xmltodict.unparse(rq))
                if not self.shell_id:
                    self.shell_id = protocol.open_shell(codepage=65001) # UTF-8
                    display.vvvvv('WINRM OPEN SHELL: %s' % self.shell_id, host=self._winrm_host)

                return protocol
            except Exception as e:
                err_msg = to_unicode(e).strip()
                if re.search(to_unicode(r'Operation\s+?timed\s+?out'), err_msg, re.I):
                    raise AnsibleError('the connection attempt timed out')
                m = re.search(to_unicode(r'Code\s+?(\d{3})'), err_msg)
                if m:
                    code = int(m.groups()[0])
                    if code == 401:
                        err_msg = 'the username/password specified for this server was incorrect'
                    elif code == 411:
                        return protocol
                errors.append(u'%s: %s' % (transport, err_msg))
                display.vvvvv(u'WINRM CONNECTION ERROR: %s\n%s' % (err_msg, to_unicode(traceback.format_exc())), host=self._winrm_host)
        if errors:
            raise AnsibleConnectionFailure(', '.join(map(to_str, errors)))
        else:
            raise AnsibleError('No transport found for WinRM connection')
Example #39
0
def protocol_fake(request):
    uuid4_patcher = patch('uuid.uuid4')
    uuid4_mock = uuid4_patcher.start()
    uuid4_mock.return_value = uuid.UUID(
        '11111111-1111-1111-1111-111111111111')

    from winrm.protocol import Protocol

    protocol_fake = Protocol(
        endpoint='http://windows-host:5985/wsman',
        transport='plaintext',
        username='******',
        password='******')

    protocol_fake.transport = TransportStub()

    def uuid4_patch_stop():
        uuid4_patcher.stop()

    request.addfinalizer(uuid4_patch_stop)
    return protocol_fake
 def _try_winrm(self, node):
     ip = node.private_ips[0]
     p = Protocol(
             endpoint='http://%s:5985/wsman' % ip,  # RFC 2732
             transport='ntlm',
             username=self.username,
             password=self.secret,
             server_cert_validation='ignore')
     shell_id = p.open_shell()
     command_id = p.run_command(shell_id, 'ipconfig', ['/all'])
     std_out, std_err, status_code = p.get_command_output(shell_id, command_id)
     p.cleanup_command(shell_id, command_id)
     p.close_shell(shell_id)
     return std_out
Example #41
0
 def run(self, host, password, username='******',
         port=5732, secure=True):
     proto = 'https' if secure else 'http'
     p = Protocol(
         endpoint='%s://%s:%i/wsman' % (proto, host, port),  # RFC 2732?
         transport='ntlm',
         username=username,
         password=password,
         server_cert_validation='ignore')
     shell_id = p.open_shell()
     command_id = p.run_command(shell_id, 'ipconfig', ['/all'])
     std_out, std_err, status_code = p.get_command_output(shell_id,
                                                          command_id)
     p.cleanup_command(shell_id, command_id)
     p.close_shell(shell_id)
     return {'stdout': std_out, 'stderr': std_err}
Example #42
0
class Session(object):
    #TODO implement context manager methods
    def __init__(self, url, auth, transport = "plaintext"):
        #TODO convert short urls into well-formed endpoint
        self.protocol = Protocol(url, auth, transport)

    def run_cmd(self, command, args=()):
        #TODO optimize perf. Do not call open/close shell every time
        shell_id = self.protocol.open_shell()
        command_id = self.protocol.run_command(shell_id, command, args)
        rs = Response(self.protocol.get_command_output(shell_id, command_id))
        self.protocol.cleanup_command(shell_id, command_id)
        self.protocol.close_shell(shell_id)
        return rs
Example #43
0
    def connect(self, username=None, password=None):
        """
        Attempts to connect to a remote server via WinRM.

        @param username: Username to be used for the WinRM connection
        @type username: string
        @param password: Password to be used for the WinRM connection
        @type password: string
        """

        endpoint = "http://{host}:5985/wsman".format(host=self.host)

        try:
            self.connection = Protocol(endpoint=endpoint, username=username, password=password)
        # Doing a wide catch as the exception handling in WinRM is not
        # very thorough or specific
        except Exception as exception:
            self._log(exception.message)
        else:
            self.shell_id = self.connection.open_shell()
    def _winrm_commands(self, node, commands):
        ip = node.private_ips[0]
        p = Protocol(
                endpoint='http://%s:5985/wsman' % ip,  # RFC 2732
                transport='ntlm',
                username=self.username,
                password=self.secret,
                server_cert_validation='ignore')
        shell_id = p.open_shell()
        std_out_logs = []
        std_err_logs = []

        # run the commands in sequence.
        for command, params in commands:
            command_id = p.run_command(shell_id, command, params)
            std_out, std_err, status_code = p.get_command_output(shell_id, command_id)
            std_out_logs.append(std_out)
            std_err_logs.append(std_err)
            p.cleanup_command(shell_id, command_id)

        p.close_shell(shell_id)
        return std_out_logs, std_err_logs
Example #45
0
class BaseWinRMClient(BaseClient):
    def __init__(self, host=None):
        """
        Initialization

        @param host: IP address or host name to connect to
        @type host: string
        """
        self.host = host
        self.connection = None
        self.shell_id = None

    def connect(self, username=None, password=None):
        """
        Attempts to connect to a remote server via WinRM.

        @param username: Username to be used for the WinRM connection
        @type username: string
        @param password: Password to be used for the WinRM connection
        @type password: string
        """

        endpoint = "http://{host}:5985/wsman".format(host=self.host)

        try:
            self.connection = Protocol(endpoint=endpoint, username=username, password=password)
        # Doing a wide catch as the exception handling in WinRM is not
        # very thorough or specific
        except Exception as exception:
            self._log(exception.message)
        else:
            self.shell_id = self.connection.open_shell()

    def is_connected(self):
        """
        Checks to see if a WinRM connection exists.

        @rtype: bool
        """

        return self.connection is not None and self.shell_id is not None

    def _format_response(self, std_out=None, std_err=None, status_code=None):
        """
        Converts the executed command responses into an object.

        @param std_out: The stdout result
        @type std_out: string
        @param std_err: The stderr result
        @type std_err: string
        @param status_code: The status code of the executed command
        @type status_code: int
        @rtype: WinRMResponse
        """
        response = WinRMResponse(std_out=std_out, std_err=std_err, status_code=status_code)
        return response

    def execute_command(self, command=None, args=None):
        """
        Executes a command via remote shell.

        @param command: The command to execute
        @type command: string
        @param args: A list of arguments to pass to the command
        @type args: list of strings
        @return: Result of command execution
        @rtype: WinRMResponse
        """

        if not self.is_connected():
            message = "Not currently connected to {host}.".format(host=self.host)
            self._log.error(message)
            raise Exception(message)

        if args is None:
            args = []

        self._log.debug("Executing command: {command} {args}".format(command=command, args=" ".join(args)))
        command_id = self.connection.run_command(self.shell_id, command, args)
        std_out, std_err, status_code = self.connection.get_command_output(self.shell_id, command_id)
        response = self._format_response(std_out=std_out, std_err=std_err, status_code=status_code)
        self._log.debug("Stdout: {std_out}".format(std_out=response.std_out))
        self._log.debug("Stderr: {std_err}".format(std_err=response.std_err))
        self._log.debug("Status code: {status_code}".format(status_code=response.status_code))
        return response
Example #46
0
class Session(object):
    # TODO implement context manager methods
    def __init__(self, target, auth, transport='plaintext'):
        username, password = auth
        self.url = self._build_url(target, transport)
        self.protocol = Protocol(self.url, transport=transport,
                                 username=username, password=password)

    def run_cmd(self, command, args=()):
        # TODO optimize perf. Do not call open/close shell every time
        shell_id = self.protocol.open_shell()
        command_id = self.protocol.run_command(shell_id, command, args)
        rs = Response(self.protocol.get_command_output(shell_id, command_id))
        self.protocol.cleanup_command(shell_id, command_id)
        self.protocol.close_shell(shell_id)
        return rs

    def run_ps_long(self, script):
        """base64 encodes a Powershell script and executes the powershell
        encoded script command
        """

        shell_id = self.protocol.open_shell()

        def run_command(command):
            command_id = self.protocol.run_command(shell_id, command)
            rs = Response(self.protocol.get_command_output(shell_id, command_id))
            self.protocol.cleanup_command(shell_id, command_id)

            # Powershell errors are returned in XML, clean them up
            if len(rs.std_err):
                rs.std_err = self.clean_error_msg(rs.std_err)
            return rs

        def make_ps_command(ps_script):
            return ("powershell -encodedcommand %s"
                        % base64.b64encode(ps_script.encode("utf_16_le")))

        def run_and_check_ps(command, stage_message):
            rs = run_command(command)
            if len(rs.std_err) or rs.status_code != 0:
                self.protocol.close_shell(shell_id)
                raise Exception("%s\n%s" % (stage_message, rs.std_err))
            return rs.std_out

        # Get the name of a temp file
        cmd = ("$script_file = [IO.Path]::GetTempFileName() | "
                    " Rename-Item -NewName { $_ -replace 'tmp$', 'tmp.ps1' } -PassThru\n"
               '"$script_file"')
        script_file = run_and_check_ps(make_ps_command(cmd), "Creating temp script file")
        script_file = script_file.strip()

        # Append the data to the file
        base64_script = base64.b64encode(script)
        chunk_size = 2000
        for chunk_index in range(0, len(base64_script), chunk_size):
            chunk = base64_script[chunk_index:chunk_index + chunk_size]
            cmd ='ECHO %s %s "%s" ' % (chunk,
                                    ('>>' if chunk_index else '>'),
                                    script_file)
            run_and_check_ps(cmd, "writing chunk %s to temp script file" % chunk_index)

        # Execute the powershell script
        cmd = '''
            # Convert it from b64 encoded
            $b64 = get-content "%(script_file)s"
            [System.Text.Encoding]::ASCII.GetString([System.Convert]::FromBase64String($b64)) |
                out-file -Encoding Default "%(script_file)s"
        ''' % {'script_file':script_file}
        run_and_check_ps(make_ps_command(cmd),
                         "Converting temp script file back from b64 encoding")

        cmd = ("""PowerShell.exe -ExecutionPolicy Bypass -Command "& '%s' " """
                    % script_file)
        rs = run_command(cmd)

        # Finally, cleanup the temp file
        cmd = "remove-item '%s' " % script_file
        run_and_check_ps(make_ps_command(cmd), "Deleting temp script file")

        self.protocol.close_shell(shell_id)

        return rs


    def run_ps(self, script):
        # Get a temp powershell file name

        # TODO optimize perf. Do not call open/close shell every time
        shell_id = self.protocol.open_shell()

        base64_script = base64.b64encode(script.encode("utf_16_le"))

        # There is an issue with powershell scripts over 2k or 8k (platform dependent)
        # You can not have a command line + argument longer than this
        if len(base64_script) > 2000:
            return self.run_ps_long(script)

        # must use utf16 little endian on windows
        rs = self.run_cmd("powershell -encodedcommand %s" % (base64_script))
        if len(rs.std_err):
            # Clean it it up and make it human readable
            rs.std_err = self.clean_error_msg(rs.std_err)
        return rs


    def clean_error_msg(self, msg):
        """converts a Powershell CLIXML message to a more human readable string
        """

        # if the msg does not start with this, return it as is
        if msg.startswith("#< CLIXML\r\n"):
            # for proper xml, we need to remove the CLIXML part
            # (the first line)
            msg_xml = msg[11:]
            try:
                # remove the namespaces from the xml for easier processing
                msg_xml = self.strip_namespace(msg_xml)
                root = ET.fromstring(msg_xml)
                # the S node is the error message, find all S nodes
                nodes = root.findall("./S")
                new_msg = ""
                for s in nodes:
                    # append error msg string to result, also
                    # the hex chars represent CRLF so we replace with newline
                    new_msg += s.text.replace("_x000D__x000A_", "\n")
            except Exception as e:
                # if any of the above fails, the msg was not true xml
                # print a warning and return the orignal string
                print("Warning: there was a problem converting the Powershell"
                      " error message: %s" % (e))
            else:
                # if new_msg was populated, that's our error message
                # otherwise the original error message will be used
                if len(new_msg):
                    # remove leading and trailing whitespace while we are here
                    msg = new_msg.strip()
        return msg

    def strip_namespace(self, xml):
        """strips any namespaces from an xml string"""
        try:
            p = re.compile("xmlns=*[\"\"][^\"\"]*[\"\"]")
            allmatches = p.finditer(xml)
            for match in allmatches:
                xml = xml.replace(match.group(), "")
            return xml
        except Exception as e:
            raise Exception(e)

    @staticmethod
    def _build_url(target, transport):
        match = re.match(
            '(?i)^((?P<scheme>http[s]?)://)?(?P<host>[0-9a-z-_.]+)(:(?P<port>\d+))?(?P<path>(/)?(wsman)?)?', target)  # NOQA
        scheme = match.group('scheme')
        if not scheme:
            # TODO do we have anything other than HTTP/HTTPS
            scheme = 'https' if transport == 'ssl' else 'http'
        host = match.group('host')
        port = match.group('port')
        if not port:
            port = 5986 if transport == 'ssl' else 5985
        path = match.group('path')
        if not path:
            path = 'wsman'
        return '{0}://{1}:{2}/{3}'.format(scheme, host, port, path.lstrip('/'))
Example #47
0
 def __init__(self, url, auth):
     #TODO convert short urls into well-formed endpoint
     username, password = auth
     self.protocol = Protocol(url, username=username, password=password)
# Run a process on a remote host
s = winrm.Session('windows-host.example.com', auth=('john.smith', 'secret'))
r = s.run_cmd('ipconfig', ['/all'])
print r.status_code, r.std_out,

# Run Powershell script on remote host
ps_script = """$strComputer = $Host
Clear
$RAM = WmiObject Win32_ComputerSystem
$MB = 1048576

"Installed Memory: " + [int]($RAM.TotalPhysicalMemory /$MB) + " MB" """
r = s.run_ps(ps_script)
print r.status_code, r.std_out,

# Run process with low-level API with domain user, disabling HTTPS cert validation
from winrm.protocol import Protocol

p = Protocol(
    endpoint='https://windows-host:5986/wsman',
    transport='ntlm',
    username=r'somedomain\someuser',
    password='******',
    server_cert_validation='ignore')
shell_id = p.open_shell()
command_id = p.run_command(shell_id, 'ipconfig', ['/all'])
std_out, std_err, status_code = p.get_command_output(shell_id, command_id)
p.cleanup_command(shell_id, command_id)
p.close_shell(shell_id)
Example #49
0
class Session(object):
    # TODO implement context manager methods
    def __init__(self, target, auth, transport='plaintext',
                 timeout=None):
        username, password = auth
        self.url = self._build_url(target, transport)
        self.protocol = Protocol(self.url, transport=transport,
                                 username=username, password=password,
                                 timeout=timeout)

    def run_cmd(self, command, args=()):
        # TODO optimize perf. Do not call open/close shell every time
        shell_id = self.protocol.open_shell()
        command_id = self.protocol.run_command(shell_id, command, args)
        rs = Response(self.protocol.get_command_output(shell_id, command_id))
        self.protocol.cleanup_command(shell_id, command_id)
        self.protocol.close_shell(shell_id)
        return rs

    def run_ps(self, script):
        """base64 encodes a Powershell script and executes the powershell
        encoded script command
        """
        # must use utf16 little endian on windows
        encoded_ps = b64encode(script.encode('utf_16_le')).decode('ascii')
        rs = self.run_cmd('powershell -encodedcommand {0}'.format(encoded_ps))
        if len(rs.std_err):
            # if there was an error message, clean it it up and make it human
            # readable
            rs.std_err = self._clean_error_msg(rs.std_err)
        return rs

    def _clean_error_msg(self, msg):
        """converts a Powershell CLIXML message to a more human readable string
        """
        # TODO prepare unit test, beautify code
        # if the msg does not start with this, return it as is
        if msg.startswith("#< CLIXML\r\n"):
            # for proper xml, we need to remove the CLIXML part
            # (the first line)
            msg_xml = msg[11:]
            try:
                # remove the namespaces from the xml for easier processing
                msg_xml = self._strip_namespace(msg_xml)
                root = ET.fromstring(msg_xml)
                # the S node is the error message, find all S nodes
                nodes = root.findall("./S")
                new_msg = ""
                for s in nodes:
                    # append error msg string to result, also
                    # the hex chars represent CRLF so we replace with newline
                    new_msg += s.text.replace("_x000D__x000A_", "\n")
            except Exception as e:
                # if any of the above fails, the msg was not true xml
                # print a warning and return the orignal string
                # TODO do not print, raise user defined error instead
                print("Warning: there was a problem converting the Powershell"
                      " error message: %s" % (e))
            else:
                # if new_msg was populated, that's our error message
                # otherwise the original error message will be used
                if len(new_msg):
                    # remove leading and trailing whitespace while we are here
                    msg = new_msg.strip()
        return msg

    def _strip_namespace(self, xml):
        """strips any namespaces from an xml string"""
        try:
            p = re.compile("xmlns=*[\"\"][^\"\"]*[\"\"]")
            allmatches = p.finditer(xml)
            for match in allmatches:
                xml = xml.replace(match.group(), "")
            return xml
        except Exception as e:
            raise Exception(e)

    @staticmethod
    def _build_url(target, transport):
        match = re.match(
            '(?i)^((?P<scheme>http[s]?)://)?(?P<host>[0-9a-z-_.]+)(:(?P<port>\d+))?(?P<path>(/)?(wsman)?)?', target)  # NOQA
        scheme = match.group('scheme')
        if not scheme:
            # TODO do we have anything other than HTTP/HTTPS
            scheme = 'https' if transport == 'ssl' else 'http'
        host = match.group('host')
        port = match.group('port')
        if not port:
            port = 5986 if transport == 'ssl' else 5985
        path = match.group('path')
        if not path:
            path = 'wsman'
        return '{0}://{1}:{2}/{3}'.format(scheme, host, port, path.lstrip('/'))
Example #50
0
 def __init__(self, url, auth, transport = "plaintext"):
     #TODO convert short urls into well-formed endpoint
     self.protocol = Protocol(url, auth, transport)
Example #51
0
class WinRMHook(BaseHook):
    """
    Hook for winrm remote execution using pywinrm.

    :seealso: https://github.com/diyan/pywinrm/blob/master/winrm/protocol.py

    :param ssh_conn_id: connection id from airflow Connections from where
        all the required parameters can be fetched like username and password.
        Thought the priority is given to the param passed during init
    :type ssh_conn_id: str
    :param endpoint: When not set, endpoint will be constructed like this:
        'http://{remote_host}:{remote_port}/wsman'
    :type endpoint: str
    :param remote_host: Remote host to connect to. Ignored if `endpoint` is set.
    :type remote_host: str
    :param remote_port: Remote port to connect to. Ignored if `endpoint` is set.
    :type remote_port: int
    :param transport: transport type, one of 'plaintext' (default), 'kerberos', 'ssl', 'ntlm', 'credssp'
    :type transport: str
    :param username: username to connect to the remote_host
    :type username: str
    :param password: password of the username to connect to the remote_host
    :type password: str
    :param service: the service name, default is HTTP
    :type service: str
    :param keytab: the path to a keytab file if you are using one
    :type keytab: str
    :param ca_trust_path: Certification Authority trust path
    :type ca_trust_path: str
    :param cert_pem: client authentication certificate file path in PEM format
    :type cert_pem: str
    :param cert_key_pem: client authentication certificate key file path in PEM format
    :type cert_key_pem: str
    :param server_cert_validation: whether server certificate should be validated on
        Python versions that support it; one of 'validate' (default), 'ignore'
    :type server_cert_validation: str
    :param kerberos_delegation: if True, TGT is sent to target server to
        allow multiple hops
    :type kerberos_delegation: bool
    :param read_timeout_sec: maximum seconds to wait before an HTTP connect/read times out (default 30).
        This value should be slightly higher than operation_timeout_sec,
        as the server can block *at least* that long.
    :type read_timeout_sec: int
    :param operation_timeout_sec: maximum allowed time in seconds for any single wsman
        HTTP operation (default 20). Note that operation timeouts while receiving output
        (the only wsman operation that should take any significant time,
        and where these timeouts are expected) will be silently retried indefinitely.
    :type operation_timeout_sec: int
    :param kerberos_hostname_override: the hostname to use for the kerberos exchange
        (defaults to the hostname in the endpoint URL)
    :type kerberos_hostname_override: str
    :param message_encryption: Will encrypt the WinRM messages if set
        and the transport auth supports message encryption. (Default 'auto')
    :type message_encryption: str
    :param credssp_disable_tlsv1_2: Whether to disable TLSv1.2 support and work with older
        protocols like TLSv1.0, default is False
    :type credssp_disable_tlsv1_2: bool
    :param send_cbt: Will send the channel bindings over a HTTPS channel (Default: True)
    :type send_cbt: bool
    """

    def __init__(self,
                 ssh_conn_id=None,
                 endpoint=None,
                 remote_host=None,
                 remote_port=5985,
                 transport='plaintext',
                 username=None,
                 password=None,
                 service='HTTP',
                 keytab=None,
                 ca_trust_path=None,
                 cert_pem=None,
                 cert_key_pem=None,
                 server_cert_validation='validate',
                 kerberos_delegation=False,
                 read_timeout_sec=30,
                 operation_timeout_sec=20,
                 kerberos_hostname_override=None,
                 message_encryption='auto',
                 credssp_disable_tlsv1_2=False,
                 send_cbt=True):
        super(WinRMHook, self).__init__(ssh_conn_id)
        self.ssh_conn_id = ssh_conn_id
        self.endpoint = endpoint
        self.remote_host = remote_host
        self.remote_port = remote_port
        self.transport = transport
        self.username = username
        self.password = password
        self.service = service
        self.keytab = keytab
        self.ca_trust_path = ca_trust_path
        self.cert_pem = cert_pem
        self.cert_key_pem = cert_key_pem
        self.server_cert_validation = server_cert_validation
        self.kerberos_delegation = kerberos_delegation
        self.read_timeout_sec = read_timeout_sec
        self.operation_timeout_sec = operation_timeout_sec
        self.kerberos_hostname_override = kerberos_hostname_override
        self.message_encryption = message_encryption
        self.credssp_disable_tlsv1_2 = credssp_disable_tlsv1_2
        self.send_cbt = send_cbt

        self.client = None
        self.winrm_protocol = None

    def get_conn(self):
        if self.client:
            return self.client

        self.log.debug('Creating WinRM client for conn_id: %s', self.ssh_conn_id)
        if self.ssh_conn_id is not None:
            conn = self.get_connection(self.ssh_conn_id)

            if self.username is None:
                self.username = conn.login
            if self.password is None:
                self.password = conn.password
            if self.remote_host is None:
                self.remote_host = conn.host

            if conn.extra is not None:
                extra_options = conn.extra_dejson

                if "endpoint" in extra_options:
                    self.endpoint = str(extra_options["endpoint"])
                if "remote_port" in extra_options:
                    self.remote_port = int(extra_options["remote_port"])
                if "transport" in extra_options:
                    self.transport = str(extra_options["transport"])
                if "service" in extra_options:
                    self.service = str(extra_options["service"])
                if "keytab" in extra_options:
                    self.keytab = str(extra_options["keytab"])
                if "ca_trust_path" in extra_options:
                    self.ca_trust_path = str(extra_options["ca_trust_path"])
                if "cert_pem" in extra_options:
                    self.cert_pem = str(extra_options["cert_pem"])
                if "cert_key_pem" in extra_options:
                    self.cert_key_pem = str(extra_options["cert_key_pem"])
                if "server_cert_validation" in extra_options:
                    self.server_cert_validation = str(extra_options["server_cert_validation"])
                if "kerberos_delegation" in extra_options:
                    self.kerberos_delegation = str(extra_options["kerberos_delegation"]).lower() == 'true'
                if "read_timeout_sec" in extra_options:
                    self.read_timeout_sec = int(extra_options["read_timeout_sec"])
                if "operation_timeout_sec" in extra_options:
                    self.operation_timeout_sec = int(extra_options["operation_timeout_sec"])
                if "kerberos_hostname_override" in extra_options:
                    self.kerberos_hostname_override = str(extra_options["kerberos_hostname_override"])
                if "message_encryption" in extra_options:
                    self.message_encryption = str(extra_options["message_encryption"])
                if "credssp_disable_tlsv1_2" in extra_options:
                    self.credssp_disable_tlsv1_2 = \
                        str(extra_options["credssp_disable_tlsv1_2"]).lower() == 'true'
                if "send_cbt" in extra_options:
                    self.send_cbt = str(extra_options["send_cbt"]).lower() == 'true'

        if not self.remote_host:
            raise AirflowException("Missing required param: remote_host")

        # Auto detecting username values from system
        if not self.username:
            self.log.debug(
                "username to WinRM to host: %s is not specified for connection id"
                " %s. Using system's default provided by getpass.getuser()",
                self.remote_host, self.ssh_conn_id
            )
            self.username = getpass.getuser()

        # If endpoint is not set, then build a standard wsman endpoint from host and port.
        if not self.endpoint:
            self.endpoint = 'http://{0}:{1}/wsman'.format(self.remote_host, self.remote_port)

        try:
            if self.password and self.password.strip():
                self.winrm_protocol = Protocol(
                    endpoint=self.endpoint,
                    transport=self.transport,
                    username=self.username,
                    password=self.password,
                    service=self.service,
                    keytab=self.keytab,
                    ca_trust_path=self.ca_trust_path,
                    cert_pem=self.cert_pem,
                    cert_key_pem=self.cert_key_pem,
                    server_cert_validation=self.server_cert_validation,
                    kerberos_delegation=self.kerberos_delegation,
                    read_timeout_sec=self.read_timeout_sec,
                    operation_timeout_sec=self.operation_timeout_sec,
                    kerberos_hostname_override=self.kerberos_hostname_override,
                    message_encryption=self.message_encryption,
                    credssp_disable_tlsv1_2=self.credssp_disable_tlsv1_2,
                    send_cbt=self.send_cbt
                )

            self.log.info("Establishing WinRM connection to host: %s", self.remote_host)
            self.client = self.winrm_protocol.open_shell()

        except Exception as error:
            error_msg = "Error connecting to host: {0}, error: {1}".format(self.remote_host, error)
            self.log.error(error_msg)
            raise AirflowException(error_msg)

        return self.client
Example #52
0
class WinRMHook(BaseHook, LoggingMixin):

    """
    Hook for winrm remote execution using pywinrm.

    :param ssh_conn_id: connection id from airflow Connections from where all
        the required parameters can be fetched like username, password or key_file.
        Thought the priority is given to the param passed during init
    :type ssh_conn_id: str
    :param remote_host: remote host to connect
    :type remote_host: str
    :param username: username to connect to the remote_host
    :type username: str
    :param password: password of the username to connect to the remote_host
    :type password: str
    :param key_file: key file to use to connect to the remote_host.
    :type key_file: str
    :param timeout: timeout for the attempt to connect to the remote_host.
    :type timeout: int
    :param keepalive_interval: send a keepalive packet to remote host
        every keepalive_interval seconds
    :type keepalive_interval: int
    """

    def __init__(self,
                 ssh_conn_id=None,
                 remote_host=None,
                 username=None,
                 password=None,
                 key_file=None,
                 timeout=10,
                 keepalive_interval=30
                 ):
        super(WinRMHook, self).__init__(ssh_conn_id)
        # TODO make new win rm connection class
        self.ssh_conn_id = ssh_conn_id
        self.remote_host = remote_host
        self.username = username
        self.password = password
        self.key_file = key_file
        self.timeout = timeout
        self.keepalive_interval = keepalive_interval
        # Default values, overridable from Connection
        self.compress = True
        self.no_host_key_check = True
        self.client = None
        self.winrm_protocol = None

    def get_conn(self):
        if not self.client:
            self.log.debug('Creating WinRM client for conn_id: %s', self.ssh_conn_id)
            if self.ssh_conn_id is not None:
                conn = self.get_connection(self.ssh_conn_id)
                if self.username is None:
                    self.username = conn.login
                if self.password is None:
                    self.password = conn.password
                if self.remote_host is None:
                    self.remote_host = conn.host
                if conn.extra is not None:
                    extra_options = conn.extra_dejson
                    self.key_file = extra_options.get("key_file")

                    if "timeout" in extra_options:
                        self.timeout = int(extra_options["timeout"], 10)

                    if "compress" in extra_options \
                            and extra_options["compress"].lower() == 'false':
                        self.compress = False
                    if "no_host_key_check" in extra_options \
                            and extra_options["no_host_key_check"].lower() == 'false':
                        self.no_host_key_check = False

            if not self.remote_host:
                raise AirflowException("Missing required param: remote_host")

            # Auto detecting username values from system
            if not self.username:
                self.log.debug(
                    "username to ssh to host: %s is not specified for connection id"
                    " %s. Using system's default provided by getpass.getuser()",
                    self.remote_host, self.ssh_conn_id
                )
                self.username = getpass.getuser()

            try:

                if self.password and self.password.strip():
                    self.winrm_protocol = Protocol(
                        # TODO pass in port from ssh conn
                        endpoint='http://' + self.remote_host + ':5985/wsman',
                        # TODO get cert transport working
                        # transport='certificate',
                        transport='plaintext',
                        # cert_pem=r'publickey.pem',
                        # cert_key_pem=r'dev.pem',
                        read_timeout_sec=70,
                        operation_timeout_sec=60,
                        username=self.username,
                        password=self.password,
                        server_cert_validation='ignore')

                self.log.info("Opening WinRM shell")
                self.client = self.winrm_protocol.open_shell()

            except Exception as error:
                self.log.error(
                    "Error connecting to host: %s, error: %s",
                    self.remote_host, error
                )
        return self.client
Example #53
0
    def get_conn(self):
        if not self.client:
            self.log.debug('Creating WinRM client for conn_id: %s', self.ssh_conn_id)
            if self.ssh_conn_id is not None:
                conn = self.get_connection(self.ssh_conn_id)
                if self.username is None:
                    self.username = conn.login
                if self.password is None:
                    self.password = conn.password
                if self.remote_host is None:
                    self.remote_host = conn.host
                if conn.extra is not None:
                    extra_options = conn.extra_dejson
                    self.key_file = extra_options.get("key_file")

                    if "timeout" in extra_options:
                        self.timeout = int(extra_options["timeout"], 10)

                    if "compress" in extra_options \
                            and extra_options["compress"].lower() == 'false':
                        self.compress = False
                    if "no_host_key_check" in extra_options \
                            and extra_options["no_host_key_check"].lower() == 'false':
                        self.no_host_key_check = False

            if not self.remote_host:
                raise AirflowException("Missing required param: remote_host")

            # Auto detecting username values from system
            if not self.username:
                self.log.debug(
                    "username to ssh to host: %s is not specified for connection id"
                    " %s. Using system's default provided by getpass.getuser()",
                    self.remote_host, self.ssh_conn_id
                )
                self.username = getpass.getuser()

            try:

                if self.password and self.password.strip():
                    self.winrm_protocol = Protocol(
                        # TODO pass in port from ssh conn
                        endpoint='http://' + self.remote_host + ':5985/wsman',
                        # TODO get cert transport working
                        # transport='certificate',
                        transport='plaintext',
                        # cert_pem=r'publickey.pem',
                        # cert_key_pem=r'dev.pem',
                        read_timeout_sec=70,
                        operation_timeout_sec=60,
                        username=self.username,
                        password=self.password,
                        server_cert_validation='ignore')

                self.log.info("Opening WinRM shell")
                self.client = self.winrm_protocol.open_shell()

            except Exception as error:
                self.log.error(
                    "Error connecting to host: %s, error: %s",
                    self.remote_host, error
                )
        return self.client
Example #54
0
 def __init__(self, target, auth, **kwargs):
     username, password = auth
     self.url = self._build_url(target, kwargs.get('transport', 'plaintext'))
     self.protocol = Protocol(self.url,
                              username=username, password=password, **kwargs)
Example #55
0
    def get_conn(self):
        if self.client:
            return self.client

        self.log.debug('Creating WinRM client for conn_id: %s', self.ssh_conn_id)
        if self.ssh_conn_id is not None:
            conn = self.get_connection(self.ssh_conn_id)

            if self.username is None:
                self.username = conn.login
            if self.password is None:
                self.password = conn.password
            if self.remote_host is None:
                self.remote_host = conn.host

            if conn.extra is not None:
                extra_options = conn.extra_dejson

                if "endpoint" in extra_options:
                    self.endpoint = str(extra_options["endpoint"])
                if "remote_port" in extra_options:
                    self.remote_port = int(extra_options["remote_port"])
                if "transport" in extra_options:
                    self.transport = str(extra_options["transport"])
                if "service" in extra_options:
                    self.service = str(extra_options["service"])
                if "keytab" in extra_options:
                    self.keytab = str(extra_options["keytab"])
                if "ca_trust_path" in extra_options:
                    self.ca_trust_path = str(extra_options["ca_trust_path"])
                if "cert_pem" in extra_options:
                    self.cert_pem = str(extra_options["cert_pem"])
                if "cert_key_pem" in extra_options:
                    self.cert_key_pem = str(extra_options["cert_key_pem"])
                if "server_cert_validation" in extra_options:
                    self.server_cert_validation = str(extra_options["server_cert_validation"])
                if "kerberos_delegation" in extra_options:
                    self.kerberos_delegation = str(extra_options["kerberos_delegation"]).lower() == 'true'
                if "read_timeout_sec" in extra_options:
                    self.read_timeout_sec = int(extra_options["read_timeout_sec"])
                if "operation_timeout_sec" in extra_options:
                    self.operation_timeout_sec = int(extra_options["operation_timeout_sec"])
                if "kerberos_hostname_override" in extra_options:
                    self.kerberos_hostname_override = str(extra_options["kerberos_hostname_override"])
                if "message_encryption" in extra_options:
                    self.message_encryption = str(extra_options["message_encryption"])
                if "credssp_disable_tlsv1_2" in extra_options:
                    self.credssp_disable_tlsv1_2 = \
                        str(extra_options["credssp_disable_tlsv1_2"]).lower() == 'true'
                if "send_cbt" in extra_options:
                    self.send_cbt = str(extra_options["send_cbt"]).lower() == 'true'

        if not self.remote_host:
            raise AirflowException("Missing required param: remote_host")

        # Auto detecting username values from system
        if not self.username:
            self.log.debug(
                "username to WinRM to host: %s is not specified for connection id"
                " %s. Using system's default provided by getpass.getuser()",
                self.remote_host, self.ssh_conn_id
            )
            self.username = getpass.getuser()

        # If endpoint is not set, then build a standard wsman endpoint from host and port.
        if not self.endpoint:
            self.endpoint = 'http://{0}:{1}/wsman'.format(self.remote_host, self.remote_port)

        try:
            if self.password and self.password.strip():
                self.winrm_protocol = Protocol(
                    endpoint=self.endpoint,
                    transport=self.transport,
                    username=self.username,
                    password=self.password,
                    service=self.service,
                    keytab=self.keytab,
                    ca_trust_path=self.ca_trust_path,
                    cert_pem=self.cert_pem,
                    cert_key_pem=self.cert_key_pem,
                    server_cert_validation=self.server_cert_validation,
                    kerberos_delegation=self.kerberos_delegation,
                    read_timeout_sec=self.read_timeout_sec,
                    operation_timeout_sec=self.operation_timeout_sec,
                    kerberos_hostname_override=self.kerberos_hostname_override,
                    message_encryption=self.message_encryption,
                    credssp_disable_tlsv1_2=self.credssp_disable_tlsv1_2,
                    send_cbt=self.send_cbt
                )

            self.log.info("Establishing WinRM connection to host: %s", self.remote_host)
            self.client = self.winrm_protocol.open_shell()

        except Exception as error:
            error_msg = "Error connecting to host: {0}, error: {1}".format(self.remote_host, error)
            self.log.error(error_msg)
            raise AirflowException(error_msg)

        return self.client
        if key == "params":
            paramlist = value.split("--")
            for param in paramlist:
                itemlist = param.split()
                if 1 < len(itemlist):
                    script = script.replace("$$"+itemlist[0], itemlist[1])
        else:
            script = script.replace("$$"+key, value)
script = script.replace("\n", ";")

if "\\" in data["serverusername"]:
    #script = base64.b64encode(script.encode("utf-16"))
    cmd = "powershell -ExecutionPolicy Bypass -command %s" % (script)
    p = Protocol(
        endpoint='https://'+data["servername"]+':5986/wsman',
        transport='credssp',
        username=data["serverusername"],
        password=data["password"],
        server_cert_validation='ignore')
    shell_id = p.open_shell()
    command_id = p.run_command(shell_id, cmd)
    std_out, std_err, status_code = p.get_command_output(shell_id, command_id)
    p.cleanup_command(shell_id, command_id)
    p.close_shell(shell_id)
else:
    script = "\n"+script
    s = winrm.Session(data["servername"], auth=(data["serverusername"], data["password"]))
    try:
        r = s.run_ps(script)
#    except winrm.exceptions.UnauthorizedError:
#        print "Could not authenticate on the remote server:", sys.exc_info()[1]
#        sys.exit(100)