Bash Scripting - passing no value - linux

My aim is to create a bash script that can add new users to Ec2 and give access to ssh keys but I am having abit of an issue.
This is my current script and the script stops whenever it requires to generate a private/public key because it asks for the passphrase . How can I configure my script to just press enter?
#!/bin/bash
username=$1
ssh-keygen -b 1024 -f $username -t dsa
chmod 600 $username.pub
useradd $username
mkdir /home/$username/.ssh
chmod 700 /home/$username/.ssh
chown ball:ball /home/$username/.ssh
cat ball.pub >> /home/$username/.ssh/authorized_keys
chown 600 /home/.ssh/$username/authorized_keys
chown ball:ball /home/$username/.ssh/authorized_keys
[root#ip-172- /]# ssh-keygen -b 1024 -f ball -t dsa
Generating public/private dsa key pair.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in ball.

You can pipe empty lines to ssh-keygen:
ssh-keygen -b 1024 -f ball -t dsa <<< ''
or
printf "" | ssh-keygen -b 1024 -f ball -t dsa
or reading from /dev/null:
ssh-keygen -b 1024 -f ball -t dsa < /dev/null

Related

Answer "Yes" or "No" ONLY IF a command request it

I a writing a script. There is a command that colud request to answer yes or no to override a certain file.
I want to automate the script to answer YES or NO ONLY IF the command request it (i don't want to echo yes inside the command).
The command I am referring to is ssh-keygen, which requires to override the key in case already exists.
In my mind there is something like this...
if (ssh-keygen requests input) --> Sends yes to the ssh-keygen
In particular, I am using the following command:
ssh-keygen -t rsa -b 4096 -N '' -f ~/.ssh/id_rsa -q
Even if i am using -q, still asks yes or no to override the file.
Thanks in advance
i suggest using the echo command to send "yes" to the command.
echo "yes" | ssh-keygen -t rsa -b 4096 -N '' -f ~/.ssh/id_rsa -q
I would suggest you to check the yes command.
It is sending a loop of y.
If you want to force the acceptation of the command it should work.
But if the keygen request for an input (filename, etc.) it will also send 'y'.
the command would be :
yes | ssh-keygen -t rsa -b 4096 -N '' -f ~/.ssh/id_rsa -q

Linux terminal: pass the answer(or arg values) in advance when installing package?

When I run a command like ssh-keygen -t rsa -b 2048, it asks me:
Generating public/private rsa key pair.
Enter file in which to save the key (/root/.ssh/id_rsa):
I'd like to write the path in advance and tried like this: ssh-keygen -t rsa -b 2048 | cat '/root/.ssh/id_rsa.pub'.
But this doesn't work....
How can I do this?
Your attempt was in reverse, meaning you were trying to pass the output of ssh-keygen to cat. But we need to pass the output of cat to ssh-keygen:
# using multiline here doc
$ cat <<EOF | ssh-keygen -t rsa -b 2048
/tmp/id_rsa
/tmp/id_rsa.pub
password
EOF
OR
$ echo -e "/tmp/id_rsa\n/tmp/id_rsa.pub" | ssh-keygen -t rsa -b 2048
But use it with caution, this just feeds the entire input to the piped command. Depending on how that command processes input this might fail if the expected input is different from what is being piped in.
It may be fine for simple scripts/commands (will NOT work for ssh-keygen reliably in all cases [because it seems to spawn another process in some cases to ask for the passphrase]).
ref. https://tldp.org/LDP/abs/html/here-docs.html for heredoc

ssh-add from bash script and automate passphrase entry

I am trying to do ssh-add from script (don't care about about security at the moment).
Now ssh prompts for passphrase, which needs to be automated, so i read couple of things like this and found expect.
And now i do following:
eval `ssh-agent -s`
script tmp.sh defined as :
#!/usr/bin/expect
spawn ssh-add /root/.ssh/id_rsa
expect "Enter passphrase for /root/.ssh/id_rsa:"
send "my_pass"
interact
./tmp.sh
ssh-add -l
If ssh-add would have worked it shows something like
4096 SHA256:wlfP/nhVSWXLcljBOen5GSYZXJGgfi/XJWfZeBwqRsM id_rsa (RSA)
But instead i get The agent has no identities. Seems like ssh-agent looses it's context.
Am open to other solutions to do this.
Personally, I find the use of expect a bit cumbersome. The following approach found how to make ssh-add read passphrase from a file rather informative.
So if your version of ssh-add allows the -p argument and you are not worried about security then this should work:
#!/bin/bash
# store a file somewheres with your passphrase. For example's sake
# I'll just use $HOME/.myscrt
<$HOME/.myscrt ssh-add -p ~/.ssh/id_rsa
Now if -p is not an option for you, I found the second method mildly ingenious:
#!/bin/bash
# Same passfile and some minor enhancements from the OP of the linked
# solution
PASS="$(<$HOME/.myscrt)"
# the following is just a one-liner method of making an executable
# one-line script echoing the password to STDOUT
install -vm700 <(echo "echo $PASS") "$PWD/ps.sh"
# then the magic happens. NOTE: your DISPLAY variable should be set
# for this method to work (see ssh-add(1))
[[ -z "$DISPLAY" ]] && export DISPLAY=:0
< id_rsa SSH_ASKPASS="$PWD/ps.sh" ssh-add - && shred -n3 -uz $PWD/ps.sh
When I tested the script I called "j", see below:
$ cd /tmp
$ ssh-keygen
Generating public/private rsa key pair.
Enter file in which to save the key (/home/me/.ssh/id_rsa): /tmp/id_rsa
Enter passphrase (empty for no passphrase): asdfasdf
Enter same passphrase again: asdfasdf
Your identification has been saved in /tmp/id_rsa.
Your public key has been saved in /tmp/id_rsa.pub.
The key fingerprint is:
ed:1a:ae:c7:ac:47:5e:31:98:8e:18:8f:1c:67:94:6d jimconn#redapt-240
The key's randomart image is:
+--[ RSA 2048]----+
| o |
| o E |
| . . o |
| o o o.o |
| . O oS .o |
| + o o.. |
| =... |
| .*o |
| o=o |
+-----------------+
$ echo 'asdfasdf' > ~/.myscrt
$ chmod 0600 ~/.myscrt
$ ls -altr ~/.myscrt
-rw------- 1 me me 9 Feb 16 19:00 /home/me/.myscrt
$ cat ~/.myscrt
asdfasdf
$ ls -ltr
total 12
-rw-r--r-- 1 me me 400 Feb 16 18:59 id_rsa.pub
-rw------- 1 me me 1766 Feb 16 18:59 id_rsa
-rwx------ 1 me me 151 Feb 16 19:04 j
$ cat j
#!/bin/bash
PASS="$(<$HOME/.myscrt)"
install -vm700 <(echo "echo $PASS") "$PWD/ps.sh"
cat id_rsa | SSH_ASKPASS="$PWD/ps.sh" ssh-add - && shred -n3 -uz $PWD/ps.sh
$ ./j
‘/dev/fd/63’ -> ‘/tmp/so/ps.sh’
Identity added: (stdin) ((stdin))
$ ls
id_rsa id_rsa.pub j
So, one thing to quickly note about this method is that listing the identities loaded into ssh-agent will only show that stdin was loaded:
$ ssh-add -D
All identities removed.
$ ssh-add -l
2048 ed:1a:ae:c7:ac:47:5e:31:98:8e:18:8f:1c:67:94:6d (stdin) (RSA)
$ ./j
‘/dev/fd/63’ -> ‘/tmp/so/ps.sh’
Identity added: (stdin) ((stdin))
$ ssh-add -l
2048 ed:1a:ae:c7:ac:47:5e:31:98:8e:18:8f:1c:67:94:6d (stdin) (RSA)
UPDATED BECAUSE THE FIRST ONE DID NOT WORK
I did not try this, but if it is realy about expect loosing the context, it might be a good idea to set it up later:
auto-passphrase-add.expect (replacing tmp.sh)
/usr/bin/expect
spawn ./ssh-agent-ssh-add.sh /root/.ssh/id_rsa
expect "Enter passphrase for /root/.ssh/id_rsa:"
send "my_pass"
interact
ssh-agent-ssh-add.sh
#!/bin/sh
eval `ssh-agent -s`
ssh-add "$#"

Generating ssh-key file for multiple users on each server

I have to create 60 ssh users on one of the servers. I created users using small user creation script which loops though each users from the user list.
I'm trying to run the similar script which will generate sshkeys for each user.
#!/bin/sh
for u in `cat sshusers.txt
do
echo $u
sudo su - $u
mkdir .ssh; chmod 700 .ssh; cd .ssh; ssh-keygen -f id_rsa -t rsa -N '';
chmod 600 /home/$u/.ssh/*;
cp id_rsa.pub authorized_keys
done
when i run this script, it basically logs into all 60 users account but does not create. ssh dir or generate passwordless ssh.key. Any idea to resolve this would be greatly appreciated!
Thanks
sudo su - $u starts a new shell; the commands that follow aren't run until that shell exits. Instead, you need to run the commands with a single shell started by sudo.
while IFS= read -r u; do
sudo -u "$u" sh -c "
mkdir .ssh
chmod 700 .ssh
cd .ssh
ssh-keygen -f id_rsa -t rsa -N ''
chmod 600 '/home/$u/.ssh/'*
cp id_rsa.pub authorized_keys
"
done < sshusers.txt
After trying several times, i made little changes that seems to work now.
#!/bin/bash
for u in `more sshuser.txt`
do
echo $u
sudo su - "$u" sh -c "
mkdir .ssh
chmod 700 .ssh
cd .ssh
ssh-keygen -f id_rsa -t rsa -N ''
chmod 600 '/home/$u/.ssh/'*
cp id_rsa.pub authorized_keys "
done

Automate SSH Configuration for new Hadoop cluster

Guessing this has been done many times, but I could not find a clean answer, so I am appealing to your expertise for a better solution:
Objective: I am setting up a moderate sized RHEL Hadoop cluster and want to automate the configuration of SSH connectivity between all nodes. On the first node I have a list of all of the IPs in the file 'remote_ips', and I have the hduser password in the file 'hduser_pw' (chmod 600).
Step 1) Create "hduser_pw" password file on each host
for x in $(cat remote_ips); do sshpass -p$(cat hduser_pw) ssh -o StrictHostKeyChecking=no hduser#$x "echo $(cat hduser_pw) > hduser_pw; chmod 600 hduser_pw"; done
Step 2) Generate RSA keys for each node in cluster:
for x in $(cat remote_ips); do sshpass -p$(cat hduser_pw) ssh -o StrictHostKeyChecking=no hduser#$x "echo -e 'y'| ssh-keygen -t rsa -N \"\"
"; done
Step 3) Copy the file 'remote_ips' to each node in the cluster:
for x in $(cat remote_ips); do sshpass -p$(cat hduser_pw) scp -o StrictHostKeyChecking=no remote_ips hduser#$x:~; done
Step 4) For each node, copy the RSA public key to "authorized_keys" in every other node:
for x in $(cat remote_ips); do sshpass -p$(cat hduser_pw) ssh -o StrictHostKeyChecking=no hduser#$x 'for y in $(cat remote_ips); do cat /home/hduser/.ssh/id_rsa.pub | sshpass -p$(cat hduser_pw) ssh -o StrictHostKeyChecking=no hduser#$y '\''cat >> .ssh/authorized_keys'\'' ; done '; done
Is there a better way to do this? Really appreciate your help.
EDIT: Here are my revisions:
I incorporated the feedback from #janos and #likewhoa --> I handled the UUOC with redirection, looped across each IP, removed any pwds from the shell history with variables, etc. Thanks so much!
hduser_pw=$(< hduser_pw)
remote_ips=$(< remote_ips)
for x in $remote_ips; do
echo "Create hduser_pw password file on node: ${x}"
sshpass -p$hduser_pw scp -o StrictHostKeyChecking=no hduser_pw hduser#$x:~
echo "chmod 600 hduser_pw on node: ${x}"
sshpass -p$hduser_pw ssh -o StrictHostKeyChecking=no hduser#$x "chmod 600 hduser_pw"
echo "Generate RSA keys for: ${x}"
sshpass -p$hduser_pw ssh -o StrictHostKeyChecking=no hduser#$x "echo y | ssh-keygen -f ~/.ssh/id_rsa -t rsa -N \"\""
echo "SCP the file remote_ips to node: ${x}"
sshpass -p$hduser_pw scp -o StrictHostKeyChecking=no remote_ips hduser#$x:~
done
for x in $remote_ips; do
for y in $remote_ips; do
echo "ssh-copy-id from node ${x} to node ${y}:"
sshpass -p$hduser_pw ssh -o StrictHostKeyChecking=no hduser#$x "sshpass -p${hduser_pw} ssh-copy-id -i ~/.ssh/id_rsa.pub hduser#${y} -o StrictHostKeyChecking=no";
done
done
Instead of running $(cat hduser_pw) and $(cat remote_ips) multiple times,
it would be better to run them only once and, save in variables and reuse.
For example:
hduser_pw=$(cat hduser_pw)
remote_ips=$(cat remote_ips)
# Step 1) Create "hduser_pw" password file on each host
for x in $remote_ips; do
sshpass -p$hduser_pw ssh -o StrictHostKeyChecking=no hduser#$x "echo $hduser_pw > hduser_pw; chmod 600 hduser_pw"
done
Can you spot the security problem? The echo $hduser_pw will be saved in the shell history, and may also be visible in ps printings. It's better to avoid it. Instead of this:
ssh server "echo $hduser_pw > hduser_pw; chmod 600 hduser_pw"
You can do like this:
ssh server "cat > hduser_pw; chmod 600 hduser_pw" < hduser_pw
That's a bit hacky and may be confusing.
A simpler option is to scp and then ssh (for the chmod):
scp hduser_pw server:
ssh server "chmod 600 hduser_pw"
Other simplifications:
Instead of echo -e 'y' | ... you can simplify to echo y | ...
Instead of the messy Step 4, take a look into ssh-copy-id if it's available (usually it is in Linux systems)
First off UUOC, you really should use a while loop and re-directions instead of CAT.
Use this instead for the following steps which merges all steps into one big while loop.
while read ips; do sshpass -p$(<hduser_pw) ssh -o StrictHostKeyChecking=no hduser#$ips "echo $(<hduser_pw) > hduser_pw; chmod 600 hduser_pw"; sshpass -p$(<hduser_pw) ssh -o StrictHostKeyChecking=no hduser#$ips ssh-keygen -f ~/.ssh/id_rsa -t rsa -N \"\"";sshpass -p$(<hduser_pw) scp -o StrictHostKeyChecking=no remote_ips hduser#$ips:;done <remote_ips
I'll let you fix Step 4 on your own. GL!
Few pointers.
Use while loops when reading through lines
ssh-keygen -f ~/.ssh/somekey to avoid 'echo y | ssh-keygen ...'
Use redirect '
Good luck! Perhaps this is best if you use some kind of Configuration Management tools to automate this and more.

Resources