Как я могу распространить мой ключ публикации SSH на список серверов, не вводя пароль снова и снова?

26

Мне недавно дали имя пользователя / пароль доступа к списку серверов, и я хочу распространить свой открытый ключ SSH на эти серверы, чтобы мне было проще войти в систему.

Так что понятно

  • На удаленных серверах отсутствует какой-либо ранее открытый открытый ключ, который я мог бы использовать для автоматизации этого процесса.
  • Это первый раз, когда я захожу на эти серверы, и мне не нужно постоянно вводить свои учетные данные для доступа к ним.
  • Также я не хочу вводить свой пароль снова и снова, используя ssh-copy-idцикл for.
SLM
источник
1
Это одно и то же имя пользователя и пароль для всех серверов?
Ройма
@roaima - ага! Эта деталь меня тоже удивила, но именно так настроены эти центры обработки данных, и вот как они это делают.
SLM
@ ott-- - дважды проверьте Q. Я явно заявляю, что я не хочу делать цикл for ssh-copy-id, перекачивая мой пароль снова и снова.
SLM
Смотрите также скрипт для автоматизации scp в сети
Жиль "ТАК - Хватит быть злым"
2
Это идеальный вариант использования для управления конфигурацией. Посмотрите на марионетку, шеф-повара, Ансила или Соль.
spuder

Ответы:

31

Вместо того, чтобы вводить пароль несколько раз, вы можете использовать psshего и его -Aпереключатель, чтобы запросить его один раз, а затем передать пароль всем серверам в списке.

ПРИМЕЧАНИЕ. Использование этого метода не позволяет использовать его ssh-copy-id, поэтому вам нужно будет применить собственный метод для добавления файла ключа публикации SSH в файл удаленной учетной записи ~/.ssh/authorized_keys.

пример

Вот пример, который делает работу:

$ cat ~/.ssh/my_id_rsa.pub                    \
    | pssh -h ips.txt -l remoteuser -A -I -i  \
    '                                         \
      umask 077;                              \
      mkdir -p ~/.ssh;                        \
      afile=~/.ssh/authorized_keys;           \
      cat - >> $afile;                        \
      sort -u $afile -o $afile                \
    '
Warning: do not enter your password if anyone else has superuser
privileges or access to your account.
Password:
[1] 23:03:58 [SUCCESS] 10.252.1.1
[2] 23:03:58 [SUCCESS] 10.252.1.2
[3] 23:03:58 [SUCCESS] 10.252.1.3
[4] 23:03:58 [SUCCESS] 10.252.1.10
[5] 23:03:58 [SUCCESS] 10.252.1.5
[6] 23:03:58 [SUCCESS] 10.252.1.6
[7] 23:03:58 [SUCCESS] 10.252.1.9
[8] 23:03:59 [SUCCESS] 10.252.1.8
[9] 23:03:59 [SUCCESS] 10.252.1.7

Приведенный выше скрипт обычно имеет такую ​​структуру:

$ cat <pubkey> | pssh -h <ip file> -l <remote user> -A -I -i '...cmds to add pubkey...'

psshДетали высокого уровня

  • cat <pubkey> выводит файл открытого ключа в pssh
  • psshиспользует -Iпереключатель для приема данных через STDIN
  • -l <remote user> учетная запись удаленного сервера (мы предполагаем, что у вас одинаковое имя пользователя на серверах в файле IP)
  • -Aговорит psshпопросить ваш пароль и затем повторно использовать его для всех серверов, к которым он подключается
  • -iприказывает psshотправлять любой вывод в STDOUT, а не сохранять его в файлах (поведение по умолчанию)
  • '...cmds to add pubkey...'- это самая сложная часть того, что происходит, поэтому я разобью это сам (см. ниже)

Команды, выполняемые на удаленных серверах

Это команды, которые psshбудут выполняться на каждом сервере:

'                                         \
  umask 077;                              \
  mkdir -p ~/.ssh;                        \
  afile=~/.ssh/authorized_keys;           \
  cat - >> $afile;                        \
  sort -u $afile -o $afile                \
'
Для того, чтобы:
  • установите umask удаленного пользователя на 077, так что любые каталоги или файлы, которые мы собираемся создать, будут иметь соответствующие права доступа следующим образом:

    $ ls -ld ~/.ssh ~/.ssh/authorized_keys
    drwx------ 2 remoteuser remoteuser 4096 May 21 22:58 /home/remoteuser/.ssh
    -rw------- 1 remoteuser remoteuser  771 May 21 23:03 /home/remoteuser/.ssh/authorized_keys
    
  • создать каталог ~/.sshи игнорировать предупреждение нас, если он уже есть

  • установить переменную, $afileс путем к файлу author_keys
  • cat - >> $afile - принять входные данные из STDIN и добавить в файл author_keys
  • sort -u $afile -o $afile - уникально сортирует файл author_keys и сохраняет его

ПРИМЕЧАНИЕ. Этот последний бит предназначен для обработки случая, когда вы запускаете вышеуказанное несколько раз на одних и тех же серверах. Это исключит возможность добавления вашего pubkey несколько раз.

Обратите внимание на одиночные галочки!

Также обратите особое внимание на то, что все эти команды вложены в одинарные кавычки. Это важно, поскольку мы не хотим $afileполучать оценку до тех пор, пока она не будет выполнена на удаленном сервере.

