diff --git a/install/share/ipa-pki-proxy.conf.template b/install/share/ipa-pki-proxy.conf.template
index 04460197e..0710641c3 100644
--- a/install/share/ipa-pki-proxy.conf.template
+++ b/install/share/ipa-pki-proxy.conf.template
@@ -1,4 +1,4 @@
-# VERSION 13 - DO NOT REMOVE THIS LINE
+# VERSION 14 - DO NOT REMOVE THIS LINE
ProxyRequests Off
@@ -6,7 +6,7 @@ ProxyRequests Off
SSLOptions +StdEnvVars +ExportCertData +StrictRequire +OptRenegotiate
SSLVerifyClient none
- ProxyPassMatch ajp://localhost:$DOGTAG_PORT
+ ProxyPassMatch ajp://localhost:$DOGTAG_PORT $DOGTAG_AJP_SECRET
ProxyPassReverse ajp://localhost:$DOGTAG_PORT
@@ -14,7 +14,7 @@ ProxyRequests Off
SSLOptions +StdEnvVars +ExportCertData +StrictRequire +OptRenegotiate
SSLVerifyClient none
- ProxyPassMatch ajp://localhost:$DOGTAG_PORT
+ ProxyPassMatch ajp://localhost:$DOGTAG_PORT $DOGTAG_AJP_SECRET
ProxyPassReverse ajp://localhost:$DOGTAG_PORT
@@ -22,7 +22,7 @@ ProxyRequests Off
SSLOptions +StdEnvVars +ExportCertData +StrictRequire +OptRenegotiate
SSLVerifyClient require
- ProxyPassMatch ajp://localhost:$DOGTAG_PORT
+ ProxyPassMatch ajp://localhost:$DOGTAG_PORT $DOGTAG_AJP_SECRET
ProxyPassReverse ajp://localhost:$DOGTAG_PORT
@@ -30,7 +30,7 @@ ProxyRequests Off
SSLOptions +StdEnvVars +ExportCertData +StrictRequire +OptRenegotiate
SSLVerifyClient optional
- ProxyPassMatch ajp://localhost:$DOGTAG_PORT
+ ProxyPassMatch ajp://localhost:$DOGTAG_PORT $DOGTAG_AJP_SECRET
ProxyPassReverse ajp://localhost:$DOGTAG_PORT
@@ -38,7 +38,7 @@ ProxyRequests Off
SSLOptions +StdEnvVars +ExportCertData +StrictRequire +OptRenegotiate
SSLVerifyClient optional
- ProxyPassMatch ajp://localhost:$DOGTAG_PORT
+ ProxyPassMatch ajp://localhost:$DOGTAG_PORT $DOGTAG_AJP_SECRET
ProxyPassReverse ajp://localhost:$DOGTAG_PORT
diff --git a/ipaplatform/base/paths.py b/ipaplatform/base/paths.py
index 5f0335f6f..c03c44296 100644
--- a/ipaplatform/base/paths.py
+++ b/ipaplatform/base/paths.py
@@ -108,6 +108,7 @@ class BasePathNamespace:
PKI_TOMCAT_ALIAS_DIR = "/etc/pki/pki-tomcat/alias"
PKI_TOMCAT_ALIAS_PWDFILE_TXT = "/etc/pki/pki-tomcat/alias/pwdfile.txt"
PKI_TOMCAT_PASSWORD_CONF = "/etc/pki/pki-tomcat/password.conf"
+ PKI_TOMCAT_SERVER_XML = "/etc/pki/pki-tomcat/server.xml"
ETC_REDHAT_RELEASE = "/etc/redhat-release"
RESOLV_CONF = "/etc/resolv.conf"
SAMBA_KEYTAB = "/etc/samba/samba.keytab"
@@ -339,6 +340,7 @@ class BasePathNamespace:
KRB5KDC_LOG = "/var/log/krb5kdc.log"
MESSAGES = "/var/log/messages"
VAR_LOG_PKI_DIR = "/var/log/pki/"
+ BIN_TOMCAT = "/usr/sbin/tomcat"
TOMCAT_TOPLEVEL_DIR = "/var/log/pki/pki-tomcat"
TOMCAT_CA_DIR = "/var/log/pki/pki-tomcat/ca"
TOMCAT_CA_ARCHIVE_DIR = "/var/log/pki/pki-tomcat/ca/archive"
diff --git a/ipaplatform/debian/paths.py b/ipaplatform/debian/paths.py
index 764b5a281..1014c6ae3 100644
--- a/ipaplatform/debian/paths.py
+++ b/ipaplatform/debian/paths.py
@@ -59,6 +59,7 @@ class DebianPathNamespace(BasePathNamespace):
SYSCONFIG_PKI = "/etc/dogtag/"
SYSCONFIG_PKI_TOMCAT = "/etc/default/pki-tomcat"
SYSCONFIG_PKI_TOMCAT_PKI_TOMCAT_DIR = "/etc/dogtag/tomcat/pki-tomcat"
+ BIN_TOMCAT = "/usr/share/tomcat9/bin/version.sh"
SYSTEMD_SYSTEM_HTTPD_D_DIR = "/etc/systemd/system/apache2.service.d/"
SYSTEMD_SYSTEM_HTTPD_IPA_CONF = "/etc/systemd/system/apache2.service.d/ipa.conf"
DNSSEC_TRUSTED_KEY = "/etc/bind/trusted-key.key"
diff --git a/ipaserver/install/cainstance.py b/ipaserver/install/cainstance.py
index fe63229af..2836bdd25 100644
--- a/ipaserver/install/cainstance.py
+++ b/ipaserver/install/cainstance.py
@@ -401,6 +401,7 @@ class CAInstance(DogtagInstance):
self.step("configuring certificate server instance",
self.__spawn_instance)
self.step("Add ipa-pki-wait-running", self.add_ipa_wait)
+ self.step("secure AJP connector", self.secure_ajp_connector)
self.step("reindex attributes", self.reindex_task)
self.step("exporting Dogtag certificate store pin",
self.create_certstore_passwdfile)
@@ -452,6 +453,7 @@ class CAInstance(DogtagInstance):
self.step("configure certificate renewals", self.configure_renewal)
self.step("Configure HTTP to proxy connections",
self.http_proxy)
+ # This restart is needed for ACL reload in CA, do not remove it
self.step("restarting certificate server", self.restart_instance)
self.step("updating IPA configuration", update_ipa_conf)
self.step("enabling CA instance", self.__enable_instance)
diff --git a/ipaserver/install/dogtaginstance.py b/ipaserver/install/dogtaginstance.py
index 18a24f02f..efcf81509 100644
--- a/ipaserver/install/dogtaginstance.py
+++ b/ipaserver/install/dogtaginstance.py
@@ -28,6 +28,9 @@ import os
import shutil
import traceback
import dbus
+import re
+import pwd
+import lxml.etree
from configparser import DEFAULTSECT, ConfigParser, RawConfigParser
@@ -42,6 +45,7 @@ from ipalib.constants import CA_DBUS_TIMEOUT, IPA_CA_RECORD, RENEWAL_CA_NAME
from ipaplatform import services
from ipaplatform.constants import constants
from ipaplatform.paths import paths
+from ipaplatform.tasks import tasks
from ipapython import directivesetter
from ipapython import ipaldap
from ipapython import ipautil
@@ -158,6 +162,7 @@ class DogtagInstance(service.Service):
self.pki_config_override = None
self.ca_subject = None
self.subject_base = None
+ self.ajp_secret = None
def is_installed(self):
"""
@@ -275,6 +280,72 @@ class DogtagInstance(service.Service):
logger.critical("failed to uninstall %s instance %s",
self.subsystem, e)
+ def __is_newer_tomcat_version(self, default=None):
+ try:
+ result = ipautil.run([paths.BIN_TOMCAT, "version"],
+ capture_output=True)
+ sn = re.search(
+ r'Server number:\s+([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)',
+ result.output)
+ if sn is None:
+ logger.info("tomcat version cannot be parsed, "
+ "default to pre-%s", default)
+ return False
+ v = tasks.parse_ipa_version(sn.group(1))
+ if v >= tasks.parse_ipa_version(default):
+ return True
+ except ipautil.CalledProcessError as e:
+ logger.info(
+ "failed to discover tomcat version, "
+ "default to pre-%s, error: %s",
+ default, str(e))
+ return False
+
+ def secure_ajp_connector(self):
+ """ Update AJP connector to use a password protection """
+
+ server_xml = lxml.etree.parse(paths.PKI_TOMCAT_SERVER_XML)
+ doc = server_xml.getroot()
+
+ # no AJP connector means no need to update anything
+ connectors = doc.xpath('//Connector[@port="8009"]')
+ if len(connectors) == 0:
+ return
+
+ # AJP connector is set on port 8009. Use non-greedy search to find it
+ connector = connectors[0]
+
+ # Detect tomcat version and choose the right option name
+ # pre-9.0.31.0 uses 'requiredSecret'
+ # 9.0.31.0 or later uses 'secret'
+ secretattr = 'requiredSecret'
+ oldattr = 'requiredSecret'
+ if self.__is_newer_tomcat_version('9.0.31.0'):
+ secretattr = 'secret'
+
+ rewrite = True
+ if secretattr in connector.attrib:
+ # secret is already in place
+ # Perhaps, we need to synchronize it with Apache configuration
+ self.ajp_secret = connector.attrib[secretattr]
+ rewrite = False
+ else:
+ if oldattr in connector.attrib:
+ self.ajp_secret = connector.attrib[oldattr]
+ connector.attrib[secretattr] = self.ajp_secret
+ del connector.attrib[oldattr]
+ else:
+ # Generate password, don't use special chars to not break XML
+ self.ajp_secret = ipautil.ipa_generate_password(special=None)
+ connector.attrib[secretattr] = self.ajp_secret
+
+ if rewrite:
+ pent = pwd.getpwnam(constants.PKI_USER)
+ with open(paths.PKI_TOMCAT_SERVER_XML, "wb") as fd:
+ server_xml.write(fd, pretty_print=True, encoding="utf-8")
+ os.fchmod(fd.fileno(), 0o660)
+ os.fchown(fd.fileno(), pent.pw_uid, pent.pw_gid)
+
def http_proxy(self):
""" Update the http proxy file """
template_filename = (
@@ -284,11 +355,20 @@ class DogtagInstance(service.Service):
DOGTAG_PORT=8009,
CLONE='' if self.clone else '#',
FQDN=self.fqdn,
+ DOGTAG_AJP_SECRET='',
)
+ if self.ajp_secret:
+ sub_dict['DOGTAG_AJP_SECRET'] = "secret={}".format(self.ajp_secret)
template = ipautil.template_file(template_filename, sub_dict)
with open(paths.HTTPD_IPA_PKI_PROXY_CONF, "w") as fd:
fd.write(template)
os.fchmod(fd.fileno(), 0o640)
+ # Restart httpd
+ http_service = services.knownservices.httpd
+ logger.debug("Restarting %s to apply AJP changes",
+ http_service.service_name)
+ http_service.restart()
+ logger.debug("%s successfully restarted", http_service.service_name)
def configure_certmonger_renewal_helpers(self):
"""
diff --git a/ipaserver/install/krainstance.py b/ipaserver/install/krainstance.py
index 09efdcad9..99a53861e 100644
--- a/ipaserver/install/krainstance.py
+++ b/ipaserver/install/krainstance.py
@@ -133,8 +133,6 @@ class KRAInstance(DogtagInstance):
self.step("configure certmonger for renewals",
self.configure_certmonger_renewal_helpers)
self.step("configure certificate renewals", self.configure_renewal)
- self.step("configure HTTP to proxy connections",
- self.http_proxy)
if not self.clone:
self.step("add vault container", self.__add_vault_container)
self.step("apply LDAP updates", self.__apply_updates)
diff --git a/ipaserver/install/server/upgrade.py b/ipaserver/install/server/upgrade.py
index 503e271da..b4ef31199 100644
--- a/ipaserver/install/server/upgrade.py
+++ b/ipaserver/install/server/upgrade.py
@@ -1966,6 +1966,14 @@ def upgrade_configuration():
os.path.join(paths.USR_SHARE_IPA_DIR,
"ipa-kdc-proxy.conf.template"))
if ca.is_configured():
+ # Handle upgrade of AJP connector configuration
+ ca.secure_ajp_connector()
+ if ca.ajp_secret:
+ sub_dict['DOGTAG_AJP_SECRET'] = "secret={}".format(
+ ca.ajp_secret)
+ else:
+ sub_dict['DOGTAG_AJP_SECRET'] = ''
+
upgrade_file(
sub_dict,
paths.HTTPD_IPA_PKI_PROXY_CONF,