Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions auto_backup/models/db_backup.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,13 @@ class DbBackup(models.Model):
help="Path to the private key file. Only the Odoo user should have "
"read permissions for that file.",
)
sftp_ignore_hostkey = fields.Boolean(
"Ignore Host Key Verification",
default=False,
help="If enabled, the SFTP connection will not verify the server's "
"host key. This is less secure but useful when the server's host key "
"is not available in the known_hosts file.",
)

backup_format = fields.Selection(
[
Expand Down Expand Up @@ -278,6 +285,15 @@ def sftp_connection(self):
"username": self.sftp_user,
"port": self.sftp_port,
}
# Optionally disable host key verification
if self.sftp_ignore_hostkey:
cnopts = pysftp.CnOpts()
cnopts.hostkeys = None
params["cnopts"] = cnopts
_logger.warning(
"SFTP host key verification disabled for %s - this is less secure",
self.sftp_host,
)
_logger.debug(
"Trying to connect to sftp://%(username)s@%(host)s:%(port)d", extra=params
)
Expand Down
26 changes: 26 additions & 0 deletions auto_backup/tests/test_db_backup.py
Original file line number Diff line number Diff line change
Expand Up @@ -234,3 +234,29 @@ def test_filename_dump(self):
now = datetime.now()
res = self.Model.filename(now, ext="dump")
self.assertTrue(res.endswith(".dump"))

@patch(f"{model}.pysftp")
def test_sftp_connection_without_ignore_hostkey(self, mock_pysftp):
"""It should NOT pass cnopts when sftp_ignore_hostkey is False"""
rec_id = self.new_record()
rec_id.write({"sftp_ignore_hostkey": False})
rec_id.sftp_connection()
# Verify cnopts is NOT passed when ignore_hostkey is False
call_kwargs = mock_pysftp.Connection.call_args.kwargs
self.assertNotIn("cnopts", call_kwargs)

@patch(f"{model}.pysftp")
def test_sftp_connection_with_ignore_hostkey(self, mock_pysftp):
"""It should pass cnopts with hostkeys=None when sftp_ignore_hostkey is True"""
rec_id = self.new_record()
rec_id.write({"sftp_ignore_hostkey": True})
rec_id.sftp_connection()
# Verify cnopts IS passed when ignore_hostkey is True
call_kwargs = mock_pysftp.Connection.call_args.kwargs
self.assertIn("cnopts", call_kwargs)
self.assertIsNone(call_kwargs["cnopts"].hostkeys)

def test_sftp_ignore_hostkey_default_value(self):
"""It should have sftp_ignore_hostkey defaulting to False"""
rec_id = self.new_record()
self.assertFalse(rec_id.sftp_ignore_hostkey)
1 change: 1 addition & 0 deletions auto_backup/view/db_backup_view.xml
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
name="sftp_private_key"
placeholder="/home/odoo/.ssh/id_rsa"
/>
<field name="sftp_ignore_hostkey" />
<button
name="action_sftp_test_connection"
type="object"
Expand Down
Loading