Jak mogę propagować mój klucz publikacji SSH na listę serwerów bez konieczności ciągłego wpisywania hasła?

26

Niedawno otrzymałem dostęp do nazwy użytkownika / hasła do listy serwerów i chcę propagować mój klucz publiczny SSH na tych serwerach, aby łatwiej się zalogować.

Aby było jasne:

  • Na zdalnych serwerach nie ma żadnego wcześniejszego klucza publicznego, którego mógłbym użyć do zautomatyzowania tego
  • To pierwszy raz, kiedy loguję się na te serwery i nie chcę ciągle wpisywać moich danych logowania, aby uzyskać do nich dostęp
  • Nie chcę też wielokrotnie wpisywać hasła przy użyciu ssh-copy-idpętli for.
slm
źródło
1
To ta sama nazwa użytkownika i hasło dla wszystkich serwerów?
roaima
@roaima - tak! Ten szczegół mnie również zaskoczył, ale taka właśnie jest konfiguracja centrum danych i tak właśnie to robią.
slm
@ ott-- - dokładnie sprawdź Q. Wyraźnie stwierdzam, że nie chcę wykonywać pętli for ssh-copy-id, pompując moje hasło w kółko.
slm
Zobacz także skrypt automatyzujący scp w sieci
Gilles „SO- przestań być zły”
2
Jest to idealny przypadek użycia do zarządzania konfiguracją. Spójrz na marionetkę, szefa kuchni, ansible lub sól.
spuder

Odpowiedzi:

31

Zamiast wpisywać hasła wielokrotnie można wykorzystać psshi jego -Aprzejście na zachęty dla niego raz, a następnie karmić hasło do wszystkich serwerów na liście.

UWAGA: Korzystanie z tej metody nie pozwala jednak na jej użycie ssh-copy-id, dlatego konieczne będzie wdrożenie własnej metody dołączania pliku klucza pub SSH do pliku konta zdalnego ~/.ssh/authorized_keys.

Przykład

Oto przykład, który wykonuje zadanie:

$ 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

Powyższy skrypt ma ogólnie taką strukturę:

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

psshSzczegóły na wysokim poziomie

  • cat <pubkey> wysyła plik klucza publicznego do pssh
  • psshużywa -Iprzełącznika do pobierania danych przez STDIN
  • -l <remote user> to konto zdalnego serwera (zakładamy, że masz taką samą nazwę użytkownika na serwerach w pliku IP)
  • -Akaże psshpoprosić o hasło, a następnie użyć go ponownie dla wszystkich serwerów, z którymi się łączy
  • -ikaże psshwysyłać dane wyjściowe do STDOUT zamiast przechowywać je w plikach (jest to zachowanie domyślne)
  • '...cmds to add pubkey...'- to jest najtrudniejsza część tego, co się dzieje, więc sam to podzielę (patrz poniżej)

Polecenia uruchamiane na zdalnych serwerach

Oto polecenia, które psshbędą uruchamiane na każdym serwerze:

'                                         \
  umask 077;                              \
  mkdir -p ~/.ssh;                        \
  afile=~/.ssh/authorized_keys;           \
  cat - >> $afile;                        \
  sort -u $afile -o $afile                \
'
W porządku:
  • ustaw umask użytkownika zdalnego na 077, dzięki temu wszelkie katalogi lub pliki, które będziemy tworzyć, będą miały odpowiednio ustawione uprawnienia:

    $ 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
  • utwórz katalog ~/.sshi zignoruj ​​ostrzeżenie, jeśli już tam jest

  • ustaw zmienną, $afileze ścieżką do pliku autoryzowanych_kluczy
  • cat - >> $afile - weź dane wejściowe ze STDIN i dołącz do pliku uprawnione klucze
  • sort -u $afile -o $afile - jednoznacznie sortuje plik uprawniony_klucz i zapisuje go

UWAGA: Ten ostatni bit dotyczy obsługi przypadku, w którym powyższe uruchamiane są wielokrotnie na tych samych serwerach. Pozwoli to wyeliminować wielokrotne dołączanie Twojego klucza publicznego.

Zwróć uwagę na pojedyncze tyknięcia!

Zwróć także szczególną uwagę na fakt, że wszystkie te polecenia są zagnieżdżone w pojedynczych cudzysłowach. To ważne, ponieważ nie chcemy $afilebyć poddawani ocenie, dopóki nie zostanie wykonana na zdalnym serwerze.

'               \
   ..cmds...    \
'

Rozszerzyłem powyższe, aby łatwiej było je tutaj przeczytać, ale generalnie uruchamiam to wszystko w jednym wierszu:

