使用 python(使用 TLS 或 FTPS)为 Azure 应用程序安全 FTP 部署

Secure FTP deployment for Azure App using python (using TLS or FTPS)

我正在尝试使用 python 将一些文件复制到 Azure 应用程序作为更广泛的 python 脚本的一部分。

我可以使用 FTP 执行此操作,但我不知道如何使用 TLS 以安全的方式执行此操作。

我正在使用从 Azure 门户下载的凭据,单击 "Get Publish Profile",然后在 python 代码中使用它们,如下所示:

import ftplib

ftpServer = ftplib.FTP_TLS(host='waws-<...>.ftp.azurewebsites.windows.net',
                        user='<MY_USER>$<MY_USER>',
                        passwd='<VERY_LONG_PSW>')

但是当执行 ftpServer.cwd('<THE_PATH_TO_INSPECT>') 然后我看到:ConnectionRefusedError: [Errno 111] Connection refused

当使用 ftplib.FTP(...) 而不是 ftplib.FTP_TLS(...) 时,一切正常。

查看此处的 Python 文档 https://docs.python.org/3.5/library/ftplib.html 似乎我应该确保满足某种 implicit/explicit 条件,但我不知道该怎么做。

在各种网络资源上阅读似乎我应该使用与标准 21 不同的端口,有人说 990,其他人说 989,但我无法弄清楚在 python代码。

编辑 1:

FTP 的这种隐式连接似乎与 TLS 1.2 版有关(根据 python 文档),我不是 100% 确定,因为我不熟悉这些标准,但是我无论如何都尝试过但没有成功。 请记住 <MY_USER>$<MY_USER>(和密码)来自我从 Azure 门户下载的文件内容 "Publish Profile",见下文:

$ python
Python 3.6.6 |Anaconda, Inc.| (default, Jun 28 2018, 17:14:51) 
[GCC 7.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> 
>>> 
>>> 
>>> 
>>> import ftplib
>>> 
>>> 
>>> ftpServer = ftplib.FTP_TLS(host='waws-<...>.ftp.azurewebsites.windows.net',
...                         user='<MY_USER>$<MY_USER>',
...                         passwd='<VERY_LONG_PSW>')
>>> 
>>> 
>>> 
>>> ftpServer.dir()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/<MY_USER>/Conda/lib/python3.6/ftplib.py", line 575, in dir
    self.retrlines(cmd, func)
  File "/home/<MY_USER>/Conda/lib/python3.6/ftplib.py", line 468, in retrlines
    with self.transfercmd(cmd) as conn, \
  File "/home/<MY_USER>/Conda/lib/python3.6/ftplib.py", line 399, in transfercmd
    return self.ntransfercmd(cmd, rest)[0]
  File "/home/<MY_USER>/Conda/lib/python3.6/ftplib.py", line 798, in ntransfercmd
    conn, size = FTP.ntransfercmd(self, cmd, rest)
  File "/home/<MY_USER>/Conda/lib/python3.6/ftplib.py", line 361, in ntransfercmd
    source_address=self.source_address)
  File "/home/<MY_USER>/Conda/lib/python3.6/socket.py", line 724, in create_connection
    raise err
  File "/home/<MY_USER>/Conda/lib/python3.6/socket.py", line 713, in create_connection
    sock.connect(sa)
ConnectionRefusedError: [Errno 111] Connection refused
>>> 
>>> 

似乎在隐式 FTPS (990/TCP) 上工作得很好:

$ openssl s_client -connect waws-prod-am2-119.ftp.azurewebsites.windows.net:990

CONNECTED(00000003)
[...]
---
Certificate chain
 0 s:/C=US/ST=Washington/L=Redmond/O=Microsoft Corporation/
      CN=waws-prod-am2-119.publish.azurewebsites.windows.net
   i:/C=US/O=DigiCert Inc/CN=DigiCert SHA2 Secure Server CA
 1 s:/C=US/O=DigiCert Inc/CN=DigiCert SHA2 Secure Server CA
   i:/C=US/O=DigiCert Inc/OU=www.digicert.com/CN=DigiCert Global Root CA
---
[...]
SSL handshake has read 3574 bytes and written 390 bytes
Verification: OK
---
New, TLSv1.2, Cipher is ECDHE-RSA-AES256-SHA384
Server public key is 2048 bit
[...]
SSL-Session:
    Protocol  : TLSv1.2
    Cipher    : ECDHE-RSA-AES256-SHA384
    [...]
    Verify return code: 0 (ok)
    Extended master secret: yes
---
220 Microsoft FTP Service

Python 客户端库可能已过期或没有包含 DigiCert CA 的最新 CA 包。您不应该 FTP-ing,而是尝试上传到 blob 存储并让 Web 应用程序提供来自该存储帐户的文件(如果文件不应该 [=26,则使用 SAS signature =]).

如果您尝试部署 Web 应用程序,请使用 git 存储库或 Web 部署,它更可靠。

使用 ftplib 库存 Python 3.6:

>>> ftpServer = FTP_TLS(host='waws-prod-am2-119.ftp.azurewebsites.windows.net',
...                         user='myuser$myuser',
...                         passwd='rM....dsFsfp')

>>> ftpServer.dir()
03-21-17  09:27AM       <DIR>          .ssh
02-22-18  08:19AM       <DIR>          ciphers
02-22-18  10:28AM       <DIR>          data
01-12-18  12:58AM       <DIR>          LogFiles
02-22-18  08:16AM       <DIR>          site

>>> ftpServer.cwd('data')
'250 CWD command successful.'