Blob Blame History Raw
From 8a8fc41a10ffb20e9e4902a9e9f74b2f05948b7a Mon Sep 17 00:00:00 2001
From: "Endi S. Dewata" <edewata@redhat.com>
Date: Wed, 3 Nov 2021 20:46:46 -0500
Subject: [PATCH] Fix AJP connector migration

In commit e70373ab131aba810f318c1d917896392b49ff4b the AJP
connector migration code for Tomcat 9.0.31 in pki-server
migrate CLI was converted into an upgrade script that would
run regardless of the Tomcat version, and this was causing
a problem on platforms that only has older Tomcat versions.

To fix the problem, the upgrade script has been converted back
into pki-server migrate, and it will check the Tomcat version
before performing the migration. The server.xml has also been
reverted to have the old AJP connectors by default.

Whenever the server is restarted the pki-server migrate will
run so it can migrate the AJP connectors automatically in
case Tomcat is upgraded to a newer version.

https://bugzilla.redhat.com/show_bug.cgi?id=2029023
---
 base/server/python/pki/server/cli/migrate.py  | 61 +++++++++++++++++
 .../upgrade/10.11.0/04-UpdateAJPConnectors.py | 67 -------------------
 ...lowLinking.py => 04-UpdateAllowLinking.py} |  0
 ...UpdateJavaHome.py => 05-UpdateJavaHome.py} |  0
 base/tomcat-9.0/conf/server.xml               |  4 +-
 5 files changed, 63 insertions(+), 69 deletions(-)
 delete mode 100644 base/server/upgrade/10.11.0/04-UpdateAJPConnectors.py
 rename base/server/upgrade/10.11.0/{05-UpdateAllowLinking.py => 04-UpdateAllowLinking.py} (100%)
 rename base/server/upgrade/10.11.0/{06-UpdateJavaHome.py => 05-UpdateJavaHome.py} (100%)

diff --git a/base/server/python/pki/server/cli/migrate.py b/base/server/python/pki/server/cli/migrate.py
index 256b83c845..2005004c4e 100644
--- a/base/server/python/pki/server/cli/migrate.py
+++ b/base/server/python/pki/server/cli/migrate.py
@@ -23,6 +23,7 @@ from __future__ import print_function
 
 import getopt
 import logging
+import re
 import sys
 
 from lxml import etree
@@ -96,9 +97,69 @@ class MigrateCLI(pki.cli.CLI):
 
             instance.load()
             instance.init()
+            instances = [instance]
 
         else:
             instances = pki.server.instance.PKIInstance.instances()
 
             for instance in instances:
                 instance.init()
