Embedding key as string in Paramiko application

Question:

I’m trying to create a single file executable in Python and using Paramiko for my SSH. I need to eliminate external files such as private key files and try to go for embedded strings.

I tried this solution but it’s not working for me:
Paramiko: Creating a PKey from a public key string

How do I accomplish this? Thanks.

Asked By: scottyp

||

Answers:

The solution you mentioned:

key = paramiko.RSAKey(data=base64.b64decode('AAblablabla...'))

works fine however it may be inconvenient to store the key in base64 format.

The following code shows how to use the key stored in "plain-text" format (as key-files in ~/.ssh directory):

import paramiko
import StringIO

my_key = """
-----BEGIN RSA PRIVATE KEY-----
<your key here>
-----END RSA PRIVATE KEY-----"""

pkey = paramiko.RSAKey.from_private_key(StringIO.StringIO(my_key))

ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(hostname='host', username='user', pkey=pkey)

...

ssh.close()

In Python 3:

import io
# ...
pkey = paramiko.RSAKey.from_private_key(io.StringIO(my_key))

See StringIO in Python3

Answered By: teegaar

To add a public key from a string on the ssh client you must set the keyword arg look_for_keys=False then use the MissingHostKeyPolicy classes missing_host_key() method to add the key from your string.

my_pub_key = "xx.xx.xx.xx ecdsa-sha2-nistp256 mlzdHAyNT....."
my_host = my_pub_key.split(' ')[0]
password = 'myFavortitePassword'
username = 'myUsername'

ssh_client=paramiko.SSHClient()

host_key_policy = paramiko.MissingHostKeyPolicy()
host_key_policy.missing_host_key(ssh_client, my_host, my_pub_key)

ssh_client.connect(hostname= my_host
                            ,username=username
                            ,password=password
                            ,port=22
                            ,look_for_keys=False)
Answered By: SpicestMemeLord

I had the same issue where I’m trying to not have private key files using AWS secrets manager, just got it to work with the following. Notice the n in the privatekey.

import io

privatekey = io.StringIO('-----BEGIN OPENSSH PRIVATE KEY-----nRestOfTheKeyn-----END OPENSSH PRIVATE KEY-----')
pkey = paramiko.Ed25519Key.from_private_key(privatekey)

Then when you’re connecting

aws_ssh = paramiko.SSHClient()
aws_ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
aws_ssh.connect(hostname='YOURHOST', username='YOURUSERNAME', pkey=pkey)

Now, however, if you’re like me and using this for Lambda+Secrets Manager, and the secrets manager has a key+value and you’re pulling the value of this privatekey from there. One thing to note is that secrets manager will escape the n and turn it into \n. To fix that, modify the above code to replace the \n to n.

awskeytemp = secrets['YOURKEY'].replace('\n', 'n')
privatekey = io.StringIO(awskeytemp)
pkey = paramiko.Ed25519Key.from_private_key(privatekey)
Answered By: Kush-Work