From 5d377f31292da71f6ec4a29b13a66a9bea967102 Mon Sep 17 00:00:00 2001
From: "Endi S. Dewata" <edewata@redhat.com>
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 <instance>/Catalina/localhost/<subsystem>.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 <instance>/Catalina/localhost/<subsystem>.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