Changeset 1259 for dassldapsync
- Timestamp:
- May 3, 2022, 7:53:07 PM (3 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
dassldapsync/dassldapsync.py
r1257 r1259 4 4 # core modules 5 5 import argparse 6 import ConfigParser6 from configparser import ConfigParser 7 7 import logging 8 8 from pprint import pprint … … 20 20 import ldap.modlist 21 21 from ldap.syncrepl import SyncreplConsumer 22 import ldapurl22 from ldapurl import LDAPUrl 23 23 import ldif 24 24 … … 46 46 self.pwd_max_days = 0 47 47 48 class ConfigParserDefaults(ConfigParser.ConfigParser, object):49 def get(self, section, option, default=None):50 try:51 result = super(self.__class__, self).get(section, option)52 except ConfigParser.NoOptionError:53 if default is None:54 raise55 else:56 result = default57 return result58 59 def get_section(self, section):60 if section in self._sections:61 return self._sections[section]62 63 def get0(self, section, option, default=None):64 try:65 result = super(self.__class__, self).get(section, option)66 except ConfigParser.NoOptionError:67 result = default68 return result69 70 def getboolean(self, section, option, default=None):71 try:72 result = super(self.__class__, self).getboolean(section, option)73 except ConfigParser.NoOptionError:74 if default is None:75 raise76 else:77 result = default78 return result79 80 def get_ldap_url_obj(self, section):81 baseurl = 'ldap://{server}:389/{basedn}'.format(**(self.get_section(section)))82 attrs = None83 if self.get0(section, 'attributes') is not None:84 attrs = self.get(section, 'attributes').split(',')85 return ldapurl.LDAPUrl(86 baseurl,87 dn=self.get(section, 'baseDn', ''),88 who=self.get0(section, 'bindDn'),89 cred=self.get0(section, 'basePassword'),90 filterstr=self.get0(section, 'filter'),91 attrs=attrs92 )93 94 95 48 def readLDIFSource(path): 96 49 logger = logging.getLogger() … … 105 58 logger = logging.getLogger() 106 59 logger.info("reading LDAP objects from server {}".format(server)) 107 con = ldap.open(server, port=389) 60 ldapurl = LDAPUrl(hostport="{}:389".format(self.server)) 61 con = ldap.initialize(ldapurl. initializeUrl()) 108 62 if starttls: 109 63 con.start_tls_s() … … 131 85 self.classmap = {} 132 86 133 self.junk_attrs = ["authzto", "memberof", "modifiersname", "modifytimestamp", "entryuuid", 134 "entrycsn", "contextcsn", "creatorsname", "createtimestamp", 135 "structuralobjectclass", "pwdaccountlockedtime", "pwdchangedtime", "pwdfailuretime" ] 87 #self.junk_objectclasses = [ b"sambaidmapentry" ] 88 #"sambasid", 89 self.junk_objectclasses = [] 90 self.junk_attrs = ["authzto", 91 "creatorsname", "createtimestamp", "contextcsn", 92 "entrycsn", "entryuuid", 93 "memberof", "modifiersname", "modifytimestamp", 94 "pwdaccountlockedtime", "pwdchangedtime", "pwdfailuretime", 95 "structuralobjectclass"] 136 96 137 97 self.reset_result() … … 149 109 if self.con is None: 150 110 self.logger.info("connect to destination LDAP server {}".format(self.destserver)) 151 self.con = ldap.open(self.destserver, port=389) 111 ldapurl = LDAPUrl(hostport="{}:389".format(self.destserver)) 112 self.con = ldap.initialize(ldapurl. initializeUrl()) 152 113 if self.options.starttls: 153 114 self.con.start_tls_s() … … 267 228 max_age = datetime.timedelta(days=self.options.pwd_max_days) 268 229 230 objectClasses = srcAttributes['objectClass'] 231 srcAttributes['objectClass'] = [oc for oc in objectClasses if oc.lower() not in self.junk_objectclasses] 232 269 233 try: 270 234 destDn, destAttributes = self._get_dest_entry(srcDn, srcAttributes) … … 294 258 self.logger.exception('modify failed') 295 259 self.notify_modified(srcDn, False) 260 else: 261 self.notify_unchanged(srcDn) 296 262 297 263 except ldap.NO_SUCH_OBJECT: 298 264 if not self.options.updateonly: 299 265 try: 300 self.con.add_s(srcDn, ldap.modlist.addModlist(srcAttributes, self.junk_attrs)) 266 entry = ldap.modlist.addModlist(srcAttributes, self.junk_attrs) 267 self.con.add_s(srcDn, entry) 301 268 self.notify_created(srcDn) 302 269 except (ldap.OBJECT_CLASS_VIOLATION, 303 270 ldap.NO_SUCH_OBJECT, 304 ldap.CONSTRAINT_VIOLATION): 271 ldap.CONSTRAINT_VIOLATION) as e: 272 #print(e) 305 273 self.notify_created(srcDn, False) 306 274 … … 366 334 ok = len(result[action]['ok']) 367 335 failed = len(result[action]['failed']) 368 print "{} (ok: {}, failed: {}):".format(action, ok, failed)336 print("{} (ok: {}, failed: {}):".format(action, ok, failed)) 369 337 370 338 if show_ok and ok > 0: 371 print "succeeded:"372 print "\n".join(result[action]['ok'])339 print("succeeded:") 340 print("\n".join(result[action]['ok'])) 373 341 374 342 if show_failed and failed > 0: 375 print "failed:"376 print "\n".join(result[action]['failed'])343 print("failed:") 344 print("\n".join(result[action]['failed'])) 377 345 378 346 def get_short_dn(self, dn): 379 347 return dn.lower().replace(',' + self.srcbasedn.lower(), '') 380 348 349 def notify_unchanged(self, dn): 350 logger.debug(u'{} unchanged'.format(self.get_short_dn(dn))) 351 381 352 def notify_created(self, dn, ok=True): 382 353 if ok: 383 logger.debug( '{} created'.format(self.get_short_dn(dn)))354 logger.debug(u'{} created'.format(self.get_short_dn(dn))) 384 355 self.result['add']['ok'].append(dn) 385 356 else: 386 self.logger.warning( "failed to add {}".format(dn))357 self.logger.warning(u"failed to add {}".format(dn)) 387 358 self.result['add']['failed'].append(dn) 388 359 389 360 def notify_modified(self, dn, ok=True): 390 361 if ok: 391 logger.debug( '{} modified'.format(self.get_short_dn(dn)))362 logger.debug(u'{} modified'.format(self.get_short_dn(dn))) 392 363 self.result['update']['ok'].append(dn) 393 364 else: 394 self.logger.error( "failed to modify {}".format(dn))365 self.logger.error(u"failed to modify {}".format(dn)) 395 366 self.result['update']['failed'].append(dn) 396 367 397 368 def notify_deleted(self, dn, ok=True): 398 369 if ok: 399 logger.debug( '{} deleted'.format(self.get_short_dn(dn)))370 logger.debug(u'{} deleted'.format(self.get_short_dn(dn))) 400 371 self.result['delete']['ok'].append(dn) 401 372 else: 402 self.logger.error( "failed to delete {}".format(dn))373 self.logger.error(u"failed to delete {}".format(dn)) 403 374 self.result['delete']['failed'].append(dn) 404 375 405 376 def notify_renamed(self, dn, newdn, uid, newuid, options): 406 print "renamed", dn, newdn377 print(u"renamed {} -> {}".format(dn, newdn)) 407 378 subprocess.check_call( 408 379 "%s %s %s %s %s" % (options.renamecommand, dn, newdn, uid, newuid), … … 519 490 self.source_ldap_connection.simple_bind_s( 520 491 self.source_ldap_url_obj.who, self.source_ldap_url_obj.cred) 521 except ldap.INVALID_CREDENTIALS ,e:522 print 'Login to LDAP server failed: ', str(e)492 except ldap.INVALID_CREDENTIALS as e: 493 print('Login to LDAP server failed: ', str(e)) 523 494 sys.exit(1) 524 495 except ldap.SERVER_DOWN: 525 print 'LDAP server is down, going to retry.'496 print('LDAP server is down, going to retry.') 526 497 time.sleep(5) 527 498 continue … … 539 510 try: 540 511 while self.source_ldap_connection.syncrepl_poll(all=1, msgid=ldap_search): 541 print ".",512 print(".", end="") 542 513 except KeyboardInterrupt: 543 514 # User asked to exit 544 print "aborted\n"515 print("aborted\n") 545 516 self.shutdown(None, None) 546 except Exception ,e:517 except Exception as e: 547 518 # Handle any exception 548 519 if self.watcher_running: … … 566 537 self.watcher_running = False 567 538 539 def get_ldap_url_obj(self, configsection): 540 baseurl = 'ldap://{server}:389/{basedn}'.format(server=configsection.get('server'), basedn=configsection.get('basedn')) 541 attrs = None 542 if configsection.get('attributes') is not None: 543 attrs = configsection.get('attributes').split(',') 544 return LDAPUrl( 545 baseurl, 546 dn=configsection.get('baseDn'), 547 who=configsection.get('bindDn'), 548 cred=configsection.get('basePassword'), 549 filterstr=configsection.get('filter'), 550 attrs=attrs 551 ) 552 568 553 569 554 if __name__ == "__main__": … … 578 563 exclude = None 579 564 580 config = ConfigParser Defaults()565 config = ConfigParser() 581 566 config.read(conffile) 582 567 … … 588 573 589 574 basedn = config.get("source", "baseDn") 590 filterstr = config.get 0("source", "filter",None)575 filterstr = config.get("source", "filter", fallback=None) 591 576 592 577 if srcfile is None: … … 600 585 destadminpw = config.get("destination", "bindPassword") 601 586 destbasedn = config.get("destination", "baseDn") 602 destdelete = config.getboolean("destination", "delete")603 587 try: 604 588 rdn = config.get("destination", "rdn") … … 613 597 pass 614 598 615 options.updateonly = not config.getboolean("destination", "create", False) 616 options.starttls = config.getboolean("destination", "starttls", False) 617 options.renameattr = config.get0("destination", "detectRename", None) 618 options.renamecommand = config.get0("destination", "detectRename", None) 619 options.pwd_max_days = int(config.get("source", "pwd_max_days", 0)) 599 options.updateonly = not config.getboolean("destination", "create", fallback=False) 600 options.delete = config.getboolean("destination", "delete", fallback=False) 601 options.starttls = config.getboolean("destination", "starttls", fallback=False) 602 options.renameattr = config.get("destination", "detectRename", fallback=None) 603 options.renamecommand = config.get("destination", "detectRename", fallback=None) 604 options.pwd_max_days = int(config.get("source", "pwd_max_days", fallback=0)) 620 605 options.filter = filterstr 621 606 … … 628 613 options.attrlist = None 629 614 630 if config.get 0('source', 'mode') == 'syncrepl':615 if config.get('source', 'mode', fallback=None) == 'syncrepl': 631 616 ldapsync = LdapSyncRepl( 632 617 destsrv, destadmindn, destadminpw, basedn, destbasedn, 633 618 options, 634 source_ldap_url_obj= config.get_ldap_url_obj('source'))619 source_ldap_url_obj=get_ldap_url_obj(config['source'])) 635 620 ldapsync.sync() 636 621 else:
Note:
See TracChangeset
for help on using the changeset viewer.