diff --git a/CHANGES.txt b/CHANGES.txt index 2da4af624d..61d9c9cfea 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -82,7 +82,7 @@ * Resumable bootstrap streaming (CASSANDRA-8838, CASSANDRA-8942) * Allow scrub for secondary index (CASSANDRA-5174) -2.1.4 +2.1.5 * Buffer bloom filter serialization (CASSANDRA-9066) * Fix anti-compaction target bloom filter size (CASSANDRA-9060) * Make FROZEN and TUPLE unreserved keywords in CQL (CASSANDRA-9047) @@ -195,6 +195,8 @@ Merged from 2.0: * Ensure SSTableSimpleUnsortedWriter.close() terminates if disk writer has crashed (CASSANDRA-8807) +2.1.4 + * Bind JMX to localhost unless explicitly configured otherwise (CASSANDRA-9085) 2.1.3 * Fix HSHA/offheap_objects corruption (CASSANDRA-8719) @@ -294,9 +296,6 @@ Merged from 2.0: * Add batch remove iterator to ABSC (CASSANDRA-8414, 8666) * Round up time deltas lower than 1ms in BulkLoader (CASSANDRA-8645) * Fix isClientMode check in Keyspace (CASSANDRA-8687) - * 'nodetool info' prints exception against older node (CASSANDRA-8796) - * Ensure SSTableSimpleUnsortedWriter.close() terminates if - disk writer has crashed (CASSANDRA-8807) * Use more efficient slice size for querying internal secondary index tables (CASSANDRA-8550) * Fix potentially returning deleted rows with range tombstone (CASSANDRA-8558) @@ -350,7 +349,6 @@ Merged from 2.0: * Use live sstables in snapshot repair if possible (CASSANDRA-8312) * Fix hints serialized size calculation (CASSANDRA-8587) - 2.1.2 * (cqlsh) parse_for_table_meta errors out on queries with undefined grammars (CASSANDRA-8262) diff --git a/NEWS.txt b/NEWS.txt index 3af2f92b35..94e225bf6c 100644 --- a/NEWS.txt +++ b/NEWS.txt @@ -83,7 +83,7 @@ Upgrading fixed, and those queries now require ALLOW FILTERING (see CASSANDRA-8418 for details). -2.1.4 +2.1.5 ===== Upgrading @@ -97,6 +97,11 @@ New features - New `SimpleDateType` (cql date). 4-byte unsigned integer w/out timestamp - New `TimeType` (cql time). 8-byte long nano-second resolution timestamp +2.1.4 +===== +The default JMX config now listens to localhost only. You must enable +the other JMX flags in cassandra-env.sh manually. + 2.1.3 ===== diff --git a/bin/cassandra.bat b/bin/cassandra.bat index 3445af2ce9..155aaf6f1a 100644 --- a/bin/cassandra.bat +++ b/bin/cassandra.bat @@ -65,11 +65,14 @@ set JAVA_OPTS=-ea^ -XX:MaxTenuringThreshold=1^ -XX:CMSInitiatingOccupancyFraction=75^ -XX:+UseCMSInitiatingOccupancyOnly^ - -Dcom.sun.management.jmxremote.port=7199^ - -Dcom.sun.management.jmxremote.ssl=false^ - -Dcom.sun.management.jmxremote.authenticate=false^ -Dlogback.configurationFile=logback.xml^ - -Djava.library.path=%CASSANDRA_HOME%\lib\sigar-bin + -Djava.library.path=%CASSANDRA_HOME%\lib\sigar-bin^ + -Dcassandra.jmx.local.port=7199 +REM **** JMX REMOTE ACCESS SETTINGS SEE: https://wiki.apache.org/cassandra/JmxSecurity *** +REM -Dcom.sun.management.jmxremote.port=7199^ +REM -Dcom.sun.management.jmxremote.ssl=false^ +REM -Dcom.sun.management.jmxremote.authenticate=true^ +REM -Dcom.sun.management.jmxremote.password.file=C:\jmxremote.password REM ***** CLASSPATH library setting ***** REM Ensure that any user defined CLASSPATH variables are not used on startup diff --git a/conf/cassandra-env.ps1 b/conf/cassandra-env.ps1 index 67db0f6f0b..3628de5bec 100644 --- a/conf/cassandra-env.ps1 +++ b/conf/cassandra-env.ps1 @@ -440,10 +440,17 @@ Function SetCassandraEnvironment # https://blogs.oracle.com/jmxetc/entry/troubleshooting_connection_problems_in_jconsole # for more on configuring JMX through firewalls, etc. (Short version: # get it working with no firewall first.) - $env:JVM_OPTS="$env:JVM_OPTS -Dcom.sun.management.jmxremote.port=$JMX_PORT" - $env:JVM_OPTS="$env:JVM_OPTS -Dcom.sun.management.jmxremote.ssl=false" - $env:JVM_OPTS="$env:JVM_OPTS -Dcom.sun.management.jmxremote.authenticate=false" + # + # Due to potential security exploits, Cassandra ships with JMX accessible + # *only* from localhost. To enable remote JMX connections, uncomment lines below + # with authentication and ssl enabled. See https://wiki.apache.org/cassandra/JmxSecurity + # + #$env:JVM_OPTS="$env:JVM_OPTS -Dcom.sun.management.jmxremote.port=$JMX_PORT" + #$env:JVM_OPTS="$env:JVM_OPTS -Dcom.sun.management.jmxremote.ssl=false" + #$env:JVM_OPTS="$env:JVM_OPTS -Dcom.sun.management.jmxremote.authenticate=true" #$env:JVM_OPTS="$env:JVM_OPTS -Dcom.sun.management.jmxremote.password.file=C:/jmxremote.password" + $env:JVM_OPTS="$env:JVM_OPTS -Dcassandra.jmx.local.port=$JMX_PORT -XX:+DisableExplicitGC" + $env:JVM_OPTS="$env:JVM_OPTS $JVM_EXTRA_OPTS" $env:JVM_OPTS = "$env:JVM_OPTS -Dlog4j.configuration=log4j-server.properties" diff --git a/conf/cassandra-env.sh b/conf/cassandra-env.sh index 4eb4c8835b..7df703bee8 100644 --- a/conf/cassandra-env.sh +++ b/conf/cassandra-env.sh @@ -334,6 +334,22 @@ JVM_OPTS="$JVM_OPTS -Djava.net.preferIPv4Stack=true" # https://blogs.oracle.com/jmxetc/entry/troubleshooting_connection_problems_in_jconsole # for more on configuring JMX through firewalls, etc. (Short version: # get it working with no firewall first.) +# +# Cassandra ships with JMX accessible *only* from localhost. +# To enable remote JMX connections, uncomment lines below +# with authentication and/or ssl enabled. See https://wiki.apache.org/cassandra/JmxSecurity +# +LOCAL_JMX=yes + +if [ "$LOCAL_JMX" = "yes" ]; then + JVM_OPTS="$JVM_OPTS -Dcassandra.jmx.local.port=$JMX_PORT -XX:+DisableExplicitGC" +else + JVM_OPTS="$JVM_OPTS -Dcom.sun.management.jmxremote.port=$JMX_PORT" + JVM_OPTS="$JVM_OPTS -Dcom.sun.management.jmxremote.rmi.port=$JMX_PORT" + JVM_OPTS="$JVM_OPTS -Dcom.sun.management.jmxremote.ssl=false" + JVM_OPTS="$JVM_OPTS -Dcom.sun.management.jmxremote.authenticate=true" + JVM_OPTS="$JVM_OPTS -Dcom.sun.management.jmxremote.password.file=/etc/cassandra/jmxremote.password" +fi # To use mx4j, an HTML interface for JMX, add mx4j-tools.jar to the lib/ # directory. @@ -348,11 +364,6 @@ JVM_OPTS="$JVM_OPTS -Djava.net.preferIPv4Stack=true" # to the location of the native libraries. JVM_OPTS="$JVM_OPTS -Djava.library.path=$CASSANDRA_HOME/lib/sigar-bin" -JVM_OPTS="$JVM_OPTS -Dcom.sun.management.jmxremote.port=$JMX_PORT" -JVM_OPTS="$JVM_OPTS -Dcom.sun.management.jmxremote.rmi.port=$JMX_PORT" -JVM_OPTS="$JVM_OPTS -Dcom.sun.management.jmxremote.ssl=false" -JVM_OPTS="$JVM_OPTS -Dcom.sun.management.jmxremote.authenticate=false" -#JVM_OPTS="$JVM_OPTS -Dcom.sun.management.jmxremote.password.file=/etc/cassandra/jmxremote.password" JVM_OPTS="$JVM_OPTS $MX4J_ADDRESS" JVM_OPTS="$JVM_OPTS $MX4J_PORT" JVM_OPTS="$JVM_OPTS $JVM_EXTRA_OPTS" diff --git a/debian/changelog b/debian/changelog index 339da0ce6e..807546033a 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +cassandra (2.1.4) unstable; urgency=medium + + * New release + + -- Jake Luciani Fri, 27 Mar 2015 13:48:25 -0400 + cassandra (2.1.3) unstable; urgency=medium * New release diff --git a/src/java/org/apache/cassandra/service/CassandraDaemon.java b/src/java/org/apache/cassandra/service/CassandraDaemon.java index d6b2d24762..4594196b20 100644 --- a/src/java/org/apache/cassandra/service/CassandraDaemon.java +++ b/src/java/org/apache/cassandra/service/CassandraDaemon.java @@ -23,15 +23,16 @@ import java.lang.management.ManagementFactory; import java.lang.management.MemoryPoolMXBean; import java.net.InetAddress; import java.net.UnknownHostException; -import java.util.Arrays; -import java.util.Date; -import java.util.Map; -import java.util.UUID; +import java.rmi.registry.LocateRegistry; +import java.rmi.server.RMIServerSocketFactory; +import java.util.*; import java.util.concurrent.TimeUnit; - import javax.management.MBeanServer; import javax.management.ObjectName; import javax.management.StandardMBean; +import javax.management.remote.JMXConnectorServer; +import javax.management.remote.JMXServiceURL; +import javax.management.remote.rmi.RMIConnectorServer; import com.google.common.collect.Iterables; import com.google.common.util.concurrent.Uninterruptibles; @@ -70,9 +71,61 @@ import org.apache.cassandra.utils.*; public class CassandraDaemon { public static final String MBEAN_NAME = "org.apache.cassandra.db:type=NativeAccess"; + public static JMXConnectorServer jmxServer = null; private static final Logger logger = LoggerFactory.getLogger(CassandraDaemon.class); + private static void maybeInitJmx() + { + String jmxPort = System.getProperty("com.sun.management.jmxremote.port"); + + if (jmxPort == null) + { + logger.warn("JMX is not enabled to receive remote connections. Please see cassandra-env.sh for more info."); + + jmxPort = System.getProperty("cassandra.jmx.local.port"); + + if (jmxPort == null) + { + logger.error("cassandra.jmx.local.port missing from cassandra-env.sh, unable to start local JMX service." + jmxPort); + } + else + { + System.setProperty("java.rmi.server.hostname","127.0.0.1"); + + try + { + RMIServerSocketFactory serverFactory = new RMIServerSocketFactoryImpl(); + LocateRegistry.createRegistry(Integer.valueOf(jmxPort), null, serverFactory); + + StringBuffer url = new StringBuffer(); + url.append("service:jmx:"); + url.append("rmi://localhost/jndi/"); + url.append("rmi://localhost:").append(jmxPort).append("/jmxrmi"); + + Map env = new HashMap(); + env.put(RMIConnectorServer.RMI_SERVER_SOCKET_FACTORY_ATTRIBUTE, serverFactory); + + jmxServer = new RMIConnectorServer( + new JMXServiceURL(url.toString()), + env, + ManagementFactory.getPlatformMBeanServer() + ); + + jmxServer.start(); + } + catch (IOException e) + { + logger.error("Error starting local jmx server: ", e); + } + } + } + else + { + logger.info("JMX is enabled to receive remote connections on port: " + jmxPort); + } + } + private static final CassandraDaemon instance = new CassandraDaemon(); /** @@ -171,6 +224,8 @@ public class CassandraDaemon CLibrary.tryMlockall(); + maybeInitJmx(); + Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() { public void uncaughtException(Thread t, Throwable e) @@ -455,6 +510,18 @@ public class CassandraDaemon // We rely on the shutdown hook to drain the node if (FBUtilities.isWindows()) System.exit(0); + + if (jmxServer != null) + { + try + { + jmxServer.stop(); + } + catch (IOException e) + { + logger.error("Error shutting down local JMX server: ", e); + } + } } diff --git a/src/java/org/apache/cassandra/utils/RMIServerSocketFactoryImpl.java b/src/java/org/apache/cassandra/utils/RMIServerSocketFactoryImpl.java new file mode 100644 index 0000000000..75331abd2f --- /dev/null +++ b/src/java/org/apache/cassandra/utils/RMIServerSocketFactoryImpl.java @@ -0,0 +1,34 @@ +package org.apache.cassandra.utils; + +import java.io.IOException; +import java.net.*; +import java.rmi.server.RMIServerSocketFactory; +import javax.net.ServerSocketFactory; + + +public class RMIServerSocketFactoryImpl implements RMIServerSocketFactory +{ + + public ServerSocket createServerSocket(final int pPort) throws IOException { + return ServerSocketFactory.getDefault().createServerSocket(pPort, 0, InetAddress.getLoopbackAddress()); + } + + 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(); + } +}