Skip to content

Commit f3d5a70

Browse files
Gwildorkaxil
authored andcommitted
[AIRFLOW-3112] Fix SFTPHook not validating hosts by default (#4085)
1 parent f53fd2d commit f3d5a70

File tree

3 files changed

+72
-6
lines changed

3 files changed

+72
-6
lines changed

airflow/contrib/hooks/sftp_hook.py

+12-4
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,9 @@ def __init__(self, ftp_conn_id='sftp_default', *args, **kwargs):
4949
self.conn = None
5050
self.private_key_pass = None
5151

52+
# Fail for unverified hosts, unless this is explicitly allowed
53+
self.no_host_key_check = False
54+
5255
if self.ssh_conn_id is not None:
5356
conn = self.get_connection(self.ssh_conn_id)
5457
if conn.extra is not None:
@@ -59,17 +62,22 @@ def __init__(self, ftp_conn_id='sftp_default', *args, **kwargs):
5962
# For backward compatibility
6063
# TODO: remove in Airflow 2.1
6164
import warnings
62-
if 'ignore_hostkey_verification' in extra_options \
63-
and str(extra_options["ignore_hostkey_verification"])\
64-
.lower() == 'false':
65+
if 'ignore_hostkey_verification' in extra_options:
6566
warnings.warn(
6667
'Extra option `ignore_hostkey_verification` is deprecated.'
6768
'Please use `no_host_key_check` instead.'
6869
'This option will be removed in Airflow 2.1',
6970
DeprecationWarning,
7071
stacklevel=2,
7172
)
72-
self.no_host_key_check = False
73+
self.no_host_key_check = str(
74+
extra_options['ignore_hostkey_verification']
75+
).lower() == 'true'
76+
77+
if 'no_host_key_check' in extra_options:
78+
self.no_host_key_check = str(
79+
extra_options['no_host_key_check']).lower() == 'true'
80+
7381
if 'private_key' in extra_options:
7482
warnings.warn(
7583
'Extra option `private_key` is deprecated.'

airflow/utils/db.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,7 @@ def initdb(rbac=False):
186186
conn_id='sftp_default', conn_type='sftp',
187187
host='localhost', port=22, login='travis',
188188
extra='''
189-
{"private_key": "~/.ssh/id_rsa", "ignore_hostkey_verification": true}
189+
{"key_file": "~/.ssh/id_rsa", "no_host_key_check": true}
190190
'''))
191191
merge_conn(
192192
models.Connection(

tests/contrib/hooks/test_sftp_hook.py

+59-1
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,13 @@
1919

2020
from __future__ import print_function
2121

22+
import mock
2223
import unittest
2324
import shutil
2425
import os
2526
import pysftp
2627

27-
from airflow import configuration
28+
from airflow import configuration, models
2829
from airflow.contrib.hooks.sftp_hook import SFTPHook
2930

3031
TMP_PATH = '/tmp'
@@ -105,6 +106,63 @@ def test_get_mod_time(self):
105106
TMP_PATH, TMP_DIR_FOR_TESTS, TMP_FILE_FOR_TESTS))
106107
self.assertEqual(len(output), 14)
107108

109+
@mock.patch('airflow.contrib.hooks.sftp_hook.SFTPHook.get_connection')
110+
def test_no_host_key_check_default(self, get_connection):
111+
connection = models.Connection(login='login', host='host')
112+
get_connection.return_value = connection
113+
hook = SFTPHook()
114+
self.assertEqual(hook.no_host_key_check, False)
115+
116+
@mock.patch('airflow.contrib.hooks.sftp_hook.SFTPHook.get_connection')
117+
def test_no_host_key_check_enabled(self, get_connection):
118+
connection = models.Connection(
119+
login='login', host='host',
120+
extra='{"no_host_key_check": true}')
121+
122+
get_connection.return_value = connection
123+
hook = SFTPHook()
124+
self.assertEqual(hook.no_host_key_check, True)
125+
126+
@mock.patch('airflow.contrib.hooks.sftp_hook.SFTPHook.get_connection')
127+
def test_no_host_key_check_disabled(self, get_connection):
128+
connection = models.Connection(
129+
login='login', host='host',
130+
extra='{"no_host_key_check": false}')
131+
132+
get_connection.return_value = connection
133+
hook = SFTPHook()
134+
self.assertEqual(hook.no_host_key_check, False)
135+
136+
@mock.patch('airflow.contrib.hooks.sftp_hook.SFTPHook.get_connection')
137+
def test_no_host_key_check_disabled_for_all_but_true(self, get_connection):
138+
connection = models.Connection(
139+
login='login', host='host',
140+
extra='{"no_host_key_check": "foo"}')
141+
142+
get_connection.return_value = connection
143+
hook = SFTPHook()
144+
self.assertEqual(hook.no_host_key_check, False)
145+
146+
@mock.patch('airflow.contrib.hooks.sftp_hook.SFTPHook.get_connection')
147+
def test_no_host_key_check_ignore(self, get_connection):
148+
connection = models.Connection(
149+
login='login', host='host',
150+
extra='{"ignore_hostkey_verification": true}')
151+
152+
get_connection.return_value = connection
153+
hook = SFTPHook()
154+
self.assertEqual(hook.no_host_key_check, True)
155+
156+
@mock.patch('airflow.contrib.hooks.sftp_hook.SFTPHook.get_connection')
157+
def test_no_host_key_check_no_ignore(self, get_connection):
158+
connection = models.Connection(
159+
login='login', host='host',
160+
extra='{"ignore_hostkey_verification": false}')
161+
162+
get_connection.return_value = connection
163+
hook = SFTPHook()
164+
self.assertEqual(hook.no_host_key_check, False)
165+
108166
def tearDown(self):
109167
shutil.rmtree(os.path.join(TMP_PATH, TMP_DIR_FOR_TESTS))
110168
os.remove(os.path.join(TMP_PATH, TMP_FILE_FOR_TESTS))

0 commit comments

Comments
 (0)