Monday, August 2, 2021

How to: non-interactive login to devices that don't support pubkey auth

tl;dr: sshpass with some shell functions and ssh_config tweaking. scroll down for configs.

more of my job is shifting to python/ansible/NMS, but at the end of the day I'm still a cli jockey. I ssh into devices all the time, and most of the deployment I manage doesn't support pubkey auth (yet). so I get to type my ssh password over and over. until now I accepted that's just life until we get everything up to cat9k. but then something snapped, and I went on a mission to find a way to get (reasonably secure) non-interactive login, without rsa keys.

sshpass does exactly what I want. it allows passing a plaintext password to ssh, simulating non-interactive login. But I didn't want to store my password in plaintext on my machine, or have to type it in over and over. I want to type my password once per session, stored in memory only, and forgotten when I close bash.

It got tricky when looping the jumphost into the mix, which can use pubkey auth. In the end I got what I wanted by using sshpass's environment variable option (-e). Passwords are never stored on disk, won't show up in bash history or ps, but persist across a bash session until I close it (or actively deauth.)

relevant bits of ~/.ssh/config:

`` host jumphost IdentityFile ~/.ssh/id_rsa User austindcc Hostname jumphost.example.com Port 22 ProxyCommand none PreferredAuthentications publickey # Also addAcceptEnv SSHPASS` to jumphost's /etc/ssh/sshd_config SendEnv SSHPASS

host * ProxyCommand ssh -W %h:%p -q austindcc@jumphost PreferredAuthentications keyboard-interactive # We need to disable StrictHostKeyChecking because sshpass intercepts the new hostkey confirmation, and returns nothing. Note: This does NOT suppress the key mismatch alarm, only the initial connection prompt to a new device. # Also add this to the jumphost's /etc/ssh/sshd_config StrictHostKeyChecking no ```

~/.bash_profile:

``` function auth() { read -sp 'Cisco password: ' pass export SSHPASS=$pass }

function deauth() { export SSHPASS='' }

function jump() { # calling jumphost with no arguments connects to jumphost directly if [ "$#" -eq 0 ]; then ssh jumphost fi if [ -z "$SSHPASS" ]; then auth fi sshpass -e ssh "$@" } ```

For extra frictionless logins, I added privilege 15 in my configs to drop into enable mode right after login. The cisco.ios.ios_user ansible module can roll this out easily.

Now after first login or manually calling auth, just type jump switch01 and drop straight into an enable-mode prompt. awesome!

Limitations:

  • All devices must use the same password, and I can't think of an easy way to overcome this, as sshpass doesn't let us specify a different environment varaible
  • Doesn't try pubkey auth first. could be done, but may add a few hundreds of ms to login times on non-pubkey-auth nodes. irrelevant for me since we don't use pubkey on managed nodes yet


No comments:

Post a Comment