Como propagar minha chave de pub SSH para uma lista de servidores sem precisar digitar minha senha repetidamente?

26

Recentemente, recebi acesso de nome de usuário / senha a uma lista de servidores e quero propagar minha chave pública SSH para esses servidores, para que eu possa efetuar login com mais facilidade.

Para que fique claro:

  • Não há nenhuma chave pública preexistente nos servidores remotos que eu possa utilizar para automatizar isso
  • É a primeira vez que faço login nesses servidores e gostaria de não precisar digitar constantemente minhas credenciais para acessá-los.
  • Também não quero digitar minha senha repetidamente usando ssh-copy-idum loop for.
slm
fonte
1
É o mesmo nome de usuário e senha para todos os servidores?
roaima
@roaima - yup! Esse detalhe também me surpreendeu, mas é assim que é essa configuração específica do data center e é assim que eles fazem.
slm
@ ott-- - verifique o Q. Eu declaro explicitamente que não quero fazer um loop for ssh-copy-id, bombeando minha senha repetidamente.
slm
Veja também script para automatizar o scp na rede
Gilles 'SO- stop be evil'
2
Este é um caso de uso perfeito para gerenciamento de configurações. Olhe fantoche, chef, ansible ou sal.
Spuder

Respostas:

31

Em vez de digitar sua senha várias vezes, você pode usar psshe sua -Aopção para solicitá-la uma vez e depois alimentar a senha para todos os servidores em uma lista.

OBSERVAÇÃO:ssh-copy-id no entanto, o uso desse método não permite o uso , portanto, você precisará rolar seu próprio método para anexar seu arquivo de chave de pub SSH ao arquivo da sua conta remota ~/.ssh/authorized_keys.

Exemplo

Aqui está um exemplo que faz o trabalho:

$ 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

O script acima é geralmente estruturado da seguinte maneira:

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

psshDetalhes de alto nível

  • cat <pubkey> gera o arquivo de chave pública para pssh
  • psshusa o -Iswitch para ingerir dados via STDIN
  • -l <remote user> é a conta do servidor remoto (presumimos que você tenha o mesmo nome de usuário nos servidores do arquivo IP)
  • -Apede psshpara solicitar sua senha e reutilizá-la para todos os servidores aos quais se conecta
  • -idiz psshpara enviar qualquer saída para STDOUT em vez de armazená-la em arquivos (seu comportamento padrão)
  • '...cmds to add pubkey...'- esta é a parte mais complicada do que está acontecendo, então eu vou explicar isso sozinha (veja abaixo)

Comandos sendo Executados em Servidores Remotos

Estes são os comandos que psshserão executados em cada servidor:

'                                         \
  umask 077;                              \
  mkdir -p ~/.ssh;                        \
  afile=~/.ssh/authorized_keys;           \
  cat - >> $afile;                        \
  sort -u $afile -o $afile                \
'
Em ordem:
  • defina o umask do usuário remoto como 077, para que todos os diretórios ou arquivos que vamos criar tenham suas permissões definidas da seguinte maneira:

    $ 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
    
  • crie o diretório ~/.sshe ignore o aviso se já estiver lá

  • defina uma variável,, $afilecom o caminho para o arquivo allowed_keys
  • cat - >> $afile - pegue a entrada do STDIN e adicione ao arquivo allowed_keys
  • sort -u $afile -o $afile - classifica exclusivamente o arquivo allowed_keys e o salva

NOTA: Esse último bit é para lidar com o caso em que você executa as opções acima várias vezes nos mesmos servidores. Isso evitará que seu pubkey seja anexado várias vezes.

Observe os carrapatos únicos!

Também preste atenção especial ao fato de que todos esses comandos estão aninhados dentro de aspas simples. Isso é importante, pois não queremos $afileser avaliados até depois da execução no servidor remoto.

'               \
   ..cmds...    \
'

Eu expandi o que foi exposto acima para facilitar a leitura aqui, mas geralmente executo tudo em uma única linha, da seguinte forma:

