From 922357b748e8d32f3d87ba7f443a8a4094775b60 Mon Sep 17 00:00:00 2001 From: Rob Crittenden Date: Fri, 18 Jun 2021 10:11:57 -0400 Subject: [PATCH] Use get_replication_plugin_name in LDAP updater This allows for a consistent way to retrieve the value from LDAP. The method is used to find an existing entry. It is not usable to add or remove entries. Moving it in the code allows the value to always be set in the substitution dictionary and not rely on a specific caller. It was moved to installutils.py to avoid circular import. https://pagure.io/freeipa/issue/8885 Signed-off-by: Rob Crittenden Reviewed-By: Florence Blanc-Renaud Reviewed-By: Alexander Bokovoy --- ipaserver/install/dsinstance.py | 5 +++-- ipaserver/install/installutils.py | 28 ++++++++++++++++++++++++++++ ipaserver/install/ldapupdate.py | 27 ++++++++++++++++----------- ipaserver/install/replication.py | 21 +++------------------ ipaserver/install/upgradeinstance.py | 17 +---------------- 5 files changed, 51 insertions(+), 47 deletions(-) diff --git a/ipaserver/install/dsinstance.py b/ipaserver/install/dsinstance.py index b0e012ab8..6033c0410 100644 --- a/ipaserver/install/dsinstance.py +++ b/ipaserver/install/dsinstance.py @@ -572,10 +572,11 @@ class DsInstance(service.Service): inst.open() def get_entry(dn, attrs): - return inst.getEntry(dn, attrlist=attrs) + return inst.getEntry(str(dn), attrlist=attrs) self.sub_dict['REPLICATION_PLUGIN'] = ( - replication.get_replication_plugin_name(get_entry)) + installutils.get_replication_plugin_name(get_entry) + ) try: ipadomain = IpaDomain(inst, dn=self.suffix.ldap_text()) diff --git a/ipaserver/install/installutils.py b/ipaserver/install/installutils.py index 4a2915042..56b137476 100644 --- a/ipaserver/install/installutils.py +++ b/ipaserver/install/installutils.py @@ -1552,3 +1552,31 @@ def validate_mask(): if mask & 0b111101101 > 0: mask_str = "{:04o}".format(mask) return mask_str + + +def get_replication_plugin_name(dirsrv_get_entry): + # Support renaming of a replication plugin in 389-ds + # IPA topology plugin depends on the replication plugin but + # 389-ds cannot handle older alias querying in the plugin + # configuration with 'nsslapd-plugin-depends-on-named: ..' attribute + # + # dirsrv_get_entry: function (dn, attrs) can return different types + # depending on the function. The 389-ds connection returns bytes + # and ipaldap will return a list of string values. + try: + entry = dirsrv_get_entry( + DN('cn=Multisupplier Replication Plugin,cn=plugins,cn=config'), + ['cn']) + except (errors.NotFound, ldap.NO_SUCH_OBJECT): + return 'Multimaster Replication Plugin' + else: + cn = entry['cn'] + if isinstance(cn, list): + return cn[0] + elif isinstance(cn, bytes): + return cn.decode('utf-8') + else: + raise RuntimeError( + 'LDAP query returned unknown type for cn %s: %s' % + (cn, type(cn)) + ) diff --git a/ipaserver/install/ldapupdate.py b/ipaserver/install/ldapupdate.py index 056a6e6bb..e7eb6c68f 100644 --- a/ipaserver/install/ldapupdate.py +++ b/ipaserver/install/ldapupdate.py @@ -306,6 +306,21 @@ class LDAPUpdate: self.modified = False self.ldapuri = ipaldap.realm_to_ldapi_uri(api.env.realm) + self.api = create_api(mode=None) + self.api.bootstrap( + in_server=True, + context='updates', + confdir=paths.ETC_IPA, + ldap_uri=self.ldapuri + ) + self.api.finalize() + + self.create_connection() + + replication_plugin = ( + installutils.get_replication_plugin_name(self.conn.get_entry) + ) + default_sub = dict( REALM=api.env.realm, DOMAIN=api.env.domain, @@ -329,19 +344,11 @@ class LDAPUpdate: # uid / gid for autobind NAMED_UID=platformconstants.NAMED_USER.uid, NAMED_GID=platformconstants.NAMED_GROUP.gid, + REPLICATION_PLUGIN=replication_plugin, ) for k, v in default_sub.items(): self.sub_dict.setdefault(k, v) - self.api = create_api(mode=None) - self.api.bootstrap( - in_server=True, - context='updates', - confdir=paths.ETC_IPA, - ldap_uri=self.ldapuri - ) - self.api.finalize() - def _template_str(self, s): try: return ipautil.template_str(s, self.sub_dict) @@ -961,8 +968,6 @@ class LDAPUpdate: """ self.modified = False try: - self.create_connection() - upgrade_files = files if ordered: upgrade_files = sorted(files) diff --git a/ipaserver/install/replication.py b/ipaserver/install/replication.py index 8fb4fd414..f20bf46ac 100644 --- a/ipaserver/install/replication.py +++ b/ipaserver/install/replication.py @@ -232,23 +232,6 @@ def get_ds_version(conn): return vendor_version -def get_replication_plugin_name(dirsrv_get_entry): - # Support renaming of a replication plugin in 389-ds - # IPA topology plugin depends on the replication plugin but - # 389-ds cannot handle older alias querying in the plugin - # configuration with 'nsslapd-plugin-depends-on-named: ..' attribute - # - # dirsrv_get_entry: function (dn, attrs) -> str - # returns entry dictionary - try: - entry = dirsrv_get_entry( - 'cn=Multisupplier Replication Plugin,cn=plugins,cn=config', - ['cn']) - return str(entry['cn'], encoding='utf-8') - except Exception: - return 'Multimaster Replication Plugin' - - class ReplicationManager: """Manage replication agreements @@ -757,7 +740,9 @@ class ReplicationManager: def get_entry(dn, attrs): return self.conn.get_entry(DN(dn), attrs) - replication_plugin_name = get_replication_plugin_name(get_entry) + replication_plugin_name = ( + installutils.get_replication_plugin_name(get_entry) + ) plgent = self.conn.get_entry( DN(('cn', replication_plugin_name), ('cn', 'plugins'), diff --git a/ipaserver/install/upgradeinstance.py b/ipaserver/install/upgradeinstance.py index 581742d6f..b84f50b05 100644 --- a/ipaserver/install/upgradeinstance.py +++ b/ipaserver/install/upgradeinstance.py @@ -98,7 +98,6 @@ class IPAUpgrade(service.Service): self.modified = False self.serverid = serverid self.schema_files = schema_files - self.sub_dict = dict() def __start(self): srv = services.service(self.service_name, api) @@ -172,20 +171,6 @@ class IPAUpgrade(service.Service): else: self.backup_state('nsslapd-global-backend-lock', global_lock) - # update self.sub_dict with the replication plugin name - # It may be different depending on 389-ds version - with open(self.filename, "r") as in_file: - parser = GetEntryFromLDIF(in_file, entries_dn=[]) - parser.parse() - - results = parser.get_results() - - dn = REPL_PLUGIN_DN_TEMPLATE % "supplier" - if dn not in results: - dn = REPL_PLUGIN_DN_TEMPLATE % "master" - - self.sub_dict['REPLICATION_PLUGIN'] = results[dn].get('cn') - with open(self.filename, "r") as in_file: parser = GetEntryFromLDIF(in_file, entries_dn=[COMPAT_DN]) parser.parse() @@ -300,7 +285,7 @@ class IPAUpgrade(service.Service): def __upgrade(self): try: - ld = ldapupdate.LDAPUpdate(api=self.api, sub_dict=self.sub_dict) + ld = ldapupdate.LDAPUpdate(api=self.api) if len(self.files) == 0: self.files = ld.get_all_files(ldapupdate.UPDATES_DIR) self.modified = (ld.update(self.files) or self.modified)