+
+        # update AJP connectors for Tomcat 9.0.31 or later
+
+        tomcat_version = pki.server.Tomcat.get_version()
+        if tomcat_version >= pki.util.Version('9.0.31'):
+
+            for instance in instances:
+                self.update_ajp_connectors(instance)
+
+    def update_ajp_connectors(self, instance):
+
+        logger.info('Updating AJP connectors in %s', instance.server_xml)
+
+        document = etree.parse(instance.server_xml, self.parser)
+        server = document.getroot()
+
+        # replace 'requiredSecret' with 'secret' in comments
+
+        services = server.findall('Service')
+        for service in services:
+
+            children = list(service)
+            for child in children:
+
+                if not isinstance(child, etree._Comment):  # pylint: disable=protected-access
+                    # not a comment -> skip
+                    continue
+
+                if 'protocol="AJP/1.3"' not in child.text:
+                    # not an AJP connector -> skip
+                    continue
+
+                child.text = re.sub(r'requiredSecret=',
+                                    r'secret=',
+                                    child.text,
+                                    flags=re.MULTILINE)
+
+        # replace 'requiredSecret' with 'secret' in Connectors
+
+        connectors = server.findall('Service/Connector')
+        for connector in connectors:
+
+            if connector.get('protocol') != 'AJP/1.3':
+                # not an AJP connector -> skip
+                continue
+
+            if connector.get('secret'):
+                # already has a 'secret' -> skip
+                continue
+
+            if connector.get('requiredSecret') is None:
+                # does not have a 'requiredSecret' -> skip
+                continue
+
+            value = connector.attrib.pop('requiredSecret')
+            connector.set('secret', value)
+
+        with open(instance.server_xml, 'wb') as f:
+            document.write(f, pretty_print=True, encoding='utf-8')
diff --git a/base/server/upgrade/10.11.0/04-UpdateAJPConnectors.py b/base/server/upgrade/10.11.0/04-UpdateAJPConnectors.py
deleted file mode 100644
index 6e7bbdae24..0000000000
--- a/base/server/upgrade/10.11.0/04-UpdateAJPConnectors.py
+++ /dev/null
@@ -1,67 +0,0 @@
-#
-# Copyright Red Hat, Inc.
-#
-# SPDX-License-Identifier: GPL-2.0-or-later
-#
-from __future__ import absolute_import
-import logging
-from lxml import etree
-import re
-
-import pki
-
-logger = logging.getLogger(__name__)
-
-
-class UpdateAJPConnectors(pki.server.upgrade.PKIServerUpgradeScriptlet):
-
-    def __init__(self):
-        super(UpdateAJPConnectors, self).__init__()
-        self.message = 'Update AJP connectors in server.xml'
-
-        self.parser = etree.XMLParser(remove_blank_text=True)
-
-    def upgrade_instance(self, instance):
-
-        logger.info('Updating %s', instance.server_xml)
-        self.backup(instance.server_xml)
-
-        document = etree.parse(instance.server_xml, self.parser)
-        server = document.getroot()
-
-        logger.info('Renaming requiredSecret to secret')
-
-        services = server.findall('Service')
-        for service in services:
-
-            children = list(service)
-            for child in children:
-
-                if isinstance(child, etree._Comment):  # pylint: disable=protected-access
-                    if 'protocol="AJP/1.3"' in child.text:
-                        child.text = re.sub(r'requiredSecret=',
-                                            r'secret=',
-                                            child.text,
-                                            flags=re.MULTILINE)
-
-        connectors = server.findall('Service/Connector')
-        for connector in connectors:
-
-            if connector.get('protocol') != 'AJP/1.3':
-                # Only modify AJP connectors.
-                continue
-
-            if connector.get('secret'):
-                # Nothing to migrate because the secret attribute already
-                # exists.
-                continue
-
-            if connector.get('requiredSecret') is None:
-                # No requiredSecret field either; nothing to do.
-                continue
-
-            connector.set('secret', connector.get('requiredSecret'))
-            connector.attrib.pop('requiredSecret', None)
-
-        with open(instance.server_xml, 'wb') as f:
-            document.write(f, pretty_print=True, encoding='utf-8')
diff --git a/base/server/upgrade/10.11.0/05-UpdateAllowLinking.py b/base/server/upgrade/10.11.0/04-UpdateAllowLinking.py
similarity index 100%
rename from base/server/upgrade/10.11.0/05-UpdateAllowLinking.py
rename to base/server/upgrade/10.11.0/04-UpdateAllowLinking.py
diff --git a/base/server/upgrade/10.11.0/06-UpdateJavaHome.py b/base/server/upgrade/10.11.0/05-UpdateJavaHome.py
similarity index 100%
rename from base/server/upgrade/10.11.0/06-UpdateJavaHome.py
rename to base/server/upgrade/10.11.0/05-UpdateJavaHome.py
diff --git a/base/tomcat-9.0/conf/server.xml b/base/tomcat-9.0/conf/server.xml
index 528300fd27..d6f3bb7ff0 100644
--- a/base/tomcat-9.0/conf/server.xml
+++ b/base/tomcat-9.0/conf/server.xml
@@ -190,12 +190,12 @@ Tomcat Port         = [TOMCAT_SERVER_PORT] (for shutdown)
                protocol="AJP/1.3"
                redirectPort="[PKI_AJP_REDIRECT_PORT]"
                address="[PKI_AJP_HOST_IPv4]"
-               secret="[PKI_AJP_SECRET]" />
+               requiredSecret="[PKI_AJP_SECRET]" />
     <Connector port="[PKI_AJP_PORT]"
                protocol="AJP/1.3"
                redirectPort="[PKI_AJP_REDIRECT_PORT]"
                address="[PKI_AJP_HOST_IPv6]"
-               secret="[PKI_AJP_SECRET]" />
+               requiredSecret="[PKI_AJP_SECRET]" />
 [PKI_CLOSE_AJP_PORT_COMMENT]
 
 
-- 
2.33.1