'               \
   ..cmds...    \
'

Я расширил вышеописанное, чтобы его было легче читать, но я обычно запускаю все это в одну строку, например:

$ cat ~/.ssh/my_id_rsa.pub | pssh -h ips.txt -l remoteuser -A -I -i 'umask 077; mkdir -p ~/.ssh; afile=~/.ssh/authorized_keys; cat - >> $afile; sort -u $afile -o $afile'

Бонусный материал

С помощью psshвы можете отказаться от того , чтобы построить файлы и либо обеспечить динамическое содержимое , используя -h <(...some command...)или вы можете создать список IP - адреса с помощью других psshпереключателей «s, -H "ip1 ip2 ip3".

Например:

$ cat .... | pssh -h <(grep -A1 dp15 ~/.ssh/config | grep -vE -- '#|--') ...

Выше можно использовать для извлечения списка IP-адресов из моего ~/.ssh/configфайла. Конечно, вы также можете использовать printfдля создания динамического контента:

$ cat .... | pssh -h <(printf "%s\n" srv0{0..9}) ....

Например:

$ printf "%s\n" srv0{0..9}
srv00
srv01
srv02
srv03
srv04
srv05
srv06
srv07
srv08
srv09

Вы также можете использовать seqдля генерации последовательности чисел тоже!

Ссылки и аналогичные инструменты для pssh

Если вы не хотите использовать, psshкак я сделал выше, есть несколько других доступных вариантов.

SLM
источник
2
Три небольших дополнения: (1) psshэто скрипт на Python, который можно установить с помощью pip install pssh. (2) Вы также можете генерировать sshключи на всех серверах одновременно, выполнив ssh-keygenчерез pssh. (3) После генерации ключей вы можете распространять ключи «все на все», копируя все открытые ключи в цикле на локальный компьютер, собирая их в общий authorized_keysи копируя их на каждый компьютер. ssh_agent/ ssh_addможет помочь с паролями.
lcd047
@ lcd047 - спасибо, я включу их в А позже сегодня!
slm
1
Я думаю, что этот скрипт подходит для бесполезного использования catнаград (старого): чтобы запустить конвейер с содержимым файла, вы можете просто перенаправить ввод из этого файла.
Марк ван Леувен
1
@MarcvanLeeuwen - я бы согласился, но я хотел, чтобы всем, кто столкнется с этим в ходе будущих поисков, было легче понять, как происходит передача pubkey pssh.
SLM
1
Не @MarcvanLeeuwen: Это уже не бесполезно , если вы делаете это так: cat ~/.ssh/*.pub | .... Это может или не может быть тем, что вы хотите в этой ситуации, хотя.
lcd047
7

Альтернативное использование xargs, sshpassи ssh-copy-id:

Предполагая, что ваши учетные данные живут в credentials.txt в формате user:password@server:

$ cat credentials.txt
root:insecure@192.168.0.1
foo:insecure@192.168.0.2
bar:realsecure@192.168.0.3

Вы могли бы сделать:

tr ':@' '\n' < credentials.txt \
| xargs -L3 sh -c 'sshpass -p $1 ssh-copy-id $0@$2'

Примечание: не забудьте удалить credentials.txt после использования!

FloHimself
источник
2
И если это одно и то же имя пользователя и пароль для всех серверов, вы можете просто жестко закодировать его напрямую и только прочитать список IP-адресов :-)
Falco
6

ClusterSSH дает вам окно на каждой машине и с общим окном для управления всеми окнами.

Если мы говорим 10 машин, это будет работать. Если речь идет о 100 машинах, будет много окон.

Прелесть ClusterSSH в том, что если одна машина не на 100% похожа на другую, вы можете просто щелкнуть окно и отправить нажатия клавиш только на эту машину, прежде чем вернуться к отправке нажатий клавиш на все машины.

Оле Танге
источник
6

Использовать Ansible довольно просто. Просто замените <USER>реальным логином

$ cd /path/to/public/key

$ cat<<END > hosts
  host1.example.com
  10.10.10.10
  END

$ ansible -i hosts all --ask-pass -u <USER> -m authorized_key \
      -a "user=<USER> key='$(cat id_rsa.pub)'"        
Дэниел Уэйкфилд
источник
0

Пара вещей, которые потенциально могут отвечать всем требованиям:

Как уже упоминалось в других ответах, sshpassэто, вероятно, самое простое решение.

Richlv
источник
-1

У вас есть два варианта здесь:

  • Вы можете создать файл со всеми IP-адресами серверов, а затем сделать следующее

    while read -r ip;do
      ssh-copy-id -i .ssh/id_rsa.pub $ip
    done < servers.txt
    

Предполагается, servers.txtчто это файл с IP-адресами / именами хостов.

  • Вы можете поместить все свои IP-адреса / имена хостов в цикл и запустить, ssh-copy-idкак показано ниже:

    for i in hostname1 hostname2
      do ssh-copy-id -i .ssh/id_rsa.pub $i
    done
    
Толга Озсес
источник
Что полностью противоречит требованиям OP: «Также я не хочу вводить свой пароль снова и снова, используя ssh-copy-idцикл for».
OldTimer
Я не думаю, что есть другой способ, если OP не хочет физически копировать на все серверы.
Толга Озсес