How to write SFTP script without expect? - bash

I have this script but it required expect package to work can we have any other way to upload file over SFTP with out expect because our security team not allowed to install expect package over production server.
my SFTP upload code.
/usr/bin/expect<<EOD
spawn /usr/bin/sftp -o Port=$PORT master#$HOST
expect "password:"
send "$PASSWORD\r"
expect "sftp>"
send "put $SOURCE_FILE $TARGET_DIR\r"
expect "sftp>"
send "bye\r"
EOD
Can some one help me to convert this to without using expect.
our SFTP server work with username password

The OpenSSH sftp client does not have a native support for providing a password for automation.
So you have to workaround that somehow:
fake user input using expect or sshpass
use public key authentication
use any other (less common) password-less authentication method

A good solution is to use lftp command which allows providing password and running sftp commands in only one command line like this:
lftp sftp://$HOST -u username,password -e "put $SOURCE_FILE $TARGET_DIR;bye"

Related

Can I pass bash arguements to an expect environment?

I need to automate an openvpn connection to a server that requires me to enter a password.
I can do this with expect but I don't want to keep the password in plain text in the script.
I found encpass to help encrypt the password which I just need to source and get it to get the encrypted version of the password.
The problem comes when I try to pass the unencrypted password to expect. From what I understand, expect and bash are 2 different environments and bash cannot run expect. What I have so far is the following:
#!/usr/bin/env bash
source encpass.sh
password=$(get_secret)
{
/usr/bin/expect <<EOF
spawn openvpn /home/pi/client.ovpn
expect "Enter Private Key Password:"
send $password
interact
EOF
}
The end result is I run this and it starts the VPN and the script enters the password in the prompt.
If there is a simpler way of doing it, please let me know.
I have tried to automate it with just openvpn and a --auth-user-pass switch pointing to a file with the password in it but I couldn't get that working either.
Two ideas spring to mind:
if you want to embed expect code into a shell script, use the environment
to pass values, and use a quoted heredoc to avoid quoting hell (don't forget
to "hit enter" for the send command)
#!/usr/bin/env bash
source encpass.sh
password=$(get_secret)
export password
/usr/bin/expect <<'EOF'
spawn openvpn /home/pi/client.ovpn
expect "Enter Private Key Password:"
send "$env(password)\r"
interact
EOF
do it all in expect
#!/usr/bin/env expect
set password [exec bash -c {source encpass.sh && get_secret}]
spawn openvpn /home/pi/client.ovpn
expect "Enter Private Key Password:"
send "$password\r"
interact

sftp file download script

I am trying to download a from from a remote sftp location so for this I am using below script.
#!/bin/bash
expect -c "
spawn sftp remoteUser#xx.xx.xx.xx
expect \"password\"
send \"User#123\r\"
interact "
The problem is in the remote server some information msg configure when you login the server, so because of this password send before this text comes on screen.
Try this -
#!/usr/bin/expect
export PASSD="User#123"
expect -c 'spawn sftp user#xxxxxx.com;
expect "*Password: ";
send "$env(PASSD)\r";
expect "sftp>";
send "cd /home/user \r";
expect "sftp>";
send "get file.txt \r";
expect "sftp>";
send "bye \r"'

Expect script for ssh connection with password and additional operations

I found the following script which gives me the possibility to go to a server without manually type in a required password.
Sadly I don't know how to execute commands after the connection is made :(
#!/usr/bin/expect -f
spawn ssh user#server
expect "assword:"
send "pw123\r"
interact
#the following is not executed anymore
cd /tmp/
The cd /tmp/ command is not executed, does someone know how to do this ?
I don't care about security :)
Key-based authentication is not an option.
Edit:
Ok, I found a solution that fits my needs:
#!/usr/bin/expect -f
spawn user#server
expect "assword:"
send "pw123\r"
expect "> " { send "cd /tmp\r" }
interact
The expect "> " has to be like your prompt.
After the connection is made, you are in the shell of the remote host to which you connected through the script. So to execute any command you will have to execute command manually on the command prompt.
If you want only to execute the command on the remote server automatically without need for ssh then you can use the below command.
#!/usr/bin/expect -f
#Changed here
spawn ssh user#server "cd /tmp && ls"
expect "password:"
send "pw123\r"
interact

expect script unable to fetch server logs into the text file

