Skip to content

Commit

Permalink
Fixed: Support SSLHostConfig in CatalinaContainer (OFBIZ-12835) (#649)
Browse files Browse the repository at this point in the history
Co-authored-by: Danny Trunk <[email protected]>
  • Loading branch information
dtrunk90 and Danny Trunk authored Aug 4, 2023
1 parent 94cc133 commit 921c0b8
Show file tree
Hide file tree
Showing 2 changed files with 99 additions and 16 deletions.
40 changes: 25 additions & 15 deletions framework/catalina/ofbiz-component.xml
Original file line number Diff line number Diff line change
Expand Up @@ -157,17 +157,22 @@ under the License.
<property name="compressibleMimeType" value="text/html,text/xml,text/plain,text/css,application/javascript,application/json"/>
<!-- SSL connector attributes -->
<property name="sslImplementationName" value="org.apache.tomcat.util.net.jsse.JSSEImplementation"/>
<property name="algorithm" value="SunX509"/>
<!-- the clientAuth to "want" in order to receive certs from the client;
note that this isn't set this way by default because with certain browsers
(like Safari) it breaks access via HTTPS, so until that problem is fixed
the default will be false
<property name="clientAuth" value="false"/>
-->
<property name="keystoreFile" value="framework/base/config/ofbizssl.jks"/>
<property name="keystoreType" value="JKS"/>
<property name="keyAlias" value="ofbiz"/>
<property name="keyPass" value="changeit"/>
<property name="default" value="sslHostConfig">
<property name="keyManagerAlgorithm" value="SunX509"/>
<!-- the certificateVerification to "want" in order to receive certs from the client;
note that this isn't set this way by default because with certain browsers
(like Safari) it breaks access via HTTPS, so until that problem is fixed
the default will be false
<property name="certificateVerification" value="false"/>
-->
<property name="default" value="certificate">
<property name="certificateType" value="RSA"/>
<property name="certificateKeystoreFile" value="framework/base/config/ofbizssl.jks"/>
<property name="certificateKeystoreType" value="JKS"/>
<property name="certificateKeyAlias" value="ofbiz"/>
<property name="certificateKeyPassword" value="changeit"/>
</property>
</property>
</property>
</container>
<container name="catalina-container-test" loaders="test" class="org.apache.ofbiz.catalina.container.CatalinaContainer">
Expand Down Expand Up @@ -225,10 +230,15 @@ under the License.
<property name="compression" value="on"/>
<property name="compressibleMimeType" value="text/html,text/xml,text/plain,text/css,application/javascript,application/json"/>
<property name="sslImplementationName" value="org.apache.tomcat.util.net.jsse.JSSEImplementation"/>
<property name="algorithm" value="SunX509"/>
<property name="keystoreFile" value="framework/base/config/ofbizssl.jks"/>
<property name="keystorePass" value="changeit"/>
<property name="keystoreType" value="JKS"/>
<property name="default" value="sslHostConfig">
<property name="keyManagerAlgorithm" value="SunX509"/>
<property name="default" value="certificate">
<property name="certificateType" value="RSA"/>
<property name="certificateKeystoreFile" value="framework/base/config/ofbizssl.jks"/>
<property name="certificateKeystorePassword" value="changeit"/>
<property name="certificateKeystoreType" value="JKS"/>
</property>
</property>
</property>
</container>
<!--
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,8 @@
import org.apache.tomcat.util.IntrospectionUtils;
import org.apache.tomcat.util.descriptor.web.FilterDef;
import org.apache.tomcat.util.descriptor.web.FilterMap;
import org.apache.tomcat.util.net.SSLHostConfig;
import org.apache.tomcat.util.net.SSLHostConfigCertificate;
import org.apache.tomcat.util.scan.StandardJarScanner;
import org.xml.sax.SAXException;

Expand Down Expand Up @@ -431,7 +433,8 @@ private static Connector prepareConnector(Configuration.Property connectorProp)
connectorProp.properties().values().stream()
.filter(prop -> {
String name = prop.name();
return !"protocol".equals(name) && !"upgradeProtocol".equals(name) && !"port".equals(name);
String value = prop.value();
return !"protocol".equals(name) && !"upgradeProtocol".equals(name) && !"port".equals(name) && !"sslHostConfig".equals(value);
})
.forEach(prop -> {
String name = prop.name();
Expand All @@ -447,9 +450,79 @@ private static Connector prepareConnector(Configuration.Property connectorProp)
Debug.logWarning("Tomcat " + connector + ": ignored parameter " + name, MODULE);
}
});
prepareSslHostConfigs(connector, connectorProp).forEach(connector::addSslHostConfig);
return connector;
}

