¿Cómo puedo propagar mi clave de publicación SSH a una lista de servidores sin tener que escribir mi contraseña una y otra vez?

26

Recientemente me dieron acceso de nombre de usuario / contraseña a una lista de servidores y quiero propagar mi clave pública SSH a estos servidores, para que pueda iniciar sesión más fácilmente.

Para que quede claro:

  • No hay ninguna clave pública preexistente en los servidores remotos que pueda utilizar para automatizar esto
  • Esto constituye la primera vez que inicio sesión en estos servidores, y me gustaría no tener que escribir constantemente mis credenciales para acceder a ellos.
  • Tampoco quiero escribir mi contraseña una y otra vez usando ssh-copy-idun bucle for.
slm
fuente
1
¿Es el mismo nombre de usuario y contraseña para todos los servidores?
roaima
@roaima - ¡sí! Ese detalle también me sorprendió, pero así es la configuración de este centro de datos en particular y así es como lo hacen.
slm
@ ott-- - retención doble del P. He estado explícitamente que no quiero hacer un bucle a través ssh-copy-id, bombeando mi contraseña una y otra vez.
slm
Ver también script para automatizar scp en la red
Gilles 'SO- deja de ser malvado'
2
Este es un caso de uso perfecto para la gestión de la configuración. Mira marionetas, chef, ansible o sal.
Spuder

Respuestas:

31

En lugar de escribir su contraseña varias veces, puede utilizar psshy su -Ainterruptor para solicitarla una vez, y luego alimentar la contraseña a todos los servidores en una lista.

NOTA:ssh-copy-id Sin embargo, el uso de este método no le permite usarlo , por lo que deberá utilizar su propio método para agregar su archivo de clave de publicación SSH al archivo de su cuenta remota ~/.ssh/authorized_keys.

Ejemplo

Aquí hay un ejemplo que hace el trabajo:

$ 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

El script anterior generalmente se estructura de la siguiente manera:

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

psshDetalles de alto nivel

  • cat <pubkey> saca el archivo de clave pública a pssh
  • psshusa el -Iinterruptor para ingerir datos a través de STDIN
  • -l <remote user> es la cuenta del servidor remoto (asumimos que tiene el mismo nombre de usuario en todos los servidores en el archivo IP)
  • -Ale dice psshque solicite su contraseña y luego la reutilice para todos los servidores a los que se conecta
  • -ile dice psshque envíe cualquier salida a STDOUT en lugar de almacenarla en archivos (su comportamiento predeterminado)
  • '...cmds to add pubkey...'- esta es la parte más complicada de lo que está sucediendo, así que lo desglosaré solo (ver más abajo)

Comandos que se ejecutan en servidores remotos

Estos son los comandos que psshse ejecutarán en cada servidor:

'                                         \
  umask 077;                              \
  mkdir -p ~/.ssh;                        \
  afile=~/.ssh/authorized_keys;           \
  cat - >> $afile;                        \
  sort -u $afile -o $afile                \
'
En orden:
  • configure la umask del usuario remoto en 077, esto es para que cualquier directorio o archivo que creemos tenga sus permisos establecidos de la siguiente manera:

    $ 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
  • crea el directorio ~/.sshe ignora avisándonos si ya está allí

  • establecer una variable, $afilecon la ruta al archivo autorizado_claves
  • cat - >> $afile - tome la entrada de STDIN y anexe al archivo autorizado_claves
  • sort -u $afile -o $afile - clasifica de forma única el archivo autorizado_claves y lo guarda

NOTA: El último bit es manejar el caso en el que ejecuta lo anterior varias veces contra los mismos servidores. Esto evitará que su pubkey se agregue varias veces.

¡Observe las marcas individuales!

También preste especial atención al hecho de que todos estos comandos están anidados dentro de comillas simples. Eso es importante, ya que no queremos $afileser evaluados hasta después de que se esté ejecutando en el servidor remoto.

'               \
   ..cmds...    \
'

He expandido lo anterior para que sea más fácil de leer aquí, pero generalmente lo ejecuto todo en una sola línea así:

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

