Creating an SSH Key Pair for User Authentication with Expect in Bash - bash

I have tried the following steps to set ssh passwordless (SSH Key Pair Authentication)login.
Set ip and port in bash.
ip="xxxx"
port="xxxx"
Set ssh config file on client side
cat > $HOME/.ssh/config <<EOF
Host $ip
IdentityFile $HOME/.ssh/id_rsa
User root
EOF
Create a ssh key pair on client side
ssh-keygen -t rsa -f $HOME/.ssh/id_rsa -q -b 2048 -N ""
Push id_rsa into ssh server from client side.
Prepare for ssh server
ssh -p $port root#$ip "mkdir -p /root/.ssh"
Push authorized file into ssh server
scp -P $port id_rsa.pub root#$ip:/root/.ssh/authorized_keys
Set permission for authorized file
ssh -p $port root#$ip "chmod 700 .ssh; chmod 640 .ssh/authorized_keys"
Succeeded!
Now i want to write all steps into a one-click bash script for the job.
Here is my try.
#! /bin/bash
ip="xxxx"
port="xxxx"
pass="yyyy"
cat > $HOME/.ssh/config <<EOF
Host $ip
IdentityFile $HOME/.ssh/id_rsa.bwg_root
User root
EOF
ssh-keygen -t rsa -f $HOME/.ssh/id_rsa.bwg_root -q -b 2048 -N ""
cd $HOME/.ssh
/usr/bin/expect <<EOF
spawn ssh -p $port root#$ip "mkdir -p /root/.ssh"
expect "password:"
send "$pass\r"
spawn scp -P $port id_rsa.pub root#$ip:/root/.ssh/authorized_keys
expect "password:"
send "$pass\r"
spawn ssh -p $port root#$ip "chmod 700 .ssh; chmod 640 .ssh/authorized_keys"
expect "password:"
send "$pass\r"
EOF
It got the following output info:
spawn ssh -p xxxx root#yyyy mkdir -p /root/.ssh
root#yyyy's password: spawn scp -P xxxx id_rsa.bwg.pub root#yyyy:/root/.ssh/authorized_keys
root#yyyy's password: spawn ssh -p xxxx root#yyyy chmod 700 .ssh; chmod 640 .ssh/authorized_keys
Why and how to fix it?

I'd simplify it with sshpass.
#!/bin/bash
ip="x.x.x.x"
port="xx"
export SSHPASS="yyy"
cat >$HOME/.ssh/config <<EOF
Host $ip
IdentityFile $HOME/.ssh/id_rsa.bwg_root
User root
EOF
ssh-keygen -t rsa -f "$HOME/.ssh/id_rsa.bwg_root" -q -b 2048 -N ""
cd "$HOME/.ssh" || exit 1
sshpass -e ssh -oStrictHostKeyChecking=no -p "$port" "root#$ip" "mkdir -p -m 700 /root/.ssh"
sshpass -e scp -oStrictHostKeyChecking=no -P "$port" id_rsa.bwg_root.pub "root#$ip:/root/.ssh/authorized_keys"
sshpass -e ssh -oStrictHostKeyChecking=no -p "$port" "root#$ip" "chmod 640 .ssh/authorized_keys"
Btw: I replaced last id_rsa.pub with id_rsa.bwg_root.pub and added -m 700 to mkdir and removed chmod 700 .ssh.

Use ssh-copy-id to push the new key to the remote host. You'll need to enter the password for that login, of course, but it's the last time you'll have to use it.
#!/bin/bash
ip="x.x.x.x"
port="xx"
id_file=$HOME/.ssh/id_rsa_$ip
cat > $HOME/.ssh/config <<EOF
HOST $ip
IdentityFile $id_file
User root
EOF
ssh-keygen -t rsa -f "$HOME/.ssh/id_rsa_$ip" -q -b 2048 -N ""
ssh-copy-id -i "$id_file" -p "$port" root#"$ip"
As a general rule, always look for a non- (or less) interactive solution using existing tools before trying except.

Related

Empty ssh invitation (no "user#host:~$") when run command after connect (sh script, sshpass)

Client OS: MacOS 12.1, Server OS: Linux Debian 9 (any server)
case 1:
#!/bin/bash
sshpass -p mypass ssh user#host.ru -o StrictHostKeyChecking=no
works fine:
case 2:
#!/bin/bash
sshpass -p mypass ssh user#host.ru -o StrictHostKeyChecking=no "cd /var/www ; git status ; /bin/bash"
Output of "git status" works fine, but
no "user#host:~$" message in output (input is active).
I tried:
/bin/bash
bash -l
(in server "echo $SHELL" shows /bin/bash)
How to fix it?
Use ssh -t and && inside commands list
#!/bin/bash
sshpass -p mypass ssh -t user#host.ru -o StrictHostKeyChecking=no "cd /var/www && git status && /bin/bash"

Run bash script on remote server

