Author: remm
Date: Thu Jan 24 09:15:03 2019
New Revision: 1852005
URL: http://svn.apache.org/viewvc?rev=1852005&view=rev
Log:
Add a bit more docs and a yaml example for the image.
Added:
tomcat/trunk/res/tomcat-maven/tomcat.yaml (with props)
Modified:
tomcat/trunk/java/org/apache/catalina/mbeans/JmxRemoteLifecycleListener.java
tomcat/trunk/java/org/apache/catalina/mbeans/LocalStrings.properties
tomcat/trunk/res/tomcat-maven/README.md
Modified:
tomcat/trunk/java/org/apache/catalina/mbeans/JmxRemoteLifecycleListener.java
URL:
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/mbeans/JmxRemoteLifecycleListener.java?rev=1852005&r1=1852004&r2=1852005&view=diff
==============================================================================
---
tomcat/trunk/java/org/apache/catalina/mbeans/JmxRemoteLifecycleListener.java
(original)
+++
tomcat/trunk/java/org/apache/catalina/mbeans/JmxRemoteLifecycleListener.java
Thu Jan 24 09:15:03 2019
@@ -31,11 +31,7 @@ import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.RMIClientSocketFactory;
import java.rmi.server.RMIServerSocketFactory;
-import java.security.NoSuchAlgorithmException;
-import java.util.ArrayList;
import java.util.HashMap;
-import java.util.List;
-import java.util.Locale;
import java.util.Map;
import javax.management.remote.JMXConnectorServer;
@@ -45,6 +41,7 @@ import javax.management.remote.rmi.RMIJR
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLServerSocket;
import javax.net.ssl.SSLServerSocketFactory;
+import javax.net.ssl.SSLSessionContext;
import javax.rmi.ssl.SslRMIClientSocketFactory;
import javax.rmi.ssl.SslRMIServerSocketFactory;
@@ -53,6 +50,9 @@ import org.apache.catalina.LifecycleEven
import org.apache.catalina.LifecycleListener;
import org.apache.juli.logging.Log;
import org.apache.juli.logging.LogFactory;
+import org.apache.tomcat.util.net.SSLHostConfig;
+import org.apache.tomcat.util.net.SSLHostConfigCertificate;
+import org.apache.tomcat.util.net.jsse.JSSEUtil;
import org.apache.tomcat.util.res.StringManager;
/**
@@ -62,7 +62,9 @@ import org.apache.tomcat.util.res.String
* the listener. The remainder of the configuration is via the standard system
* properties for configuring JMX.
*/
-public class JmxRemoteLifecycleListener implements LifecycleListener {
+public class JmxRemoteLifecycleListener extends SSLHostConfig implements
LifecycleListener {
+
+ private static final long serialVersionUID = 1L;
private static final Log log =
LogFactory.getLog(JmxRemoteLifecycleListener.class);
@@ -74,9 +76,6 @@ public class JmxRemoteLifecycleListener
protected int rmiServerPortPlatform = -1;
protected boolean rmiRegistrySSL = true;
protected boolean rmiServerSSL = true;
- protected String ciphers[] = null;
- protected String protocols[] = null;
- protected boolean clientAuth = true;
protected boolean authenticate = true;
protected String passwordFile = null;
protected String loginModuleName = null;
@@ -156,48 +155,138 @@ public class JmxRemoteLifecycleListener
this.useLocalPorts = useLocalPorts;
}
- private void init() {
+ /**
+ * @return the rmiRegistrySSL
+ */
+ public boolean isRmiRegistrySSL() {
+ return rmiRegistrySSL;
+ }
+
+ /**
+ * @param rmiRegistrySSL the rmiRegistrySSL to set
+ */
+ public void setRmiRegistrySSL(boolean rmiRegistrySSL) {
+ this.rmiRegistrySSL = rmiRegistrySSL;
+ }
+
+ /**
+ * @return the rmiServerSSL
+ */
+ public boolean isRmiServerSSL() {
+ return rmiServerSSL;
+ }
+
+ /**
+ * @param rmiServerSSL the rmiServerSSL to set
+ */
+ public void setRmiServerSSL(boolean rmiServerSSL) {
+ this.rmiServerSSL = rmiServerSSL;
+ }
+
+ /**
+ * @return the authenticate
+ */
+ public boolean isAuthenticate() {
+ return authenticate;
+ }
+
+ /**
+ * @param authenticate the authenticate to set
+ */
+ public void setAuthenticate(boolean authenticate) {
+ this.authenticate = authenticate;
+ }
+
+ /**
+ * @return the passwordFile
+ */
+ public String getPasswordFile() {
+ return passwordFile;
+ }
+
+ /**
+ * @param passwordFile the passwordFile to set
+ */
+ public void setPasswordFile(String passwordFile) {
+ this.passwordFile = passwordFile;
+ }
+
+ /**
+ * @return the loginModuleName
+ */
+ public String getLoginModuleName() {
+ return loginModuleName;
+ }
+
+ /**
+ * @param loginModuleName the loginModuleName to set
+ */
+ public void setLoginModuleName(String loginModuleName) {
+ this.loginModuleName = loginModuleName;
+ }
+
+ /**
+ * @return the accessFile
+ */
+ public String getAccessFile() {
+ return accessFile;
+ }
+
+ /**
+ * @param accessFile the accessFile to set
+ */
+ public void setAccessFile(String accessFile) {
+ this.accessFile = accessFile;
+ }
+
+ protected void init() {
// Get all the other parameters required from the standard system
// properties. Only need to get the parameters that affect the creation
// of the server port.
- String rmiRegistrySSLValue = System.getProperty(
- "com.sun.management.jmxremote.registry.ssl", "false");
- rmiRegistrySSL = Boolean.parseBoolean(rmiRegistrySSLValue);
-
- String rmiServerSSLValue = System.getProperty(
- "com.sun.management.jmxremote.ssl", "true");
- rmiServerSSL = Boolean.parseBoolean(rmiServerSSLValue);
+ String rmiRegistrySSLValue =
System.getProperty("com.sun.management.jmxremote.registry.ssl");
+ if (rmiRegistrySSLValue != null) {
+ setRmiRegistrySSL(Boolean.parseBoolean(rmiRegistrySSLValue));
+ }
+
+ String rmiServerSSLValue =
System.getProperty("com.sun.management.jmxremote.ssl");
+ if (rmiServerSSLValue != null) {
+ setRmiServerSSL(Boolean.parseBoolean(rmiServerSSLValue));
+ }
- String protocolsValue = System.getProperty(
- "com.sun.management.jmxremote.ssl.enabled.protocols");
+ String protocolsValue =
System.getProperty("com.sun.management.jmxremote.ssl.enabled.protocols");
if (protocolsValue != null) {
- protocols = protocolsValue.split(",");
+ setEnabledProtocols(protocolsValue.split(","));
}
- String ciphersValue = System.getProperty(
- "com.sun.management.jmxremote.ssl.enabled.cipher.suites");
+ String ciphersValue =
System.getProperty("com.sun.management.jmxremote.ssl.enabled.cipher.suites");
if (ciphersValue != null) {
- ciphers = ciphersValue.split(",");
+ setCiphers(ciphersValue);
}
- String clientAuthValue = System.getProperty(
- "com.sun.management.jmxremote.ssl.need.client.auth", "true");
- clientAuth = Boolean.parseBoolean(clientAuthValue);
+ String clientAuthValue =
System.getProperty("com.sun.management.jmxremote.ssl.need.client.auth");
+ if (clientAuthValue != null) {
+ setCertificateVerification(clientAuthValue);
+ }
- String authenticateValue = System.getProperty(
- "com.sun.management.jmxremote.authenticate", "true");
- authenticate = Boolean.parseBoolean(authenticateValue);
+ String authenticateValue =
System.getProperty("com.sun.management.jmxremote.authenticate");
+ if (authenticateValue != null) {
+ setAuthenticate(Boolean.parseBoolean(authenticateValue));
+ }
- passwordFile = System.getProperty(
- "com.sun.management.jmxremote.password.file",
- "jmxremote.password");
+ String passwordFileValue =
System.getProperty("com.sun.management.jmxremote.password.file");
+ if (passwordFileValue != null) {
+ setPasswordFile(passwordFileValue);
+ }
- accessFile = System.getProperty(
- "com.sun.management.jmxremote.access.file",
- "jmxremote.access");
+ String accessFileValue =
System.getProperty("com.sun.management.jmxremote.access.file");
+ if (accessFileValue != null) {
+ setAccessFile(accessFileValue);
+ }
- loginModuleName = System.getProperty(
- "com.sun.management.jmxremote.login.config");
+ String loginModuleNameValue =
System.getProperty("com.sun.management.jmxremote.login.config");
+ if (loginModuleNameValue != null) {
+ setLoginModuleName(loginModuleNameValue);
+ }
}
@@ -205,9 +294,30 @@ public class JmxRemoteLifecycleListener
public void lifecycleEvent(LifecycleEvent event) {
// When the server starts, configure JMX/RMI
if (Lifecycle.START_EVENT.equals(event.getType())) {
- // Configure using standard jmx system properties
+
+ // Configure using standard JMX system properties
init();
+ SSLContext sslContext = null;
+ // Create SSL context if properties were set to define a
certificate
+ if (getCertificates().size() > 0) {
+ SSLHostConfigCertificate certificate =
getCertificates().iterator().next();
+ // This can only support JSSE
+ JSSEUtil sslUtil = new JSSEUtil(certificate);
+ try {
+ sslContext =
javax.net.ssl.SSLContext.getInstance(getSslProtocol());
+ setEnabledProtocols(sslUtil.getEnabledProtocols());
+ setEnabledCiphers(sslUtil.getEnabledCiphers());
+ sslContext.init(sslUtil.getKeyManagers(),
sslUtil.getTrustManagers(), null);
+ SSLSessionContext sessionContext =
sslContext.getServerSessionContext();
+ if (sessionContext != null) {
+ sslUtil.configureSessionContext(sessionContext);
+ }
+ } catch (Exception e) {
+
log.error(sm.getString("jmxRemoteLifecycleListener.invalidSSLConfiguration"),
e);
+ }
+ }
+
// Prevent an attacker guessing the RMI object ID
System.setProperty("java.rmi.server.randomIDs", "true");
@@ -224,11 +334,14 @@ public class JmxRemoteLifecycleListener
if (rmiRegistrySSL) {
registryCsf = new SslRMIClientSocketFactory();
if (rmiBindAddress == null) {
- registrySsf = new SslRMIServerSocketFactory(
- ciphers, protocols, clientAuth);
+ registrySsf = new SslRMIServerSocketFactory(sslContext,
+ getEnabledCiphers(), getEnabledProtocols(),
+ getCertificateVerification() ==
CertificateVerification.REQUIRED);
} else {
- registrySsf = new SslRmiServerBindSocketFactory(
- ciphers, protocols, clientAuth, rmiBindAddress);
+ registrySsf = new SslRmiServerBindSocketFactory(sslContext,
+ getEnabledCiphers(), getEnabledProtocols(),
+ getCertificateVerification() ==
CertificateVerification.REQUIRED,
+ rmiBindAddress);
}
} else {
if (rmiBindAddress != null) {
@@ -240,11 +353,14 @@ public class JmxRemoteLifecycleListener
if (rmiServerSSL) {
serverCsf = new SslRMIClientSocketFactory();
if (rmiBindAddress == null) {
- serverSsf = new SslRMIServerSocketFactory(
- ciphers, protocols, clientAuth);
+ serverSsf = new SslRMIServerSocketFactory(sslContext,
+ getEnabledCiphers(), getEnabledProtocols(),
+ getCertificateVerification() ==
CertificateVerification.REQUIRED);
} else {
- serverSsf = new SslRmiServerBindSocketFactory(
- ciphers, protocols, clientAuth, rmiBindAddress);
+ serverSsf = new SslRmiServerBindSocketFactory(sslContext,
+ getEnabledCiphers(), getEnabledProtocols(),
+ getCertificateVerification() ==
CertificateVerification.REQUIRED,
+ rmiBindAddress);
}
} else {
if (rmiBindAddress != null) {
@@ -410,34 +526,13 @@ public class JmxRemoteLifecycleListener
public static class SslRmiServerBindSocketFactory extends
SslRMIServerSocketFactory {
- private static final SSLServerSocketFactory sslServerSocketFactory;
- private static final String[] defaultProtocols;
-
- static {
- SSLContext sslContext;
- try {
- sslContext = SSLContext.getDefault();
- } catch (NoSuchAlgorithmException e) {
- // Can't continue. Force a failure.
- throw new IllegalStateException(e);
- }
- sslServerSocketFactory = sslContext.getServerSocketFactory();
- String[] protocols =
sslContext.getDefaultSSLParameters().getProtocols();
- List<String> filteredProtocols = new ArrayList<>(protocols.length);
- for (String protocol : protocols) {
- if (protocol.toUpperCase(Locale.ENGLISH).contains("SSL")) {
- continue;
- }
- filteredProtocols.add(protocol);
- }
- defaultProtocols = filteredProtocols.toArray(new
String[filteredProtocols.size()]);
- }
-
private final InetAddress bindAddress;
+ private final SSLContext sslContext;
- public SslRmiServerBindSocketFactory(String[] enabledCipherSuites,
+ public SslRmiServerBindSocketFactory(SSLContext sslContext, String[]
enabledCipherSuites,
String[] enabledProtocols, boolean needClientAuth, String
address) {
- super(enabledCipherSuites, enabledProtocols, needClientAuth);
+ super(sslContext, enabledCipherSuites, enabledProtocols,
needClientAuth);
+ this.sslContext = sslContext;
InetAddress bindAddress = null;
try {
bindAddress = InetAddress.getByName(address);
@@ -451,15 +546,16 @@ public class JmxRemoteLifecycleListener
}
@Override
- public ServerSocket createServerSocket(int port) throws IOException {
+ public ServerSocket createServerSocket(int port) throws IOException {
+ SSLServerSocketFactory sslServerSocketFactory = (sslContext ==
null)
+ ? (SSLServerSocketFactory)
SSLServerSocketFactory.getDefault()
+ : sslContext.getServerSocketFactory();
SSLServerSocket sslServerSocket =
(SSLServerSocket)
sslServerSocketFactory.createServerSocket(port, 0, bindAddress);
if (getEnabledCipherSuites() != null) {
sslServerSocket.setEnabledCipherSuites(getEnabledCipherSuites());
}
- if (getEnabledProtocols() == null) {
- sslServerSocket.setEnabledProtocols(defaultProtocols);
- } else {
+ if (getEnabledProtocols() != null) {
sslServerSocket.setEnabledProtocols(getEnabledProtocols());
}
sslServerSocket.setNeedClientAuth(getNeedClientAuth());
Modified: tomcat/trunk/java/org/apache/catalina/mbeans/LocalStrings.properties
URL:
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/mbeans/LocalStrings.properties?rev=1852005&r1=1852004&r2=1852005&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/mbeans/LocalStrings.properties
[UTF-8] (original)
+++ tomcat/trunk/java/org/apache/catalina/mbeans/LocalStrings.properties
[UTF-8] Thu Jan 24 09:15:03 2019
@@ -27,6 +27,7 @@ jmxRemoteLifecycleListener.createRegistr
jmxRemoteLifecycleListener.createServerFailed=The JMX connector server could
not be created or failed to start for the [{0}] server
jmxRemoteLifecycleListener.destroyServerFailed=The JMX connector server could
not be stopped for the [{0}] server
jmxRemoteLifecycleListener.invalidRmiBindAddress=Invalid RMI bind address [{0}]
+jmxRemoteLifecycleListener.invalidSSLConfiguration=SSL configuration error
jmxRemoteLifecycleListener.invalidURL=The JMX Service URL requested for the
[{0}] server, [{1}], was invalid
jmxRemoteLifecycleListener.start=The JMX Remote Listener has configured the
registry on port [{0}] and the server on port [{1}] for the [{2}] server
Modified: tomcat/trunk/res/tomcat-maven/README.md
URL:
http://svn.apache.org/viewvc/tomcat/trunk/res/tomcat-maven/README.md?rev=1852005&r1=1852004&r2=1852005&view=diff
==============================================================================
--- tomcat/trunk/res/tomcat-maven/README.md (original)
+++ tomcat/trunk/res/tomcat-maven/README.md Thu Jan 24 09:15:03 2019
@@ -39,7 +39,7 @@ mvn clean; mvn package
```
docker build -t apache/tomcat-maven:1.0 -f ./Dockerfile .
```
-Docker build arguments include `namepsace` (default is `myproject`) and `port`
which should match the Tomcat port in `server.xml` (default is `8080`). Other
ports that need to be exposed can be added in the `Dockerfile` as needed.
Webapps should be added to the `webapps` folder where they will be auto
deployed by the host if using the defaults. Otherwise, the `Dockerfile` command
line can be edited like below to include the necesary resources and command
line arguments to run a single or multiple hardcoded web applications.
+Docker build arguments include `namepsace` (default is `tomcat`) and `port`
which should match the Tomcat port in `server.xml` (default is `8080`). Other
ports that need to be exposed can be added in the `Dockerfile` as needed.
Webapps should be added to the `webapps` folder where they will be auto
deployed by the host if using the defaults. Otherwise, the `Dockerfile` command
line can be edited like below to include the necesary resources and command
line arguments to run a single or multiple hardcoded web applications.
## Running
@@ -65,10 +65,15 @@ java -Dcatalina.base=. -Djava.util.loggi
java -Dcatalina.base=.
-Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager
-Djava.util.logging.config.file=conf/logging.properties -jar
target/tomcat-maven-1.0.jar --war myrootwebapp --path /path1 --war mywebapp1
--path /path2 --war mywebapp2
```
-## Deployment
+## Cloud
+
+### Deployment
+
+An example `tomcat.yaml` is included which uses the Docker image. It uses the
health check valve which can be added in `conf/server.xml`, or a similar
service responding to requests on `/health`. It also declares the optional
Jolokia and Prometheus ports for monitoring.
+
+### Cluster
If using the Kubernetes cloud clustering membership provider, the pod needs to
have the persmission to view other pods. For exemple with Openshift, this is
done with:
```
oc policy add-role-to-user view system:serviceaccount:$(oc project -q):default
-n $(oc project -q)
```
-
Added: tomcat/trunk/res/tomcat-maven/tomcat.yaml
URL:
http://svn.apache.org/viewvc/tomcat/trunk/res/tomcat-maven/tomcat.yaml?rev=1852005&view=auto
==============================================================================
--- tomcat/trunk/res/tomcat-maven/tomcat.yaml (added)
+++ tomcat/trunk/res/tomcat-maven/tomcat.yaml Thu Jan 24 09:15:03 2019
@@ -0,0 +1,36 @@
+kind: Deployment
+apiVersion: extensions/v1beta1
+metadata:
+ name: tomcat
+ creationTimestamp:
+ labels:
+ run: tomcat
+spec:
+ replicas: 1
+ selector:
+ matchLabels:
+ run: tomcat
+ template:
+ metadata:
+ creationTimestamp:
+ labels:
+ run: tomcat
+ spec:
+ containers:
+ - name: tomcat
+ image: apache/tomcat:1.0
+ ports:
+ - containerPort: 8080
+ - containerPort: 8778
+ name: jolokia
+ - containerPort: 9404
+ name: prometheus
+ readinessProbe:
+ httpGet:
+ path: /health
+ port: 8080
+ initialDelaySeconds: 3
+ periodSeconds: 3
+ resources: {}
+ strategy: {}
+status: {}
Propchange: tomcat/trunk/res/tomcat-maven/tomcat.yaml
------------------------------------------------------------------------------
svn:eol-style = native
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]