I am trying to access remote ssh server from a unix client machine. For this i have used expect script which is calling a bash script to fetch some lines from server log file.
Below is my code:
#!/usr/local/bin/expect -f
set pass "password"
set prompt "(%|$|#)"
spawn ssh deployed#172.16.166.111
expect "password:"
send "$pass\r"
expect -re $prompt
send -- "./access_srvr_log.sh\r"
send -- "exit\r"
code for access_srvr_log.sh file:
#!/usr/local/bin/expect
dir="/home/deployer/Desktop/McKinsey-McKinsey-AdminPanel/log"
tail -n 100 $dir/development.log
echo "hello"
echo >> log.txt
i get this error :
./access_srvr_log.sh
-bash: ./access_srvr_log.sh: No such file or directory
Please help. I have tried lot many changes on the above code and finally reached here.
Thanks.
Friends don't let friends use SSH passwords. It's much less secure.
Use ssh-copy-id to copy your public key to the remote server. (It puts the client ~/.ssh/id_rsa.pub into the server .ssh/authorized_keys) Now you can run "ssh deployer#172.16.144.111 ./access_srvr_log.sh", and it won't prompt for a password. That means you no longer need expect and all the odd problems that come with it.
In fact, it's highly recommended that you disable SSH passwords all together.
To make your script even simpler (maintenance-wise) do this:
1) run ssh-keygen -f ~/.ssh/scriptkey on your client (don't enter a password).
2) Put the public part of your key (~/.ssh/scriptkey.pub on the client) into .ssh/authorized_keys on the server. But this time, put command="/home/deployer/access_srvr_log.sh" just before your new key. This tells the server to run that command for that key.
3) Now your script doesn't even need to specify the command, just the private key. (i.e. scp -i ~/.ssh/scriptkey deployer#172.16.144.111 will run the script). This allows the server to change (i.e. move the script, change the script name) without changing the client. It also means someone stealing your (non-password-protected) key can't log in to the server, but only run your log script.
And there are no guessable passwords laying around in scripts. (You are checking your scripts into version control, right?)
You can simplify it down too
#!/bin/bash
{
/usr/bin/expect <<- EOF
spawn ssh deployer#172.16.144.111 "tail -n 100 /home/deployer/Desktop/McKinsey-McKinsey-AdminPanel/log/development.log"
expect "password:"
send "deployer\r"
expect eof
EOF
} |grep -v "deployer#172.16.144.111's password:">> log.txt

Bash Script to SSH into a machine without prompting password and without using keys

I realize this question has been asked a few times but I could not find a relevant answer anywhere in my searching.
I am working in a development environment where security is not an issue and anyone could just guess the password if the thought for a few seconds.
What I am trying to do is simple. I have created an alias function in my local .bashrc file and I would like this function to automatically log into a machine with a default password.
My current implementation looks something like this:
function s () {
ssh root#192.168.1.$1
}
When I run it I get something like this:
~]s 122
ssh root#192.168.1.122
root#192.168.1.122's password:
Using Bash, and not using RSA keys I would like to get this to use the default password 'password'.
I've tried the following where IP and User have already been set.
Do=$(expect -c "
spawn ssh $User#${IP[0]}.${IP[1]}.${IP[2]}.${IP[3]}
expect \"yes/no\"
send \"yes\r\"
expect \"assword\" send \"password\"")
echo $Do
$Do
It gives the follwing error:
Connecting and logging into server using expect
usage: send [args] string
while executing
"send"
invoked from within
"expect "assword" send "password""
Administrator#192.168.1.176's password:
bash: spawn: command not found...
Using the following command I am able to connect a machine. If I remove the interact it just runs the uptime command and closes the connection. With the interact command I am unable to see what I am typing or actually interact with the machine. Any ideas?
Do=$(expect -c "spawn ssh $User#${IP[0]}.${IP[1]}.${IP[2]}.${IP[3]}; set timeout 4; expect \"assword\"; send \"password\n\"; expect \"test\"; send \"uptime\n\"; interact;");echo $Do;
You can do this with the expect tool: http://expect.sourceforge.net/
It's widely available, so depending on your system, the equivalent of sudo apt-get install expect or yum install expect will install it.
Here's an example of an expect script with ssh. This logs you in and gives you control of the interactive prompt:
#!/usr/bin/expect
set login "root"
set addr "127.0.0.1"
set pw "password"
spawn ssh $login#$addr
expect "$login#$addr\'s password:"
send "$pw\r"
expect "#"
send "cd /developer\r"
interact
Here's an example of how to use expect as part of a bash script. This logs in with ssh, cd to /var, runs a script, then exits the ssh session.
#!/bin/bash
...
login_via_ssh_and_do_stuff() {
# build the expect script in bash
expect_sh=$(expect -c "
spawn ssh root#127.0.0.1
expect \"password:\"
send \"password\r\"
expect \"#\"
send \"cd /var\r\"
expect \"#\"
send \"chmod +x my_script.sh\r\"
expect \"#\"
send \"./my_script.sh\r\"
expect \"#\"
send \"exit\r\"
")
# run the expect script
echo "$expect_sh"
}
You can leave these snippets in a script on your local system, and then just alias to the scripts.
Also: I know you said security isn't an issue, but I'd like to just note, again, that the "proper" way to ssh without using a password is to use a ssh key-pair =)
Use sshpass which is available in package repositories on major Linux-es.
For example, when password is in password.txt file:
sshpass -fpassword.txt ssh username#hostname
sshpass runs ssh in a dedicated tty, fooling it into thinking it is
getting the password from an interactive user.

Resources