I'm trying to run a bash script on the remote server that is already on the remote server. I'm using ssh pass to do it but I'm seeing errors
test.sh (resides on the remote server)
#!/usr/bin/env bash
echo "This is test"
adb start-server
sshpass command (I'm running this sshpass command from docker ubuntu image
sshpass -p password ssh -oStrictHostKeyChecking=no -oCheckHostIP=no user#host "bash -s" < /Users/user/Documents/workspace/test.sh
I also tried
sshpass -p password ssh -oStrictHostKeyChecking=no -oCheckHostIP=no user#host 'cd /Users/user/Documents/workspace/; sh test.sh'
I get this error message
bash: /Users/user/Documents/workspace/test.sh: No such file or directory
The examples you're showing are for a local script, and you said it's a remote script.
sshpass -p password ssh -oStrictHostKeyChecking=no -oCheckHostIP=no user#host "bash /path/to/test.sh"
that ought to do it.
you can try to find your test.sh on the remote computer:
sshpass -p password ssh -oStrictHostKeyChecking=no -oCheckHostIP=no user#host "find ~/ -name \"test.sh\""
Try with here-document:
sshpass -p password ssh -oStrictHostKeyChecking=no -oCheckHostIP=no -T user#host <<EOF
bash /Users/user/Documents/workspace/test.sh
EOF
Include -T option for ssh command, as mentioned above, to disable pseudo-tty.
[AT REMOTE MATCHINE] Ensure that path of adb executable is included in PATH environment variable. Else, specify it with absolute path in the Shell script.

How to run shell script with sudo inside through nohup on remote machine

I ran the following command from my local machine:
ssh -i key remote_host "nohup sh test.sh > nohup.out 2> nohup.err < /dev/null &"
then I got error: sudo: sorry, you must have a tty to run sudo
I added -tt option:
ssh -tt -i key remote_host "nohup sh test.sh > nohup.out 2> nohup.err < /dev/null &"
I checked on the remote, test.sh was not running (there was no process id).
I took out the nohup, everything runs fine, ssh -tt -i key remote_host "sh test.sh" but I need to use nohup. Can someone help me? Thanks a lot!
One remote_host: test.sh script:
#!/bin/bash
sudo iptables -A OUTPUT -p tcp --dport 443 -j DROP
sleep 30
sudo iptables -D OUTPUT -p tcp --dport 443 -j DROP
sudo is probably trying to prompt you for a password. You need to set up NOPASSWD in your remote_host's sudoers file or you can use expect

multiple commands in spawn script to copy keys

I'm trying to create a script to copy ssh keys to multiple servers for passwordless login. I have a list of servers entered one per line in serverlist.txt. Below is the script I created.
#!/usr/bin/expect -f
set f [open "serverlist.txt"]
set hosts [split [read $f] "\n"]
close $f
foreach host $hosts {
spawn -noecho sh -c "cat ~/.ssh/id_rsa.pub | ssh -t -o StrictHostKeyChecking=no $host 'mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys'"
expect "assword:";
send "abc123\r"; # sending the password
expect "$"; #expecting the $prompt
send "exit\r";
interact
}
Im getting below error while running this script
send: spawn id exp4 not open
while executing
"send "exit\r""
("foreach" body line 6)
invoked from within
"foreach host $hosts {
spawn -noecho sh -c "cat ~/.ssh/id_rsa.pub | ssh -t -o StrictHostKeyChecking=no $host 'mkdir -p ~/.ssh && cat >> ~/.ssh/authori..."
(file "sshkeys" line 6)
If i commented below lines I'm getting diff error
#expect "assword:";
#send "abc123\r";
#expect "$";
#send "exit\r";
Pseudo-terminal will not be allocated because stdin is not a terminal.
user#1.1.1.1's password:
Pseudo-terminal will not be allocated because stdin is not a terminal.
ssh: mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys: Name or service not known
Note:
ssh-copy-id is not available.
None of the target servers have the .ssh directory created.
Can somebody help me to identify the issue.

How to not echo here document to terminal?

I have a script that prompts the user for their sudo password, and then iterates through a list of hosts and performs commands on remote hosts. I can 'read -s' to get their password silently, but each time their password is used on a remote host, it's echoed back to the terminal. Changing stty on the local host doesn't help. Example:
#!/bin/sh -x
echo "Enter sudo pass:"
read -s SUDOPASS
stty_orig=$(stty -g)
stty -echo
ssh -tt remote_host sudo cat /etc/cma.conf <<EOP
$SUDOPASS
EOP
stty $stty_orig
The output still includes the password:
+ ssh -tt remote_host sudo cat /etc/cma.conf
My_P4ssW0rd!
Password:
<?xml version="1.0" encoding="UTF-8"?>
...
It also doesn't help to play with stty on the remote host:
stty_orig=$(ssh -t remote_host stty -g)
ssh -t remote_host stty -echo
ssh -tt remote_host sudo cat /etc/cma.conf <<EOP
$SUDOPASS
EOP
ssh -t remote_host stty $stty_orig
FWIW, I'm mainly concerned with OSX bash/sh
Try expect:
#!/bin/sh
echo "Enter sudo pass:"
read -s SUDOPASS
expect -c 'spawn ssh -tt remote_host sudo cat /etc/cma.conf ; expect -re "\\\[sudo\\\] password for .*:"; send "'"$SUDOPASS"'\n";interact'
To be honest, I haven't spotted the problem here. But I often redirect the output manually to silence it:
ssh -tt remote_host sudo cat /etc/cma.conf <<EOP >& /dev/null
I'm not sure if this will help.

Resources