I got a great Paramiko Python script to transfer file over SCP protocol. But My need is a single file (script.py) without any other file dependencies so I don't want to have an external file for my SSH private key.
What I'm trying to do is to embed the private key into a string variable and use this variable as the file needed by the script to connect. I tried with the StringIO library but it doesn't seems to work :
hostname = '1.1.1.1' # remote hostname where SSH server is running
port = 22
username = 'user'
password = 'pswd'
dir_local='/home/paramikouser/local_data'
dir_remote = "remote_machine_folder/subfolder"
glob_pattern='*.*'
import os
import glob
import paramiko
import md5
import StringIO
private_key = StringIO.StringIO('-----BEGIN RSA PRIVATE KEY-----\n-----END RSA PRIVATE KEY-----')
def agent_auth(transport, username):
"""
Attempt to authenticate to the given transport using any of the private
keys available from an SSH agent or from a local private RSA key file (assumes no pass phrase).
"""
try:
ki = paramiko.RSAKey.from_private_key_file(private_key)
except Exception, e:
print 'Failed loading' % (private_key, e)
agent = paramiko.Agent()
agent_keys = agent.get_keys() + (ki,)
if len(agent_keys) == 0:
return
for key in agent_keys:
print 'Trying ssh-agent key %s' % key.get_fingerprint().encode('hex'),
try:
transport.auth_publickey(username, key)
print '... success!'
return
except paramiko.SSHException, e:
print '... failed!', e
# get host key, if we know one
hostkeytype = None
hostkey = None
files_copied = 0
try:
host_keys = paramiko.util.load_host_keys(os.path.expanduser('~/.ssh/known_hosts'))
except IOError:
try:
# try ~/ssh/ too, e.g. on windows
host_keys = paramiko.util.load_host_keys(os.path.expanduser('~/ssh/known_hosts'))
except IOError:
print '*** Unable to open host keys file'
host_keys = {}
if host_keys.has_key(hostname):
hostkeytype = host_keys[hostname].keys()[0]
hostkey = host_keys[hostname][hostkeytype]
print 'Using host key of type %s' % hostkeytype
# now, connect and use paramiko Transport to negotiate SSH2 across the connection
try:
print 'Establishing SSH connection to:', hostname, port, '...'
t = paramiko.Transport((hostname, port))
t.start_client()
agent_auth(t, username)
if not t.is_authenticated():
print 'RSA key auth failed! Trying password login...'
t.connect(username=username, password=password, hostkey=hostkey)
else:
sftp = t.open_session()
sftp = paramiko.SFTPClient.from_transport(t)
# dirlist on remote host
# dirlist = sftp.listdir('.')
# print "Dirlist:", dirlist
How can I use this string as a key?
Use RSAKey.from_private_key:
ki = paramiko.RSAKey.from_private_key(private_key)
See How do use paramiko.RSAKey.from_private_key()?
The answer on the above question shows code for Python 3.
In Python 2.7, this works:
import os
import glob
import paramiko
import StringIO
private_key_file = StringIO.StringIO()
private_key_file.write('-----BEGIN RSA PRIVATE KEY-----\nMIIEoQIBAAKCAQEAvG9YlF2da0jJ5PvvlmVnVnYYFc7kkJuC0wvsACVuvep/sds5\nIEX0e+/rq9UBj/V3rzsvbHzb6IVulSjEqcM32NA4SyqR1m5jAj/WVDXQcxzruBDO\nZbdNhDS1T4+HckTWzttAE4o83bRju+3BhR9CtrDtt+7CSei4MccSMEH7yxo1BGuL\nONfkhB6qAWh55T6tamTyjLg9R9xqBkG6x3ZmoOB9j/11P5awuUoE1DfbqQ3KMLSR\nr64unavECfBaBYvuxlWbxRJFAN8C95oE+Kbc1g1bEL9du6FIeHZ/eaBbkcl84Fm7\nswdHBnd7+tqfo4TGzvbEW4H2ZQLiuiGK23ao0wIBJQKCAQEAiYGvV4KVd81VDuFb\nzp0GOCypyrmSCKjVFowowdYgYRLnj5/5QRB0IxbcaKJbFgYm56e60qBNclOIC/sn\nuiasNm5uRLBclY7SoMbM1aq6tN3AxJakc70c4+8chip3mJMZStdYRZw6QOtrX5+o\n5JpFcI7yqNDS96nShTBnN/jMf3K6yjQjvTv/DJi9SHJ6dTtrY1AuUNEoiO3cwgeH\nFks169756L+fpweL4VjQl4UyClL0bwHWpe579XzjBV0AlGu1tHaE5zslTPtGw1lg\nnZhj/7skZKAIGQxIzfmGv4QEcvePKYzM8EUhOr/0O3BHjLC0lp5hMwmsPJfaHlMb\nBak0JQKBgQD0cRu65WNkCcRlpuUvp5/kiMvu7PmcFUsY6dMeV0bL4oQ+PCqfwXFj\nhkyS7V2DJnllYPwi6E68soie+IL1blmY7hWcoznJ48PWJ0bJmqBgzhpC623RtTKS\ny/O0IbrGKPpaRGfD/PAvqJOpwx7Im2k6/UVQ0OYSurC8CB3BDRTCXQKBgQDFWEq7\ny2SntPFA9zu+31bW57lb26l8nNmUXmRLnXyvqomAkCGSadiW/i5nBEBDV/zJ/rXp\n0QWrmrpfvjnMF6g26m4sj6Pfs5zoSV1+FEidqYDcytUPJnpR55Ulpshf57TGuFbx\n1SCnda1dmm3TzAzzKTc6MbSPV0krMyAgCP7E7wKBgFXijTPUDioRRQEe9pQz+eiD\nFzhFbHUcPPrqXu78EfSbsexaVCpK4qZtdNmtWDT/rhyzX4Hi6zthUpi4LgM0nAVM\nu3w5WX5JG0s+O3dEKoLgoXF1UBk/qfw50iqIZDfJNV38W889McuOQbgvzIusObrH\nsJIENSks1k/nLQx6N7npAoGAUAEzDdzVx3LeWJuUwwCY06oM4Azxrw8nxochvco5\nd6YAZI11ZN7NbaVRFQG5MA7p8QZlbKDYyQdgUFQJl+3qP8bSuB6Oix9Ncu1Panbt\nAaWVGz14+E3ej+hDYkqIlZVJSaStoE978NyuETDEvaXAD40/5yjoVclwsKYGGtM2\n2jcCgYA6v1tvd2QdDeijiSRnXAeJ1hDLB8Jj2WJqnDZ7dQ5+XTIKfY4POIpHCPx8\n6Uk4NCnyJGmBHog1M7Bjb/o0c1UTid6CNBI4ciVaRyXXcy6Czup2EhkiNGom2883\n8+9pdxShKf0pJCqdZxJdVmg1NHZnr20PwN7PASbVcRg3t+wt2g==\n-----END RSA PRIVATE KEY-----')
private_key_file.seek(0)
ki = paramiko.RSAKey.from_private_key(private_key_file)
Related
I'm trying to connect to SFTP server that is hosted locally (that's a POC ...). I'm using python 3.9 and the library paramiko.
The code I use is the following :
import paramiko
import sys
def main() -> None:
hostkeys = paramiko.hostkeys.HostKeys("known_hosts.txt")
ip = "127.0.0.1"
username = "my_username"
password = "my_password"
# As per the paramiko doc. The host fingerprint is stored using the ed25519 algorithm
hostFingerprint = hostkeys.lookup(ip)["ssh-ed25519"]
try:
tp = paramiko.Transport(ip, 22)
tp.connect(username=username, password=password, hostkey=hostFingerprint)
# Upload operations happening here...
tp.close()
except Exception as e:
print(e)
finally:
return None
The file known_hsts.txt has been generated via Powershell cmd : ssh-keyscan 127.0.0.1 > C:\Users\my_username\PycharmProjects\POC\known_hosts.txt.
When i run the script i don't understand why hostkeys.keys() == []
When i look at the file known_hosts.txt I see the different keys : ssh-rsa, ssh-ed25519, etc.
Is it Possible if the Connection to a Server cuts off for some reason that I get a Text or something, so I know that the Error has something to do with the Server?
import paramiko
import time
def connSFTP(ssh_key_filepath,host,user):
#Fehleroptionen 1. Pfad zum SSH-KeyError
#-SSH-Key vorhanden?
#2.Host und/oder Username ist falsch
k = paramiko.RSAKey.from_private_key_file(ssh_key_filepath) #SSH KEY
c = paramiko.SSHClient()
c.set_missing_host_key_policy(paramiko.AutoAddPolicy())
c.connect( hostname = host, username = user , pkey = k )
sftp = c.open_sftp()
return sftp
def main():
ssh_key_filepath = '/home/dtv/.ssh/id_rsa'
hostname = 'HostAdress'
username = 'user'
sftp = connSFTP(ssh_key_filepath,hostname,username)
print('Connected')
time.sleep(30)
#sftp.close()
if __name__ == '__main__':
main()
I built in a sleep, so I can kill the procedure for the Connection and Simulate the Connection lost in time.
You should use exception handling with the following:
Raises:
BadHostKeyException – if the server’s host key could not be verified
Raises:
AuthenticationException – if authentication failed
Raises:
SSHException – if there was any other error connecting or establishing an SSH session
Raises:
socket.error – if a socket error occurred while connecting
Paramiko api documentation link: http://docs.paramiko.org/en/1.15/api/client.html#paramiko.client.SSHClient.connect
I want to connect to my remote machine with python module paramsiko. First, I try with password, it is ok, like this:
import paramiko
import socket
import os
paramiko.util.log_to_file('demo_sftp.log')
username = 'xxxxx'
hostname = 'dev81'
Port = 22
password = "xxxxx"
t = paramiko.Transport((hostname, Port))
t.connect(None, username, password)
sftp = paramiko.SFTPClient.from_transport(t)
# dirlist on remote host
dirlist = sftp.listdir('.')
print("Dirlist: %s" % dirlist)
then I want to remove password, use key, according to demo in demo_sftp like this:
import paramiko
import socket
import os
paramiko.util.log_to_file('demo_sftp.log')
username = 'xxxxx'
hostname = 'dev81'
Port = 22
password = None
host_keys = paramiko.util.load_host_keys(os.path.expanduser('~/.ssh/known_hosts'))
hostkeytype = host_keys[hostname].keys()[0]
hostkey = host_keys[hostname][hostkeytype]
print('Using host key of type %s' % hostkeytype)
t = paramiko.Transport((hostname, Port))
t.connect(hostkey, username, password, gss_host=socket.getfqdn(hostname),
gss_auth=True, gss_kex=True)
sftp = paramiko.SFTPClient.from_transport(t)
# dirlist on remote host
dirlist = sftp.listdir('.')
print("Dirlist: %s" % dirlist)
This fail with Exception paramiko.ssh_exception.BadAuthenticationType: ('Bad authentication type', [u'publickey', u'password']) (allowed_types=[u'publickey', u'password'])
And I can login with command ssh xxxxx#dev81 without password
If you Have passphrase for the Key pair
It throws this error
paramiko.ssh_exception.BadAuthenticationType: ('Bad authentication type', [u'publickey', u'password']) (allowed_types=[u'publickey', u'password'])
To Resolve this
ssh.connect('<your ip>', port=22, username='<username>',password='<passphrase for the RSA key>', key_filename='<full path of the private key>')
So I've heard that it's an incredibly bad idea to host media on the same server as your Django/Apache web framework. So to solve this problem with my iOS app and greatly improve server side performance in the long run would be to upload the images to the Django server and then right after that, transfer the newly uploaded image to a separate server dedicated to hosting user profile images.
So using Paramiko I can send files directly to the directory of my choosing, but this does not seem to be working in my Django view.
Here's an incredible simple python script using Paramiko that allows you to upload files to a remote server via SMTP:
import base64
import getpass
import os
import socket
import sys
import traceback
import paramiko
#from paramiko.py3compat import input
# setup logging
#paramiko.util.log_to_file('demo_sftp.log')
port = 22
hostname = '198.199.101.115'
password = 'XXXXXXXXX'
username = 'root'
hostkeytype = 'ecdsa-sha2-nistp256'
hostkey = 'XXXXXXXXX'
try:
host_keys = paramiko.util.load_host_keys(os.path.expanduser('~/.ssh/known_hosts'))
except IOError:
try:
# try ~/ssh/ too, because windows can't have a folder named ~/.ssh/
host_keys = paramiko.util.load_host_keys(os.path.expanduser('~/ssh/known_hosts'))
except IOError:
print('*** Unable to open host keys file')
host_keys = {}
if hostname in host_keys:
hostkeytype = host_keys[hostname].keys()[0]
hostkey = host_keys[hostname][hostkeytype]
print('Using host key of type %s' % hostkeytype)
# now, connect and use paramiko Transport to negotiate SSH2 across the connection
t = paramiko.Transport((hostname, port))
t.connect(username=username, password=password, hostkey=hostkey)
sftp = paramiko.SFTPClient.from_transport(t)
# dirlist on remote host
dirlist = sftp.listdir('.')
print("Dirlist: %s" % dirlist)
# copy this demo onto the server
target_directory = '3COOL'
sftp.put('test_image.jpg', target_directory+'/test_image.jpg')
t.close()
So this script works perfectly fine when I run the script on my remote server which successfully transfers the jpeg image to another remote server I own. So I'd like to just cut and paste this script into my Django view which will transfer all freshly uploaded images to a different server, here's how this looks:
def profile_picture(request):
if request.POST:
form = UserProfileForm(request.POST, request.FILES)
obj = form.save(commit=False)
obj.user_id = request.user.id
obj.profile_picture = obj.profile_picture
check = UserProfile.objects.filter(user_id=request.user.id)
if check:
oldup = UserProfile.objects.get(user_id=request.user.id)
oldup.delete()
obj.save()
formNew = UserProfileForm()
args = {}
args.update(csrf(request))
args['uid'] = request.user.id
args['form'] = formNew
# CONVERT THE IMAGE TO A SMALLER SIZE
basewidth = 256
img = Image.open('var/www/bitcraft/static/'+str(obj.profile_picture))
wpercent = (basewidth/float(img.size[0]))
hsize = int((float(img.size[1])*float(wpercent)))
img = img.resize((basewidth,hsize), PIL.Image.ANTIALIAS)
img.save('var/www/bitcraft/static/'+str(obj.profile_picture))
import getpass
import os
import socket
import sys
import traceback
import paramiko
from paramiko.py3compat import input
# TRANSFER THIS IMAGE TO MEDIA HOSTING SERVER
port = 22
hostname = '198.199.101.115'
password = 'pcorysatqwrw'
username = 'root'
hostkeytype = 'ecdsa-sha2-nistp256'
hostkey = 'pcorysatqwrw'
try:
host_keys = paramiko.util.load_host_keys(os.path.expanduser('~/.ssh/known_hosts'))
except IOError:
try:
host_keys = paramiko.util.load_host_keys(os.path.expanduser('~/ssh/known_hosts'))
except IOError:
print('*** Unable to open host keys file')
host_keys = {}
if hostname in host_keys:
hostkeytype = host_keys[hostname].keys()[0]
hostkey = host_keys[hostname][hostkeytype]
print('Using host key of type %s' % hostkeytype)
t = paramiko.Transport((hostname, port))
t.connect(username=username, password=password, hostkey=hostkey)
sftp = paramiko.SFTPClient.from_transport(t)
dirlist = sftp.listdir('.')
print("Dirlist: %s" % dirlist)
target_directory = '3COOL'
sftp.put('var/www/bitcraft/static/'+str(obj.profile_picture), target_directory+str(obj.profile_picture))
t.close()
return render_to_response('profile.html', args, RequestContext(request))
else:
formNew = UserProfileForm()
args = {}
args.update(csrf(request))
args['uid'] = request.user.id
args['form'] = formNew
return render_to_response('profile.html', args, RequestContext(request))
Ultimately though, adding the simple Python script has not worked due to a strange error:
AttributeError at /upload_profile/ 'str' object has no attribute 'get_name'
Exception Location: /usr/local/lib/python2.7/dist-packages/paramiko-1.14.0-py2.7.egg/paramiko/transport.py in connect, line 873
/srv/www/django/chatfeed/views.py in profile_picture
t.connect(username=username, password=password, hostkey=hostkey)
I don't understand what's causing this... is this related to directory permission denied??
The problem is that you're passing a string for hostkey. As the docs show, that's supposed to be a PKey—that is, an object that wraps a private key.
And if you click on PKey, you'll see that a PKey has a get_name method. A string obviously doesn't. Hence the error.
You have some code that's supposed to use Paramiko to load a hostkey out of ~/.ssh/known_hosts at the top of your script. But if that hostname in host_keys is false, it won't do anything, and you'll end up with the default values you stuck at the top of the script:
hostkeytype = 'ecdsa-sha2-nistp256'
hostkey = 'XXXXXXXXX'
I don't know what you have in place of that 'XXXXXXXXX' in your real code, but presumably it's a string, and therefore not a valid hostkey.
I don't understand what's causing this... is this related to directory permission denied??
You'd have to tell us what you're talking about. Exactly what error or warning or whatever are you getting, and where? If the server is running as a user who doesn't have access to its own ~/.ssh, so you're seeing a "directory permission denied" warning of some kind and your host keys aren't getting loaded, then yes, this problem is indirectly related to that one—as in, if the host actually was in known_keys, and you solved the permissions problem, that would mask the error in your code, so you wouldn't notice it. But there are plenty of other things you could mean where the answer would be no, that has nothing to do with anything.
key = paramiko.RSAKey.from_private_key_file(filename='openssh key f',password='passphrase')
The keys file does not support .ppk format.
This is the error am getting
ri#ri-desktop:~/workspace/ssh$ python ssh.py
Establishing SSH connection to: upload.partner.com 19321 ...
Failed loading ~/workspace/ssh/rsa_private_key
No handlers could be found for logger "paramiko.transport"
Trying ssh-agent key b747f6899b3a450e63bc6faab1625686 ... failed! key cannot be used for signing
*** Caught exception: <type 'exceptions.AttributeError'>: 'NoneType' object has no attribute 'get_fingerprint'
============================================================
Total files copied: 0
All operations complete!
============================================================
ri#ri-desktop:~/workspace/ssh$
This is my setup code. i took this setup code from activstate . I given correct path only and my doubt is firstly the error showing Failed loading ~/workspace/ssh/rsa_private_key. but its showing some ssh-agent key failed what is that?
hostname = 'upload.partner.com' # remote hostname where SSH server is running
port = 19321
username = 'music--test'
password = 'grg'
rsa_private_key = r"~/workspace/ssh/rsa_private_key"
dir_local='~/workspace/ssh/New/'
dir_remote = "remote_machine_folder/subfolder"
glob_pattern='*.*'
import os
import glob
import paramiko
import md5
rsa = None
def agent_auth(transport, username):
ki = None
#ppk = None
Attempt to authenticate to the given transport using any of the private
keys available from an SSH agent or from a local private RSA key file (assumes no pass phrase).
try:
ki = paramiko.RSAKey.from_private_key_file(rsa_private_key)
except Exception, e:
print 'Failed loading {0}'.format (rsa_private_key, e)
agent = paramiko.Agent()
agent_keys = agent.get_keys() + (ki,)
if len(agent_keys) == 0:
return
for key in agent_keys:
print 'Trying ssh-agent key {0}'.format(key.get_fingerprint().encode('hex')),
try:
transport.auth_publickey(username, key)
print '... success!'
return
except paramiko.SSHException, e:
print '... failed!', e
hostkeytype = None
hostkey = None
files_copied = 0
try:
host_keys = paramiko.util.load_host_keys(os.path.expanduser('~/.ssh/known_hosts'))
except IOError:
try:
# try ~/ssh/ too, e.g. on windows
host_keys = paramiko.util.load_host_keys(os.path.expanduser('~/ssh/known_hosts'))
except IOError:
print ' Unable to open host keys file'
host_keys = {hostname:'upload.partner.com'}
if hostname in host_keys:
hostkeytype = host_keys[hostname].keys()[0]
hostkey = host_keys[hostname][hostkeytype]
print 'Using host key of type {0}'.format(hostkeytype)
try:
print 'Establishing SSH connection to:', hostname, port, '...'
t = paramiko.Transport((hostname, port))
t.connect()
agent_auth(t, username)
if not t.is_authenticated():
print 'RSA key auth failed! Trying password login...'
t.connect(username=username, password=password, hostkey=hostkey)
else:
sftp = t.open_session()
sftp = paramiko.SFTPClient.from_transport(t)
try:
sftp.mkdir(dir_remote)
except IOError, e:
print '(assuming ', dir_remote, 'exists)', e
for fname in glob.glob(dir_local + os.sep + glob_pattern):
is_up_to_date = False
if fname.lower().endswith('xml'):
local_file = os.path.join(dir_local, fname)
remote_file = dir_remote + '/' + os.path.basename(fname)
try:
if sftp.stat(remote_file):
local_file_data = open(local_file, "rb").read()
remote_file_data = sftp.open(remote_file).read()
md1 = md5.new(local_file_data).digest()
md2 = md5.new(remote_file_data).digest()
if md1 == md2:
is_up_to_date = True
print "UNCHANGED:", os.path.basename(fname)
else:
print "MODIFIED:", os.path.basename(fname),
except:
print "NEW: ", os.path.basename(fname),
if not is_up_to_date:
print 'Copying', local_file, 'to ', remote_file
sftp.put(local_file, remote_file)
files_copied += 1
t.close()
except Exception, e:
print '*** Caught exception: %s: %s' % (e.__class__, e)
try:
t.close()
except:
pass
print '=' * 60
print 'Total files copied:',files_copied
print 'All operations complete!'
print '=' * 60
can you help me to solve this error
EDIT After much to and fro, the solution was simply to add user's private key to she ssh agent via ssh-add.
Actually, you might be trying to use your public key, not your private key.
The file name "id-rsa.pub" looks suspiciously like a public key. The corresponding private key is usually named "id-rsa". Public keys look something like this:
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCUmHZlySQqmZCGgE0NKWYyYlPHb3g1Bwdll2ztngUWNkrDSWGmLq6IqJP9EwwxungwJkdkR/U86gFv5MQfQ92+0ote7pUXOACwHfqvIoUXXFI3ZLo/C2cuqDIO7fcO50KKGFAuWbjTd3rugbpoMnNqT99wz/1lrCkTsJLd0YxtRo/QsJ8jiZXRuaEzbdXKwZJaP8G3eBHSMiEa1781yWklk50xxLk2qtpWVzen+Om6InbQ2cR6bBvfiA4B3LES53ccmMfzrCygjl8B6yaV3NI60Re5oNdyNrPZgH4VXf5p4VwrKpY4dCcJZyNmHlFhJlTgZu25uKAbp8Wk4u1ky0vJ mhawke#localhost.localdomain
Whereas unencypted private keys look something like this:
-----BEGIN RSA PRIVATE KEY-----
MIICXQIBAAKBgQCfqBLoK4Vec7r0df4a2CYNzmhJn74qIDqbJnkGasHcN5/GYuDv
.
.
xLCNrVMXYPd1I7L5NGzZalaTrS+DkgLwNvGhkVGKUGao
-----END RSA PRIVATE KEY-----
and encrypted private keys like this:
-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: AES-128-CBC,1ACD09B7F078AEB84B9A109979B77CBB
LDEuf08/xMGsHyesZxFGkRNHf8C78vpdDJyBBManOt/mRf/5fkjOel8RgoH4oYEz
.
.
tKjd+PlR4WLluMPFeHujdqhvyC4fQeFzWqak+rlUG5o3lm+TAcKqjypAEU4RVUuW
-----END RSA PRIVATE KEY-----
Check to see if you are using the correct key file. You can test it by:
openssl rsa -text -noout -in private_key_file
You shouldn't see any errors.
The first problem is occurring in this block of code
rsa_private_key = r"~/workspace/ssh/rsa_private_key"
.
.
.
try:
ki = paramiko.RSAKey.from_private_key_file(rsa_private_key)
except Exception, e:
print 'Failed loading {0}'.format (rsa_private_key, e)
I don't think that from_private_key_file() handles file expansion, so the ~ is interpreted literally as a tilde. Try changing rsa_private_key to the absolute file name.
Also the print statement in your except clause doesn't print out the exception. I suggest changing it to print 'Failed loading {0} : {1}'.format (rsa_private_key, e). You will probably then see the cause of the problem in the following error message:
Failed loading ~/workspace/ssh/rsa_private_key : [Errno 2] No such file or directory: '~/workspace/ssh/rsa_private_key'
Also, you may need to supply a password to from_private_key_file() if your key is encrypted.