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

25

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

Para que fique claro:

  • Não há nenhuma chave pública pré-existente nos servidores remotos que eu possa utilizar para automatizar isso
  • Isso constitui a primeira vez que estou fazendo login nesses servidores e gostaria de não precisar digitar minhas credenciais constantemente para acessá-las
  • Também não quero digitar minha senha repetidamente usando ssh-copy-id em um loop for.
por slm 22.05.2015 / 06:21

6 respostas

30

Em vez de digitar sua senha várias vezes, é possível usar a opção pssh e sua -A para solicitar uma vez e, em seguida, alimentar a senha para todos os servidores em uma lista.

OBSERVAÇÃO: No entanto, o uso desse método não permite que você use ssh-copy-id , então você precisará aplicar seu próprio método para anexar o arquivo de chave do seu SSH à% da sua conta remota~/.ssh/authorized_keys file.

Exemplo

Veja 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 forma:

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

Alto nível pssh detalhes

  • cat <pubkey> envia o arquivo de chave pública para pssh
  • pssh usa a opção -I 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 no arquivo IP)
  • -A informa pssh para pedir sua senha e reutilizá-la para todos os servidores aos quais ela se conecta
  • -i informa pssh para 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 dividir isso por si mesmo (veja abaixo)

Comandos sendo executados em servidores remotos

Estes são os comandos que pssh executará em cada servidor:

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

    $ 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 ~/.ssh e ignore o aviso se já estiver lá

  • definir uma variável, $afile , com o caminho para o arquivo authorized_keys
  • cat - >> $afile - recebe entrada de STDIN e anexa ao arquivo authorized_keys
  • sort -u $afile -o $afile - classifica exclusivamente o arquivo authorized_keys e salva-o

OBSERVAÇÃO: Esse último bit é para lidar com o caso em que você executa o exemplo acima várias vezes em relação aos mesmos servidores. Isso eliminará o seu pubkey de ser adicionado várias vezes.

Observe o único carrapato!

Preste também atenção especial ao fato de que todos esses comandos estão aninhados dentro de aspas simples. Isso é importante, já que não queremos que $afile seja avaliado até que esteja sendo executado no servidor remoto.

'               \
   ..cmds...    \
'

Expandi o 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

Ao usar pssh , você pode não ter que construir arquivos e fornecer conteúdo dinâmico usando -h <(...some command...) ou pode criar uma lista de IPs usando outro dos comutadores pssh , -H "ip1 ip2 ip3" .

Por exemplo:

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

O acima pode ser usado para extrair uma lista de IPs do meu arquivo ~/.ssh/config . Você também pode usar printf para gerar conteúdo dinâmico também:

$ 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 seq para gerar sequências de números formatados também!

Referências e amp; ferramentas semelhantes para pssh

Se você não quiser usar pssh como eu fiz acima, há algumas outras opções disponíveis.

por 22.05.2015 / 06:21
7

Alternativa usando xargs , sshpass e ssh-copy-id :

Presumindo que suas credenciais estejam em credentials.txt no formato user:password@server :

$ cat credentials.txt
root:[email protected]
foo:[email protected]
bar:[email protected]

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!

    
por 22.05.2015 / 09:13
6

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

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

A beleza do ClusterSSH é que, se uma máquina não for 100% como o resto, você pode simplesmente clicar na janela e enviar pressionamentos de tecla somente para essa máquina antes de voltar a enviar pressionamentos de tecla para todas as máquinas.

    
por 22.05.2015 / 12:41
6

O uso de Ansible é bastante simples. Basta substituir <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)'"        
    
por 22.05.2015 / 17:37
0

Algumas coisas que podem potencialmente se encaixar na fatura:

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

    
por 27.02.2016 / 19:45
-1

Você tem duas opções aqui:

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

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

Assumindo que servers.txt é o arquivo com IPs / nomes de host.

  • Você pode colocar todos os seus IPs / hostnames em um loop e executar ssh-copy-id como abaixo:

    for i in hostname1 hostname2
      do ssh-copy-id -i .ssh/id_rsa.pub $i
    done
    
por 23.05.2015 / 19:48