Repository navigation
Conversation
pysftp 0.2.9 verifies the host key of the SFTP server by default against ~/.ssh/known_hosts, and fails with "No hostkey for host X found" when the Odoo user has no such file. Until now the check could not be configured at all: a missing known_hosts file only produced a UserWarning, and an empty one raised HostKeysException before the connection test could handle it. Replace it with an explicit policy: - SFTP Host Keys accepts one or more OpenSSH public keys, one per line (the output of ssh-keyscan, or bare keys), and enforces exactly those keys when set. - Ignore Host Key skips the verification on purpose: it logs a warning and the form shows a banner while it is enabled. - With neither of them configured, the keys of ~/.ssh/known_hosts are used, and when no key is available at all the connection is refused with a UserError explaining how to provide one. The connection options no longer build pysftp.CnOpts, whose constructor loads known_hosts before any policy can be applied: a missing file emits a UserWarning and an empty file raises HostKeysException outside the UserError handling of the connection test.
pysftp's last release is 0.2.9, from 2016. Its module-level DSSKey import breaks on paramiko >= 4.0, which is why this module had to pin paramiko<4.0.0, and it only tries RSA and DSS private keys, so Ed25519 and ECDSA key files are rejected. Its makedirs raises OSError, never ConnectionException, so the handler wrapped around that call was dead code. Talk to paramiko directly through a small _SftpClient wrapper that stays a context manager, so sftp_connection() keeps returning something usable in a "with" block, as all its callers already expect. paramiko.SSHClient cannot express a host key pinned per record, so the wrapper builds the transport from a socket itself and passes hostkey to Transport.connect; the socket also carries the read timeout. The host key policy is unchanged: pinned keys first, then ~/.ssh/known_hosts, then the explicit "Ignore Host Key" bypass, and the connection is refused with a UserError when no key is available at all. Validated against paramiko 3.5.1, the version shipped in the images. No model field, view, ACL or data changes, so no migration script is needed. The paramiko<4.0.0 upper bound stays for now: paramiko 4 renamed the passphrase argument of PKey.from_path to password.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Replace the abandoned
pysftpwithparamikoinauto_backup, keeping the host key policy addedin #3462.
Why
pysftprelease is 0.2.9 (2016), and its module-levelfrom paramiko import DSSKeybreaksimport pysftpon paramiko >= 4, which is why this module had to pinparamiko<4.0.0.makedirsraisesOSError, neverConnectionException, so the handler wrapped around thatcall was dead code.
How
_SftpClient: a context manager overparamiko.Transportbuilt from an explicit socket(
timeout=60), so the per-recordhostkeycan be passed toTransport.connect; it exposesopen,listdir,unlinkand a recursivemakedirsthat refuses a regular file where adirectory is expected.
_get_sftp_host_keyskeeps the policy unchanged: pinned keys, then~/.ssh/known_hosts, then theexplicit Ignore Host Key bypass, and a
UserErrorwhen no key is available at all._SftpConnectionOptionsdisappears with pysftp.AuthenticationException,SSHExceptionandOSError.Compatibility
No field, view, ACL or data change: no migration script is needed.
paramiko<4.0.0stays for now: paramiko 4 renamedPKey.from_path(passphrase=...)topassword=...and this was validated against 3.5.1. Dropping the bound is a follow-up once an environment with
paramiko >= 4 is available (see #3705, which starts that migration on 18.0).
Tests
18 -> 22. The pysftp mocks are replaced by assertions on the transport (
hostkeyis the pinned key),the socket timeout, the private-key loading, the bypass (
hostkey=None), an unknown host raisingSSHException, andmakedirstop-down plus the "not a directory" case. A mutation check (drophostkey=, or create directories bottom-up) makes the suite fail.Depends on:
@BinhexTeam T26503