【问题标题】:SFTP with pysftp and paramiko on AWS using Elastic Beanstalk EB known_hosts使用 Elastic Beanstalk EB known_hosts 在 AWS 上使用 pysftp 和 paramiko 进行 SFTP
【发布时间】:2020-07-16 08:17:25
【问题描述】:

所以我正在构建一个 Flask 微服务来连接两个 API。其中一个 API 要求所有通信都通过 SFTP 来移动 XML 文件(耶!????)。

在 Windows 上,经过相当多的摆弄,我能够让它工作。问题是除非我使用 FileZilla 登录并接受主机密钥,否则 pysftp/paramiko 将无法连接。

为了解决这个问题,我编写了一个函数来检查“C:/Users/{user}/.ssh/known_hosts”中的 known_hosts 文件,如果该站点缺少密钥,我使用 paramiko 来获取密钥。

from pysftp import known_hosts
import paramiko


def check_for_host_key(hostname):
    """
    Checks for host key in known_hosts file
    If it is not found, it will get it and add it to known_hosts
    """
    
    KNOWN_HOSTS = known_hosts()  # this fn returns a string looking like 'C:/Users/{user}/.ssh/known_hosts' but is OS agnostic and works fine under Linux.

    if os.path.isfile(KNOWN_HOSTS):
        pass
    else:
        # if known_hosts doesn't exist, create it in default directory
        try:
            open(KNOWN_HOSTS, 'a+').close()
        except FileNotFoundError:
            KNOWN_HOSTS = "/home/ec2-user/.ssh/known_hosts"
            open(KNOWN_HOSTS, 'a+').close()

    # check if host key is present
    if open(KNOWN_HOSTS, 'r').read().find(hostname) != -1:
        return

    # if not get it...
    print(f"host key not found in known_hosts({KNOWN_HOSTS})\ngetting host key")
    transport = paramiko.Transport(hostname)
    transport.connect()
    key = transport.get_remote_server_key()
    transport.close()

    # and save it
    hostfile = paramiko.HostKeys(filename=KNOWN_HOSTS)
    hostfile.add(hostname=hostname, key=key, keytype=key.get_name())
    hostfile.save(filename=KNOWN_HOSTS)
    print(f"host key saved to known_hosts({KNOWN_HOSTS})")
    return

上述函数在 Windows 上运行良好,我希望它在部署到 LInux 服务器上的 AWS 时运行良好,因为我最初看到的用于修改 known_hosts 文件的代码是为 Linux 编写的(如果内存服务......)。但是当我部署到 Elastic Beanstalk(使用 EB CLI)时,我不断收到 502 错误。

检查 AWS 日志我可以看到在启动期间调用 check_for_host_key 函数时出现了一个特定错误(因此是 502):

Jul 15 21:15:21 ip-172-31-19-61 web: Traceback (most recent call last):
Jul 15 21:15:21 ip-172-31-19-61 web: File "/var/app/current/app/config.py", line 16, in Config
Jul 15 21:15:21 ip-172-31-19-61 web: open(KNOWN_HOSTS, 'a+').close()
Jul 15 21:15:21 ip-172-31-19-61 web: FileNotFoundError: [Errno 2] No such file or directory: '/home/webapp/.ssh/known_hosts'
.......
Jul 15 21:15:21 ip-172-31-19-61 web: open(KNOWN_HOSTS, 'a+').close()
Jul 15 21:15:21 ip-172-31-19-61 web: PermissionError: [Errno 13] Permission denied: '/home/ec2-user/.ssh/known_hosts'

第一个错误是真实的,FileNotFoundError: [Errno 2] No such file or directory: '/home/webapp/.ssh/known_hosts'

为什么我的 python 应用程序找不到相关目录?如果在 Windows 上缺少该文件,有问题的代码行实际上会创建该文件,我的理解是它应该在 Linux 上做同样的事情。

第二个错误是我尝试排除故障并使用不同的用户主文件夹,但由于权限错误而失败。

接下来,我在 Powershell 终端中使用eb ssh SSH 到我的应用程序实例(这会自动以 ec2-user 身份登录),然后我开始浏览文件夹结构。我发现我根本无法进入 /home/webapp/ 目录,再次由于权限错误。确切的错误是:

[ec2-user@ip-172-31-19-61 home]$ cd ./webapp
-bash: cd: ./webapp: Permission denied

据我所知,我从 AWS 成功启动 SFTP 连接的唯一方法是将主机密钥存储在 known_hosts 中(我知道自动执行此操作的 MITM 含义,但那是'这不是一个问题)但这似乎不是一个选项,无论是通过 SSH 还是从应用程序实例。

我是否可能需要对 IAM 角色做一些事情?我认为这可以解释 SSH 配置文件无法浏览 /home/webapp/ 目录,但我不确定这将如何帮助应用程序本身。

我完全迷失了。我是 AWS 的新手,而且我也不是 Linux 专家,所以我非常感谢任何帮助。

谢谢

【问题讨论】:

    标签: linux amazon-web-services amazon-elastic-beanstalk paramiko pysftp


    【解决方案1】:

    用户和文件夹似乎有些混乱。

    您的应用程序在webapp 用户下执行。因此,您的应用程序将无法在您尝试修改属于 ec2-user 的任何文件夹:

    KNOWN_HOSTS = "/home/ec2-user/.ssh/known_hosts"
    

    创建这样的/home/webapp/.ssh/known_hosts 文件也会失败,因为默认情况下文件夹/home/webapp/.ssh/ 不存在。必须先创建它,然后才能将known_hosts 添加到其中。

    【讨论】:

    • 谢谢,谢谢!我认为文件夹的事情可能与错误的用户等有关。最后你是绝对正确的,./ssh/ 目录不存在,我不得不更改一些代码来添加它。谢谢!
    • @ShmuliMargulies 没问题。很高兴它解决了:-)
    猜你喜欢
    • 2019-02-14
    • 2011-09-07
    • 2020-06-03
    • 2015-07-17
    • 2015-11-05
    • 2017-09-08
    • 1970-01-01
    • 2020-09-08
    • 2012-12-21
    相关资源
    最近更新 更多