$ 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 bônus

Usando psshvocê pode abdicar de construir arquivos e quer fornecer conteúdo dinâmico usando -h <(...some command...)ou você pode criar uma lista de IPs usando outro dos psshinterruptores 's, -H "ip1 ip2 ip3".

Por exemplo:

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

O exemplo acima pode ser usado para extrair uma lista de IPs do meu ~/.ssh/configarquivo. Obviamente, você também pode usar printfpara gerar conteúdo dinâmico:

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

Por exemplo:

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

Você também pode usar seqpara gerar seqüências de números formatados também!

Referências e ferramentas similares a pssh

Se você não quiser usar psshcomo eu fiz acima, existem outras opções disponíveis.

slm
fonte
2
Três pequenas inclusões: (1) psshé um script Python e pode ser instalado com pip install pssh. (2) Você também pode gerar sshchaves em todos os servidores simultaneamente, executando ssh-keygenatravés pssh. (3) Após gerar as chaves, você pode distribuir as chaves "todos para todos", copiando todas as chaves públicas em um loop para a máquina local, montando-as em comum authorized_keyse copiando-as para cada máquina. ssh_agent/ ssh_addpode ajudar com as senhas.
Lcd047 22/05
@ lcd047 - obrigado, vou incorporá-los ao A mais tarde hoje!
slm
1
Eu acho que esse script se qualifica para o uso inútil do catprêmio (antigo): para iniciar um pipeline com o conteúdo de um arquivo, basta redirecionar a entrada desse arquivo.
Marc van Leeuwen
1
@MarcvanLeeuwen - eu tenderia a concordar, mas eu queria que fosse mais fácil para qualquer um que possa se deparar com isso através de pesquisas futuras para entender claramente como o pubkey está sendo repassado pssh.
slm
1
@MarcvanLeeuwen: Já não é inútil se você fazê-lo como este: cat ~/.ssh/*.pub | .... Pode ou não ser o que você deseja nesta situação.
Lcd047 22/05
7

Usando alternativa xargs, sshpasse ssh-copy-id:

Supondo que suas credenciais estejam em credentials.txt no 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

Você poderia fazer:

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

Nota: Lembre-se de remover credentials.txt após o uso!

FloHimself
fonte
2
E se é o mesmo nome de usuário e senha para todos os servidores, você pode apenas codificá-lo diretamente e só ler uma lista de IP-Endereços :-)
Falco
6

O ClusterSSH fornece uma janela em cada máquina e uma janela comum para controlar todas as janelas.

Se estivermos falando de 10 máquinas, isso funcionará. Se estamos falando de 100 máquinas, haverá muitas janelas.

A vantagem do ClusterSSH é que, se uma máquina não for 100% como as demais, basta clicar na janela e enviar pressionamentos de tecla apenas para essa máquina antes de voltar a enviar pressionamentos de tecla para todas as máquinas.

Ole Tange
fonte
6

Usar o Ansible é bastante simples. Apenas substitua <USER>pelo nome de login 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
fonte
0

Algumas coisas que podem se encaixar na conta:

Como mencionado em outras respostas, sshpassé provavelmente a solução mais fácil.

Richlv
fonte
-1

Você tem duas opções aqui:

  • Você pode criar um arquivo com todos os endereços IP dos servidores e faça o seguinte

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

Supondo que servers.txtseja o arquivo com IPs / nomes de host.

  • Você pode colocar todos os seus IPs / nomes de host em um loop e executar ssh-copy-idcomo abaixo:

    for i in hostname1 hostname2
      do ssh-copy-id -i .ssh/id_rsa.pub $i
    done
Tolga Ozses
fonte
O que é totalmente contrário aos requisitos do OP: "Também não quero digitar minha senha repetidamente usando ssh-copy-idum loop for".
Oldtimer
Não acho que exista outra maneira, a menos que o OP esteja disposto a copiar fisicamente para todos os servidores.
precisa saber é o seguinte