You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@uima.apache.org by cw...@apache.org on 2017/11/02 13:44:55 UTC

svn commit: r1814082 - in /uima/uima-ducc/trunk/uima-ducc-common/src/main/java/org/apache/uima/ducc/common: component/AbstractDuccComponent.java utils/JdkEvaluator.java

Author: cwiklik
Date: Thu Nov  2 13:44:55 2017
New Revision: 1814082

URL: http://svn.apache.org/viewvc?rev=1814082&view=rev
Log:
UIMA-5636 introspect java version to check if it contains jmx security fix. The code does not start JMX server if java does not contins the fix

Modified:
    uima/uima-ducc/trunk/uima-ducc-common/src/main/java/org/apache/uima/ducc/common/component/AbstractDuccComponent.java
    uima/uima-ducc/trunk/uima-ducc-common/src/main/java/org/apache/uima/ducc/common/utils/JdkEvaluator.java

Modified: uima/uima-ducc/trunk/uima-ducc-common/src/main/java/org/apache/uima/ducc/common/component/AbstractDuccComponent.java
URL: http://svn.apache.org/viewvc/uima/uima-ducc/trunk/uima-ducc-common/src/main/java/org/apache/uima/ducc/common/component/AbstractDuccComponent.java?rev=1814082&r1=1814081&r2=1814082&view=diff
==============================================================================
--- uima/uima-ducc/trunk/uima-ducc-common/src/main/java/org/apache/uima/ducc/common/component/AbstractDuccComponent.java (original)
+++ uima/uima-ducc/trunk/uima-ducc-common/src/main/java/org/apache/uima/ducc/common/component/AbstractDuccComponent.java Thu Nov  2 13:44:55 2017
@@ -18,9 +18,13 @@
  */
 package org.apache.uima.ducc.common.component;
 
+import java.io.IOException;
 import java.lang.management.ManagementFactory;
 import java.net.InetAddress;
+import java.net.ServerSocket;
 import java.rmi.registry.LocateRegistry;
+import java.rmi.server.RMIServerSocketFactory;
+import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Properties;
@@ -34,6 +38,8 @@ import javax.management.ObjectName;
 import javax.management.remote.JMXConnectorServer;
 import javax.management.remote.JMXConnectorServerFactory;
 import javax.management.remote.JMXServiceURL;
+import javax.management.remote.rmi.RMIConnectorServer;
+import javax.net.ServerSocketFactory;
 
 import org.apache.activemq.camel.component.ActiveMQComponent;
 import org.apache.camel.CamelContext;
@@ -49,7 +55,10 @@ import org.apache.uima.ducc.common.excep
 import org.apache.uima.ducc.common.main.DuccService;
 import org.apache.uima.ducc.common.utils.DuccLogger;
 import org.apache.uima.ducc.common.utils.DuccProperties;
+import org.apache.uima.ducc.common.utils.JdkEvaluator;
 import org.apache.uima.ducc.common.utils.Utils;
+import org.apache.uima.ducc.common.utils.JdkEvaluator.JDKVendor;
+import org.apache.uima.ducc.common.utils.JdkEvaluator.Vendors;
 import org.apache.uima.ducc.common.utils.id.DuccId;
 
 /**
@@ -408,20 +417,40 @@ public abstract class AbstractDuccCompon
 			}
 		}
 	}
-  
+	private boolean daemonProcess() {
+		 if (System.getProperty("ducc.deploy.components") != null
+		            &&
+		            ( System.getProperty("ducc.deploy.components").equals("sm")
+		              || 
+		              System.getProperty("ducc.deploy.components").equals("orchestrator")
+		              ||
+		              System.getProperty("ducc.deploy.components").equals("pm")
+		              ||
+		              System.getProperty("ducc.deploy.components").equals("rm")
+		              ||
+		              System.getProperty("ducc.deploy.components").equals("ws")
+		              ||
+		              System.getProperty("ducc.deploy.components").equals("agent")
+		              ) ) {
+			 return true;
+		 }
+		 return false;
+	}
     public void start(DuccService service, String[] args) throws Exception {
 	    String endpoint = null;
 	    this.service = service;
 	    
 	    dumpArgs(args);
 	    dumpProps();
-	    
+	    /*
 	    if (System.getProperty("ducc.deploy.components") != null
 	            && !System.getProperty("ducc.deploy.components").equals("uima-as")
 	            && !System.getProperty("ducc.deploy.components").equals("job-process")
 	            && !System.getProperty("ducc.deploy.components").equals("service")
 	            && !System.getProperty("ducc.deploy.components").equals("jd")
 	            && (endpoint = System.getProperty("ducc.admin.endpoint")) != null) {
+	    	*/
+	    if ( daemonProcess() && ( endpoint = System.getProperty("ducc.admin.endpoint")) != null  ) {  
 	        logger.info("start", null, ".....Starting Admin Channel on endpoint:" + endpoint);
             startAdminChannel(endpoint, this);
             logger.info("start", null, "Admin Channel started on endpoint:" + endpoint);
@@ -437,20 +466,32 @@ public abstract class AbstractDuccCompon
 	    }
         logger.info("start",null, "..... Camel Initialized and Started");
 
