5 Gentoo-keys - gkeyldap/actions.py
7 Primary api interface module
9 @copyright: 2012 by Brian Dolbec <dol-sen@gentoo.org>
10 @license: GNU GPL2, see COPYING for details.
16 from collections import defaultdict
17 from gkeys.seed import Seeds
18 from gkeyldap.search import (LdapSearch, UID, gkey2ldap_map, gkey2SEARCH)
21 Available_Actions = ['ldapsearch', 'updateseeds']
24 def get_key_ids(key_len, keyids):
25 '''Small utility function to return only keyid (short)
28 @param key_len: string, the key length desired
29 @param keyids: list of keysid's to process
30 @return list of the desired key length id's
35 if keyid.startswith('0x'):
36 target_len = target_len + 2
37 if len(keyid) == target_len:
42 class Actions(object):
45 def __init__(self, config, output=None, logger=None):
50 self.fingerprint_re = re.compile('[0-9A-Fa-f]{40}')
53 def ldapsearch(self, args):
55 self.logger.info("Search... Establishing connection")
56 self.output("Search... Establishing connection")
58 self.logger.info("Aborting search... Connection failed")
59 self.output("Aborting search... Connection failed")
61 self.logger.debug("MAIN: _action_ldapsearch; args = %s" % str(args))
62 x, target, search_field = self.get_args(args)
63 results = l.search(target, search_field)
64 devs = l.result2dict(results, gkey2ldap_map[x])
65 for dev in sorted(devs):
66 self.output(dev, devs[dev])
67 self.output("============================================")
68 self.output("Total number of developers in results:", len(devs))
69 self.logger.info("============================================")
70 self.logger.info("Total number of developers in results: %d" % len(devs))
74 def updateseeds(self, args):
75 self.logger.info("Beginning LDAP search...")
76 self.output("Beginning LDAP search...")
79 self.output("Aborting update... Connection failed")
80 self.logger.info("Aborting update... Connection failed")
82 results = l.search('*', UID)
83 info = l.result2dict(results, 'uid')
85 "MAIN: _action_updateseeds; got results :) converted to info")
86 if not self.create_seedfile(info):
87 self.logger.error("Developer seed file update failure: "
88 "Original seed file is intact & untouched.")
89 filename = self.config['dev-seedfile']
90 old = filename + '.old'
92 self.output("Backing up existing file...")
93 self.logger.info("Backing up existing file...")
94 if os.path.exists(old):
96 "MAIN: _action_updateseeds; Removing 'old' seed file: %s"
99 if os.path.exists(filename):
101 "MAIN: _action_updateseeds; Renaming current seed file to: "
103 os.rename(filename, old)
105 "MAIN: _action_updateseeds; Renaming '.new' seed file to: %s"
107 os.rename(filename + '.new', filename)
110 self.output("Developer seed file updated!")
114 def create_seedfile(self, devs):
115 self.output("Creating seeds from LDAP data...")
116 filename = self.config['dev-seedfile'] + '.new'
117 self.seeds = Seeds(filename)
120 for dev in sorted(devs):
121 if devs[dev]['gentooStatus'][0] not in ['active']:
123 #self.logger.debug("create_seedfile, dev = "
124 # "%s, %s" % (str(dev), str(devs[dev])))
125 developer_attrs = self.build_gkeydict(devs[dev])
127 self.seeds.add(dev, developer_attrs)
131 self.output("Total number of seeds created:", count)
132 self.output("Seeds created... Saving file: %s" % filename)
133 self.output("Total number of Dev's with GPG errors:", error_count)
134 self.logger.info("Total number of seeds created: %d" % count)
135 self.logger.info("Seeds created... Saving file: %s" % filename)
136 self.logger.info("Total number of Dev's with GPG errors: %d" % error_count)
137 return self.seeds.save()
142 for attr in ['nick', 'name', 'gpgkey', 'fingerprint', 'status']:
144 target = getattr(args, attr)
145 search_field = gkey2SEARCH[attr]
147 return (attr, target, search_field)
150 def build_gkeydict(self, info):
151 keyinfo = defaultdict()
153 keyid_missing = False
154 # assume it's good until an error is found
156 #self.logger.debug("Actions: build_gkeylist; info = %s" % str(info))
157 for attr in gkey2ldap_map:
158 field = gkey2ldap_map[attr]
164 # strip errant line feeds
165 values = [y.strip('\n') for y in values]
166 # separate out short/long key id's
167 if values and attr in ['keyid', 'longkeyid']:
168 if len(get_key_ids(attr, values)):
170 elif values and attr in ['fingerprint']:
171 values = [v.replace(' ', '') for v in values]
172 if 'undefined' in values:
173 self.logger.error('ERROR in LDAP info for: %s, %s'
174 % (info['uid'][0],info['cn'][0]))
175 self.logger.error(' %s = "undefined"' % (field))
177 keyinfo[attr] = values
179 self.logger.debug('LDAP info for: %s, %s'
180 % (info['uid'][0],info['cn'][0]))
181 self.logger.debug(' MISSING or EMPTY LDAP field ' +
182 '[%s] GPGKey field [%s]' % (field, attr))
183 if attr in ['keyid', 'longkeyid']:
188 if not keyid_found and keyid_missing:
191 fingerprint = info[gkey2ldap_map['fingerprint']]
192 self.logger.debug(' Generate gpgkey, Found LDAP fingerprint field')
194 gpgkey = 'Missing fingerprint from LDAP info'
195 self.logger.debug(' Generate gpgkey, LDAP fingerprint KeyError')
197 values = [y.strip('\n') for y in fingerprint]
198 values = [v.replace(' ', '') for v in values]
199 # assign it to gpgkey to prevent a possible
200 # "gpgkey" undefined error
201 gpgkey = ['0x' + x[-16:] for x in values]
202 keyinfo['longkeyid'] = gpgkey
203 self.logger.debug(' Generate gpgkey, NEW keyinfo[\'fingerprint\'] = %s'
204 % str(keyinfo['longkeyid']))
206 gpgkey = 'Missing or Bad fingerprint from LDAP info'
208 if not keyinfo['longkeyid']:
209 self.logger.error('ERROR in ldap info for: %s, %s'
210 %(info['uid'][0],info['cn'][0]))
211 self.logger.error(' A valid keyid, longkeyid or fingerprint '
212 'was not found for %s : gpgkey = %s' %(info['cn'][0], gpgkey))
215 if keyinfo['fingerprint']: # fingerprints exist check
216 is_ok = self._check_fingerprint_integrity(info, keyinfo)
217 is_match = self._check_id_fingerprint_match(info, keyinfo)
218 if not is_ok or not is_match:
225 def _check_id_fingerprint_match(self, info, keyinfo):
226 # assume it's good until found an error is found
228 for attr in ['keyid', 'longkeyid']:
229 # skip blank id field
230 if not keyinfo[attr]:
232 for y in keyinfo[attr]:
233 index = len(y.lstrip('0x'))
234 if y.lstrip('0x').upper() not in \
235 [x[-index:].upper() for x in keyinfo['fingerprint']]:
236 self.logger.error('ERROR in LDAP info for: %s, %s'
237 %(info['uid'][0],info['cn'][0]))
238 self.logger.error(' ' + str(keyinfo))
239 self.logger.error(' GPGKey id %s not found in the '
240 % y.lstrip('0x') + 'listed fingerprint(s)')
245 def _check_fingerprint_integrity(self, info, keyinfo):
246 # assume it's good until found an error is found
248 for fingerprint in keyinfo['fingerprint']:
249 # check fingerprint integrity
250 if len(fingerprint) != 40:
251 self.logger.error('ERROR in LDAP info for: %s, %s'
252 %(info['uid'][0],info['cn'][0]))
253 self.logger.error(' GPGKey incorrect fingerprint ' +
254 'length (%s) for fingerprint: %s' %(len(fingerprint), fingerprint))
257 if not self.fingerprint_re.match(fingerprint):
258 self.logger.error('ERROR in LDAP info for: %s, %s'
259 % (info['uid'][0],info['cn'][0]))
260 self.logger.error(' GPGKey: Non hexadecimal digits in ' +
261 'fingerprint for fingerprint: ' + fingerprint)