Сбой PySFTP с «Не найден хост-ключ для хоста X» при развертывании Django / Heroku - PullRequest
1 голос
/ 20 января 2020

Я пытаюсь развернуть веб-приложение Django, которое использует pysftp для доступа к SFTP-серверу через некоторые представления.

Эта вещь отлично работала в локальной разработке, но при попытке первого развертывания на Heroku, нижеприведенная трассировка появилась с ошибкой. Кажется, мне нужно настроить ключи хоста, и я считаю, что мне также нужно установить их в known_hosts в Heroku, но я понятия не имею, как это сделать. В локальной разработке я без проблем обращался к пользователю / паролю, но из Heroku появляется эта ошибка:

remote: paramiko.ssh_exception.SSHException: No hostkey for host somehost.myftp.org found

Вы можете увидеть весь вывод здесь:

remote: -----> Compressing...
remote:        Done: 68.8M
remote: -----> Launching...
remote:  !     Release command declared: this new release will not be available until the command succeeds.
remote:        Released v16
remote:        https://somehostonlineproject.herokuapp.com/ deployed to Heroku
remote: 
remote: Verifying deploy... done.
remote: Running release command...
remote: 
remote: ===============> ParseResult(scheme='', netloc='', path='somehost.sytes.net', params='', query='', fragment='')
remote: /app/.heroku/python/lib/python3.7/site-packages/pysftp/__init__.py:61: UserWarning: Failed to load HostKeys from /app/.ssh/known_hosts.  You will need to explicitly load HostKeys (cnopts.hostkeys.load(filename)) or disableHostKey checking (cnopts.hostkeys = None).
remote:   warnings.warn(wmsg, UserWarning)
remote: Traceback (most recent call last):
remote:   File "manage.py", line 31, in <module>
remote:     execute_from_command_line(sys.argv)
remote:   File "/app/.heroku/python/lib/python3.7/site-packages/django/core/management/__init__.py", line 381, in execute_from_command_line
remote:     utility.execute()
remote:   File "/app/.heroku/python/lib/python3.7/site-packages/django/core/management/__init__.py", line 375, in execute
remote:     self.fetch_command(subcommand).run_from_argv(self.argv)
remote:   File "/app/.heroku/python/lib/python3.7/site-packages/django/core/management/base.py", line 323, in run_from_argv
remote:     self.execute(*args, **cmd_options)
remote:   File "/app/.heroku/python/lib/python3.7/site-packages/django/core/management/base.py", line 361, in execute
remote:     self.check()
remote:   File "/app/.heroku/python/lib/python3.7/site-packages/django/core/management/base.py", line 390, in check
remote:     include_deployment_checks=include_deployment_checks,
remote:   File "/app/.heroku/python/lib/python3.7/site-packages/django/core/management/commands/migrate.py", line 65, in _run_checks
remote:     issues.extend(super()._run_checks(**kwargs))
remote:   File "/app/.heroku/python/lib/python3.7/site-packages/django/core/management/base.py", line 377, in _run_checks
remote:     return checks.run_checks(**kwargs)
remote:   File "/app/.heroku/python/lib/python3.7/site-packages/django/core/checks/registry.py", line 72, in run_checks
remote:     new_errors = check(app_configs=app_configs)
remote:   File "/app/.heroku/python/lib/python3.7/site-packages/django/core/checks/urls.py", line 40, in check_url_namespaces_unique
remote:     all_namespaces = _load_all_namespaces(resolver)
remote:   File "/app/.heroku/python/lib/python3.7/site-packages/django/core/checks/urls.py", line 57, in _load_all_namespaces
remote:     url_patterns = getattr(resolver, 'url_patterns', [])
remote:   File "/app/.heroku/python/lib/python3.7/site-packages/django/utils/functional.py", line 80, in __get__
remote:     res = instance.__dict__[self.name] = self.func(instance)
remote:   File "/app/.heroku/python/lib/python3.7/site-packages/django/urls/resolvers.py", line 584, in url_patterns
remote:     patterns = getattr(self.urlconf_module, "urlpatterns", self.urlconf_module)
remote:   File "/app/.heroku/python/lib/python3.7/site-packages/django/utils/functional.py", line 80, in __get__
remote:     res = instance.__dict__[self.name] = self.func(instance)
remote:   File "/app/.heroku/python/lib/python3.7/site-packages/django/urls/resolvers.py", line 577, in urlconf_module
remote:     return import_module(self.urlconf_name)
remote:   File "/app/.heroku/python/lib/python3.7/importlib/__init__.py", line 127, in import_module
remote:     return _bootstrap._gcd_import(name[level:], package, level)
remote:   File "<frozen importlib._bootstrap>", line 1006, in _gcd_import
remote:   File "<frozen importlib._bootstrap>", line 983, in _find_and_load
remote:   File "<frozen importlib._bootstrap>", line 967, in _find_and_load_unlocked
remote:   File "<frozen importlib._bootstrap>", line 677, in _load_unlocked
remote:   File "<frozen importlib._bootstrap_external>", line 728, in exec_module
remote:   File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed
remote:   File "/app/config/urls.py", line 27, in <module>
remote:     path("browse/", include("django_sftpbrowser.urls", namespace="sftpbrowser-root"), name='browse_option'),
remote:   File "/app/.heroku/python/lib/python3.7/site-packages/django/urls/conf.py", line 34, in include
remote:     urlconf_module = import_module(urlconf_module)
remote:   File "/app/.heroku/python/lib/python3.7/importlib/__init__.py", line 127, in import_module
remote:     return _bootstrap._gcd_import(name[level:], package, level)
remote:   File "<frozen importlib._bootstrap>", line 1006, in _gcd_import
remote:   File "<frozen importlib._bootstrap>", line 983, in _find_and_load
remote:   File "<frozen importlib._bootstrap>", line 967, in _find_and_load_unlocked
remote:   File "<frozen importlib._bootstrap>", line 677, in _load_unlocked
remote:   File "<frozen importlib._bootstrap_external>", line 728, in exec_module
remote:   File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed
remote:   File "/app/django_sftpbrowser/urls.py", line 2, in <module>
remote:     from .views import browse_page
remote:   File "/app/django_sftpbrowser/views.py", line 9, in <module>
remote:     srv = pysftp.Connection(settings.SOMEHOST_SFTP_SERVER_URL, username='madtyn', password=settings.SFTP_PASSWORD)
remote:   File "/app/.heroku/python/lib/python3.7/site-packages/pysftp/__init__.py", line 132, in __init__
remote:     self._tconnect['hostkey'] = self._cnopts.get_hostkey(host)
remote:   File "/app/.heroku/python/lib/python3.7/site-packages/pysftp/__init__.py", line 71, in get_hostkey
remote:     raise SSHException("No hostkey for host %s found." % host)
remote: paramiko.ssh_exception.SSHException: No hostkey for host somehost.myftp.org found.
remote: Exception ignored in: <function Connection.__del__ at 0x7fd94274b950>
remote: Traceback (most recent call last):
remote:   File "/app/.heroku/python/lib/python3.7/site-packages/pysftp/__init__.py", line 1013, in __del__
remote:     self.close()
remote:   File "/app/.heroku/python/lib/python3.7/site-packages/pysftp/__init__.py", line 784, in close
remote:     if self._sftp_live:
remote: AttributeError: 'Connection' object has no attribute '_sftp_live'
remote: Waiting for release... failed.
To https://git.heroku.com/somehostonlineproject.git
 * [new branch]      deployment -> master