-	    // Instrument this process with JMX Agent. The Agent will
-	    // find an open port and start JMX Connector allowing
-	    // jmx clients to connect to this jvm using standard
-	    // jmx connect url. This process does not require typical
-	    // -D<jmx params> properties. Currently the JMX does not
-	    // use security allowing all clients to connect.
-
-        logger.info("start",null, "..... Starting JMX Agent");
-	    processJmxUrl = startJmxAgent();
-	    if (processJmxUrl != null && processJmxUrl.trim().length() > 0 ) {
-	        logger.info("start",null, "..... JMX Agent Ready");
-	        logger.info("start",null, "Connect jConsole to this process using JMX URL:" + processJmxUrl);
-	      }
-	    System.getProperties().setProperty("ducc.jmx.url", processJmxUrl);
+
+        JDKVendor jdkVendor = Vendors.getVendor();
+        logger.info("start",null,"JDK Vendor:"+jdkVendor.getVendor()+" Version:"+System.getProperty("java.version")+" Runtime:"+jdkVendor.getRuntimeVersion());
+        try {
+            if ( JdkEvaluator.secureJdk(jdkVendor)) {
+        	    // Instrument this process with JMX Agent. The Agent will
+        	    // find an open port and start JMX Connector allowing
+        	    // jmx clients to connect to this jvm using standard
+        	    // jmx connect url. This process does not require typical
+        	    // -D<jmx params> properties. Currently the JMX does not
+        	    // use security allowing all clients to connect.
+                logger.info("start",null, "..... Starting JMX Agent");
+        	    processJmxUrl = startJmxAgent();
+        	    if (processJmxUrl != null && processJmxUrl.trim().length() > 0 ) {
+        	        logger.info("start",null, "..... JMX Agent Ready");
+        	        logger.info("start",null, "Connect jConsole to this process using JMX URL:" + processJmxUrl);
+        	      }
+        	    System.getProperties().setProperty("ducc.jmx.url", processJmxUrl);
+            } else {
+            	logger.info("start",null,"Remote JMX will not be enabled due to a dated JDK - consider using more recent JDK. Please review Java vulnerability report: CVE-2016-3427");
+        	    System.getProperties().setProperty("ducc.jmx.url", "Unavailable");
+            }
+        	
+        } catch( Exception e) {
+        	logger.error("start", null,e);
+        }
 
 	    if ( !System.getProperty("ducc.deploy.components").equals("uima-as")
 	             && !System.getProperty("ducc.deploy.components").equals("jd")) {
@@ -581,12 +622,19 @@ public abstract class AbstractDuccCompon
       }
       boolean done = false;
       JMXServiceURL url = null;