Material de bonificación

Mediante el uso psshse puede renunciar a tener que construir archivos y, o bien proporcionar contenido dinámico utilizando -h <(...some command...)o puede crear una lista de direcciones IP utilizando otro de los psshinterruptores 's, -H "ip1 ip2 ip3".

Por ejemplo:

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

Lo anterior podría usarse para extraer una lista de IP de mi ~/.ssh/configarchivo. Por supuesto, también puede usar printfpara generar contenido dinámico:

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

Por ejemplo:

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

¡También puedes usar seqpara generar secuencias de números formateadas!

Referencias y herramientas similares a pssh

Si no desea usar psshcomo lo he hecho anteriormente, hay algunas otras opciones disponibles.

slm
fuente
2
Tres adiciones menores: (1) psshes un script de Python, y se puede instalar con pip install pssh. (2) También se pueden generar sshlas claves de todos los servidores de forma simultánea mediante la ejecución ssh-keygena través pssh. (3) Después de generar las claves, puede distribuir las claves "todo a todos" copiando todas las claves públicas en un bucle a la máquina local, ensamblándolas en un común authorized_keysy copiándolas en cada máquina. ssh_agent/ ssh_addpuedo ayudar con las contraseñas.
lcd047
@ lcd047 - gracias, ¡los incorporaré a la A más tarde hoy!
slm
1
Creo que este script califica para el uso inútil de cataward (of old): para comenzar una canalización con el contenido de un archivo, simplemente puede redirigir la entrada de ese archivo.
Marc van Leeuwen
1
@MarcvanLeeuwen: tendería a estar de acuerdo, pero quería que fuera más fácil para cualquiera que pueda encontrar esto a través de búsquedas futuras para comprender claramente cómo se le pasa a la pubkey pssh.
slm
1
@MarcvanLeeuwen: Ya no sirve de nada si lo haces de esta manera: cat ~/.ssh/*.pub | .... Sin embargo, puede o no ser lo que quieres en esta situación.
lcd047
7

Alternativa usando xargs, sshpassy ssh-copy-id:

Suponiendo que sus credenciales vivan en credentials.txt en formato user:password@server:

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

Podrías hacerlo:

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

Nota: ¡Recuerde eliminar credentials.txt después del uso!

Flo Mismo
fuente
2
Y si es el mismo nombre de usuario y contraseña para todos los servidores, puede codificarlo directamente y solo leer una lista de direcciones IP :-)
Falco
6

ClusterSSH le ofrece una ventana en cada máquina y una ventana común para controlar todas las ventanas.

Si estamos hablando de 10 máquinas, esto funcionará. Si estamos hablando de 100 máquinas, habrá muchas ventanas.

La belleza de ClusterSSH es que si una máquina no es 100% como el resto, simplemente puede hacer clic en la ventana y enviar pulsaciones de teclas solo a esa máquina antes de volver a enviar pulsaciones de teclas a todas las máquinas.

Ole Tange
fuente
6

Usar Ansible es bastante simple. Simplemente reemplace <USER>con el nombre de inicio de sesión real

$ 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
fuente
0

Un par de cosas que podrían ajustarse a la factura:

Como se menciona en otras respuestas, sshpasses probable que sea la solución más fácil.

Richlv
fuente
-1

Tienes dos opciones aquí:

  • Puede crear un archivo con todas las direcciones IP de los servidores, luego haga lo siguiente

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

Asumiendo servers.txtes el archivo con IP / nombres de host.

  • Puede poner todas sus direcciones IP / nombres de host en un bucle y ejecutar ssh-copy-idcomo a continuación:

    for i in hostname1 hostname2
      do ssh-copy-id -i .ssh/id_rsa.pub $i
    done
Tolga Ozses
fuente
Lo que va completamente en contra de los requisitos de los OP: "Tampoco quiero escribir mi contraseña una y otra vez ssh-copy-iden un bucle for".
OldTimer
No creo que haya otra forma, a menos que OP esté dispuesto a copiar físicamente a todos los servidores.
Tolga Ozses