This shell command isn't working:
ssh root#IP "if '$(cat ~/.ssh/authorized_keys | grep $KEY)' == '';then;echo $KEY >> ~/.ssh/authorized_keys;done"
$KEY contains my public RSA key. What I'm trying to do is to check if my key has been added to the authorized_keys file, if not, then to add it. IP of course is replaced with a real ip address.
Any idea what I'm doing wrong?
Edit:
In case anyone is curious, this is what I was doing:
#!/bin/sh
# Get your RSA key.
KEY=""
for line in $(cat ~/.ssh/id_rsa.pub)
do
KEY="$KEY $line"
done
# Add your RSA key to the machine's authorized_keys if it's not already there.
ssh root#$1 "grep -q '$KEY' ~/.ssh/authorized_keys || echo '$KEY' >> ~/.ssh/authorized_keys"
# Connect to the machine.
ssh root#$1
The idea was to ssh into a machine (using this script) and not have to enter the password in the next time I log in. The IP address is passed as a command line argument.
You expand $() thingie on the client side. (at least).
ssh root#IP "grep -q '$KEY' .ssh/authorized_keys || echo '$KEY' >>.ssh/authorized_keys"
looks like a shorter way to do the same.
Related
I have 2 GitHub account and I can't use the same public key for both accounts. I have already generated 2 ssh key
C:\Users\{User_Name}\.ssh\id_rsa
C:\Users\{User_Name}\.ssh\id_rsa_another
My question is, how I can use multiple ssh keys for Windows? On Linux, I just have to add by using ssh-add command, but on Windows, this command does not exist.
What have I done to make the other ssh key work, I have to change the id_rsa to id_rsa_temp and id_rsa_another to id_rsa. I know this is stupid.
First, ssh-add exists on Windows, as part of Git For Windows:
C:\Users\vonc>where ssh-add
C:\Program Files\Git\usr\bin\ssh-add.exe
It is needed for caching the passphrase protecting a private key (which is not always needed, since you can create a private key without passphrase)
Using different account, as commented, uses a %USERPROFILE%.ssh\config file, with in it:
Host gh1
Hostname github.com
User git
IdentityFile ~/.ssh/id_rsa
Host gh2
Hostname github.com
User git
IdentityFile ~/.ssh/id_rsa_another
You can test them with:
ssh -Tv gh1
ssh -Tv gh2
You should see a different "Welcome" message per key.
And the URL to use for cloning your repo would be:
gh1:user1/repo1
gh2:user2/repo2
If, and only if, your private ssh keys are encrypted (protected by a passphrase), then you need a .bashrc to start the SSH agent, and register your keys in it, effectively caching said keys.
See "Auto-launching ssh-agent on Git for Windows"
You can run ssh-agent automatically when you open bash or Git shell.
Copy the following lines and paste them into your ~/.bashrc (%USERPROFILE%/.bashrc) file in Git shell:
env=~/.ssh/agent.env
agent_load_env () { test -f "$env" && . "$env" >| /dev/null ; }
agent_start () {
(umask 077; ssh-agent >| "$env")
. "$env" >| /dev/null ; }
agent_load_env
# agent_run_state: 0=agent running w/ key; 1=agent w/o key; 2=agent not running
agent_run_state=$(ssh-add -l >| /dev/null 2>&1; echo $?)
if [ ! "$SSH_AUTH_SOCK" ] || [ $agent_run_state = 2 ]; then
agent_start
ssh-add
ssh-add ~/.ssh/id_rsa_another
elif [ "$SSH_AUTH_SOCK" ] && [ $agent_run_state = 1 ]; then
ssh-add
ssh-add ~/.ssh/id_rsa_another
fi
unset env
You will have to enter the passphrase on the first start, then no more: said passphrase will be cached by the agent.
Finally, I found the solution
I have to use Git Bash because I can't use a regular Windows terminal when running this command
$ eval $(ssh-agent -s)
And then I can add the SSH key by running this command
$ ssh-add C:/Users/{User_Name}/.ssh/id_rsa_another
We must use the forward-slash for the path
I found this code elsewhere on stackoverflow:
if [ -z "`ssh-keygen -F ${wPCS_IP}`" ]; then
ssh-keyscan -p ${wPCS_PT} -H ${wPCS_IP} >> ~/.ssh/known_hosts
fi
I have two issues where I'm using the code:
This code is generating an error ($?=1) even though it succeeds.
If I run ssh-keygen -F ${wPCS_IP} again after known_hosts is appended, it does not find the keys in known_hosts, even though they were just added. This is the larger problem.
The local machine is Ubuntu Server 16.04 LTS, the remote machine is Ubuntu Server 14.04 LTS.
The major difference between my code and the code sample I found is my use of the port option -p.
Also, I've noticed that the known_hosts file does not list the machines by name or IP address. Which is different from my Gentoo laptop.
So it turns out that when there's an alternate port for ssh, it is stored in the known_hosts file as part of the IP address in this format:
[${WPCS_IP}]:WPCS_PT
Which means that for the if statement to work, it needs to look like this:
if ! ssh-keygen -F "[${wPCS_IP}]:${WPCS_PT}" -f ~/.ssh/known_hosts > /dev/null 2>&1; then ssh-keyscan -p ${wPCS_PT} ${wPCS-IP} >> ~/.ssh/known_hosts; fi
Thanks to alvits for getting me moving in the right direction...
Update: it turns out the Ubuntu 16.04 encrypts the IP address of the remote host (but not the port). I'm still trying to figure out how to adapt to this difference.
Another update: It turns out the the -H option is what's failing. Once you hash the key, it isn't found anymore. This works on Ubuntu 14.04:
if ! ssh-keygen -F ${IP_ADDR} -f ~/.ssh/known_hosts > /dev/null 2>&1; then ssh-keyscan -p ${PORT} ${IP_ADDR} >> ~/.ssh/known_hosts; fi
# IP_ADDR SSH-2.0-OpenSSH_7.2p2 Ubuntu-4ubuntu2.1
# IP_ADDR SSH-2.0-OpenSSH_7.2p2 Ubuntu-4ubuntu2.1
if ! ssh-keygen -F ${IP_ADDR} -f ~/.ssh/known_hosts > /dev/null 2>&1; then ssh-keyscan -p ${PORT} ${IP_ADDR} >> ~/.ssh/known_hosts; fi
You can see that the first if statement generates the keyscan data and the second does not because the keyscan data is correct, but if you add the -H, the keygen does not detect the hashed key entries...
However, to get a similar command to work on Ubuntu 16.04, the if has to be changed:
if ! ssh-keygen -F [${IP_ADDR}]:${PORT} -f ~/.ssh/known_hosts > /dev/null 2>&1; then ssh-keyscan -p ${PORT} ${IP_ADDR} >> ~/.ssh/known_hosts; fi
# IP_ADDR:PORT SSH-2.0-OpenSSH_6.6.1p1 Ubuntu-2ubuntu2.8
# IP_ADDR:PORT SSH-2.0-OpenSSH_6.6.1p1 Ubuntu-2ubuntu2.8
# IP_ADDR:PORT SSH-2.0-OpenSSH_6.6.1p1 Ubuntu-2ubuntu2.8
if ! ssh-keygen -F [${IP_ADDR}]:${PORT} -f ~/.ssh/known_hosts > /dev/null 2>&1; then ssh-keyscan -p ${PORT} ${IP_ADDR} >> ~/.ssh/known_hosts; fi
In this case the known_hosts file must include the port...
-H is right out here as well. The if won't find the key if it was generated with -H.
It's frustrating that the behavior varies from version to version and that the safest hashed version doesn't work.
Yet another edit: It may be the port is specified in known_hosts when the remote server uses a non-standard port in sshd_config. This may be an expected behavior.
I sent an email to the open-ssh list and had several good suggestions. Basically, it is not good to rely on ssh-keygen -F and ssh-keyscan -H as file formats and locations tend to vary from system to system.
The real solution, which I will implement today is to generate certificates for each of the servers so they recognize each other. This works well for me because I have complete control over both servers.
I was given a link that explains how to setup server certificates:
https://blog.habets.se/2011/07/OpenSSH-certificates.html
Here's a link specifically for Ubuntu.
https://www.digitalocean.com/community/tutorials/how-to-create-an-ssh-ca-to-validate-hosts-and-clients-with-ubuntu
If this is my last update, assume this worked for me.
I'm writting a shell script and I want to automate login into a remote machine using ssh-copy-id, so manually when I print :
ssh-copy-id -i /root/.ssh/id_rsa $2#$4 -p $3 | echo $1
$1 refer to password,
$2 refer to username,
$3 refer to port, and
$4 refer to ip,
It is ok with that, the problem is that I have to automate inserting password after :
ssh-copy-id -i /root/.ssh/id_rsa $2#$4 -p $3
I add this "| printf $1", but it does not work it shows "password:" in the screen and still wait for the password ..
I hope you understand me and thank you.
As #Leon pointed out, you had the pipeline backwards. But even if you do it with the correct order, it will still not work because ssh-copy-id (and all other programs from openssh) do not read passwords from their stdin. The solution is to use the $SSH_ASKPASS environment variable. You can do that as follows: first, create an auxiliary script, say /var/tmp/ssh-pass.sh (actually find a better name than that), with the following contents:
#!/bin/sh
echo "$PASS"
Then you can use the following command to accomplish what you've asked for:
PASS="$1" SSH_ASKPASS="/var/tmp/ssh-pass.sh" setsid -w ssh-copy-id -i /root/.ssh/id_rsa "$2"#"$4" -p "$3"
Explanation: we use setsid -w to disassociate the ssh-copy-id process from the currently used terminal. That forces ssh-copy-id to run the executable specified in the $SSH_ASKPASS in order to obtain the password. We have specified our own script in that variable, so ssh-copy-id will execute just that. Now the script is supposed to provide the password to ssh-copy-id by printing it to its stdout. We use the $PASS variable to the password to the script, so the script just prints that variable.
2020 / Mac OS X:
Install sshpass (original answer)
brew install hudochenkov/sshpass/sshpass
Run ssh-copy-id using sshpass and with the password as an arg
sshpass -p $1 ssh-copy-id -i ~/PATH/TO/KEY $2#$4 -p $3
If you want to turn off strict host checking as well, use the -o flag, which is passed to the underlying ssh:
sshpass -p hunter2 ssh-copy-id -o StrictHostKeyChecking=no -i ~/PATH/TO/KEY $2#$4 -p $3
I tried the solution by #redneb, and installed setsid through util-linux by following this answer, but kept receiving a password denied.
I found this strategy to work for uploading my SSH key while setting up multiple raspberry pis in successino. In my script, I also run ssh-keygen -R raspberrypi.local each time too, to avoid the The ECDSA host key for raspberrypi.local has changed error.
I execute the following commands a few times a day:
ssh-keygen -t rsa -N "" -C "info#example.com" -f ~/.ssh/id_rsa_projectname
eval `ssh-agent`
ssh-add ~/.ssh/id_rsa_projectname
cat ~/.ssh/id_rsa_projectname.pub
ssh -T git#github.com
The only variable in this script is the projectname, I would like to make a keygen.sh script or something like that to automate this process and pass along the projectname. Is this possible?
Also where should I start looking and what not to forget, I'm a bit new to bash scripting and I know it can be quite dangerous in the wrong hands.
Would it not be easier to just maintain a single set of staging or development keys rather than generating them for everything? IMHO you're losing configurability and not gaining much in security.
That aside, you're on the right track but I would do things a bit different.
export PROJECT=foo;
ssh-keygen -t rsa -N "" -C "info#example.com" -f ~/.ssh/id_rsa_${PROJECT}
That will generate named keys id_rsa_foo and id_rsa_foo.pub
Now you need to make your ssh config use it for github. ~/.ssh/config should have something like:
Host remote github.com
IdentityFile ~/.ssh/id_rsa_foo
User git
StrictHostKeyChecking no
You'll need to upload the public key to github. You'll have to figure this out for yourself using their API.
If you do all this correctly you should be able to git clone automagically.
#!/bin/bash
[[ -z "${PROJECT}" ]] && echo "project must be set" && exit 1
ssh-keygen -t rsa -N "" -C "info#example.com" -f ~/.ssh/id_rsa_${PROJECT}
chmod 400 ~/.ssh/id_rsa_${PROJECT}
echo $' Host remote github.com\n IdentityFile ~/.ssh/id_rsa_'${PROJECT}'\n User git\n StrictHostKeyChecking no' >> ~/.ssh/config
chmod 644 ~/.ssh/config
# do the github api stuff to add the pub key
I have a shell script that continuously put some data from one server to another. It works fine but I want to make it more secure. So at the moment if the other server denied the permission because the password was changed the scipts freezes. Is there a possibility so if this occurs it just ignores this line and just goes on?
inotifywait -m /srv/watchfolderfilme -e create -e moved_to |
while read path action file; do
...
sshpass -p "****" scp -r /srv/newtorrentfiles/* user#0.0.0.0:/srv/torrentfiles && rm -r /srv/newtorrentfiles/*
done
scp is no the best tool to deal with your problem.
As George said, using public keys with ssh is the best way to get rid of password change.
Also you can do the trick with rsync like this :
rsync -ahz --remove-source-files /srv/newtorrentfiles/ user#SRVNAME:/srv/torrentfiles/
or
rsync -ahz /srv/newtorrentfiles/ user#SRVNAME:/srv/torrentfiles/ && rm -r /srv/newtorrentfiles/*
To be sure that all is done like you wanted (make this script more "secure"), you can send you an email if the script fails for one reason or another not due to lack of permission.
Maybe not the answer you're looking for but why don't you use SSH keys?
Updated Script:
inotifywait -m /srv/watchfolderfilme -e create -e moved_to |
while read path action file; do
...
scp -r /srv/newtorrentfiles/* b#B:/srv/torrentfiles && rm -r /srv/newtorrentfiles/*
done
How to do it
a#A:~> ssh-keygen -t rsa
Generating public/private rsa key pair.
Enter file in which to save the key (/home/a/.ssh/id_rsa):
Created directory '/home/a/.ssh'.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/a/.ssh/id_rsa.
Your public key has been saved in /home/a/.ssh/id_rsa.pub.
The key fingerprint is:
3e:4f:05:79:3a:9f:96:7c:3b:ad:e9:58:37:bc:37:e4 a#A
Now use ssh to create a directory ~/.ssh as user b on B. (The directory may already exist, which is fine):
a#A:~> ssh b#B mkdir -p .ssh
b#B's password:
Finally append a's new public key to b#B:.ssh/authorized_keys and enter b's password one last time:
a#A:~> cat .ssh/id_rsa.pub | ssh b#B 'cat >> .ssh/authorized_keys'
b#B's password:
From now on you can log into B as b from A as a without password:
a#A:~> ssh b#B
Source >> http://www.linuxproblem.org/art_9.html