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