1 Ответ

1 голос
/ 20 января 2020

Общие сведения о "Хост-ключ для хоста ... не найден" см.
Проверьте ключ хоста с помощью pysftp


Относительно реализации на Heroku: я не знаком с ней, но на самом деле, и как вы также прокомментировали, она не имеет постоянного файлового хранилища.

По этой причине, используя реализацию, которая имеет Ключ хоста жестко запрограммирован. Два решения из моего ответа на вышеуказанный вопрос удовлетворяют потребности:

  1. Если вы не хотите использовать внешний файл, вы также можете использовать

    from base64 import decodebytes
    # ...
    
    keydata = b"""AAAAB3NzaC1yc2EAAAADAQAB..."""
    key = paramiko.RSAKey(data=decodebytes(keydata))
    cnopts = pysftp.CnOpts()
    cnopts.hostkeys.add('example.com', 'ssh-rsa', key)
    
    with pysftp.Connection(host, username, password, cnopts=cnopts) as sftp:
    
  2. Если вам нужно проверить ключ хоста только по отпечатку пальца, см.
    Python - pysftp / paramiko - Проверьте ключ хоста по отпечатку пальца .


Это также актуально (хотя касается непосредственно Paramiko, а не об оболочке pysftp):
Paramiko S SH с ошибкой " Сервер "..." не найден в known_hosts "при запуске на веб-сервере

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...