26

This code helps me make an ssh connection. I know that set_missing_host_key_policy helps when the key is not found in the known_hosts. But it is not behaving like the actual ssh, because after the first time I run this code, I assumed that that the host_key would be added to known_hosts and that I need not have the function set_missing_host_key_policy() anymore. But, I was wrong (paramiko.ssh_exception.SSHException). How can I permanently add the host_key to known_hosts using paramiko? (As a certain part of the backend code is written in 'C' and it needs the host_key to be found in known_hosts)

Or am I misunderstanding something? I would need some guidance on this...

import paramiko

client = paramiko.SSHClient()
client.load_system_host_keys()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
client.connect(hostname=str(host),username =str(user),password=str(pswd))
CharlesB
  • 86,532
  • 28
  • 194
  • 218
nidHi
  • 833
  • 3
  • 10
  • 21

3 Answers3

31

From the package documentation, compare

client.load_system_host_keys(filename=None)

Load host keys from a system (read-only) file.  Host keys read with
this method will not be saved back by `save_host_keys`.

with

client.load_host_keys(filename)

Load host keys from a local host-key file.  Host keys read with this
method will be checked after keys loaded via `load_system_host_keys`,
but will be saved back by `save_host_keys` (so they can be modified).
The missing host key policy `.AutoAddPolicy` adds keys to this set and
saves them, when connecting to a previously-unknown server.

So to make Paramiko store any new host keys, you need to use load_host_keys, not load_system_host_keys. E.g.

client.load_host_keys(os.path.expanduser('~/.ssh/known_hosts'))

But it's generally a good idea to avoid using AutoAddPolicy, since it makes you open to man-in-the-middle attacks. What I ended up doing was to generate a local known_hosts in the same folder as the script:

ssh -o GlobalKnownHostsFile=/dev/null -o UserKnownHostsFile=./known_hosts user@host

and then load this file instead:

client.load_host_keys(os.path.join(os.path.dirname(__file__), 'known_hosts'))

This way I can distribute the known_hosts together with my script and run it on different machines without touching the actual known_hosts on those machines.

Martin Prikryl
  • 188,800
  • 56
  • 490
  • 992
danmichaelo
  • 1,706
  • 1
  • 25
  • 30
  • If you generate `known_hosts` using `ssh`, it's basically the same as if you generate it using `AutoAddPolicy` (of course, I mean if you generate it yourself and then distribute it with the script). +1 – Martin Prikryl Dec 05 '17 at 07:52
  • 1
    I find it is a little bit cleaner to use the Path library: hostkeys = Path.cwd() / 'known_hosts' client.load_host_keys(hostkeys) – Harper Aug 12 '19 at 13:08
7

If you want to add one specific key in runtime (without any file):

from paramiko import RSAKey
from paramiko.py3compat import decodebytes

client = SSHClient()

# known host key
know_host_key = "<KEY>"
keyObj = RSAKey(data=decodebytes(know_host_key.encode()))

# add to host keys
client.get_host_keys().add(hostname=HOST, keytype="ssh-rsa", key=keyObj)

# login to ssh hostname
client.connect(hostname=HOST, port=PORT, username=USER)...

source: https://github.com/paramiko/paramiko/blob/2.6.0/tests/test_hostkeys.py#L75-L84

Ramon Medeiros
  • 2,272
  • 2
  • 24
  • 41
  • This is ssh. How do you set the known_hosts when the server only allows basic sftp connections? – isaaclw Feb 22 '21 at 18:43
-6

##add user remotely ssh using paramiko

import paramiko
import os

ssh= paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect('192.168.10.49', port=22,username='root', password='abc@123')
def addnewuser():

    uname=input("Type your new Create userName")
    upass=input("Enter Password")



    os.system("useradd -m -p "+upass+" "+uname)

addnewuser()
Ganesh Jat
  • 19
  • 4