Отправка файла через winrm / powershell ограничена 3000 байтами - PullRequest
0 голосов
/ 28 марта 2019

Я пытаюсь отправить файл через WinRM / PowerShell, но мне кажется, что у меня ограничение в 3000 байт, и я не знаю, как от него избавиться.

Из локальной оболочки PowerShell, Я могу запустить эту команду и успешно отправить куски данных BASE64, я не ограничен:

while ($l=[System.Convert]::FromBase64String((Read-Host))){add-content -value ($l) -encoding byte  -path 'tstfile.txt'}

Однако, если я пытаюсь отправить данные удаленно (из скрипта Python), передача запускается успешно исервер останавливается после того, как 3000 байт были записаны в tstfile.txt ...

Вот мой «упрощенный» код (Python 3.5.3 + pywinrm 0.3.0), вдохновленный Ansible (https://github.com/ansible/ansible/blob/devel/lib/ansible/plugins/connection/winrm.py):

import winrm

class TestUpload() :

    def put_file(self, location, contents):

        # start shell
        self._shell_id = self._conn.open_shell()
        ps_script='while ($l=[System.Convert]::FromBase64String((Read-Host))){add-content -value ($l) -encoding byte  -path ' + location + '}'
        command_id = self._conn.run_command(self._shell_id, "powershell -Command %s " % (ps_script))

        # send data
        b64contents = base64.b64encode(contents.encode('utf-8')).decode('ascii')
        for i in range(0, len(b64contents), self._step):
            self._raw_send_data(self._shell_id, command_id, b64contents[i:i+self._step] )
        self._raw_send_data(self._shell_id, command_id, '', eof=True)

        # close shell
        self._conn.cleanup_command(self._shell_id, command_id)
        self._conn.close_shell(self._shell_id)


    def _raw_send_data(self, shell_id, command_id,content, eof=False):
        req = {'env:Envelope': self._conn._get_soap_header(
            resource_uri='http://schemas.microsoft.com/wbem/wsman/1/windows/shell/cmd',
            action='http://schemas.microsoft.com/wbem/wsman/1/windows/shell/Send',
            shell_id=shell_id)}

        stream = req['env:Envelope'].setdefault('env:Body', {}).setdefault(
            'rsp:Send', {}).setdefault('rsp:Stream', {})
        stream['@CommandId'] = command_id
        stream['@Name'] = 'stdin'
        content += '\r\n'
        stream['#text'] = base64.b64encode(content.encode('utf-8'))
        stream['@xmlns:rsp'] = 'http://schemas.microsoft.com/wbem/wsman/1/windows/shell'

        if eof:
            stream['@End'] = 'true'

        res = self._conn.send_message(xmltodict.unparse(req))

Это работает:

t=TestUpload(step=100)
t.put_file('tstfile.txt',open('900bytesfile.txt').read())

Это не удается:

t=TestUpload(step=100)
t.put_file('tstfile.txt',open('9000bytesfile.txt').read())
Traceback (most recent call last):
  File "/opt/environments/pypy/site-packages/winrm/transport.py", line 262, in _send_message_request
    response.raise_for_status()
  File "/opt/environments/pypy/site-packages/requests/models.py", line 940, in raise_for_status
    raise HTTPError(http_error_msg, response=self)
requests.exceptions.HTTPError: 500 Server Error:  for url: https://win-srv1.local.activcloud.eu:5986/wsman

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/opt/environments/pypy/site-packages/winrm/protocol.py", line 234, in send_message
    resp = self.transport.send_message(message)
  File "/opt/environments/pypy/site-packages/winrm/transport.py", line 256, in send_message
    response = self._send_message_request(prepared_request, message)
  File "/opt/environments/pypy/site-packages/winrm/transport.py", line 273, in _send_message_request
    raise WinRMTransportError('http', ex.response.status_code, response_text)
winrm.exceptions.WinRMTransportError: Bad HTTP response returned from server. Code 500

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File "/opt/repos/poc4/tst.py", line 158, in put_file
    self._raw_send_data(self._shell_id, command_id, b64contents[i:i+self._step] )
  File "/opt/repos/poc4/tst.py", line 332, in _raw_send_data
    res = self._conn.send_message(xmltodict.unparse(req))
  File "/opt/environments/pypy/site-packages/winrm/protocol.py", line 256, in send_message
    raise WinRMOperationTimeoutError()
winrm.exceptions.WinRMOperationTimeoutError

У меня нет сообщений об ошибках (кроме времени ожидания), я не сделалничего не могу найти в логах сервера, единственная подсказка в том, что файл имеет длину 3000 байт на стороне сервера (данные внутри верны):

Mode                LastWriteTime         Length Name
----                -------------         ------ ----
-a----        3/28/2019   2:52 PM           3000 tstfile.txt

У кого-нибудь есть идея? Может быть, проверитьесли ansible способен выполнить эту команду с более чем 3000 байтов данных?

...