33

Is there a command (or a one-liner) to remove a ssh key on a server? Something like the opposite of ssh-copy-id?

  • 2
    Some SSH server software support the RFC 4819 protocol for managing authorized SSH keys, but it's so rare it's almost nonexistent on Linux :( – user1686 May 29 '12 at 7:38
  • 3
    Excellent question, this is really missing functionality to ssh-copy-id to facilitate key rotation. – Zabuzzman Mar 27 '15 at 22:33
  • 1
    Its worth noting that ssh-keygen does provide the -R option for removing keys from known_hosts, but sadly ssh-keygen -R <HOSTNAME> -f ~/.ssh/authorized_keys doesn't work. I would use the sed option below, instead. – Digital Trauma Mar 23 '18 at 18:27
11

As Ignatio suggested this can be done with grep -v.

Here is a example which removes the key containing some unique string or just deletes the authorized_keys file when no other key remains.

if test -f $HOME/.ssh/authorized_keys; then
  if grep -v "some unique string" $HOME/.ssh/authorized_keys > $HOME/.ssh/tmp; then
    cat $HOME/.ssh/tmp > $HOME/.ssh/authorized_keys && rm $HOME/.ssh/tmp;
  else
    rm $HOME/.ssh/authorized_keys && rm $HOME/.ssh/tmp;
  fi;
fi

Replace some unique string with something that only exists in the key you wish to remove.

As a oneliner over ssh this becomes

ssh hostname 'if test -f $HOME/.ssh/authorized_keys; then if grep -v "some unique string" $HOME/.ssh/authorized_keys > $HOME/.ssh/tmp; then cat $HOME/.ssh/tmp > $HOME/.ssh/authorized_keys && rm $HOME/.ssh/tmp; else rm $HOME/.ssh/authorized_keys && rm $HOME/.ssh/tmp; fi; fi'

Tested on Linux (SLES) and HP-UX.

| improve this answer | |
  • 2
    see below answer: sed is better at doing this – woohoo Jul 12 '16 at 1:31
31

sed provides a compact solution:

sed -i.bak '/REGEX_MATCHING_KEY/d' ~/.ssh/authorized_keys

This will save the original authorized_keys in authorized_keys.bak. If you don't want the backup then just change -i.bak to -i.

You can even remove multiple keys:

sed -i.bak '/REGEX1/d; /REGEX2/d' ~/.ssh/authorized_keys

The only tricky bit here is special characters in the regex need to be escaped.

| improve this answer | |
  • 1
    If you only use the base64 characters in the public keyfile (e.g., awk '{print $2}' ~/.ssh/id_rsa.pub), then you don't need to worry about escaping any special characters. – Juan Mar 22 '18 at 23:30
7

Nope. You'll need to SSH in and use sed or grep to remove the key from the file.

| improve this answer | |
  • Thank you. I will keep the question open a little longer to see if someone also can provide a script that does the opposite of ssh-copy-id – grm May 30 '12 at 11:56
  • 1
    @grm : I'd suggest you keep the question open forever, or at least until a ssh-undo-copy-id is implemented ! ;-) – Max L. Jul 30 '15 at 18:28
0

Phil already answered this question but I want to do addition and make it easier for you. And since you are asking reverse of ssh-copy-id, I am assuming you want to run it on authorized machine.

ssh keys only contains base64 characters. So you can use a char as sed delimiter that not in that list. Let us use '#'.

ssh root@<hostname> -o PasswordAuthentication=no "sed -i.bak 's#`cat ~/.ssh/id_rsa.pub`##' ~/.ssh/authorized_keys"

Replace hostname with the server IP.

PasswordAuthentication option will cause ssh fail if it ask password

| improve this answer | |
  • 1
    The 'comment' in the pub key might not have base64 characters. If it has a "#", then your example breaks. Maybe use awk '{print $2}' ~/.ssh/id_rsa.pub with some sed or grep -v instead. – Juan Mar 22 '18 at 23:24

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.