...
 
Commits (16)
But de la branche:
* Garder le même protocole de communication
* Moduler le code en plusieurs fichiers
* Changer le format des fichiers de confs, en gardant l'ancien format
pour le moment
* Renommage progressif en cpasswords (et virer les kludges de noms
de fichiers)
Pour tester rapidement ses modifs :
......
* Replication auto
* CLI
* prepare python3 \o/
* ./configure
* Tester python
* Tester xclip
* Proposer des profils tous faits dans un sous-dosier
* refaire Makefile
* Système de templates/exemples de conf
* make update (après git pull)
* remplissage via ldap
* installation de dev
* retirer le binaire serveur de /usr/local/bin/
* Modulariser le code (client.py devient gros)
* renommer en "cpasswords" ? (aka common passwords :p)
* internationalisation
* annotation des dates de dernières màj et cie
diff --git a/client.py b/client.py
index 6ba2a6e..6486e11 100755
--- a/client.py
......
This diff is collapsed.
#!/usr/bin/env python
# -*- coding: utf-8 -*-
def _setify_roles(roles):
"""Makes set of pairs (rolename, user)"""
out = set()
role_names = roles.keys()
list.sort(role_names)
for k in role_names:
list.sort(roles[k])
for v in roles[k]:
out.add((k,v))
return out
def diff_set(a, b, item_dump):
"""Return difference between two sets"""
out = u""
added = set()
deleted = set()
for x in a.symmetric_difference(b):
if x in b:
added.add(x)
else:
deleted.add(x)
out += u" * Added *\n"
for x in added:
out += u" " + item_dump(x) + u'\n'
out += u" * Removed *\n"
for x in deleted:
out += u" " + item_dump(x) + u'\n'
return out
def _dump_key_pair(item):
if item[1][1] is not None:
return "%s with key %s (%s)" % (item[0], item[1][0], item[1][1])
else:
return "%s with mail %s (no key)" % (item[0], item[1][0])
def _dump_role_pair(item):
return "%s in %s" % (item[1], item[0])
def diff_config(cfga, cfgb):
"""Compare two server configurations"""
out = u"** Keys **\n"
out += diff_set(set(cfga.KEYS.items()), set(cfgb.KEYS.items()), _dump_key_pair)
out += u"** Roles **\n"
out += diff_set(_setify_roles(cfga.ROLES),
_setify_roles(cfgb.ROLES), _dump_role_pair)
return out
# test
if __name__ == '__main__':
import serverconfig2
import serverconfig
print diff_config(serverconfig, serverconfig2)
#!/bin/bash /usr/scripts/python.sh
# -*- coding: utf-8 -*-
from __future__ import print_function
from lc_ldap import shortcuts
import collections
import serverconfig_example as prev_config
conn = shortcuts.lc_ldap_admin()
role_of_droit = {
u'apprenti': [u'apprentis',],
u'bureau': [u'ca', u'ca-w',],
u'tresorier': [u'tresorerie', u'tresorerie-w', ],
u'nounou': [u'nounous', u'nounous-w', u'apprentis', u'apprentis-w'],
}
role_of_mail = {
u'rtc@crans.org': [u'tresorerie', u'tresorerie-w', ],
u'president@crans.org': [u'tresorerie', u'tresorerie-w', ],
}
def format_fpr(fpr):
return fpr.replace(' ','')
def populate_db(login, field, value):
print(("%s has no %s ldap value, populate ldap from former config " +
"(value=%s) ? [yn]") % (login, field, value))
if raw_input().lower() in ['y', 'o']:
member = conn.search(u'uid=%s' % login, mode='rw')[0]
member[field] = value
member.history_add(unicode(shortcuts.current_user), unicode(field))
member.save()
else:
print("Nevermind.")
roles = collections.defaultdict(list)
keys = dict()
fa = u'(|%s)' % u''.join(u'(droits=%s)' % x for x in role_of_droit.iterkeys())
fb = u'(|%s)' % u''.join(u'(mailAlias=%s)' % x for x in role_of_mail.iterkeys())
filterstr = u'(|%s%s)' % (fa, fb)
for member in conn.search(filterstr):
login = member['uid'][0].value
# On remplit la clé
if member['gpgFingerprint']:
fpr = format_fpr(member['gpgFingerprint'][0].value)
elif prev_config.KEYS.get(login, (None,None))[1] is not None:
fpr = prev_config.KEYS[login][1]
populate_db(login, 'gpgFingerprint', fpr)
else:
fpr = None
# Now le mail associé
if member['gpgMail']:
mail = member['gpgMail'][0].value
elif fpr is not None and prev_config.KEYS.has_key(login):
mail = prev_config.KEYS[login][0] # <!>
populate_db(login, 'gpgMail', mail)
else:
#mail = login + u'@crans.org'
# pas de fpr ni de mail, go away
continue
keys[login] = (mail, fpr)
# Tous les droits pour login (sans doublon)
his_roles = set()
for droit in member['droits']:
his_roles.update(role_of_droit.get(droit.value.lower(), []))
for x in member['mailAlias']:
his_roles.update(role_of_mail.get(x.value.lower(), []))
# On remplit roles
for role in his_roles:
roles[role].append(login)
class NewConfig(object):
KEYS = None
ROLES = None
def __init__(self, a, b):
self.KEYS = a
self.ROLES = b
new_config = NewConfig(keys, roles)
from diff_rights import diff_config
print(diff_config(prev_config, new_config))
Ce dossier contient des exemples de config et servira à terme à
l'installation des fichiers de config (via configure et make).
Pour l'instant,
$ for f in `ls *.ini`; do ln -s `pwd`/$f ~/.config/cranspasswords/$f; done
Puis choisir son default (au crans, vert)
$ cd ~/.config/cranspasswords/; ln -s vert.srv default.srv
; Serveur principal des mots de passes (adm only, il faut une proxy command dans sont .ssh/config)
[default]
server_cmd=ssh vert.adm.crans.org sudo -n /usr/local/bin/cranspasswords-server
keep-alive=true
; Serveur de backup des mots de passes extérieur au réseau
[ovh]
server_cmd=/home/dstan/crans/cranspasswords/server.py
keep-alive=true
[perso]
server_cmd=sudo /usr/local/bin/cranspasswords-server
[default]
[test]
server_cmd=/home/dstan/crans/cranspasswords/server.py
keep-alive=true
......@@ -41,6 +41,8 @@ def validate(roles, mode='r'):
def getpath(filename, backup=False):
"""Récupère le chemin du fichier ``filename``"""
assert(isinstance(filename, unicode))
filename = filename.encode('utf-8')
return os.path.join(serverconfig.STORE, '%s.%s' % (filename, 'bak' if backup else 'json'))
def writefile(filename, contents):
......@@ -140,7 +142,8 @@ def listfiles():
files = {}
for filename in filenames:
file_dict = json.loads(open(filename).read())
files[filename[:-5]] = file_dict["roles"]
fname = filename[:-5].decode('utf-8')
files[fname] = file_dict["roles"]
return files
@server_command('getfile')
......
......@@ -31,7 +31,7 @@ KEYS = {
u'becue': (u'becue@crans.org', u'9AE04D986400E3B67528F4930D442664194974E2'),
u'blockelet': (u'blockelet@crans.org', u'550A057BC913EA4637D250495314C173AF087A52'),
u'boilard': (u'boilard@crans.org', u'E73A648AAB5E81BE38038350C1690AB9C39EB6F4'),
u'cauderlier': (u'cauderlier@crans.org', None),
u'cauderlier': (u'cauderlier@crans.org', u'4D302A566C2956334DF6AD8E1B199227E5ABC502'),
u'chambart': (u'pierre.chambart@crans.org', u'085D0DFB66EAF9448C42979C43680A46F2530FCE'),
u'dandrimont': (u'nicolas.dandrimont@crans.org', u'791F12396630DD71FD364375B8E5087766475AAF'),
u'dimino': (u'jdimino@dptinfo.ens-cachan.fr', u'2C938EAC93A16F8129F807C81E8A30532127F85A'),
......@@ -45,7 +45,7 @@ KEYS = {
u'legallic': (u'legallic@crans.org', u'4BDD2DC3F10C26B9BC3B0BD93602E1C9A94025B0'),
u'lerisson': (u'lerisson@crans.org', None),
u'maioli': (u'maioli@crans.org', None),
u'parret-freaud': (u'parret-freaud@crans.org', u'A93D3EB37C3669F89C01F9AE13AC8F777D980513'),
u'parret-freaud': (u'apf@crans.org', u'41049BA24909F12F958386A336381C4C2CBB08AA'),
u'samir': (u'samir@crans.org', u'C7B8823E96E8DC2798970340C86AD2AA41C2B76B'),
u'tvincent': (u'vincent.thomas@crans.org', u'DFB04CE4394B1115C587AE101C6BE33AC5C4ACC0'),
#Autogen
......@@ -67,7 +67,8 @@ KEYS = {
u'randazzo': (u'randazzo@crans.org', None),
u'epalle': (u'epalle@crans.org', None),
u'bonaque': (u'bonaque@crans.org', None),
u'kviard': (u'kviard@crans.org', None)
u'kviard': (u'kviard@crans.org', None),
u'delorme': (u'jordy@crans.org', u'E2250729CF7D2C801748D33F8219ECBA6B1DD5EF'),
}
#: Les variables suivantes sont utilisées pour définir le dictionnaire des
......@@ -96,6 +97,7 @@ NOUNOUS = RTC + [
u'pommeret',
u'serrano',
u'lasseri',
u'delorme',
]
# Autogen:
......