From 5d377f31292da71f6ec4a29b13a66a9bea967102 Mon Sep 17 00:00:00 2001 From: "Endi S. Dewata" Date: Tue, 2 Nov 2021 14:46:02 -0500 Subject: [PATCH] Fix replica reinstallation The pkispawn and pkidestroy have been modified to ignore failures caused by adding an entry or attribute that is already exists and to check whether a file exists before removing it during replica removal and reinstallation. One of the CA clone tests has been modified to test removing and reinstalling a replica. Resolves: https://github.com/dogtagpki/pki/issues/3544 --- .github/workflows/ca-tests.yml | 11 ++ .../python/pki/server/deployment/__init__.py | 39 +++++-- .../scriptlets/webapp_deployment.py | 19 +-- .../cms/servlet/csadmin/LDAPConfigurator.java | 110 +++++++++++------- 4 files changed, 116 insertions(+), 63 deletions(-) diff --git a/.github/workflows/ca-tests.yml b/.github/workflows/ca-tests.yml index 4832e73c65..fffcb9c3e4 100644 --- a/.github/workflows/ca-tests.yml +++ b/.github/workflows/ca-tests.yml @@ -1137,6 +1137,17 @@ jobs: --pkcs12-password-file ${PKIDIR}/pkcs12_password.conf docker exec secondary pki -n caadmin ca-user-show caadmin + - name: Remove CA from secondary PKI container + run: | + docker exec secondary pkidestroy -i pki-tomcat -s CA -v + + - name: Re-install CA in secondary PKI container + run: | + docker exec secondary pkispawn \ + -f /usr/share/pki/server/examples/installation/ca-secure-ds-secondary.cfg \ + -s CA \ + -v + - name: Gather artifacts from primary container if: always() run: | diff --git a/base/server/python/pki/server/deployment/__init__.py b/base/server/python/pki/server/deployment/__init__.py index 6eb5b0a78a..d179718dd6 100644 --- a/base/server/python/pki/server/deployment/__init__.py +++ b/base/server/python/pki/server/deployment/__init__.py @@ -1074,26 +1074,41 @@ class PKIDeployer: secure_port = server_config.get_secure_port() uid = 'CA-%s-%s' % (self.mdict['pki_hostname'], secure_port) - logger.info('Adding %s', uid) - subsystem.add_user( - uid, - full_name=uid, - user_type='agentType', - state='1') - logger.info('Adding subsystem certificate into %s', uid) + try: + subsystem.add_user( + uid, + full_name=uid, + user_type='agentType', + state='1') + except Exception: # pylint: disable=W0703 + logger.warning('Unable to add %s', uid) + # TODO: ignore error only if user already exists + cert_data = pki.nssdb.convert_cert( cert['data'], 'base64', 'pem') - subsystem.add_user_cert( - uid, - cert_data=cert_data.encode(), - cert_format='PEM') + + logger.info('Adding certificate for %s', uid) + + try: + subsystem.add_user_cert( + uid, + cert_data=cert_data.encode(), + cert_format='PEM') + except Exception: # pylint: disable=W0703 + logger.warning('Unable to add certificate for %s', uid) + # TODO: ignore error only if user cert already exists logger.info('Adding %s into Subsystem Group', uid) - subsystem.add_group_member('Subsystem Group', uid) + + try: + subsystem.add_group_member('Subsystem Group', uid) + except Exception: # pylint: disable=W0703 + logger.warning('Unable to add %s into Subsystem Group', uid) + # TODO: ignore error only if user already exists in the group def backup_keys(self, instance, subsystem): diff --git a/base/server/python/pki/server/deployment/scriptlets/webapp_deployment.py b/base/server/python/pki/server/deployment/scriptlets/webapp_deployment.py index 342477028a..f9e73fd069 100644 --- a/base/server/python/pki/server/deployment/scriptlets/webapp_deployment.py +++ b/base/server/python/pki/server/deployment/scriptlets/webapp_deployment.py @@ -60,12 +60,13 @@ class PkiScriptlet(pkiscriptlet.AbstractBasePkiScriptlet): logger.info('Undeploying /%s web application', deployer.mdict['pki_subsystem'].lower()) - # Delete /Catalina/localhost/.xml - pki.util.remove( - path=os.path.join( - deployer.mdict['pki_instance_configuration_path'], - "Catalina", - "localhost", - deployer.mdict['pki_subsystem'].lower() + ".xml"), - force=deployer.mdict['pki_force_destroy'] - ) + # Delete /Catalina/localhost/.xml if exists + + context_xml = os.path.join( + deployer.mdict['pki_instance_configuration_path'], + 'Catalina', + 'localhost', + deployer.mdict['pki_subsystem'].lower() + '.xml') + + if os.path.exists(context_xml): + pki.util.remove(context_xml) diff --git a/base/server/src/main/java/com/netscape/cms/servlet/csadmin/LDAPConfigurator.java b/base/server/src/main/java/com/netscape/cms/servlet/csadmin/LDAPConfigurator.java index 651d166321..1e0364cfea 100644 --- a/base/server/src/main/java/com/netscape/cms/servlet/csadmin/LDAPConfigurator.java +++ b/base/server/src/main/java/com/netscape/cms/servlet/csadmin/LDAPConfigurator.java @@ -661,26 +661,35 @@ public class LDAPConfigurator { try { connection.add(entry); + // replication manager added -> done + return; } catch (LDAPException e) { - if (e.getLDAPResultCode() == LDAPException.ENTRY_ALREADY_EXISTS) { - logger.warn("Entry already exists: " + dn); + if (e.getLDAPResultCode() != LDAPException.ENTRY_ALREADY_EXISTS) { + logger.error("Unable to add " + dn + ": " + e.getMessage(), e); + throw e; + } + logger.warn("Replication manager already exists: " + dn); + } - try { - logger.info("Deleting " + dn); - connection.delete(dn); + logger.warn("Deleting existing replication manager: " + dn); - logger.info("Re-adding " + dn); - connection.add(entry); + try { + connection.delete(dn); - } catch (LDAPException ee) { - logger.warn("Unable to recreate " + dn + ": " + ee.getMessage()); - } + } catch (LDAPException e) { + logger.error("Unable to delete " + dn + ": " + e.getMessage()); + throw e; + } - } else { - logger.error("Unable to add " + dn + ": " + e.getMessage(), e); - throw e; - } + logger.warn("Adding new replication manager: " + dn); + + try { + connection.add(entry); + + } catch (LDAPException e) { + logger.error("Unable to add " + dn + ": " + e.getMessage()); + throw e; } } @@ -799,28 +808,41 @@ public class LDAPConfigurator { try { connection.add(entry); + // replica object added -> done + return true; } catch (LDAPException e) { - if (e.getLDAPResultCode() != LDAPException.ENTRY_ALREADY_EXISTS) { + logger.error("Unable to add " + replicaDN + ": " + e.getMessage(), e); throw e; } + logger.warn("Replica object already exists: " + replicaDN); + } + + logger.info("Adding replica bind DN"); - // BZ 470918: We can't just add the new dn. - // We need to do a replace until the bug is fixed. - logger.warn("Entry already exists, adding bind DN"); + // BZ 470918: We can't just add the new dn. + // We need to do a replace until the bug is fixed. - entry = connection.read(replicaDN); - LDAPAttribute attr = entry.getAttribute("nsDS5ReplicaBindDN"); - attr.addValue(bindDN); + entry = connection.read(replicaDN); + LDAPAttribute attr = entry.getAttribute("nsDS5ReplicaBindDN"); + attr.addValue(bindDN); - LDAPModification mod = new LDAPModification(LDAPModification.REPLACE, attr); + LDAPModification mod = new LDAPModification(LDAPModification.REPLACE, attr); + + try { connection.modify(replicaDN, mod); + // replica bind DN added -> done - return false; + } catch (LDAPException e) { + if (e.getLDAPResultCode() != LDAPException.ATTRIBUTE_OR_VALUE_EXISTS) { + logger.error("Unable to add " + bindDN + ": " + e.getMessage(), e); + throw e; + } + logger.warn("Replica bind DN already exists: " + bindDN); } - return true; + return false; } public void createReplicationAgreement( @@ -864,29 +886,33 @@ public class LDAPConfigurator { try { connection.add(entry); + // replication agreement added -> done + return; } catch (LDAPException e) { - if (e.getLDAPResultCode() == LDAPException.ENTRY_ALREADY_EXISTS) { - logger.warn("Entry already exists: " + dn); - - try { - connection.delete(dn); - } catch (LDAPException ee) { - logger.error("Unable to delete " + dn + ": " + ee.getMessage(), ee); - throw ee; - } - - try { - connection.add(entry); - } catch (LDAPException ee) { - logger.error("Unable to add " + dn + ": " + ee.getMessage(), ee); - throw ee; - } - - } else { + if (e.getLDAPResultCode() != LDAPException.ENTRY_ALREADY_EXISTS) { logger.error("Unable to add " + dn + ": " + e.getMessage(), e); throw e; } + logger.warn("Replication agreement already exists: " + dn); + } + + logger.warn("Removing existing replication agreement: " + dn); + + try { + connection.delete(dn); + } catch (LDAPException e) { + logger.error("Unable to delete " + dn + ": " + e.getMessage(), e); + throw e; + } + + logger.warn("Adding new replication agreement: " + dn); + + try { + connection.add(entry); + } catch (LDAPException e) { + logger.error("Unable to add " + dn + ": " + e.getMessage(), e); + throw e; } } -- 2.31.1