diff options
Diffstat (limited to 'ipsilon/info')
-rwxr-xr-x | ipsilon/info/common.py | 42 | ||||
-rwxr-xr-x | ipsilon/info/infoldap.py | 54 | ||||
-rwxr-xr-x | ipsilon/info/nss.py | 55 |
3 files changed, 139 insertions, 12 deletions
diff --git a/ipsilon/info/common.py b/ipsilon/info/common.py index c4be8fe..92a3ba2 100755 --- a/ipsilon/info/common.py +++ b/ipsilon/info/common.py @@ -47,6 +47,48 @@ class InfoProviderBase(PluginObject, Log): self.debug('Info plugin disabled: %s' % self.name) +class InfoMapping(Log): + + def __init__(self): + self.standard_attributes = { + 'fullname': 'Full Name', + 'nickname': 'Nickname', + 'surname': 'Last Name', + 'firstname': 'First Name', + 'title': 'Title', + 'dob': 'Date of Birth', + 'email': 'E-mail Address', + 'gender': 'Gender', + 'postcode': 'Postal Code', + 'street': 'Street Address', + 'state': 'State or Province', + 'country': 'Country', + 'phone': 'Telephone Number', + 'language': 'Language', + 'timezone': 'Time Zone', + } + self.mapping = dict() + + def set_mapping(self, attrs_map): + self.mapping = attrs_map + + def display_name(self, name): + if name in self.standard_attributes: + return self.standard_attributes[name] + return name + + def map_attrs(self, attrs): + s = dict() + e = dict() + for a in attrs: + if a in self.mapping: + s[self.mapping[a]] = attrs[a] + else: + e[a] = attrs[a] + + return s, e + + FACILITY = 'info_config' diff --git a/ipsilon/info/infoldap.py b/ipsilon/info/infoldap.py index 6d710bd..fb1c121 100755 --- a/ipsilon/info/infoldap.py +++ b/ipsilon/info/infoldap.py @@ -6,15 +6,33 @@ from ipsilon.info.common import InfoProviderBase from ipsilon.info.common import InfoProviderInstaller +from ipsilon.info.common import InfoMapping from ipsilon.util.plugin import PluginObject from ipsilon.util.log import Log import ldap +# TODO: fetch mapping from configuration +ldap_mapping = { + 'cn': 'fullname', + 'commonname': 'fullname', + 'sn': 'surname', + 'mail': 'email', + 'destinationindicator': 'country', + 'postalcode': 'postcode', + 'st': 'state', + 'statetorprovincename': 'state', + 'streetaddress': 'street', + 'telephonenumber': 'phone', +} + + class InfoProvider(InfoProviderBase, Log): def __init__(self): super(InfoProvider, self).__init__() + self.mapper = InfoMapping() + self.mapper.set_mapping(ldap_mapping) self.name = 'ldap' self.description = """ Info plugin that uses LDAP to retrieve user data. """ @@ -92,24 +110,48 @@ Info plugin that uses LDAP to retrieve user data. """ return conn - def get_user_data_from_conn(self, conn, dn): + def _get_user_data(self, conn, dn): result = conn.search_s(dn, ldap.SCOPE_BASE) if result is None or result == []: raise Exception('User object could not be found!') elif len(result) > 1: raise Exception('No unique user object could be found!') - return result[0][1] + data = dict() + for name, value in result[0][1].iteritems(): + if type(value) is list and len(value) == 1: + value = value[0] + data[name] = value + return data + + def _get_user_groups(self, conn, dn, ldapattrs): + # TODO: fixme to support RFC2307bis schemas + if 'memberuid' in ldapattrs: + return ldapattrs['memberuid'] + else: + return [] + + def get_user_data_from_conn(self, conn, dn): + reply = dict() + try: + ldapattrs = self._get_user_data(conn, dn) + userattrs, extras = self.mapper.map_attrs(ldapattrs) + groups = self._get_user_groups(conn, dn, ldapattrs) + reply['userdata'] = userattrs + reply['groups'] = groups + reply['extras'] = {'ldap': extras} + except Exception, e: # pylint: disable=broad-except + self.error(e) + + return reply def get_user_attrs(self, user): - userattrs = None try: conn = self._ldap_bind() dn = self.user_dn_tmpl % {'username': user} - userattrs = self.get_user_data_from_conn(conn, dn) + return self.get_user_data_from_conn(conn, dn) except Exception, e: # pylint: disable=broad-except self.error(e) - - return userattrs + return {} class Installer(InfoProviderInstaller): diff --git a/ipsilon/info/nss.py b/ipsilon/info/nss.py index e9a3a96..4208442 100755 --- a/ipsilon/info/nss.py +++ b/ipsilon/info/nss.py @@ -6,27 +6,70 @@ from ipsilon.info.common import InfoProviderBase from ipsilon.info.common import InfoProviderInstaller +from ipsilon.info.common import InfoMapping from ipsilon.util.plugin import PluginObject +import grp import pwd +import os + + +posix_map = { + 'gecos': 'fullname' +} class InfoProvider(InfoProviderBase): def __init__(self): super(InfoProvider, self).__init__() + self.mapper = InfoMapping() + self.mapper.set_mapping(posix_map) self.name = 'nss' + def _get_posix_user(self, user): + p = pwd.getpwnam(user) + return {'username': p.pw_name, 'uidNumber': p.pw_uid, + 'gidNumber': p.pw_gid, 'gecos': p.pw_gecos, + 'homeDirectory': p.pw_dir, 'loginShell': p.pw_shell} + + def _get_posix_groups(self, user, group): + groups = set() + getgrouplist = getattr(os, 'getgrouplist', None) + if getgrouplist: + ids = getgrouplist(user, group) + for i in ids: + try: + g = grp.getgrgid(i) + groups.add(g.gr_name) + except KeyError: + pass + + else: + g = grp.getgrgid(group) + groups.add(g.gr_name) + + allg = grp.getgrall() + for g in allg: + if user in g.gr_mem: + groups.add(g.gr_name) + + return list(groups) + def get_user_attrs(self, user): - userattrs = None + reply = dict() try: - p = pwd.getpwnam(user) - userattrs = {'uidNumber': p[2], 'gidNumber': p[3], - 'gecos': p[4], 'homeDirectory': p[5], - 'loginShell': p[6]} + posix_user = self._get_posix_user(user) + userattrs, extras = self.mapper.map_attrs(posix_user) + groups = self._get_posix_groups(posix_user['username'], + posix_user['gidNumber']) + reply['userdata'] = userattrs + reply['groups'] = groups + reply['extras'] = {'posix': extras} + except KeyError: pass - return userattrs + return reply class Installer(InfoProviderInstaller): |