diff --git a/freeipa.spec.in b/freeipa.spec.in index 9e42a6119..bc47df4c9 100644 --- a/freeipa.spec.in +++ b/freeipa.spec.in @@ -130,7 +130,7 @@ Requires: %{name}-client = %{version}-%{release} Requires: %{name}-admintools = %{version}-%{release} Requires: %{name}-common = %{version}-%{release} Requires: python2-ipaserver = %{version}-%{release} -Requires: 389-ds-base >= 1.3.4.4 +Requires: 389-ds-base >= 1.3.4.6 Requires: openldap-clients > 2.4.35-4 Requires: nss >= 3.14.3-12.0 Requires: nss-tools >= 3.14.3-12.0 @@ -162,7 +162,7 @@ Requires: zip Requires: policycoreutils >= 2.1.12-5 Requires: tar Requires(pre): certmonger >= 0.78 -Requires(pre): 389-ds-base >= 1.3.4.4 +Requires(pre): 389-ds-base >= 1.3.4.6 Requires: fontawesome-fonts Requires: open-sans-fonts Requires: openssl diff --git a/ipaserver/install/dsinstance.py b/ipaserver/install/dsinstance.py index b7a480749..0c54b01da 100644 --- a/ipaserver/install/dsinstance.py +++ b/ipaserver/install/dsinstance.py @@ -1261,3 +1261,107 @@ class DsInstance(service.Service): # check for open secure port 636 from now on self.open_ports.append(636) + + def update_dna_shared_config(self, method="SASL/GSSAPI", protocol="LDAP"): + + dna_bind_method = "dnaRemoteBindMethod" + dna_conn_protocol = "dnaRemoteConnProtocol" + dna_plugin = DN(('cn', 'Distributed Numeric Assignment Plugin'), + ('cn', 'plugins'), + ('cn', 'config')) + dna_config_base = DN(('cn', 'posix IDs'), dna_plugin) + + if not self.admin_conn: + self.ldap_connect() + conn = self.admin_conn + + # Check the plugin is enabled else it is useless to update + # the shared entry + try: + entry = conn.get_entry(dna_plugin) + if entry.single_value.get('nsslapd-pluginenabled') == 'off': + return + except errors.NotFound: + root_logger.error("Could not find DNA plugin entry: %s" % + dna_config_base) + return + + try: + entry = conn.get_entry(dna_config_base) + except errors.NotFound: + root_logger.error("Could not find DNA config entry: %s" % + dna_config_base) + return + + sharedcfgdn = entry.single_value.get("dnaSharedCfgDN") + if sharedcfgdn is not None: + sharedcfgdn = DN(sharedcfgdn) + else: + root_logger.error( + "Could not find DNA shared config DN in entry: %s" % + dna_config_base) + return + + # + # Update the shared config entry related to that host + # + # If the shared config entry already exists (like upgrade) + # the update occurs immediately without sleep. + # + # If the shared config entry does not exist (fresh install) + # DS server waits for 30s after its startup to create it. + # Startup likely occurred few sec before this function is + # called so this loop will wait for 30s max. + # + # In case the server is not able to create the entry + # The loop gives a grace period of 60s before logging + # the failure to update the shared config entry and return + # + max_wait = 30 + for i in range(0, max_wait + 1): + try: + entries = conn.get_entries( + sharedcfgdn, scope=ldap.SCOPE_ONELEVEL, + filter='dnaHostname=%s' % self.fqdn + ) + break + except errors.NotFound: + root_logger.debug( + "Unable to find DNA shared config entry for " + "dnaHostname=%s (under %s) so far. Retry in 2 sec." % + (self.fqdn, sharedcfgdn) + ) + time.sleep(2) + else: + root_logger.error( + "Could not get dnaHostname entries in {} seconds".format( + max_wait * 2) + ) + return + + # If there are several entries, all of them will be updated + # just log a debug msg. This is likely the result of #5510 + if len(entries) != 1: + root_logger.debug( + "%d entries dnaHostname=%s under %s. One expected" % + (len(entries), self.fqdn, sharedcfgdn) + ) + + # time to set the bind method and the protocol in the + # shared config entries + for entry in entries: + mod = [] + if entry.single_value.get(dna_bind_method) != method: + mod.append((ldap.MOD_REPLACE, dna_bind_method, method)) + + if entry.single_value.get(dna_conn_protocol) != method: + mod.append((ldap.MOD_REPLACE, dna_conn_protocol, protocol)) + + if mod: + try: + conn.modify_s(entry.dn, mod) + except Exception as e: + root_logger.error( + "Failed to set SASL/GSSAPI bind method/protocol " + "in entry {}: {}".format(entry, e) + ) diff --git a/ipaserver/install/server/install.py b/ipaserver/install/server/install.py index 0ab5b268d..b7a38a57c 100644 --- a/ipaserver/install/server/install.py +++ b/ipaserver/install/server/install.py @@ -988,6 +988,10 @@ def install(installer): service.print_msg("Restarting the web server") http.restart() + # update DNA shared config entry is done as far as possible + # from restart to avoid waiting for its creation + ds.update_dna_shared_config() + # Set the admin user kerberos password ds.change_admin_password(admin_password) diff --git a/ipaserver/install/server/replicainstall.py b/ipaserver/install/server/replicainstall.py index 3a3bbc092..e3052c129 100644 --- a/ipaserver/install/server/replicainstall.py +++ b/ipaserver/install/server/replicainstall.py @@ -881,6 +881,10 @@ def install(installer): ds.replica_populate() + # update DNA shared config entry is done as far as possible + # from restart to avoid waiting for its creation + ds.update_dna_shared_config() + # Everything installed properly, activate ipa service. services.knownservices.ipa.enable() @@ -1457,6 +1461,10 @@ def promote(installer): ds.replica_populate() + # update DNA shared config entry is done as far as possible + # from restart to avoid waiting for its creation + ds.update_dna_shared_config() + custodia.import_dm_password(config.master_host_name) promote_sssd(config.host_name) diff --git a/ipaserver/install/server/upgrade.py b/ipaserver/install/server/upgrade.py index d6e6b2e0d..fc9c2eb62 100644 --- a/ipaserver/install/server/upgrade.py +++ b/ipaserver/install/server/upgrade.py @@ -1544,6 +1544,7 @@ def upgrade_configuration(): ds.ldap_connect() ds_enable_sidgen_extdom_plugins(ds) + ds.update_dna_shared_config() ds.ldap_disconnect() # Now 389-ds is available, run the remaining http tasks