Reputation: 31
I'm trying to upload file from s3 bucket to external SFTP server using paramiko. I've been getting BadHostKeyException: Host key for server 'XXXXXXX' does not match: got 'got_key' expected 'expect_key'. I've checked Automatically updating known_hosts file when host key changes using Paramiko but not sure that the "BadHostKeyException" is a sign of man-in-the-middle-attack. Can someone help?
#Read ssh key
key_obj = boto3.resource('s3').Object(s3_bucket, key_file)
key_str = key_obj.get()['Body'].read().decode('utf-8')
key = paramiko.RSAKey.from_private_key(io.StringIO(key_str), password='XXX') // password is private key password
#Create SSH client for SFTP upload
ssh_client = paramiko.SSHClient()
ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh_client.get_host_keys().add('sftp_host', 'ssh-rsa', key)
ssh_client.connect('sftp_host', port=22, username='user_name', pkey=key)
ftp_client= ssh_client.open_sftp()
Upvotes: 2
Views: 7339
Reputation: 31
ssh_client.get_host_keys().add('sftp_host', 'ssh-rsa', key)
is causing the problem here. Its actually adding my private key as host key and the same is compared with the host key from server, hence I was getting host key doesn't match. I've used key.get_base64()
to get the pub key of the host and added it to known hosts which is then used during connect method to authenticate with host key generated during connect method
#Read ssh key
key_obj = boto3.resource('s3').Object(s3_bucket, key_file)
key_str = key_obj.get()['Body'].read().decode('utf-8')
key = paramiko.RSAKey.from_private_key(io.StringIO(key_str), password='XXX') // password is private key password
#Get pub key to add to known hosts
key_pub = paramiko.RSAKey(data=decodebytes(bytes(key.get_base64(), 'utf-8')), password='sftp_key_password')
#Create SSH client for SFTP upload
ssh_client = paramiko.SSHClient()
ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh_client.get_host_keys().add('sftp_host', 'ssh-rsa', key_pub)
ssh_client.connect('sftp_host', port=22, username='user_name', pkey=key)
ftp_client= ssh_client.open_sftp()
#Upload gz using SFTP
def upload_file(file_name, pandasdf, sep='|', encoding='utf-8'):
with gzip.open(ftp_client.open(file_name, "w+", 32768), 'w+') as f:
f.write(bytes(pandasdf.to_csv(index=False, sep=sep), encoding=encoding))
#Call upload file function
try:
upload_file(file_name, pandasdf)
except Exception as e:
print(e)
print('Error while uploading file to SFTP ' + file_name)
raise e
#Close SFTP and file resources opened
ftp_client.close()
ssh_client.close()
Upvotes: 1
Reputation: 202242
Your SSH/SFTP server host key has changed. When that happens, any decent SSH/SFTP library or client will warn you and/or prevent the connections from continuing. Change of the host key is a sign of a man-in-the-middle attack.
When this happens, you should contact your server administrator to ask whether the host key change was legitimate (e.g. the server was reinstalled) or not. If the server key has not changed, you might be under an attack.
If the key changed was legitimate, the administrator should have warned you in advance. Anyway, is this case, update the host key in your code or configuration. In your case, it's the get_host_keys().add
call. In other cases, the host key might be cached in .ssh/known_hosts
file.
Note that the host key has nothing to do with the "private key" you use to authenticate to your SSH server (RSAKey.from_private_key
). You might want to read my article Understanding SSH key pairs.
Related question: Verify host key with pysftp.
Upvotes: 0