diff --git a/README b/README index 4ef3794dc966bca2595df23f1d4bbbb667d4be14..b81b26b1f7fcbbebd39cc0b9c4457baa6aaef8e4 100644 --- a/README +++ b/README @@ -9,6 +9,9 @@ c'est possible. Il faut pour cela changer la variable cmd_name dans le Makefile avant de lancer make install ou make install-server. == Installation et configuration du client == + +Sous Debian il faut avoir `python2.7` et `python-paramiko` d'installés. + * Copiez le dépôt git sur votre machine : $ git clone git@gitlab.crans.org:nounous/cranspasswords.git * Si ce n'est déjà fait, indiquer votre clé publique sur gest_crans diff --git a/client.py b/client.py index 8d00756585b50adabb533939c2e1fde1ec0fdc1e..76322ed2399261db8923f4805d2cda6181826fb6 100755 --- a/client.py +++ b/client.py @@ -25,6 +25,9 @@ import time import datetime import copy +# Import a SSH client +from paramiko.client import SSHClient + # Import de la config envvar = "CRANSPASSWORDS_CLIENT_CONFIG_DIR" try: @@ -265,35 +268,38 @@ class simple_memoize(object): def remote_proc(options, command, arg=None): """ Fabrique un process distant pour communiquer avec le serveur. - Cela consiste à lancer une commande (indiquée dans la config) - qui va potentiellement lancer ssh. + Cela consiste à lancer une commande par ssh (indiquée dans la config). ``command`` désigne l'action à envoyer au serveur ``arg`` est une chaîne (str) accompagnant la commande en paramètre ``options`` contient la liste usuelle d'options """ - full_command = list(options.serverdata['server_cmd']) - full_command.append(command) + host = str(options.serverdata['host']) + remote_cmd = list(options.serverdata['remote_cmd']) + remote_cmd.append(command) if arg: - full_command.append(arg) + remote_cmd.append(arg) if options.verbose and not options.quiet: - print("Running command %s ..." % " ".join(full_command)) + print("Running command %s ..." % " ".join(remote_cmd)) - proc = subprocess.Popen(full_command, - stdin = subprocess.PIPE, - stdout = subprocess.PIPE, - stderr = sys.stderr, - close_fds = True) - return proc + # Crée un client SSH et charge l'agent et les clés du système + client = SSHClient() + client.load_system_host_keys() + client.connect(host) + + # Crée un Channel et lance la commande + chan = client.get_transport().open_session() + chan.exec_command(remote_cmd) + return chan @simple_memoize def get_keep_alive_connection(options): """Fabrique un process parlant avec le serveur suivant la commande 'keep-alive'. On utilise une fonction séparée pour cela afin de memoizer le résultat, et ainsi utiliser une seule connexion""" - proc = remote_proc(options, 'keep-alive', None) - atexit.register(proc.stdin.close) - return proc + chan = remote_proc(options, 'keep-alive', None) + atexit.register(chan.close) + return chan def remote_command(options, command, arg=None, stdin_contents=None): """Exécute la commande distante, et retourne la sortie de cette @@ -302,20 +308,22 @@ def remote_command(options, command, arg=None, stdin_contents=None): keep_alive = options.serverdata.get('keep-alive', False) if keep_alive: - conn = get_keep_alive_connection(options) + chan = get_keep_alive_connection(options) args = filter(None, [arg, stdin_contents]) msg = {u'action': unicode(command), u'args': args } - conn.stdin.write('%s\n' % json.dumps(msg)) - conn.stdin.flush() - raw_out = conn.stdout.readline() + stdin = chan.makefile_stdin() + stdin.write('%s\n' % json.dumps(msg)) + stdin.flush() + raw_out = chan.recv() else: - proc = remote_proc(options, command, arg) + chan = remote_proc(options, command, arg) if stdin_contents is not None: - proc.stdin.write(json.dumps(stdin_contents)) - proc.stdin.flush() + stdin = chan.makefile_stdin() + stdin.write(json.dumps(stdin_contents)) + stdin.flush() - raw_out, raw_err = proc.communicate() - ret = proc.returncode + raw_out = chan.recv() + ret = chan.recv_exit_status() if ret != 0: if not options.quiet: diff --git a/clientconfig.example.py b/clientconfig.example.py index ccdc5a2c4cff2acaa9b106aab897966bbac1ebeb..13ba00053a782bc583af417fc4edb1086f96fdee 100755 --- a/clientconfig.example.py +++ b/clientconfig.example.py @@ -21,18 +21,20 @@ distant_cmd = ["sudo", '-n', server_path] #: #: Sans précision du paramètre --server, la clé ``'default'`` sera utilisée. #: -#: * ``'server_cmd'`` : La commande exécutée sur le client pour appeler -#: le script sur le serveur distant. +#: * ``'remote_cmd'`` : La commande exécutée sur le serveur. servers = { 'default': { - 'server_cmd': [ssh_path, 'odlyd.crans.org'] + distant_cmd, + 'host': 'odlyd.crans.org', + 'remote_cmd': distant_cmd, }, # Utile pour tester 'localhost': { - 'server_cmd': [ssh_path, 'localhost'] + distant_cmd, + 'host': 'localhost', + 'remote_cmd': distant_cmd, 'keep-alive': True, # <-- experimental, n'ouvre qu'une connexion }, 'ovh': { - 'server_cmd': [ssh_path, 'ovh.crans.org'] + distant_cmd, + 'host': 'soyouz.crans.org', + 'remote_cmd': distant_cmd, } } diff --git a/clientconfigs/crans/clientconfig.py b/clientconfigs/crans/clientconfig.py index b3cd6236e4405ddc60a404e3126cb4f2064f434a..2ccc13131b2de46fda1b09b59c1a8a4a95a86af6 100644 --- a/clientconfigs/crans/clientconfig.py +++ b/clientconfigs/crans/clientconfig.py @@ -8,9 +8,6 @@ import os #: Pour override le nom si vous voulez renommer la commande cmd_name = 'cranspasswords' -#: Path du binaire ssh sur la machine client -ssh_path = '/usr/bin/ssh' - #: Path du script ``cmd_name``-server sur le serveur server_path = '/usr/local/bin/%s-server' % (cmd_name,) @@ -22,21 +19,25 @@ print distant_cmd #: #: Sans précision du paramètre --server, la clé ``'default'`` sera utilisée. #: -#: * ``'server_cmd'`` : La commande exécutée sur le client pour appeler -#: le script sur le serveur distant. +#: * ``'remote_cmd'`` : La commande exécutée sur le serveur. servers = { 'default': { - 'server_cmd': [ssh_path, 'odlyd.crans.org'] + distant_cmd, + 'host': 'odlyd.crans.org', + 'remote_cmd': distant_cmd, }, 'titanic': { - 'server_cmd': [ssh_path, 'freebox.crans.org', ssh_path, 'odlyd.crans.org'] + distant_cmd, + 'host': 'freebox.crans.org', + # manual ssh jump + 'remote_cmd': ['ssh', 'odyld.crans.org'] + distant_cmd, }, # Utile pour tester 'localhost': { - 'server_cmd': [ssh_path, 'localhost'] + distant_cmd, + 'host': 'localhost', + 'remote_cmd': distant_cmd, 'keep-alive': True, # <-- experimental, n'ouvre qu'une connexion }, 'ovh': { - 'server_cmd': [ssh_path, 'soyouz.crans.org', 'sudo', '-n', '/usr/local/bin/cpasswords-server'], + 'host': 'soyouz.crans.org', + 'remote_cmd': ['sudo', '-n', '/usr/local/bin/cpasswords-server'], } } diff --git a/clientconfigs/tudor/clientconfig.py b/clientconfigs/tudor/clientconfig.py index eac5e68166dc5de09fd285eb894448d1d39dc01a..99826944d0625816ec4240d01c58445e131aea3a 100644 --- a/clientconfigs/tudor/clientconfig.py +++ b/clientconfigs/tudor/clientconfig.py @@ -10,23 +10,26 @@ import os #: #: Sans précision du paramètre --server, la clé ``'default'`` sera utilisée. #: -#: * ``'server_cmd'`` : La commande exécutée sur le client pour appeler -#: le script sur le serveur distant. +#: * ``'remote_cmd'`` : La commande exécutée sur le serveur. servers = { 'default': { - 'server_cmd': ['/home/dstan/cranspasswords/serverconfigs/tudor/cpasswords-server', ], + 'host': '', + 'remote_cmd': ['/home/dstan/cranspasswords/serverconfigs/tudor/cpasswords-server', ], 'keep-alive': True, }, 'gladys': { - 'server_cmd': ['/usr/bin/ssh', 'home.b2moo.fr', '/home/dstan/cranspasswords/serverconfigs/tudor/cpasswords-server', ], + 'host': 'home.b2moo.fr', + 'remote_cmd': ['/home/dstan/cranspasswords/serverconfigs/tudor/cpasswords-server', ], 'keep-alive': True, }, 'gladys-home': { - 'server_cmd': ['/usr/bin/ssh', 'gladys.home', '/home/dstan/cranspasswords/serverconfigs/tudor/cpasswords-server', ], + 'host': 'gladys.home', + 'remote_cmd': ['/home/dstan/cranspasswords/serverconfigs/tudor/cpasswords-server', ], 'keep-alive': True, }, 'pimeys': { - 'server_cmd': ['/usr/bin/ssh', 'pimeys.fr', 'sudo', '-n', '/usr/local/bin/cranspasswords-server', ], + 'host': 'pimeys.fr', + 'remote_cmd': ['sudo', '-n', '/usr/local/bin/cranspasswords-server', ], 'keep-alive': True, }, }