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: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org