Automatize the cert creation OpenVPN - bash

I do not know why I am getting an error when I run my script with SSH, but when I run the bash from my CA server everything works fine.
I installed my VPN server based on this article https://www.digitalocean.com/community/tutorials/how-to-set-up-an-openvpn-server-on-ubuntu-18-04
I wrote a bash for the VPN creation but when I try to run it I need to SSH to the other server at some point. If I start the script with SSH in it I got an error message:
>./easyrsa: 341: set: Illegal option -o echo
My bash contain this and run from my VPN server:
sshpass -p $PASSWORD ssh username#"CA server IP" "/home/username/makevpn.sh $NAME $PASSWORD"
And makevpn.sh contain this:
>./easyrsa sign-req client $NAME
After this run it seems okay but give that error above.
I tried to read after this error and found nothing. :( Hope someone can help because I am hopeless after 4 days of troubleshooting.
Code of VPN script
#!/bin/sh
clear
read -p "Please enter the name of the new certificate : " NAME
read -p "Please enter the Password : " PASSWORD
cd /home/username/EasyRSA-3.0.7/
./easyrsa gen-req $NAME nopass
echo "gen-req done"
cp /home/username/EasyRSA-3.0.7/pki/private/$NAME.key /home/username/client-configs/keys/
echo "cp done"
sshpass -p $PASSWORD scp /home/username/EasyRSA-3.0.7/pki/reqs/$NAME.req username#192.168.1.105:/tmp
echo "scp done"
sshpass -p $PASSWORD ssh username#192.168.1.105 "/home/username/makevpn.sh $NAME $PASSWORD"
echo "ssh done"
cp /tmp/$NAME.crt /home/username/client-configs/keys/
echo "last CP done"
sudo /home/username/client-configs/make_config.sh $NAME
echo "All Done"
Code on CA server
#!/bin/sh
NAME=$1
PASSWORD=$2
cd /home/username/EasyRSA-3.0.7/
echo "CD Done"
./easyrsa import-req /tmp/$NAME.req $NAME
echo "Import-req done"
./easyrsa sign-req client $NAME
echo "Sign-req done"
sshpass -p $PASSWORD scp /home/username/EasyRSA-3.0.7/pki/issued/$NAME.crt username#192.168.1.103:/tmp
echo "Scp done"

I was just browsing the code of that easyrsa script here. This one is likely different from yours given the line for the error is 341. On the Github page, it is line 352 and it is part of a function called cleanup. It appears that this function is only attached as a trap (line 2744). Traps are used to catch signals like sigint (interrupt) which is normally sent on the terminal with ctrl+c (and may display a character like ^C). The reason the error only displays in your script is it likely causes a signal to be emitted that you would not normally receive if you ran it manually over ssh.
The error itself is really not an issue.
Code from Github:
Line 352:
(stty echo 2>/dev/null) || { (set -o echo 2>/dev/null) && set -o echo; }
Line 2744:
trap "cleanup" EXIT
It appears that line is just trying to turn terminal output of your typed characters back on (via stty echo). Sometimes programs will disable terminal output somewhere, and then re-enable it when the program finishes. However, if you were to kill the program mid way through (e.g. with ctrl+c), your program would terminate with the terminal output still disabled. This would make the terminal appear to be frozen. It would still work, but would not display the characters you type with your keyboard. The point of the trap is to ensure that terminal output is re-enabled no matter how the program exits.
More info...
At line 567 there is a function that disables echo. Looks like the point is to not show a password to the screen. If you were to kill the program during password reading, echo would remain disabled on the terminal. Likely the reason for the error has more to do with the way you are running the script. For whatever reason it causes stty echo to fail. Line 352 is assuming that the failure is due to stty echo not being a valid command. So on failure ( || ), it tries a different method (set -o echo) of enabling echo. If I try to run that on my terminal, I also get an error (bash 4.2):
-bash: set: echo: invalid option name

Related

WIN10 openssh in cmd "ssh xxx#xxx.xxx.xxx.xxx sh xxx.sh" error ,cant read variable normaly

Im Win10 and installed the Openssh. My router is running Openwrt.The code is write via BASH
!!!The code is here!!!
flag1=1
option1_1="Its num1"
while [[ "$flag1" = "1" ]];do
read -n 1 -p "Please input num1 :" input1
case ${input1} in
1)
echo .
read -n 1 -p "Your input is: $input1,comfirm?[1/0]" comfirm1
if [[ "$comfirm1" = "1" ]];then
echo .
echo Your input is $input1,Goodbye
flag1=0
fi
;;
*)
echo Its not num1 ,please input again
flag1=1
;;
esac
done
There is a .sh file in my router and i need to run it through the steps follow:
Steps:
Win+R to open cmd.exe
type this command : ssh example#192.168.1.1 sh example.sh
And here the problem comes : it can't read the variable normally and cant output the words that i write in the file.
BUT,if i run this script use the command below,it would work normally:
Steps:
Win+R to open cmd.exe
type : ssh example#192.168.1.1
type : sh example.sh
Problems: (i have upload the video to Youtube :https://youtu.be/TPE9CjUQvxo)
It should read twich "1" and save to $input1 and $comfirm1,but it actually only read correctly when i type "11",other input will cause it loop forever.
I have noticed something , but i dont know what can do:
The things that i noticed:
When i use one command "ssh xxx#xxx.xxx.xxx.xxx sh xxx.sh",the cmd.exe window's title is still "C:\Winodws\system32\cmd.exe -ssh xxx#xxx.xxx.xxx.xxx sh test.sh".BUT when i break this command to two commands ,it change to "OpenSSH SSH client"
When i use one command,the code read -n 1 -p "xxx" wont work.it cant show the -p words or read only 1 character.
Anyone knows whats wrong and give me a advice to fix this ??

Syntax error after "read" only when script invoked with "bash -s <script"

I have two scripts and both are in different servers and I use these for automating a small process.
script1 starts script2 using command
ssh -i /pathToKeyFile/keyfile.pem user#server2 'bash -s < /pathToScriptFile/script2.sh'
In script2.sh I have a "case" question:
#!/bin/bash
# Ask to start up JBOSS
read -p "DB restore completed. Start JBOSS and FACADE (y/n)" startJBOSS
case "$startJBOSS" in
y|Y ) echo "Starting JBOSS and FACADE";;
n|N ) echo "Stopping here"
exit;;
* ) echo "Invalid option..."
exit;;
esac
echo "More commands here"
exit
So when I execute script1.sh it works fine and starst script2 on remote server.
But script2 fails to error
bash: line 5: syntax error near unexpected token `)'
bash: line 5: ` y|Y ) echo "Starting JBOSS and FACADE";;'
If I execute script2.sh directly from remote server it works as expected.
I also tried so that both script files are located in one server. Of cource in this case commant to start script2.sh is different, but in this case both works again as expected.
I cannot figure out why script2.sh fails when it is started from and other script located in an other server. I assume that script2.sh "code" is correct as it works when ran separately.
The problem is that read reads from stdin -- the same place your code is coming from.
Thus, instead of reading a line from the user, it reads a line from the file of source, consuming the case command, leaving the rest of the source file syntactically invalid.
Simple Answer: Don't Do That.
bash -s <filename makes sense when the <filename is coming from somewhere not accessible to the copy of bash (like the other side of the SSH connection, or a file that can only be read by a different user), but that's not the case for your example. Thus, you can just stop using the -s argument and the redirection:
ssh -i /pathToKeyFile/keyfile.pem user#server2 'bash /pathToScriptFile/script2.sh'
...or make the prompt conditional...
Another approach is to make the read conditional on there actually being a user listening at the TTY:
if [[ -t 0 ]]; then # test whether FD 0, stdin, is a TTY
read -p "DB restore completed. Start JBOSS and FACADE (y/n)" startJBOSS
else
startJBOSS=y # no TTY, so assume yes
fi
...or make the prompt read from /dev/tty, and make sure SSH passes it through.
An alternate approach is to read from /dev/tty explicitly, and then to arrange for that to be valid in the context of your script by passing appropriate arguments to ssh:
if read -p "DB restore completed. Start JBOSS and FACADE (y/n)" startJBOSS </dev/tty; then
: "read $startJBOSS from user successfully" # <- will be logged if run with set -x
else
echo "Unable to read result from user; is this being run with a TTY?" >&2
exit 1
fi
...and then, on the other side, using the -t argument to SSH, to force there to be a TTY (if one is available to SSH itself; if not, it won't have a means to read from the user out-of-band either):
ssh -t -i /pathToKeyFile/keyfile.pem user#server2 'bash -s < /pathToScriptFile/script2.sh'

How to catch/write - success/failure logs for sFTP - PUT command

In my shell script, after sFTP put process is completed. I need to check if the PUT process is completed successfully or failed.
Don't use expect at all.
#!/usr/bin/env bash
batchfile=$(mktemp -t sftp-batchfile.XXXXXX) || exit
trap 'rm -f "$batchfile"' EXIT
cat >"$batchfile" <EOF
put test_file.txt $dest_location
bye
EOF
if sftp -b "$batchfile" "user#hostname"; then
echo "The put succeeded"
else
echo "The put failed"
fi
As given in the SFTP man page, with emphasis added:
The final usage format allows for automated sessions using the -b option. In such cases, it is necessary to configure non-interactive authentication to obviate the need to enter a password at connection time (see sshd(8) and ssh-keygen(1) for details).

Batch Script Error - unexpected end of file

I'm trying to run a task where I have a script that will add a user to a remote server via ssh.
Here is my code:
#echo off
setlocal enabledelayedexpansion
set username=%1
set password=%2
for /F "tokens=*" %%a in (Linuxhosts.txt) do (
ssh -i svcaccount_id_rsa svcaccount#%%a 'bash -s' < adduser.txt
)
Here are the contents of the adduser.txt file
#!/bin/bash
#========================================================================================================
# This script allows for account creation on a server |
# It also performs error handling to ensure that the user doesn't currently exist on the system. |
# Also provides feedback from the input to verify the entries are correct. |
#========================================================================================================
while true; do
echo -n "Enter username: "
read -r username
/bin/egrep -i "^${username}:" /etc/passwd
if [ $? -eq 0 ]; then
echo "User $username already exists. Please check the username and try again."
else
echo "User $username does not exist. Proceed with account creation."
break
fi
done
adduser "$username"
if [ $? -gt 0 ]; then
echo "Error encountered."
exit 1
fi
echo -n "Enter password: "
read -r -s password
echo "$username:$password" | chpasswd
echo "Password was succesfully set for $username."
if [ $? -gt 0 ]; then
echo "Error encountered. There was a problem with your entry. Please re-run the script and try again."
exit 1
fi
usermod -a -G wheel "$username"
echo "User was succesfully added to the group wheel."
if [ $? -gt 0 ]; then
echo "Error encountered."
exit 1
fi
echo "Successfully added $username to the system."
However, when I try to run the first set of code through a cmd prompt, I get the following error:
bash: line 41: syntax error: unexpected end of file
I'm not sure what I'm missing. I have tested it with another file called hello.txt and it ran fine so I'm wondering if maybe there's spacing issues somewhere that I can't see because it's a text file.
I'm pretty sure the immediate problem here is that the file adduser.txt is in DOS/Windows format, with its lines terminated with a carriage return character, followed by a linefeed. Unix (including bash) expects just a linefeed as the line terminator, and hence treats the carriage return as part of the line's text. In this case, that means that bash sees line 17, "done", as "done[carriage return]" which isn't a valid keyword and does not end the while loop, so it keeps looking for the "done" keyword... until it runs out of file.
(Credit to Squashman for suggesting this in a comment.)
You're likely to have this problem a lot transferring files from Windows to unix; unfortunately, the tools available to fix the problem vary quite a bit depending on what OS you're using, etc.
BTW, I see a couple of other problems here. For one thing, the read commands in the script are going to be trying to read from the same source that bash is reading commands from, which is the adduser.txt file. So when it does e.g. read -r username it's actually going to be reading some later line from the script file, not from the user running the batch script. This is going to be very hard to solve the way you're doing it; I think it'll be much better to actually copy the script file to the unix system, then run it separately.
Also, as Socowi pointed out in the comments, $? gets the exit status of the last command executed, so in sections like this:
echo "$username:$password" | chpasswd
echo "Password was succesfully set for $username."
if [ $? -gt 0 ]; then
...
the if condition is checks the exit status of the command echo "Password was succesfully set for $username.", not the chpasswd command. The same problem applies to the usermod command later. The better way to do this is to use the command you want to check for success directly as the if condition:
if echo "$username:$password" | chpasswd; then
echo "Password was succesfully set for $username."
else
echo "Error encountered. There was a problem with your entry. Please re-run the script and try again."
exit 1
fi
I'd use this same format in all of the places you're checking exit status: the egrep, useradd, chpasswd, and usermod commands.
[UPDATE] After a bit of mulling, I have a couple of possible solutions: First, to fix the carriage return problem, you could pipe the file through tr -d "\r" as a quick-n-dirty CR remover (although you may have to play around with the quoting and/or escaping to get that \r through both batch and bash's command processing). Second, pass the username and password as arguments to the script instead of having it read them. Thus, your batch script would use something like this:
ssh -i svcaccount_id_rsa svcaccount#%%a 'tr -d "\r" | bash -s "username" "password"' < adduser.txt
... then change adduser.txt to use username="$1"; password="$2" instead of the read commands (and also changing that while loop into an if, since there wouldn't be an option to try again with a different username).

Bash - Start Script running again?

I'm trying to learn some scripting.
I have a scenario where I have lost my truecrypt password. I run the script below.
#!/bin/sh
DIRECTORY=/media/truecrypt1
for i in 1 2 password
do
clear
echo "Trying $i as a password"
truecrypt -k "" --protect-hidden=no ITSTUDY $DIRECTORY -p $i
if [[ -d "${DIRECTORY}" && ! -L "${DIRECTORY}" ]] ; then
echo "It Worked!"
fi
done
However if the password is wrong I get
Trying 1 as a password
Incorrect password or not a TrueCrypt volume.
Enter password for /mnt/ITSTUDY:
The only way to get the script to start running again I have to ctrl+c. If I push ctrl+c after each failure eventually the script gets to the correct password. However if I have 1000 possible passwords that is not an option.
How do I get the script to look for the output
Incorrect password or not a TrueCrypt volume.
then send a ctrl+c? or quit? Everything I've tried so far doesn't proceed below the truecrypt -k line until I do the ctrl+c.
Truecrypt is entering an interactive mode to ask for your password each iteration around the loop, this will block on input so the loop won't continue.
Adding the --non-interactive flag should solve this issue.

Resources