This commit is contained in:
Daniel STAN 2012-05-23 23:10:48 +02:00
commit a3d0fee0df
2 changed files with 333 additions and 0 deletions

156
cranspasswords.py Executable file
View file

@ -0,0 +1,156 @@
#!/usr/bin/env python
# -*- encoding: utf-8 -*-
"""cranspasswords: gestion des mots de passe du Cr@ns"""
import sys
import subprocess
import json
######
## GPG Definitions
GPG = '/usr/bin/gpg'
GPG_ARGS = {
'decrypt': ['-d'],
'encrypt': ['--armor', '-es'],
'fingerprint': ['--fingerprint'],
'receive-keys': ['--recv-keys'],
}
def gpg(command, args = None):
"""Lance gpg pour la commande donnée avec les arguments
donnés. Renvoie son entrée standard et sa sortie standard."""
full_command = [GPG]
full_command.extend(GPG_ARGS[command])
if args:
full_command.extend(args)
proc = subprocess.Popen(full_command,
stdin = subprocess.PIPE,
stdout = subprocess.PIPE,
stderr = sys.stderr,
close_fds = True)
return proc.stdin, proc.stdout
######
## Remote commands
SSH = '/usr/bin/ssh'
SSH_HOST = 'localhost'
REMOTE_COMMAND = ['/home/nicolasd/cranspasswords-server.py']
def ssh(command, arg = None):
"""Lance ssh avec les arguments donnés. Renvoie son entrée
standard et sa sortie standard."""
full_command = [SSH, SSH_HOST]
full_command.extend(REMOTE_COMMAND)
full_command.append(command)
if arg:
full_command.append(arg)
proc = subprocess.Popen(full_command,
stdin = subprocess.PIPE,
stdout = subprocess.PIPE,
stderr = sys.stderr,
close_fds = True)
return proc.stdin, proc.stdout
def remote_command(command, arg = None, stdin_contents = None):
"""Exécute la commande distante, et retourne la sortie de cette
commande"""
sshin, sshout = ssh(command, arg)
if stdin_contents:
sshin.write(json.dumps(stdin_contents))
sshin.close()
return json.loads(sshout.read())
def all_keys():
"""Récupère les clés du serveur distant"""
return remote_command("listkeys")
def all_roles():
"""Récupère les roles du serveur distant"""
return remote_command("listroles")
def all_files():
"""Récupère les fichiers du serveur distant"""
return remote_command("listfiles")
def get_file(filename):
"""Récupère le contenu du fichier distant"""
return remote_command("getfile", filename)
def put_file(filename, roles, contents):
"""Dépose le fichier sur le serveur distant"""
return remote_command("putfile", filename, {'roles': roles,
'contents': contents})
def rm_file(filename):
"""Supprime le fichier sur le serveur distant"""
return remote_command("rmfile", filename)
######
## Local commands
def update_keys():
"""Met à jour les clés existantes"""
keys = all_keys()
_, stdout = gpg("receive-keys", [key for _, key in keys.values() if key])
return stdout.read()
def check_keys():
"""Vérifie les clés existantes"""
keys = all_keys()
for mail, key in keys.values():
if key:
_, stdout = gpg("fingerprint", [key])
if "<%s>" % mail.lower() not in stdout.read().lower():
break
else:
return True
return False
def encrypt(roles, contents):
"""Chiffre le contenu pour les roles donnés"""
recipients = set()
allroles = all_roles()
allkeys = all_keys()
email_recipients = []
for role in roles:
for recipient in allroles[role]:
recipients.add(recipient)
for recipient in recipients:
email, key = allkeys[recipient]
if key:
email_recipients.append("-r")
email_recipients.append(email)
stdin, stdout = gpg("encrypt", email_recipients)
stdin.write(contents)
stdin.close()
return stdout.read()
def decrypt(contents):
"""Déchiffre le contenu"""
stdin, stdout = gpg("decrypt")
stdin.write(contents)
stdin.close()
return stdout.read()
def put_password(name, roles, contents):
"""Dépose le mot de passe après l'avoir chiffré pour les
destinataires donnés"""
enc_pwd = encrypt(roles, contents)
return put_file(name, roles, enc_pwd)
def get_password(name):
"""Récupère le mot de passe donné par name"""
remotefile = get_file(name)
return decrypt(remotefile['contents'])