-      
+      /*
+      String jmxAccess = "local";
+      String hostname = "localhost";
+      if ( (jmxAccess = System.getProperty("ducc.jmx.access") ) != null && jmxAccess.equals("remote") ) {
+         hostname = InetAddress.getLocalHost().getHostName();
+      }
+      RMIServerSocketFactory serverFactory = new RMIServerSocketFactoryImpl(InetAddress.getByName(hostname));
+      */
       // retry until a valid rmi port is found
       while (!done) {
         	try {
-             	//	 set up RMI registry on a given port
-        		LocateRegistry.createRegistry(rmiRegistryPort);
+        //		LocateRegistry.createRegistry(rmiRegistryPort, null, serverFactory);
+                LocateRegistry.createRegistry(rmiRegistryPort);
                 done = true;
                 // Got a valid port
         	} catch( Exception exx) {
@@ -596,12 +644,22 @@ public abstract class AbstractDuccCompon
       } // while
 
       try {
-        	MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
-         
-            final String hostname = InetAddress.getLocalHost().getHostName();
+          	MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
+ 
+            String hostname = InetAddress.getLocalHost().getHostName();
+      
             String s = String.format("service:jmx:rmi:///jndi/rmi://%s:%d/jmxrmi", hostname,
                     rmiRegistryPort);
             url = new JMXServiceURL(s);
+            /*
+            Map<String,Object> env = new HashMap<>();
+            env.put(RMIConnectorServer.RMI_SERVER_SOCKET_FACTORY_ATTRIBUTE, serverFactory);
+
+            RMIConnectorServer rmiServer = new RMIConnectorServer( new JMXServiceURL(url.toString()),
+               env, ManagementFactory.getPlatformMBeanServer() );
+
+            rmiServer.start();
+             */
             jmxConnector = JMXConnectorServerFactory.newJMXConnectorServer(url, null, mbs);
             jmxConnector.start();
         } catch (Exception e) {
@@ -724,4 +782,34 @@ public abstract class AbstractDuccCompon
   public boolean isStopping() {
     return stopping;
   }
+  
+  public class RMIServerSocketFactoryImpl implements RMIServerSocketFactory {
+
+	    private final InetAddress localAddress;
+
+	    public RMIServerSocketFactoryImpl( final InetAddress pAddress ) {
+	        localAddress = pAddress;
+	    }
+
+	    public ServerSocket createServerSocket(final int pPort) throws IOException  {
+	        return ServerSocketFactory.getDefault()
+	            .createServerSocket(pPort, 0, localAddress);
+	    }
+
+	    public boolean equals(Object obj) {
+	        if (obj == null) {
+	            return false;
+	        }
+	        if (obj == this) {
+	            return true;
+	        }
+
+	        return obj.getClass().equals(getClass());
+	    }
+
+	    public int hashCode() {
+	        return RMIServerSocketFactoryImpl.class.hashCode();
+	    }
+	}
+
 }

Modified: uima/uima-ducc/trunk/uima-ducc-common/src/main/java/org/apache/uima/ducc/common/utils/JdkEvaluator.java
URL: http://svn.apache.org/viewvc/uima/uima-ducc/trunk/uima-ducc-common/src/main/java/org/apache/uima/ducc/common/utils/JdkEvaluator.java?rev=1814082&r1=1814081&r2=1814082&view=diff
==============================================================================
--- uima/uima-ducc/trunk/uima-ducc-common/src/main/java/org/apache/uima/ducc/common/utils/JdkEvaluator.java (original)
+++ uima/uima-ducc/trunk/uima-ducc-common/src/main/java/org/apache/uima/ducc/common/utils/JdkEvaluator.java Thu Nov  2 13:44:55 2017
@@ -18,6 +18,11 @@
  */
 package org.apache.uima.ducc.common.utils;
 
+/*
+ * Evaluates java version to determine if it contains JMX security
+ * fix described in CVE-2016-3427.
+ * 
+ */
 public class JdkEvaluator {
 	public static final int JAVA7=7;
 	public static final int JAVA8=8;
@@ -95,27 +100,11 @@ public class JdkEvaluator {
 		public boolean containsSecurityFix(String javaVersion) {
         	boolean containsFix = false;
 			String runtimeVersion = getRuntimeVersion();
-//			String [] vs = javaVersion.split("\\.");
-//			int pos = 0;
 			int major = IbmJdkVersion.getMajor(javaVersion);
 			// Java 9 comes with a different version string format.
 			// It can be just 9, 9-ea or 9.X.X. We just need to 
 			// establish if its 9 or higher looking at the major. Any
 			// JDK 9 or higher has the jmx fix
-//			if ( (pos = vs[0].indexOf('-')) > 0 ) {
-//				major = Integer.parseInt(vs[0].substring(0, pos));
-//			} else {
-//				major = Integer.parseInt(vs[0]);
-//			}
-			// versions 9 and above are safe
-//			if ( major >= JAVA9) {
-//				containsFix = true;   // good
-//			} else if ( Integer.parseInt(vs[1]) == JAVA8 ) {
-//				containsFix = isJava8Fixed(runtimeVersion);
-//			} else if ( Integer.parseInt(vs[1]) == JAVA7 ) {
-//				int minor = Integer.parseInt(vs[2]);
-//				containsFix = isJava7Fixed(runtimeVersion, minor);
-//			}
 			if ( major >= JAVA9) {
 				containsFix = true;
 			} else if ( major == JAVA8 ) {
@@ -129,13 +118,15 @@ public class JdkEvaluator {
 			boolean containsFix = false;
 			// if Java 1.7.2+ the jmx fix is there
 			if ( minor > 1) {
-				containsFix = true;
-			} else if ( minor == 1 ) {  // Java 1.7.1
+				return true;
+			} 
+			int serviceReleaseVersion = getSecurityReleaseVersion(runtimeVersion);
+			int fixPackVersion = getFixPackVersion(runtimeVersion);
+			
+			if ( minor == 1 ) {  // Java 1.7.1
 				// check if service release is at least 3 ( SR3)
-				int serviceReleaseVersion = getServiceReleaseVersion(runtimeVersion);
 				if ( serviceReleaseVersion >= SR3) {
 					// check if fix pack at least 40
-					int fixPackVersion = getServiceFixPackVersion(runtimeVersion);
 					if ( fixPackVersion >= FIXPACK40) {
 						// 1.7.1 JDK equal or above SR3 FP40 we're good
 						containsFix = true;
@@ -143,9 +134,7 @@ public class JdkEvaluator {
 				} 
 			} else if ( minor == 0 ) {  // Java 1.7.0
 				// check if service release is at least 9 ( SR9)
-				int serviceReleaseVersion = getServiceReleaseVersion(runtimeVersion);
 				if ( serviceReleaseVersion >= SR9) {
-					int fixPackVersion = getServiceFixPackVersion(runtimeVersion);
 					if ( fixPackVersion >= FIXPACK40) {
 						// 1.7.0 JDK equal or above SR9 FP40 we're good
 						containsFix = true;
@@ -158,9 +147,9 @@ public class JdkEvaluator {
 			boolean containsFix = false;
 			// Locate Service Release (SR) first. Anything equal or above version 3 is good
 			// for IBM Java 8.
-			int serviceReleaseVersion = getServiceReleaseVersion(runtimeVersion);
+			int serviceReleaseVersion = getSecurityReleaseVersion(runtimeVersion);
 			if ( serviceReleaseVersion >= 3) {
-				int fixPackVersion = getServiceFixPackVersion(runtimeVersion);
+				int fixPackVersion = getFixPackVersion(runtimeVersion);
 				if ( fixPackVersion >= 0) {
 					// anything above SR3 is good for Java8
 					containsFix = true;
@@ -168,16 +157,22 @@ public class JdkEvaluator {
 			} 
 			return containsFix;
 		}
-		private int getServiceReleaseVersion(String runtimeVersion) {
+		private int getSecurityReleaseVersion(String runtimeVersion) {
 			int start = runtimeVersion.indexOf("(SR");
 			if (start > 0 ) {
 				String upgradeStringVersion = runtimeVersion.substring(start+1, runtimeVersion.indexOf(')', start));
-				String srAsString = upgradeStringVersion.substring(2, upgradeStringVersion.indexOf(' '));
+				String srAsString = ""; // could be {SR[number])
+				if ( upgradeStringVersion.indexOf(' ') > -1 ) {
+					// this version comes with a fix pack (SR[Number] FP[Number])
+					srAsString = upgradeStringVersion.substring(2, upgradeStringVersion.indexOf(' '));
+				} else {
+					srAsString = upgradeStringVersion.substring(2);
+				}
 				return Integer.parseInt(srAsString);
 			}
 			return -1;
 		}
-		private int getServiceFixPackVersion(String runtimeVersion) {
+		private int getFixPackVersion(String runtimeVersion) {
 			int fixPackVersion = -1;
 			int start = runtimeVersion.indexOf("(SR");
 			if (start > 0 ) {
@@ -209,17 +204,6 @@ public class JdkEvaluator {
         	boolean containsFix = false;
 			// 9, 9-ea, 9.0.1
 			String [] vs = javaVersion.split("\\.");
-//			int pos = 0;
-//			int major = 1;
-//			// Java 9 comes with a different version string format.
-//			// It can be just 9, 9-ea or 9.X.X. We just need to 
-//			// establish if its 9 or higher looking at the major. Any
-//			// JDK 9 or higher has the jmx fix
-//			if ( (pos = vs[0].indexOf('-')) > 0 ) {
-//				major = Integer.parseInt(vs[0].substring(0, pos));
-//			} else {
-//				major = Integer.parseInt(vs[0]);
-//			}
         	int pos=0;
         	int major = JdkVersion.getMajor(javaVersion);
         	// versions 9 and above are safe