使用 Elastic Beanstalk EB 在 AWS 上使用 pysftp 和 paramiko 的 SFTP known_hosts
SFTP with pysftp and paramiko on AWS using Elastic Beanstalk EB known_hosts
所以我正在构建一个 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 专家,所以我真的很感激任何帮助。
谢谢
用户和文件夹似乎有些混乱。
您的应用程序在 webapp
用户下执行。因此,您的应用程序将无法在您尝试修改属于 ec2-user
的任何文件夹时:
KNOWN_HOSTS = "/home/ec2-user/.ssh/known_hosts"
创建这样的 /home/webapp/.ssh/known_hosts
文件也会失败,因为默认文件夹 /home/webapp/.ssh/
不存在 。必须先创建它,然后才能将 known_hosts
添加到其中。
所以我正在构建一个 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 专家,所以我真的很感激任何帮助。
谢谢
用户和文件夹似乎有些混乱。
您的应用程序在 webapp
用户下执行。因此,您的应用程序将无法在您尝试修改属于 ec2-user
的任何文件夹时:
KNOWN_HOSTS = "/home/ec2-user/.ssh/known_hosts"
创建这样的 /home/webapp/.ssh/known_hosts
文件也会失败,因为默认文件夹 /home/webapp/.ssh/
不存在 。必须先创建它,然后才能将 known_hosts
添加到其中。