$ 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'

Materiał bonusowy

Dzięki zastosowaniu psshmożna zrezygnować z konieczności konstruowania pliki i albo zapewnienie dynamicznej zawartości przy użyciu -h <(...some command...)lub można utworzyć listę adresów IP, z wykorzystaniem innego pssh„s przełączników -H "ip1 ip2 ip3".

Na przykład:

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

Powyższe można wykorzystać do wyodrębnienia listy adresów IP z mojego ~/.ssh/configpliku. Oczywiście możesz także użyć printfdo generowania dynamicznej treści:

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

Na przykład:

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

Możesz także użyć seqdo generowania sformatowanych sekwencji liczb!

Referencje i podobne narzędzia do pssh

Jeśli nie chcesz używać psshtak jak ja to zrobiłem powyżej, dostępne są inne opcje.

slm
źródło
2
Trzy drobne dodatki: (1) psshto skrypt w języku Python, który można zainstalować za pomocą pip install pssh. (2) Można również wygenerować sshklucze na wszystkich serwerach jednocześnie uruchamiając ssh-keygenpoprzez pssh. (3) Po wygenerowaniu kluczy możesz rozdzielić klucze „wszystko do wszystkich”, kopiując wszystkie klucze publiczne w pętli na maszynę lokalną, składając je we wspólnej authorized_keysi kopiując je na każdą maszynę. ssh_agent/ ssh_addmoże pomóc z hasłami.
lcd047
@ lcd047 - dzięki, włączę je później do A!
slm
1
Myślę, że ten skrypt kwalifikuje się do bezużytecznego użycia catnagrody (starych): aby uruchomić potok z zawartością pliku, wystarczy przekierować dane wejściowe z tego pliku.
Marc van Leeuwen
1
@MarcvanLeeuwen - Chciałbym się zgodzić, ale chciałem, aby było łatwiej dla każdego, kto natknie się na to podczas przyszłych wyszukiwań, aby jasno zrozumieć, w jaki sposób przekazywany jest klucz pub pssh.
slm
1
@MarcvanLeeuwen: To już nie ma sensu, jeśli robisz to tak: cat ~/.ssh/*.pub | .... W tej sytuacji może jednak nie być tym, czego chcesz.
lcd047,
7

Alternatywą korzystania xargs, sshpassoraz ssh-copy-id:

Zakładając, że dane logowania znajdują się w pliku credentials.txt w formacie user:password@server:

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

Mógłbyś:

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

Uwaga: pamiętaj, aby usunąć credentials.txt po użyciu!

FloHimself
źródło
2
A jeśli jest to ta sama nazwa użytkownika i hasło dla wszystkich serwerów, możesz po prostu kodować bezpośrednio i czytać tylko listę adresów IP :-)
Falco
6

ClusterSSH daje okno na każdym komputerze i ze wspólnym oknem do sterowania wszystkimi oknami.

Jeśli mówimy o 10 maszynach, to zadziała. Jeśli mówimy o 100 maszynach, będzie wiele okien.

Zaletą ClusterSSH jest to, że jeśli jedna maszyna nie jest w 100% podobna do reszty, możesz po prostu kliknąć okno i wysłać klawisze tylko na tę maszynę, zanim wrócisz do wysyłania klawiszy na wszystkie maszyny.

Ole Tange
źródło
6

Korzystanie z Ansible jest dość proste. Po prostu zamień <USER>na prawdziwą nazwę logowania

$ 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)'"        
Daniel Wakefield
źródło
0

Kilka rzeczy, które mogą potencjalnie pasować do rachunku:

Jak wspomniano w innych odpowiedziach, sshpassjest to prawdopodobnie najłatwiejsze rozwiązanie.

Richlv
źródło
-1

Masz tutaj dwie opcje:

  • Możesz utworzyć plik ze wszystkimi adresami IP serwerów, a następnie wykonaj poniższe czynności

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

Zakładając, że servers.txtjest to plik z adresami IP / nazwami hostów.

  • Możesz umieścić wszystkie swoje adresy IP / nazwy hostów w pętli i uruchomić ssh-copy-idjak poniżej:

    for i in hostname1 hostname2
      do ssh-copy-id -i .ssh/id_rsa.pub $i
    done
Tolga Ozses
źródło
Co jest całkowicie sprzeczne z wymaganiami PO: „Nie chcę też wielokrotnie wpisywać hasła przy użyciu ssh-copy-idpętli for”.
OldTimer,
Nie sądzę, że istnieje inny sposób, chyba że OP jest skłonny fizycznie skopiować na wszystkie serwery.
Tolga Ozses