web-dev-qa-db-fra.com

Automatisation de ssh-copy-id

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

ssh-copy-id user@myserver

est appelé pour chaque serveur. Comme ils ont tous le même utilisateur/pass, cela devrait être facile mais ssh-copy-id veut que je tape le mot de passe séparément à chaque fois, ce qui va à l'encontre de l'objectif de mon script. Il n'y a pas d'option pour saisir un mot de passe, c'est-à-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 le demande?

32
devin

Jetez un œil à sshpass . Placez votre mot de passe dans un fichier texte et faites quelque chose comme ceci:

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

Vous pouvez utiliser attendre d'écouter l'invite de mot de passe et 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

20
MonkeeSage

la réponse de quanta est assez bonne, mais elle vous oblige à mettre votre mot de passe dans un fichier texte.

Depuis la page de manuel "sshpass":

Si aucune option n'est donnée, sshpass lit le mot de passe à partir de l'entrée standard.

Donc, ce que vous pouvez faire est de capturer le mot de passe une fois pendant le script, de le stocker dans une variable, de faire écho au mot de passe et de le diriger vers sshpass en entrée.

Je fais ça tout le temps et ça marche bien. Exemple: echo "Please insert the password used for ssh login on remote machine:" read -r USERPASS for TARGETIP in $@; do echo "$USERPASS" | sshpass ssh-copy-id -f -i $KEYLOCATION "$USER"@"$TARGETIP" done

4
Esoteric Eric

Il s'agit d'un problème avec ssh-copy-id; il ajoute également une clé chaque fois que vous l'exécutez. Si vous automatisez le processus, votre fichier authorized_keys est rapidement encombré de clés en double. Voici un programme Python qui évite les deux problèmes. Il s'exécute à partir du serveur de contrôle et place les clés d'un serveur distant dans un autre serveur 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','').strip()
authkeys = Remote(getauth, target).replace('\n','').strip()
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'
2
mfs

L'un des outils SSH parallèles (clusterssh, mssh, pssh) peut vous convenir.

Par exemple, utilisez cssh pour vous connecter à toutes les machines et ajoutez la clé vous-même.

1
MikeyB

Je veux souligner à quel point une idée est mauvaise pour:

  1. Utilisez un mot de passe codé en dur dans vos scripts
  2. Utilisez le même mot de passe sur TOUS vos serveurs ... comme ... pourquoi!?
  3. NE PAS utiliser l'authentification par clé publique SSH + mot de passe si vous insistez
  4. Enregistrez le mot de passe dans un fichier texte

Voici une implémentation un peu plus sécurisée ...

#!/usr/bin/python3
import os
import getpass
import argparse

parser = argparse.argument_parser()
parser.add_argument('-l','--login', action='store', help='username')
parser.add_argument('-p','--port', action='store', default='22', help='port')
parser.add_argument('-L','--list', action='store', help='file list of IPs')
parser.add_argument('-i','--ip-address', action='store', nargs='+', metavar='Host' help='ip or list of ips')

args = parser.parse_args()
if not args.login:
    print("You need a login, broski!")
    return 0

if args.list:
    ips = [i for i in open(args.list, 'r').readlines()]
    passwd = getpass.getpass('Password: ')

    for ip in ips:
        cmd = 'ssh-id-copy {0}@{1} -p {2}'.format(ip,args.port,passwd)            
        os.system('sshpass -p ' + passwd + ' ' + cmd)
        print("Key added: ", ip)   # prints if successful
        # ex: sshpass -p passwd ssh-id-copy [email protected]

Elif args.Host:
    ip = args.Host
    cmd = 'ssh-id-copy {0}@{1} -p {2}'.format(ip,args.port,passwd)
    os.system('sshpass -p ' + passwd + ' ' + cmd)
    print("Key added: ", ip)   # prints if successful
else:
    print("No IP addresses were given to run script...")
    return 0 
0
True Demon

Quelques choses qui pourraient convenir:

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

0
Richlv