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 gkeys.config import GKEY, KEYID, LONGKEYID, FINGERPRINT, KEY_LEN
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, info):
25 '''Small utility function to return only keyid (short)
28 @param key: string, the key length desired
29 @param info: list of keysid's to process
30 @return list of the desired key length id's
34 if x.startswith('0x'):
35 mylen = KEY_LEN[key] + 2
43 class Actions(object):
46 def __init__(self, config, output=None, logger=None):
51 self.fingerprint_re = re.compile('[0-9A-Fa-f]{40}')
54 def ldapsearch(self, args):
56 self.logger.info("Search...establishing connection")
57 self.output("Search...establishing connection")
59 self.logger.info("Aborting Search...Connection failed")
60 self.output("Aborting Search...Connection failed")
62 self.logger.debug("MAIN: _action_ldapsearch; args = %s" % str(args))
63 x, target, search_field = self.get_args(args)
64 results = l.search(target, search_field)
65 devs = l.result2dict(results, gkey2ldap_map[x])
66 for dev in sorted(devs):
67 self.output(dev, devs[dev])
68 self.output("============================================")
69 self.output("Total number of devs in results:", len(devs))
70 self.logger.info("============================================")
71 self.logger.info("Total number of devs in results: %d" % len(devs))
75 def updateseeds(self, args):
76 self.logger.info("Beginning ldap search...")
77 self.output("Beginning ldap search...")
80 self.output("Aborting Update...Connection failed")
81 self.logger.info("Aborting Update...Connection failed")
83 results = l.search('*', UID)
84 info = l.result2dict(results, 'uid')
86 "MAIN: _action_updateseeds; got results :) converted to info")
87 if not self.create_seedfile(info):
88 self.logger.error("Dev seed file update failure: "
89 "Original seed file is intact & untouched.")
90 filename = self.config['dev-seedfile']
91 old = filename + '.old'
93 self.output("Backing up existing file...")
94 self.logger.info("Backing up existing file...")
95 if os.path.exists(old):
97 "MAIN: _action_updateseeds; Removing 'old' seed file: %s"
100 if os.path.exists(filename):
102 "MAIN: _action_updateseeds; Renaming current seed file to: "
104 os.rename(filename, old)
106 "MAIN: _action_updateseeds; Renaming '.new' seed file to: %s"
108 os.rename(filename + '.new', filename)
111 self.output("Developer Seed file updated")
115 def create_seedfile(self, devs):
116 self.output("Creating seeds from ldap data...")
117 filename = self.config['dev-seedfile'] + '.new'
118 self.seeds = Seeds(filename)
121 for dev in sorted(devs):
122 if devs[dev]['gentooStatus'][0] not in ['active']:
124 #self.logger.debug("create_seedfile, dev = "
125 # "%s, %s" % (str(dev), str(devs[dev])))
126 keyinfo = self.build_gkeylist(devs[dev])
128 new_gkey = GKEY._make(keyinfo)
129 self.seeds.add(new_gkey)
133 self.output("Total number of seeds created:", count)
134 self.output("Seeds created...saving file: %s" % filename)
135 self.output("Total number of Dev's with gpg errors:", error_count)
136 self.logger.info("Total number of seeds created: %d" % count)
137 self.logger.info("Seeds created...saving file: %s" % filename)
138 self.logger.info("Total number of Dev's with gpg errors: %d" % error_count)
139 return self.seeds.save()
144 for x in ['nick', 'name', 'gpgkey', 'fingerprint', 'status']:
146 target = getattr(args, x)
147 search_field = gkey2SEARCH[x]
149 return (x, target, search_field)
153 def build_gkeydict(self, info):
155 for x in GKEY._fields:
156 field = gkey2ldap_map[x]
160 # strip errant line feeds
161 values = [y.strip('\n') for y in info[field]]
162 if values and values in ['uid', 'cn' ]:
164 # separate out short/long key id's
165 elif values and x in ['keyid', 'longkeyid']:
166 value = get_key_ids(x, values)
169 if 'undefined' in values:
170 self.logger.error('%s = "undefined" for %s, %s'
171 %(field, info['uid'][0], info['cn'][0]))
179 def build_gkeylist(self, info):
182 keyid_missing = False
183 # assume it's good until an error is found
185 #self.logger.debug("Actions: build_gkeylist; info = %s" % str(info))
186 for x in GKEY._fields:
187 field = gkey2ldap_map[x]
192 # strip errant line feeds
193 values = [y.strip('\n') for y in info[field]]
194 if values and field in ['uid', 'cn' ]:
196 # separate out short/long key id's
197 elif values and x in ['keyid', 'longkeyid']:
198 value = get_key_ids(x, values)
201 elif values and x in ['fingerprint']:
202 value = [v.replace(' ', '') for v in values]
205 if 'undefined' in values:
206 self.logger.error('ERROR in ldap info for: %s, %s'
207 %(info['uid'][0],info['cn'][0]))
208 self.logger.error(' %s = "undefined"' %(field))
210 keyinfo.append(value)
212 self.logger.debug('Ldap info for: %s, %s'
213 %(info['uid'][0],info['cn'][0]))
214 self.logger.debug(' MISSING or EMPTY ldap field ' +
215 '[%s] GPGKey field [%s]' %(field, x))
216 if x in ['keyid', 'longkeyid']:
221 if not keyid_found and keyid_missing:
224 fingerprint = info[gkey2ldap_map['fingerprint']]
225 self.logger.debug(' Generate gpgkey, Found ldap fingerprint field')
227 gpgkey = 'Missing fingerprint from ldap info'
228 self.logger.debug(' Generate gpgkey, ldap fingerprint KeyError')
230 values = [y.strip('\n') for y in fingerprint]
231 value = [v.replace(' ', '') for v in values]
232 # assign it to gpgkey to prevent a possible
233 # "gpgkey" undefined error
234 gpgkey = ['0x' + x[-KEY_LEN['longkeyid']:] for x in value]
235 keyinfo[LONGKEYID] = gpgkey
236 self.logger.debug(' Generate gpgkey, NEW keyinfo[LONGKEYID] = %s'
237 % str(keyinfo[LONGKEYID]))
239 gpgkey = 'Missing or Bad fingerprint from ldap info'
241 if not keyinfo[LONGKEYID]:
242 self.logger.error('ERROR in ldap info for: %s, %s'
243 %(info['uid'][0],info['cn'][0]))
244 self.logger.error(' A valid keyid, longkeyid or fingerprint '
245 'was not found for %s : gpgkey = %s' %(info['cn'][0], gpgkey))
248 if keyinfo[FINGERPRINT]: # fingerprints exist check
249 is_ok = self._check_fingerprint_integrity(info, keyinfo)
250 is_match = self._check_id_fingerprint_match(info, keyinfo)
251 if not is_ok or not is_match:
258 def _check_id_fingerprint_match(self, info, keyinfo):
259 # assume it's good until found an error is found
261 for x in [KEYID, LONGKEYID]:
262 # skip blank id field
266 index = len(y.lstrip('0x'))
267 if y.lstrip('0x').upper() not in \
268 [x[-index:].upper() for x in keyinfo[FINGERPRINT]]:
269 self.logger.error('ERROR in ldap info for: %s, %s'
270 %(info['uid'][0],info['cn'][0]))
271 self.logger.error(' ' + str(keyinfo))
272 self.logger.error(' GPGKey id %s not found in the '
273 % y.lstrip('0x') + 'listed fingerprint(s)')
278 def _check_fingerprint_integrity(self, info, keyinfo):
279 # assume it's good until found an error is found
281 for x in keyinfo[FINGERPRINT]:
282 # check fingerprint integrity
284 self.logger.error('ERROR in ldap info for: %s, %s'
285 %(info['uid'][0],info['cn'][0]))
286 self.logger.error(' GPGKey incorrect fingerprint ' +
287 'length (%s) for fingerprint: %s' %(len(x), x))
290 if not self.fingerprint_re.match(x):
291 self.logger.error('ERROR in ldap info for: %s, %s'
292 %(info['uid'][0],info['cn'][0]))
293 self.logger.error(' GPGKey: Non hexadecimal digits in ' +
294 'fingerprint for fingerprint: ' + x)