Automatisation de ssh-copy-id

J'ai un nombre arbitraire de servers avec la même combinaison user / passe. Je veux écrire un script (que j'appelle une fois) afin que

ssh-copy-id user@myserver

est appelé pour chaque server. Comme ils ont tous le même user / passe, cela devrait être facile, mais ssh-copy-id veut que je tape le mot de passe séparément à chaque fois qui dégrade le but de mon script. Il n'y a pas d'option pour mettre un mot de passe, c'est ssh-copy-id -p mypassword user@myserver dire ssh-copy-id -p mypassword user@myserver .

Comment puis-je écrire un script qui remplit automatiquement le champ du mot de passe lorsque ssh-copy-id request?

Jetez un oeil à sshpass . Placez votre mot de passe dans un file text et faites quelque chose comme ceci:

 $ sshpass -f password.txt ssh-copy-id user@yourserver 

Vous pouvez utiliser l'attente d'écouter l'invite du mot de passe et d'envoyer votre mot de passe:

 #!/usr/bin/expect -f spawn ssh-copy-id $argv expect "password:" send "YOUR_PASSWORD\n" expect eof 

Enregistrez le script, rendez-le exécutable et appelez-le comme: ./login.expect user@myserver

C'est un problème avec ssh-copy-id; Il ajoute également une key chaque fois que vous l'exécutez. Si vous automatisez le process, votre file authorized_keys devient rapidement encombré de keys en double. Voici un programme Python qui évite les deux problèmes. Il fonctionne à partir du server de contrôle et met les keys d'un server distant dans un autre server distant.

 import subprocess def Remote(cmd,IP): cmd = '''ssh root@%s '''%(IP)+cmd lines = subprocess.check_output(cmd.split()) return '\n'.join(lines) source = '123.456.78.90' target = '239.234.654.123' getkey = 'cat /root/.ssh/id_rsa.pub' getauth = 'cat /root/.ssh/authorized_keys' sourcekey = Remote(getkey, source).replace('\n','').ssortingp() authkeys = Remote(getauth, target).replace('\n','').ssortingp() if sourcekey not in authkeys: keycmd=''' echo "%s" >>/root/.ssh/authorized_keys; chmod 600 /root/.ssh/authorized_keys '''%(sourcekey) # A compound shell statement print 'Installed key', Remote(keycmd,target) else: print 'Does not need key' 

Plutôt que de taper votre mot de passe à plusieurs resockets, vous pouvez utiliser pssh et son -A commutateur pour l' pssh une fois, puis le mot de passe à tous les servers d'une list.

REMARQUE: l' utilisation de cette méthode ne vous permet pas d'utiliser ssh-copy-id , mais vous devrez rouler votre propre méthode pour append votre file de key de pub SSH au file ~/.ssh/authorized_keys de votre count distant.

Exemple

Voici un exemple qui fait le travail:

 $ 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 

Le script ci-dessus est généralement structuré de la manière suivante:

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

pssh haut niveau pssh

  • cat <pubkey> produit le file de key publique vers pssh
  • pssh utilise le -I commute pour ingérer des données via STDIN
  • -l <remote user> est le count du server distant (nous supposons que vous avez le même nom d'user sur les servers du file IP)
  • -A dit à pssh de requestr votre mot de passe, puis le réutiliser pour tous les servers auxquels il se connecte
  • -i dit à pssh d'envoyer n'importe quelle sortie à STDOUT plutôt que de la stocker dans les files (son comportement par défaut)
  • '...cmds to add pubkey...' – c'est la partie la plus délicate de ce qui se passe, alors je vais rompre cela par lui-même (voir ci-dessous)

Commandes exécutées sur des servers distants

Ce sont les commands que pssh exécutera sur chaque server:

 ' \ umask 077; \ mkdir -p ~/.ssh; \ afile=~/.ssh/authorized_keys; \ cat - >> $afile; \ sort -u $afile -o $afile \ ' 

En ordre:

  • définissez l'umask de l'user distant à 077, ce qui signifie que tous les directorys ou files que nous allons créer auront leurs permissions définies comme suit:

     $ 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 
  • créez le directory ~/.ssh et ignorez nous l'avertissement s'il est déjà là

  • définissez une variable, $afile , avec le path du file authorized_keys
  • cat - >> $afile – prendre la part de STDIN et append au file authorized_keys
  • sort -u $afile -o $afile – class exclusivement le file authorized_keys et l'enregistre

REMARQUE: Ce dernier bit consiste à gérer le cas où vous exécutez les multiples fois ci-dessus contre les mêmes servers. Cela éliminera votre pubkey d'être ajouté plusieurs fois.

Notez les ticks simples!

Veillez également à ce que toutes ces commands soient nestedes dans des guillemets simples. C'est important, car nous ne voulons pas que $afile soit évalué jusqu'à ce qu'il soit exécuté sur le server distant.

 ' \ ..cmds... \ ' 

J'ai élargi ce qui précède, donc il est plus facile de lire ici, mais je l'exécute généralement sur une seule ligne:

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

Matériel bonus

En utilisant pssh vous pouvez renoncer à build des files et à fournir un contenu dynamic à l'aide de -h <(...some command...) ou vous pouvez créer une list d'adresses IP à l'aide d'un autre pssh de pssh , -H "ip1 ip2 ip3" .

Par exemple:

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

Ce qui précède pourrait être utilisé pour extraire une list d'IP à partir de mon file ~/.ssh/config . Vous pouvez bien sûr utiliser également printf pour générer du contenu dynamic aussi:

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

Par exemple:

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

Vous pouvez également utiliser seq pour générer des séquences de nombres formatés aussi!

Références et outils similaires à pssh

Si vous ne souhaitez pas utiliser pssh comme je l'ai fait ci-dessus, d'autres options sont disponibles.

  • spppt
  • Le module autorisé autorisé Ansible_key_module

L'un des outils SSH parallèles (clusterssh, mssh, pssh) peut être approprié pour vous.

Par exemple, utilisez cssh pour vous connecter à toutes les machines et append la key vous-même.

Quelques choses qui pourraient convenir à la facture:

  • Fonctionnellement, la même question a également été posée: Comment puis-je propager ma key de pub SSH à une list de servers sans avoir à taper mon mot de passe à plusieurs resockets? .
  • Il existe un module perl, mais il ne semble pas être très bien entretenu: https://github.com/Ruyk/pssh-copy-id

Comme mentionné dans d'autres réponses, sshpass est probablement la solution la plus simple.