private static List<SSLHostConfig> prepareSslHostConfigs(Connector connector, Configuration.Property connectorProp) {
return connectorProp.getPropertiesWithValue("sslHostConfig").stream()
.filter(sslHostConfigProp -> UtilValidate.isNotEmpty(sslHostConfigProp.properties()))
.map(sslHostConfigProp -> prepareSslHostConfig(connector, sslHostConfigProp))
.collect(Collectors.toList());
}

private static SSLHostConfig prepareSslHostConfig(Connector connector, Configuration.Property sslHostConfigProp) {
SSLHostConfig sslHostConfig = new SSLHostConfig();
sslHostConfigProp.properties().values().stream()
.filter(prop -> {
String value = prop.value();
return !"certificate".equals(value);
})
.forEach(prop -> {
String name = prop.name();
String value = prop.value();
if (IntrospectionUtils.setProperty(sslHostConfig, name, value)) {
if (name.indexOf("Pass") != -1) {
// this property may be a password, do not include its value in the logs
Debug.logInfo("Tomcat " + connector + " " + sslHostConfig.getHostName() + ": set " + name, MODULE);
} else {
Debug.logInfo("Tomcat " + connector + " " + sslHostConfig.getHostName() + ": set " + name + "=" + value, MODULE);
}
} else {
Debug.logWarning("Tomcat " + connector + " " + sslHostConfig.getHostName() + ": ignored parameter " + name, MODULE);
}
});
prepareSslHostConfigCerts(connector, sslHostConfig, sslHostConfigProp).forEach(sslHostConfig::addCertificate);
return sslHostConfig;
}

private static List<SSLHostConfigCertificate> prepareSslHostConfigCerts(Connector connector, SSLHostConfig sslHostConfig,
Configuration.Property sslHostConfigProp) {
return sslHostConfigProp.getPropertiesWithValue("certificate").stream()
.filter(certProp -> UtilValidate.isNotEmpty(certProp.properties()))
.map(certProp -> prepareSslHostConfigCert(connector, sslHostConfig, certProp))
.collect(Collectors.toList());
}

private static SSLHostConfigCertificate prepareSslHostConfigCert(Connector connector, SSLHostConfig sslHostConfig,
Configuration.Property certProp) {
String certificateType = ContainerConfig.getPropertyValue(certProp, "certificateType", SSLHostConfigCertificate.DEFAULT_TYPE.name());
SSLHostConfigCertificate sslHostConfigCert = new SSLHostConfigCertificate(sslHostConfig,
SSLHostConfigCertificate.Type.valueOf(certificateType));
certProp.properties().values().stream()
.filter(prop -> {
String name = prop.name();
return !"certificateType".equals(name);
})
.forEach(prop -> {
String name = prop.name();
String value = prop.value();
if (IntrospectionUtils.setProperty(sslHostConfigCert, name, value)) {
if (name.indexOf("Pass") != -1) {
// this property may be a password, do not include its value in the logs
Debug.logInfo("Tomcat " + connector + " " + sslHostConfig.getHostName() + " certificate: set " + name, MODULE);
} else {
Debug.logInfo("Tomcat " + connector + " " + sslHostConfig.getHostName() + " certificate: set " + name + "=" + value,
MODULE);
}
} else {
Debug.logWarning("Tomcat " + connector + " " + sslHostConfig.getHostName() + " certificate: ignored parameter " + name,
MODULE);
}
});
return sslHostConfigCert;
}

private static void loadWebapps(Tomcat tomcat, Configuration configuration, Configuration.Property clusterProp) {
ScheduledExecutorService executor = ExecutionPool.getScheduledExecutor(new ThreadGroup(MODULE),
"catalina-startup", Runtime.getRuntime().availableProcessors(), 0, true);
Expand Down

0 comments on commit 921c0b8

Please sign in to comment.