Outils de création et mise à jour d'annuaire AuF.
authorProgfou <jean-christophe.andre@auf.org>
Fri, 14 Jan 2011 11:22:18 +0000 (18:22 +0700)
committerProgfou <jean-christophe.andre@auf.org>
Fri, 14 Jan 2011 11:22:18 +0000 (18:22 +0700)
openldap/auf-annuaire [new file with mode: 0755]
openldap/auf-annuaire-update [new file with mode: 0755]

diff --git a/openldap/auf-annuaire b/openldap/auf-annuaire
new file mode 100755 (executable)
index 0000000..9296e23
--- /dev/null
@@ -0,0 +1,189 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+"""Outil de gestion d'annuaire LDAP pour l'AuF.
+
+Copyright ©2009-2010  Agence universitaire de la Francophonie
+Licence : GPL version 3
+Auteur : Progfou <jean-christophe.andre@auf.org>
+
+Dépendances Debian : python >= 2.5, python-simplejson, auf-refer
+
+Usage :
+
+  auf-annuaire.py | ldapmodify -x -c -D "cn=admin,o=AUF" -y /etc/ldap.secret
+"""
+
+import os
+import aufrefer
+import simplejson as json
+
+LDAP_HOST = '127.0.0.1'
+LDAP_BASE = 'ou=People,o=AUF'
+LDAP_BINDDN = 'cn=admin,' + LDAP_BASE
+LDAP_PWFILE = ['~/.ldap.secret', '/etc/ldap.secret']
+
+LDAP_INIT_LDIF = u"""dn: ou=People,o=AuF
+changeType: add
+objectClass: top
+objectClass: organizationalUnit
+ou: People
+"""
+
+PERSONNELS = aufrefer.get('personnels.json')
+ISO_3166 = aufrefer.get('iso-3166-fr.json')
+NOMS_BUREAU = aufrefer.get('bureaux.json')
+PAYS_IMPLANT = {'IFMT': 'LA', 'DANANG.VN': 'VN'}
+
+def capitale_sur_les_mots(s):
+    r = ''
+    previous_isalpha = False
+    for c in s:
+        isalpha = c.isalpha()
+        if isalpha and not previous_isalpha:
+            c = c.upper()
+        r += c
+        previous_isalpha = isalpha
+    return r
+
+def pays_implantation(implant):
+    return PAYS_IMPLANT.get(implant.upper(), implant.upper())
+
+def nom_pays(country):
+    return ISO_3166.get(country.upper(),
+                                u'### Pays absent de la norme ISO-3166 ###')
+
+def noms_bureau(cc):
+    for code, data in NOMS_BUREAU.items():
+        if cc.upper() in data[1]:
+            return code, data[0]
+    return u'### implantation inconnue ###', u'### implantation inconnue ###'
+
+def login_nom_personnel(adel):
+    info = filter(lambda p: p['adel'] == adel, PERSONNELS)
+    if not info:
+        return None, None
+    return info[0]['login'], info[0]['nom']
+
+class LdapEntry(object):
+    _attributes_order = [
+        'objectClass', 'sn', 'givenName', 'cn', 'ou', 'l', 'mail', 'o',
+        'userPassword', 'telephoneNumber', 'uid',
+    ]
+
+    def __init__(self, dn, d=None, **kv):
+        self.dn = dn
+        if d:
+            self.dict = d
+        else:
+            self.dict = { }
+        self.dict.update(kv)
+
+    def get(self, attribute):
+        return self.dict.get(attribute, None)
+
+    def set(self, attribute, value):
+        old_value = self.dict.get(attribute, None)
+        self.dict[attribute] = value
+        return old_value
+
+    def from_ldif(self, ldif):
+        raise RuntimeError('Note implemented')
+
+    def _to_ldif_line(self, attribute, value):
+        to_encode = False
+        for c in value:
+            if c < ' ' or 'z' < c:
+                to_encode = True
+                break
+        if to_encode:
+            attribute = attribute + ':'
+            if type(value) == unicode:
+                value = value.encode('utf-8')
+            value = value.encode('base64').rstrip('\n')
+        return u'%s: %s' % (attribute, value)
+
+    def to_ldif(self, changeType=None):
+        ldif = [ ]
+        ldif.append(self._to_ldif_line(u'dn', self.dn))
+        if changeType:
+            ldif.append(u'changeType: %s' % changeType)
+        set_keys = set(self.dict.keys())
+        set_attr_order = set(self._attributes_order)
+        for k in set_keys & set_attr_order:
+            for e in self.dict[k]:
+                ldif.append(self._to_ldif_line(k, e))
+        for k in set_keys - set_attr_order:
+            for e in self.dict[k]:
+                ldif.append(self._to_ldif_line(k, e))
+        ldif.append(u'')
+        return '\n'.join(ldif).encode('utf-8')
+
+
+class AnnuaireAuF(object):
+    _attributes = [
+        'adel', 'redir', 'nom', 'mdp', 'implant', 'coda', 'tel_ext', 'tel_ip',
+    ]
+
+    def __init__(self, ldap_base):
+        self.ldap_base = ldap_base
+        self.data = None
+
+    def json2ldap(self, json_dict):
+        CC = pays_implantation(json_dict['implant'])
+        nom_bureau_court, nom_bureau_long = noms_bureau(CC)
+        adel = json_dict['adel']
+        user, domain = adel.split('@')
+        cn = capitale_sur_les_mots(user)
+        cn = cn.replace('-De-', '-de-').replace('.', ' ')
+        prenom, nom = cn.rsplit(' ', 1)
+        login, nom_affichage = login_nom_personnel(user)
+        if nom_affichage is None:
+            nom_affichage = json_dict['nom'] and json_dict['nom'] or cn
+
+        ldap_dict = { }
+        ldap_dict['objectClass'] = [
+            u'top', u'person', u'organizationalPerson', u'inetOrgPerson'
+        ]
+        ldap_dict['sn'] = [ nom ]
+        ldap_dict['givenName'] = [ prenom ]
+        ldap_dict['cn'] = [ nom_affichage ]
+        ldap_dict['ou'] = [ u'People', nom_bureau_court, nom_bureau_long ]
+        ldap_dict['l'] = [ nom_pays(CC) ]
+        ldap_dict['mail'] = [ adel ]
+        ldap_dict['o'] = [ u'AuF', u'Agence universitaire de la Francophonie' ]
+        if json_dict.has_key('mdp') and json_dict['mdp']:
+            ldap_dict['userPassword'] = [ '{CRYPT}' + json_dict['mdp'] ]
+        if json_dict.has_key('tel_ip') and json_dict['tel_ip']:
+            ldap_dict['telephoneNumber'] = [ json_dict['tel_ip'] ]
+        if login is not None and login:
+            ldap_dict['uid'] = [ login ]
+        ldap_dn = u'mail=%s,%s' % (adel, self.ldap_base)
+        return ldap_dn, ldap_dict
+
+    def load(self):
+        self.data = [ ]
+        for json_dict in aufrefer.get('annuaire.json'):
+            ldap_dn, ldap_dict = self.json2ldap(json_dict)
+            self.data.append(LdapEntry(ldap_dn, ldap_dict))
+
+    def to_ldif(self):
+        ldif = [ LDAP_INIT_LDIF ]
+        for d in self.data:
+            ldif.append(d.to_ldif(changeType='add'))
+        ldif.append('')
+        return '\n'.join(ldif)
+
+    def search(self, name):
+        return filter(lambda x: x['adel'].find(name) >= 0, self.data)
+
+    def update_ldap(self, base=LDAP_BASE,
+                    host=LDAP_HOST, binddn=LDAP_BINDDN, pwfile=LDAP_PWFILE):
+        pass
+
+if __name__ == '__main__':
+    annuaire = AnnuaireAuF(LDAP_BASE)
+    annuaire.load()
+    #print "search('andre'): %s" % \
+    #                    map(lambda x: x['adel'], annuaire.search('andre'))
+    print annuaire.to_ldif(),
+
diff --git a/openldap/auf-annuaire-update b/openldap/auf-annuaire-update
new file mode 100755 (executable)
index 0000000..7e6b972
--- /dev/null
@@ -0,0 +1,12 @@
+#!/bin/sh
+PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
+
+HOST="ldap.vn.auf.org"
+BINDDN="cn=admin,o=AUF"
+BINDPWFILE="/etc/ldap/ldap.secret"
+DELETEBASEDN="ou=People,o=AuF"
+
+ldapdelete -x -c -h $HOST -D $BINDDN -y $BINDPWFILE -r $DELETEBASEDN
+
+auf-annuaire |
+ldapmodify -x -c -h $HOST -D $BINDDN -y $BINDPWFILE