Gentoo Way Linux, Gentoo, Kubuntu, Ubuntu, Debian … компилируем всё!

28Ноя/09Off

SSH — Авторизация по ключу, что делать если ключ украли.

Ни для кого ни секрет насколько удобна авторизация по публичному ключу, а если для кого-то секрет - то можете ознакомиться вот с этой статьёй.

Но случается и такое, что ключ нужно заменить, причины? Честно говоря вижу только две - ключ скомпрометирован и, что почти то же самое, его украли.

Заменить ключ не составляет особого труда - всего-то нужно удалить с серверов старый публичный и записать вместо него новый. Вроде бы всё предельно просто, а что если серверов не один, не два и не три, а 10, 20 и более? Вот тут-то и просыпается великая и могучая лень 🙂 Но есть необходимость, а значит нужно что-то делать.

На этот случай и был написан небольшой скрипт:
renew.sh

#!/bin/bash                                              
# Author: Dmitriy Beketov (freemandigger --@-- gmail.com)
# Site: http://gentooway.ru                              
# Licence: Attribution-Noncommercial 3.0 Unported (http://creativecommons.org/licenses/by-nc/3.0/)

USAGE="Usage: ${0#*/} [-i id_rsa.old] [-d] <id_rsa.pub.old> <id_rsa.pub.new> <host list>"

privkey=""
dryrun=0  
# Parse command line
while getopts i:d opt; do                                                    
    case "$opt" in                                                          
      i) privkey="$OPTARG";;                                                
      d) dryrun=1;;                                                          
      *) echo $USAGE;;                                                      
    esac                                                                    
done                                                                        
shift $(($OPTIND - 1))                                                      
[[ "$1" == '--' ]] && shift                                                  
if [[ $# -lt 3 ]]; then                                                      
    echo $USAGE                                                              
    exit 1                                                                  
fi                                                                          
oldpubkey=$1                                                                
hostlist=$3                                                                  
newpubkey=$2                                                                
# Check files for exist                                                      
if [ "$privkey" ]; then                                                      
        if [ ! -f "$privkey" ]; then                                        
                echo $USAGE                                                  
                echo "Old private key file not found"                        
                exit 1                                                      
        fi                                                                  
        privkey="-i $privkey"                                                
fi                                                                          
if [ ! -f "$oldpubkey" ]; then
        echo $USAGE
        echo "Old public key file not found"
        exit 1
fi
if [ ! -f "$hostlist" ]; then
        echo $USAGE
        echo "Host list not found"
        exit 1
fi
if [ ! -f "$newpubkey" ]; then
        echo $USAGE
        echo "New public key file not found"
        exit 1
fi

# Get the part of old public key for grep
OLD=`cat $oldpubkey | awk '{print $2}'`

SSH='/usr/bin/ssh'
SSH_COPY='/usr/bin/ssh-copy-id'
SCP='/usr/bin/scp'

test $dryrun -gt 0 && echo "START DRY RUN" || echo "START"
for host in `cat $hostlist`
do
printf "Copy new key to $host\n"
$SCP -q $privkey $newpubkey $host:.ssh/newpubkey
if [ "$?" > 0 ]; then
        printf "\t[OK]\n"
        printf "\tAdding new key to authorized_keys\n"
        test $dryrun -gt 0 && printf "dry run" || $SSH $privkey $host "cat ~/.ssh/newpubkey >> ~/.ssh/authorized_keys"
        test $? -gt 0 && printf "\t[FAIL]\n" || printf "\t[OK]\n"
        printf "\tDeleting temporary file of new public key\n"
        $SSH $privkey $host "rm ~/.ssh/newpubkey"
        test $? -gt 0 && printf "\t[FAIL]\n" || printf "\t[OK]\n"
        printf "\tBackup authorized_keys to authorized_keys.bak\n"
        test $dryrun -gt 0 && printf "dry run" || $SSH $privkey $host cp .ssh/authorized_keys .ssh/authorized_keys.bak
        test $? -gt 0 && printf "\t[FAIL]\n" || printf "\t[OK]\n"
        printf "\tDeleting old public key from authorized_keys\n"
        test $dryrun -gt 0 && printf "dry run" || $SSH $privkey $host "cat ~/.ssh/authorized_keys.bak | grep -v '$OLD' > ~/.ssh/authorized_keys"
        test $? -gt 0 && printf "\t[FAIL]\n" || printf "\t[OK]\n"

else
        printf "\t[FALSE]\n"
fi
done
echo "FINISH"
exit 0
Параметры вызова (не обязательные):

-d - Тестовый запуск, скрипт попробует скопировать новый ключ во временный файл на удалённом сервере, а затем его же и удалить.
-i - Ключ для авторизации на серверах, на случай если в ~/.ssh/id_rsa уже установлен новый ключ то в данном параметре можно указать где брать старый.

Параметры вызова (обязательные):

id_rsa.pub.old - старый публичный ключ, который нужно заменить.
id_rsa.pub.new - новый публичный ключ.
host list - файл со списком пользователей/серверов, где нужно заменить ключ, формат user@host или из ~/.ssh/config

user1@host1
user2@host2
user223@host4
my_predefined_host
blabla@eee

Также можно скачать скрипт