f7d20452b1502991a49f5b60b802728ccf5140de
[gentoo-keys.git] / gkeyldap / search.py
1 #
2 #-*- coding:utf-8 -*-
3
4
5 import ldap
6
7 from gkeys import log
8 from gkeys.config import GKEY
9
10 logger = log.logger
11
12 default_server = 'ldap://ldap1.gentoo.org'
13 # add uid to the results so you don't have to
14 # separate it out of the results tuple[0] value
15 default_fields = ['uid', 'cn', 'mail', 'gentooStatus', 'gpgkey', 'gpgfingerprint']
16 default_criteria = 'ou=devs,dc=gentoo,dc=org'
17
18 # establish a ldap fields to GKEY._fields map
19 gkey2ldap_map = {
20     'nick': 'uid',
21     'name': 'cn',
22     'keyid': 'gpgkey',
23     'longkeyid': 'gpgkey',
24     # map the uid to keyring, since we want
25     # dev keyrings to be separate from each other
26     'keyring': 'uid',
27     'fingerprint': 'gpgfingerprint'
28 }
29 # Sanity check they are in sync
30 if not sorted(gkey2ldap_map) == sorted(GKEY._fields):
31     raise "Search.py out of sync with GKEY class"
32
33
34 # Now for some search field defaults
35 UID = '(uid=%s)'
36 CN = '(cn=%s)'
37 STATUS = '(gentooStatus=%s)'
38 GPGKEY = '(gpgkey=%s)'
39 MAIL = '(mail=%s)'
40 GPGFINGERPRINT = '(gpgfingerprint=%s)'
41
42 gkey2SEARCH = {
43     'nick': UID,
44     'name': CN,
45     'status': STATUS,
46     'keyid': GPGKEY,
47     'mail': MAIL,
48     'fingerprint': GPGFINGERPRINT,
49 }
50
51
52 class LdapSearch(object):
53     '''Class to perform searches on the configured ldap server
54     '''
55
56     def __init__(self, server=None, fields=None, criteria=None):
57         self.server = server or default_server
58         self.fields = fields or default_fields
59         self.criteria = criteria or default_criteria
60         logger.debug('LdapSearch: __init__; server...: %s' % self.server)
61         logger.debug('LdapSearch: __init__; fields...: %s' % self.fields)
62         logger.debug('LdapSearch: __init__; criteria.: %s' % self.criteria)
63         self.ldap_connection = None
64
65
66     def connect(self, server=None,):
67         '''Creates our ldap server connection
68
69         '''
70         if server:
71             self.server = server
72             logger.debug('LdapSearch: connect; new server: %s' % self.server)
73         try:
74             self.ldap_connection = ldap.initialize(self.server)
75             self.ldap_connection.set_option(ldap.OPT_X_TLS_DEMAND, True)
76             self.ldap_connection.start_tls_s()
77             self.ldap_connection.simple_bind_s()
78         except Exception as e:
79             logger.error('LdapSearch: connect; failed to connect to server: %s' % self.server)
80             logger.error("Exception was: %s" % str(e))
81             return False
82         logger.debug('LdapSearch: connect; connection: %s' % self.ldap_connection)
83         return True
84
85
86
87     def search(self, target, search_field=UID, fields=None, criteria=None):
88         '''Perform the ldap search
89         '''
90         if not target:
91             logger.debug('LdapSearch: search; invalid target: "%s"' % target)
92             return {}
93         if not fields:
94             fields = self.fields
95         else:
96             logger.debug('LdapSearch: search; new fields: %s' % str(fields))
97         if not criteria:
98             criteria = self.criteria
99         else:
100             logger.debug('LdapSearch: search; new criteria: %s' % criteria)
101         results = self.ldap_connection.search_s(criteria,
102             ldap.SCOPE_ONELEVEL, search_field % target, fields)
103         #logger.debug('LdapSearch: search; result = %s' % str(results))
104         return results
105
106
107     def result2dict(self, results, key='uid'):
108         _dict = {}
109         for entry in results:
110             info = entry[1]
111             key_value = info[key][0]
112             _dict[key_value] = info
113         return _dict