diff --git a/CHANGES.txt b/CHANGES.txt index ffe042e3f35a..f3b51f4972eb 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,4 +1,5 @@ 5.1 + * Enable JMX server configuration to be in cassandra.yaml (CASSANDRA-11695) * Parallelized UCS compactions (CASSANDRA-18802) * Avoid prepared statement invalidation race when committing schema changes (CASSANDRA-20116) * Restore optimization in MultiCBuilder around building one clustering (CASSANDRA-20129) diff --git a/NEWS.txt b/NEWS.txt index ae1ba39d303c..b493e48d5187 100644 --- a/NEWS.txt +++ b/NEWS.txt @@ -88,7 +88,6 @@ New features generate a password of configured password strength policy upon role creation or alteration when 'GENERATED PASSWORD' clause is used. Character sets supported are: English, Cyrillic, modern Cyrillic, German, Polish and Czech. - - JMX SSL configuration can be now done in cassandra.yaml via jmx_encryption_options section instead of cassandra-env.sh - There is new MBean of name org.apache.cassandra.service.snapshot:type=SnapshotManager which exposes user-facing snapshot operations. Snapshot-related methods on StorageServiceMBean are still present and functional but marked as deprecated. @@ -102,6 +101,12 @@ New features compactions. To avoid the possibility of starving background compactions from resources, the number of threads used for major compactions is limited to half the available compaction threads by default, and can be controlled by a new --jobs / -j option of nodetool compact. + - It is possible to configure JMX server in cassandra.yaml in jmx_server_options configuration section. + JMX SSL configuration can be configured via jmx_encryption_options in jmx_server_options. The old way of + configuring JMX is still present and default, but new way is preferable as it will e.g. not leak credentials for + JMX to JVM parameters. You have to opt-in to use the configuration via cassandra.yaml by uncommenting + the respective configuration sections and by commenting out `configure_jmx` function call in cassandra-env.sh. + Enabling both ways of configuring JMX will result in a node failing to start. Upgrading diff --git a/bin/nodetool b/bin/nodetool index f78b02e34418..6ba19e16f061 100755 --- a/bin/nodetool +++ b/bin/nodetool @@ -52,6 +52,19 @@ if [ -f "$CASSANDRA_CONF/cassandra-env.sh" ]; then JVM_OPTS="$JVM_OPTS_SAVE" fi +# In case JMX_PORT is not set (when configure_jmx in cassandra-env.sh is commented out), +# try to parse it from cassandra.yaml. +if [ "x$JMX_PORT" = "x" ]; then + if [ -f "$CASSANDRA_CONF/cassandra.yaml" ]; then + JMX_PORT=`grep jmx_port $CASSANDRA_CONF/cassandra.yaml | cut -d ':' -f 2 | tr -d '[[:space:]]'` + fi +fi + +# If, by any chance, it is not there either, set it to default. +if [ "x$JMX_PORT" = "x" ]; then + JMX_PORT=7199 +fi + # JMX Port passed via cmd line args (-p 9999 / --port 9999 / --port=9999) # should override the value from cassandra-env.sh ARGS="" diff --git a/conf/cassandra-env.sh b/conf/cassandra-env.sh index 98b7ed8ccdf1..46085068dae2 100644 --- a/conf/cassandra-env.sh +++ b/conf/cassandra-env.sh @@ -218,55 +218,66 @@ if [ "x$LOCAL_JMX" = "x" ]; then LOCAL_JMX=yes fi -# Specifies the default port over which Cassandra will be available for -# JMX connections. -# For security reasons, you should not expose this port to the internet. Firewall it if needed. -JMX_PORT="7199" - -if [ "$LOCAL_JMX" = "yes" ]; then - JVM_OPTS="$JVM_OPTS -Dcassandra.jmx.local.port=$JMX_PORT" - JVM_OPTS="$JVM_OPTS -Dcom.sun.management.jmxremote.authenticate=false" -else - JVM_OPTS="$JVM_OPTS -Dcassandra.jmx.remote.port=$JMX_PORT" - # if ssl is enabled the same port cannot be used for both jmx and rmi so either - # pick another value for this property or comment out to use a random port (though see CASSANDRA-7087 for origins) - JVM_OPTS="$JVM_OPTS -Dcom.sun.management.jmxremote.rmi.port=$JMX_PORT" - - # turn on JMX authentication. See below for further options - JVM_OPTS="$JVM_OPTS -Dcom.sun.management.jmxremote.authenticate=true" - - # jmx ssl options - # Consider using the jmx_encryption_options section of cassandra.yaml instead - # to prevent sensitive information being exposed. - # In case jmx ssl options are configured in both the places - this file and cassandra.yaml, and - # if com.sun.management.jmxremote.ssl is configured to be true here and encryption_options are marked enabled in - # cassandra.yaml, then we will get exception at the startup - #JVM_OPTS="$JVM_OPTS -Dcom.sun.management.jmxremote.ssl=true" - #JVM_OPTS="$JVM_OPTS -Dcom.sun.management.jmxremote.ssl.need.client.auth=true" - #JVM_OPTS="$JVM_OPTS -Dcom.sun.management.jmxremote.ssl.enabled.protocols=" - #JVM_OPTS="$JVM_OPTS -Dcom.sun.management.jmxremote.ssl.enabled.cipher.suites=" - #JVM_OPTS="$JVM_OPTS -Djavax.net.ssl.keyStore=/path/to/keystore" - #JVM_OPTS="$JVM_OPTS -Djavax.net.ssl.keyStorePassword=" - #JVM_OPTS="$JVM_OPTS -Djavax.net.ssl.trustStore=/path/to/truststore" - #JVM_OPTS="$JVM_OPTS -Djavax.net.ssl.trustStorePassword=" -fi +configure_jmx() +{ + JMX_PORT=$1 + + if [ "$LOCAL_JMX" = "yes" ]; then + JVM_OPTS="$JVM_OPTS -Dcassandra.jmx.local.port=$JMX_PORT" + JVM_OPTS="$JVM_OPTS -Dcom.sun.management.jmxremote.authenticate=false" + else + JVM_OPTS="$JVM_OPTS -Dcassandra.jmx.remote.port=$JMX_PORT" + # if ssl is enabled the same port cannot be used for both jmx and rmi so either + # pick another value for this property or comment out to use a random port (though see CASSANDRA-7087 for origins) + JVM_OPTS="$JVM_OPTS -Dcom.sun.management.jmxremote.rmi.port=$JMX_PORT" + + # turn on JMX authentication. See below for further options + JVM_OPTS="$JVM_OPTS -Dcom.sun.management.jmxremote.authenticate=true" + + # jmx ssl options + # Consider using the jmx_encryption_options section of jmx_server_options in cassandra.yaml instead + # to prevent sensitive information being exposed. + # In case jmx ssl options are configured in both the places - this file and cassandra.yaml, and + # if com.sun.management.jmxremote.ssl is configured to be true here and encryption_options are marked enabled in + # cassandra.yaml, then we will get exception at the startup + #JVM_OPTS="$JVM_OPTS -Dcom.sun.management.jmxremote.ssl=true" + #JVM_OPTS="$JVM_OPTS -Dcom.sun.management.jmxremote.ssl.need.client.auth=true" + #JVM_OPTS="$JVM_OPTS -Dcom.sun.management.jmxremote.ssl.enabled.protocols=" + #JVM_OPTS="$JVM_OPTS -Dcom.sun.management.jmxremote.ssl.enabled.cipher.suites=" + #JVM_OPTS="$JVM_OPTS -Djavax.net.ssl.keyStore=/path/to/keystore" + #JVM_OPTS="$JVM_OPTS -Djavax.net.ssl.keyStorePassword=" + #JVM_OPTS="$JVM_OPTS -Djavax.net.ssl.trustStore=/path/to/truststore" + #JVM_OPTS="$JVM_OPTS -Djavax.net.ssl.trustStorePassword=" + fi + + # jmx authentication and authorization options. By default, auth is only + # activated for remote connections but they can also be enabled for local only JMX + ## Basic file based authn & authz + JVM_OPTS="$JVM_OPTS -Dcom.sun.management.jmxremote.password.file=/etc/cassandra/jmxremote.password" + #JVM_OPTS="$JVM_OPTS -Dcom.sun.management.jmxremote.access.file=/etc/cassandra/jmxremote.access" + ## Custom auth settings which can be used as alternatives to JMX's out of the box auth utilities. + ## JAAS login modules can be used for authentication by uncommenting these two properties. + ## Cassandra ships with a LoginModule implementation - org.apache.cassandra.auth.CassandraLoginModule - + ## which delegates to the IAuthenticator configured in cassandra.yaml. See the sample JAAS configuration + ## file cassandra-jaas.config + #JVM_OPTS="$JVM_OPTS -Dcassandra.jmx.remote.login.config=CassandraLogin" + #JVM_OPTS="$JVM_OPTS -Djava.security.auth.login.config=$CASSANDRA_CONF/cassandra-jaas.config" + + ## Cassandra also ships with a helper for delegating JMX authz calls to the configured IAuthorizer, + ## uncomment this to use it. Requires one of the two authentication options to be enabled + #JVM_OPTS="$JVM_OPTS -Dcassandra.jmx.authorizer=org.apache.cassandra.auth.jmx.AuthorizationProxy" +} -# jmx authentication and authorization options. By default, auth is only -# activated for remote connections but they can also be enabled for local only JMX -## Basic file based authn & authz -JVM_OPTS="$JVM_OPTS -Dcom.sun.management.jmxremote.password.file=/etc/cassandra/jmxremote.password" -#JVM_OPTS="$JVM_OPTS -Dcom.sun.management.jmxremote.access.file=/etc/cassandra/jmxremote.access" -## Custom auth settings which can be used as alternatives to JMX's out of the box auth utilities. -## JAAS login modules can be used for authentication by uncommenting these two properties. -## Cassandra ships with a LoginModule implementation - org.apache.cassandra.auth.CassandraLoginModule - -## which delegates to the IAuthenticator configured in cassandra.yaml. See the sample JAAS configuration -## file cassandra-jaas.config -#JVM_OPTS="$JVM_OPTS -Dcassandra.jmx.remote.login.config=CassandraLogin" -#JVM_OPTS="$JVM_OPTS -Djava.security.auth.login.config=$CASSANDRA_CONF/cassandra-jaas.config" - -## Cassandra also ships with a helper for delegating JMX authz calls to the configured IAuthorizer, -## uncomment this to use it. Requires one of the two authentication options to be enabled -#JVM_OPTS="$JVM_OPTS -Dcassandra.jmx.authorizer=org.apache.cassandra.auth.jmx.AuthorizationProxy" +# If this function call is commented out, then Cassandra will start with no system properties for JMX set whatsoever. +# We will be expecting the settings in jmx_server_options and jmx_encryption_options respectively instead. +# The argument specifies the default port over which Cassandra will be available for JMX connections. +# +# If you comment out configure_jmx method call, then JMX_PORT variable will not be set, which means +# nodetool which sources this file will not see it either and port from cassandra.yaml will be parsed instead, +# if not found there either, it defaults to 7199. +# +# For security reasons, you should not expose this port to the internet. Firewall it if needed. +configure_jmx 7199 # To use mx4j, an HTML interface for JMX, add mx4j-tools.jar to the lib/ # directory. diff --git a/conf/cassandra.yaml b/conf/cassandra.yaml index b93b41fa0bb7..f8d9f354cbf0 100644 --- a/conf/cassandra.yaml +++ b/conf/cassandra.yaml @@ -1721,14 +1721,59 @@ client_encryption_options: # JMX SSL. # Similar to `client/server_encryption_options`, you can specify PEM-based # key material or customize the SSL configuration using `ssl_context_factory` in `jmx_encryption_options`. -#jmx_encryption_options: -# enabled: true -# cipher_suites: [TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256] -# accepted_protocols: [TLSv1.2,TLSv1.3,TLSv1.1] -# keystore: conf/cassandra_ssl.keystore -# keystore_password: cassandra -# truststore: conf/cassandra_ssl.truststore -# truststore_password: cassandra +# If you uncomment this section, please be sure that you comment out configure_jmx function call in cassandra-env.sh +# as it is errorneous to have JMX set by two ways, both in cassandra-env.sh and in this yaml. +#jmx_server_options: + # enabled: true + # remote: false + # jmx_port: 7199 + # + # Port used by the RMI registry when remote connections are enabled. + # To simplify firewall configs, this can be set to the same as the JMX server port (port). See CASSANDRA-7087. + # However, if ssl is enabled the same port cannot be used for both jmx and rmi so either + # pick another value for this property. Alternatively, comment out or set to 0 to use a random + # port (pre-CASSANDRA-7087 behaviour) + # rmi_port: 7199 + # + # jmx ssl options - only apply when remote connections are enabled + # + # jmx_encryption_options: + # enabled: true + # cipher_suites: [TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256] + # accepted_protocols: [TLSv1.2,TLSv1.3,TLSv1.1] + # keystore: conf/cassandra_ssl.keystore + # keystore_password: cassandra + # truststore: conf/cassandra_ssl.truststore + # truststore_password: cassandra + # + # jmx authentication and authorization options. + # authenticate: false + # + # Options for basic file based authentication & authorization + # password_file: /etc/cassandra/jmxremote.password + # access_file: /etc/cassandra/jmxremote.access + # + # Custom auth settings which can be used as alternatives to JMX's out of the box auth utilities. + # JAAS login modules can be used for authentication using this property.Cassandra ships with a + # LoginModule implementation - org.apache.cassandra.auth.CassandraLoginModule - which delegates + # to the IAuthenticator configured in cassandra.yaml. + # + # login_config_name refers to the Application Name in the JAAS configuration under which the + # desired LoginModule(s) are configured. + # The location of the JAAS config file may be set using the standard JVM mechanism, by setting + # the system property "java.security.auth.login.config". If this property is set, it's value + # will be used to locate the config file. For convenience, if the property is not already set + # at startup, a value can be supplied here via the login_config_file setting. + # + # The Application Name specified must be present in the JAAS config or an error will be thrown + # when authentication is attempted. + # See the sample JAAS configuration file conf/cassandra-jaas.config + # login_config_name: CassandraLogin + # login_config_file: conf/cassandra-jaas.config + # + # Cassandra also ships with a helper for delegating JMX authz calls to the configured IAuthorizer, + # uncomment this to use it. Requires one of the two authentication options to be enabled + # authorizer: org.apache.cassandra.auth.jmx.AuthorizationProxy # internode_compression controls whether traffic between nodes is # compressed. diff --git a/conf/cassandra_latest.yaml b/conf/cassandra_latest.yaml index 2ad1a25f0779..109811956db4 100644 --- a/conf/cassandra_latest.yaml +++ b/conf/cassandra_latest.yaml @@ -1685,14 +1685,59 @@ client_encryption_options: # JMX SSL. # Similar to `client/server_encryption_options`, you can specify PEM-based # key material or customize the SSL configuration using `ssl_context_factory` in `jmx_encryption_options`. -#jmx_encryption_options: -# enabled: true -# cipher_suites: [TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256] -# accepted_protocols: [TLSv1.2,TLSv1.3,TLSv1.1] -# keystore: conf/cassandra_ssl.keystore -# keystore_password: cassandra -# truststore: conf/cassandra_ssl.truststore -# truststore_password: cassandra +# If you uncomment this section, please be sure that you comment out configure_jmx function call in cassandra-env.sh +# as it is errorneous to have JMX set by two ways, both in cassandra-env.sh and in this yaml. +#jmx_server_options: + # enabled: true + # remote: false + # jmx_port: 7199 + # + # Port used by the RMI registry when remote connections are enabled. + # To simplify firewall configs, this can be set to the same as the JMX server port (port). See CASSANDRA-7087. + # However, if ssl is enabled the same port cannot be used for both jmx and rmi so either + # pick another value for this property. Alternatively, comment out or set to 0 to use a random + # port (pre-CASSANDRA-7087 behaviour) + # rmi_port: 7199 + # + # jmx ssl options - only apply when remote connections are enabled + # + # jmx_encryption_options: + # enabled: true + # cipher_suites: [TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256] + # accepted_protocols: [TLSv1.2,TLSv1.3,TLSv1.1] + # keystore: conf/cassandra_ssl.keystore + # keystore_password: cassandra + # truststore: conf/cassandra_ssl.truststore + # truststore_password: cassandra + # + # jmx authentication and authorization options. + # authenticate: false + # + # Options for basic file based authentication & authorization + # password_file: /etc/cassandra/jmxremote.password + # access_file: /etc/cassandra/jmxremote.access + # + # Custom auth settings which can be used as alternatives to JMX's out of the box auth utilities. + # JAAS login modules can be used for authentication using this property.Cassandra ships with a + # LoginModule implementation - org.apache.cassandra.auth.CassandraLoginModule - which delegates + # to the IAuthenticator configured in cassandra.yaml. + # + # login_config_name refers to the Application Name in the JAAS configuration under which the + # desired LoginModule(s) are configured. + # The location of the JAAS config file may be set using the standard JVM mechanism, by setting + # the system property "java.security.auth.login.config". If this property is set, it's value + # will be used to locate the config file. For convenience, if the property is not already set + # at startup, a value can be supplied here via the login_config_file setting. + # + # The Application Name specified must be present in the JAAS config or an error will be thrown + # when authentication is attempted. + # See the sample JAAS configuration file conf/cassandra-jaas.config + # login_config_name: CassandraLogin + # login_config_file: conf/cassandra-jaas.config + # + # Cassandra also ships with a helper for delegating JMX authz calls to the configured IAuthorizer, + # uncomment this to use it. Requires one of the two authentication options to be enabled + # authorizer: org.apache.cassandra.auth.jmx.AuthorizationProxy # internode_compression controls whether traffic between nodes is # compressed. diff --git a/doc/scripts/convert_yaml_to_adoc.py b/doc/scripts/convert_yaml_to_adoc.py index 061706f83589..6062f9f79954 100644 --- a/doc/scripts/convert_yaml_to_adoc.py +++ b/doc/scripts/convert_yaml_to_adoc.py @@ -49,7 +49,7 @@ 'hints_compression', 'server_encryption_options', 'client_encryption_options', - 'jmx_encryption_options', + 'jmx_server_options', 'transparent_data_encryption_options', 'hinted_handoff_disabled_datacenters', 'startup_checks', diff --git a/src/java/org/apache/cassandra/config/CassandraRelevantProperties.java b/src/java/org/apache/cassandra/config/CassandraRelevantProperties.java index e409e975f638..8e5b0c6dd9dc 100644 --- a/src/java/org/apache/cassandra/config/CassandraRelevantProperties.java +++ b/src/java/org/apache/cassandra/config/CassandraRelevantProperties.java @@ -146,6 +146,8 @@ public enum CassandraRelevantProperties COM_SUN_MANAGEMENT_JMXREMOTE_PASSWORD_FILE("com.sun.management.jmxremote.password.file"), /** Port number to enable JMX RMI connections - com.sun.management.jmxremote.port */ COM_SUN_MANAGEMENT_JMXREMOTE_PORT("com.sun.management.jmxremote.port"), + /** Enables SSL sockets for the RMI registry from which clients obtain the JMX connector stub */ + COM_SUN_MANAGEMENT_JMXREMOTE_REGISTRY_SSL("com.sun.management.jmxremote.registry.ssl"), /** * The port number to which the RMI connector will be bound - com.sun.management.jmxremote.rmi.port. * An Integer object that represents the value of the second argument is returned @@ -287,6 +289,10 @@ public enum CassandraRelevantProperties IO_NETTY_EVENTLOOP_THREADS("io.netty.eventLoopThreads"), IO_NETTY_TRANSPORT_ESTIMATE_SIZE_ON_SUBMIT("io.netty.transport.estimateSizeOnSubmit"), IO_NETTY_TRANSPORT_NONATIVE("io.netty.transport.noNative"), + JAVAX_NET_SSL_KEYSTORE("javax.net.ssl.keyStore"), + JAVAX_NET_SSL_KEYSTOREPASSWORD("javax.net.ssl.keyStorePassword"), + JAVAX_NET_SSL_TRUSTSTORE("javax.net.ssl.trustStore"), + JAVAX_NET_SSL_TRUSTSTOREPASSWORD("javax.net.ssl.trustStorePassword"), JAVAX_RMI_SSL_CLIENT_ENABLED_CIPHER_SUITES("javax.rmi.ssl.client.enabledCipherSuites"), JAVAX_RMI_SSL_CLIENT_ENABLED_PROTOCOLS("javax.rmi.ssl.client.enabledProtocols"), /** Java class path. */ diff --git a/src/java/org/apache/cassandra/config/Config.java b/src/java/org/apache/cassandra/config/Config.java index 9335953d20ee..aaf6167ebb27 100644 --- a/src/java/org/apache/cassandra/config/Config.java +++ b/src/java/org/apache/cassandra/config/Config.java @@ -434,7 +434,8 @@ public static class SSTableConfig public EncryptionOptions.ServerEncryptionOptions server_encryption_options = new EncryptionOptions.ServerEncryptionOptions(); public EncryptionOptions client_encryption_options = new EncryptionOptions(); - public EncryptionOptions jmx_encryption_options = new EncryptionOptions(); + + public JMXServerOptions jmx_server_options; public InternodeCompression internode_compression = InternodeCompression.none; @@ -1322,7 +1323,8 @@ public enum BatchlogEndpointStrategy private static final Set SENSITIVE_KEYS = new HashSet() {{ add("client_encryption_options"); add("server_encryption_options"); - add("jmx_encryption_options"); + // jmx_server_options output (JMXServerOptions.toString()) doesn't + // include sensitive encryption config so no need to blocklist here }}; public static void log(Config config) diff --git a/src/java/org/apache/cassandra/config/DatabaseDescriptor.java b/src/java/org/apache/cassandra/config/DatabaseDescriptor.java index f80dcfd5b5fb..169fc1380f17 100644 --- a/src/java/org/apache/cassandra/config/DatabaseDescriptor.java +++ b/src/java/org/apache/cassandra/config/DatabaseDescriptor.java @@ -960,8 +960,19 @@ else if (conf.commitlog_segment_size.toKibibytes() < 2 * conf.max_mutation_size. if (conf.client_encryption_options != null) conf.client_encryption_options.applyConfig(); - if (conf.jmx_encryption_options != null) - conf.jmx_encryption_options.applyConfig(); + if (conf.jmx_server_options == null) + { + conf.jmx_server_options = JMXServerOptions.createParsingSystemProperties(); + } + else if (JMXServerOptions.isEnabledBySystemProperties()) + { + throw new ConfigurationException("Configure either jmx_server_options in cassandra.yaml and comment out " + + "configure_jmx function call in cassandra-env.sh or keep cassandra-env.sh " + + "to call configure_jmx function but you have to keep jmx_server_options " + + "in cassandra.yaml commented out."); + } + + conf.jmx_server_options.jmx_encryption_options.applyConfig(); if (conf.snapshot_links_per_second < 0) throw new ConfigurationException("snapshot_links_per_second must be >= 0"); @@ -1310,7 +1321,7 @@ public static void applySslContext() SSLFactory.validateSslContext("Internode messaging", conf.server_encryption_options, REQUIRED, true); SSLFactory.validateSslContext("Native transport", conf.client_encryption_options, conf.client_encryption_options.getClientAuth(), true); // For JMX SSL the validation is pretty much the same as the Native transport - SSLFactory.validateSslContext("JMX transport", conf.jmx_encryption_options, conf.jmx_encryption_options.getClientAuth(), true); + SSLFactory.validateSslContext("JMX transport", conf.jmx_server_options.jmx_encryption_options, conf.jmx_server_options.jmx_encryption_options.getClientAuth(), true); SSLFactory.initHotReloading(conf.server_encryption_options, conf.client_encryption_options, false); /* For JMX SSL, the hot reloading of the SSLContext is out of scope for CASSANDRA-18508. @@ -3663,9 +3674,9 @@ public static EncryptionOptions getNativeProtocolEncryptionOptions() return conf.client_encryption_options; } - public static EncryptionOptions getJmxEncryptionOptions() + public static JMXServerOptions getJmxServerOptions() { - return conf.jmx_encryption_options; + return conf.jmx_server_options; } @VisibleForTesting diff --git a/src/java/org/apache/cassandra/config/EncryptionOptions.java b/src/java/org/apache/cassandra/config/EncryptionOptions.java index eeac859f317c..8d922aa96e2f 100644 --- a/src/java/org/apache/cassandra/config/EncryptionOptions.java +++ b/src/java/org/apache/cassandra/config/EncryptionOptions.java @@ -470,7 +470,12 @@ public ClientAuth getClientAuth() public String[] acceptedProtocolsArray() { List ap = getAcceptedProtocols(); - return ap == null ? new String[0] : ap.toArray(new String[0]); + return ap == null ? null : ap.toArray(new String[0]); + } + + public List getCipherSuites() + { + return sslContextFactoryInstance == null ? null : sslContextFactoryInstance.getCipherSuites(); } public String[] cipherSuitesArray() diff --git a/src/java/org/apache/cassandra/config/JMXServerOptions.java b/src/java/org/apache/cassandra/config/JMXServerOptions.java new file mode 100644 index 000000000000..8b51d3b75688 --- /dev/null +++ b/src/java/org/apache/cassandra/config/JMXServerOptions.java @@ -0,0 +1,240 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.cassandra.config; + +import java.util.HashMap; +import java.util.List; + +import org.apache.commons.lang3.StringUtils; + +import static org.apache.cassandra.config.CassandraRelevantProperties.CASSANDRA_JMX_AUTHORIZER; +import static org.apache.cassandra.config.CassandraRelevantProperties.CASSANDRA_JMX_LOCAL_PORT; +import static org.apache.cassandra.config.CassandraRelevantProperties.CASSANDRA_JMX_REMOTE_LOGIN_CONFIG; +import static org.apache.cassandra.config.CassandraRelevantProperties.CASSANDRA_JMX_REMOTE_PORT; +import static org.apache.cassandra.config.CassandraRelevantProperties.COM_SUN_MANAGEMENT_JMXREMOTE_ACCESS_FILE; +import static org.apache.cassandra.config.CassandraRelevantProperties.COM_SUN_MANAGEMENT_JMXREMOTE_AUTHENTICATE; +import static org.apache.cassandra.config.CassandraRelevantProperties.COM_SUN_MANAGEMENT_JMXREMOTE_PASSWORD_FILE; +import static org.apache.cassandra.config.CassandraRelevantProperties.COM_SUN_MANAGEMENT_JMXREMOTE_RMI_PORT; +import static org.apache.cassandra.config.CassandraRelevantProperties.COM_SUN_MANAGEMENT_JMXREMOTE_SSL; +import static org.apache.cassandra.config.CassandraRelevantProperties.COM_SUN_MANAGEMENT_JMXREMOTE_SSL_ENABLED_CIPHER_SUITES; +import static org.apache.cassandra.config.CassandraRelevantProperties.COM_SUN_MANAGEMENT_JMXREMOTE_SSL_ENABLED_PROTOCOLS; +import static org.apache.cassandra.config.CassandraRelevantProperties.COM_SUN_MANAGEMENT_JMXREMOTE_SSL_NEED_CLIENT_AUTH; +import static org.apache.cassandra.config.CassandraRelevantProperties.JAVAX_NET_SSL_KEYSTORE; +import static org.apache.cassandra.config.CassandraRelevantProperties.JAVAX_NET_SSL_KEYSTOREPASSWORD; +import static org.apache.cassandra.config.CassandraRelevantProperties.JAVAX_NET_SSL_TRUSTSTORE; +import static org.apache.cassandra.config.CassandraRelevantProperties.JAVAX_NET_SSL_TRUSTSTOREPASSWORD; +import static org.apache.cassandra.config.CassandraRelevantProperties.JAVAX_RMI_SSL_CLIENT_ENABLED_CIPHER_SUITES; +import static org.apache.cassandra.config.CassandraRelevantProperties.JAVAX_RMI_SSL_CLIENT_ENABLED_PROTOCOLS; +import static org.apache.cassandra.config.CassandraRelevantProperties.JAVA_SECURITY_AUTH_LOGIN_CONFIG; + +public class JMXServerOptions +{ + //jmx server settings + public final Boolean enabled; + public final Boolean remote; + public final int jmx_port; + public final int rmi_port; + public final Boolean authenticate; + + // ssl options + public final EncryptionOptions jmx_encryption_options; + + // options for using Cassandra's own authentication mechanisms + public final String login_config_name; + public final String login_config_file; + + // location for credentials file if using JVM's file-based authentication + public final String password_file; + // location of standard access file, if using JVM's file-based access control + public final String access_file; + + // classname of authorizer if using a custom authz mechanism. Usually, this will + // refer to o.a.c.auth.jmx.AuthorizationProxy which delegates to the IAuthorizer + // configured in cassandra.yaml + public final String authorizer; + + public JMXServerOptions() + { + this(true, false, 7199, 0, false, + new EncryptionOptions(), null, null, null, + null, null); + } + + public static JMXServerOptions create(boolean enabled, boolean local, int jmxPort, EncryptionOptions options) + { + return new JMXServerOptions(enabled, !local, jmxPort, 0, false, + options, null, null, null, + null, null); + } + + public static JMXServerOptions fromDescriptor(boolean enabled, boolean local, int jmxPort) + { + JMXServerOptions from = DatabaseDescriptor.getJmxServerOptions(); + return new JMXServerOptions(enabled, !local, jmxPort, jmxPort, from.authenticate, + from.jmx_encryption_options, from.login_config_name, from.login_config_file, from.password_file, + from.access_file, from.authorizer); + } + + public JMXServerOptions(Boolean enabled, + Boolean remote, + int jmxPort, + int rmiPort, + Boolean authenticate, + EncryptionOptions jmx_encryption_options, + String loginConfigName, + String loginConfigFile, + String passwordFile, + String accessFile, + String authorizer) + { + this.enabled = enabled; + this.remote = remote; + this.jmx_port = jmxPort; + this.rmi_port = rmiPort; + this.authenticate = authenticate; + this.jmx_encryption_options = jmx_encryption_options; + this.login_config_name = loginConfigName; + this.login_config_file = loginConfigFile; + this.password_file = passwordFile; + this.access_file = accessFile; + this.authorizer = authorizer; + } + + @Override + public String toString() + { + // we are not including encryption options on purpose + // as that contains credentials etc. + String jmxOptionsString; + if (jmx_encryption_options == null) + jmxOptionsString = "unspecified"; + else + jmxOptionsString = jmx_encryption_options.enabled ? "enabled" : "disabled"; + + return "JMXServerOptions{" + + "enabled=" + enabled + + ", remote=" + remote + + ", jmx_port=" + jmx_port + + ", rmi_port=" + rmi_port + + ", authenticate=" + authenticate + + ", jmx_encryption_options=" + jmx_encryption_options + + ", login_config_name='" + login_config_name + '\'' + + ", login_config_file='" + login_config_file + '\'' + + ", password_file='" + password_file + '\'' + + ", access_file='" + access_file + '\'' + + ", authorizer='" + authorizer + '\'' + + '}'; + } + + public static boolean isEnabledBySystemProperties() + { + return CASSANDRA_JMX_REMOTE_PORT.isPresent() || CASSANDRA_JMX_LOCAL_PORT.isPresent(); + } + + public static JMXServerOptions createParsingSystemProperties() + { + int jmxPort; + boolean remote; + if (CASSANDRA_JMX_REMOTE_PORT.isPresent()) + { + jmxPort = CASSANDRA_JMX_REMOTE_PORT.getInt(); + remote = true; + } + else + { + jmxPort = CASSANDRA_JMX_LOCAL_PORT.getInt(7199); + remote = false; + } + + boolean enabled = isEnabledBySystemProperties(); + + int rmiPort = COM_SUN_MANAGEMENT_JMXREMOTE_RMI_PORT.getInt(); + + boolean authenticate = COM_SUN_MANAGEMENT_JMXREMOTE_AUTHENTICATE.getBoolean(); + + String loginConfigName = CASSANDRA_JMX_REMOTE_LOGIN_CONFIG.getString(); + String loginConfigFile = JAVA_SECURITY_AUTH_LOGIN_CONFIG.getString(); + String accessFile = COM_SUN_MANAGEMENT_JMXREMOTE_ACCESS_FILE.getString(); + String passwordFile = COM_SUN_MANAGEMENT_JMXREMOTE_PASSWORD_FILE.getString(); + String authorizer = CASSANDRA_JMX_AUTHORIZER.getString(); + + // encryption options + + String keystore = JAVAX_NET_SSL_KEYSTORE.getString(); + String keystorePassword = JAVAX_NET_SSL_KEYSTOREPASSWORD.getString(); + String truststore = JAVAX_NET_SSL_TRUSTSTORE.getString(); + String truststorePassword = JAVAX_NET_SSL_TRUSTSTOREPASSWORD.getString(); + + String rawCipherSuites = COM_SUN_MANAGEMENT_JMXREMOTE_SSL_ENABLED_CIPHER_SUITES.getString(); + List cipherSuites = null; + if (rawCipherSuites != null) + cipherSuites = List.of(StringUtils.split(rawCipherSuites, ",")); + + String rawSslProtocols = COM_SUN_MANAGEMENT_JMXREMOTE_SSL_ENABLED_PROTOCOLS.getString(); + List acceptedProtocols = null; + if (rawSslProtocols != null) + acceptedProtocols = List.of(StringUtils.split(rawSslProtocols, ",")); + + String requireClientAuth = COM_SUN_MANAGEMENT_JMXREMOTE_SSL_NEED_CLIENT_AUTH.getString("false"); + + boolean sslEnabled = COM_SUN_MANAGEMENT_JMXREMOTE_SSL.getBoolean(); + + EncryptionOptions encryptionOptions = new EncryptionOptions(new ParameterizedClass("org.apache.cassandra.security.DefaultSslContextFactory", new HashMap<>()), + keystore, + keystorePassword, + truststore, + truststorePassword, + cipherSuites, + null, // protocol + acceptedProtocols, + null, // algorithm + null, // store_type + requireClientAuth, + false, // require endpoint verification + sslEnabled, + false, // optional + null, // max_certificate_validity_period + null); // certificate_validity_warn_threshold + + return new JMXServerOptions(enabled, remote, jmxPort, rmiPort, authenticate, + encryptionOptions, loginConfigName, loginConfigFile, passwordFile, accessFile, + authorizer); + } + + + /** + * Sets the following JMX system properties. + *
+     *     com.sun.management.jmxremote.ssl=true
+     *     javax.rmi.ssl.client.enabledCipherSuites=<applicable cipher suites provided in the configuration>
+     *     javax.rmi.ssl.client.enabledProtocols=<applicable protocols provided in the configuration>
+     * 
+ * + * @param acceptedProtocols for the SSL communication + * @param cipherSuites for the SSL communication + */ + public static void setJmxSystemProperties(List acceptedProtocols, List cipherSuites) + { + COM_SUN_MANAGEMENT_JMXREMOTE_SSL.setBoolean(true); + if (acceptedProtocols != null) + JAVAX_RMI_SSL_CLIENT_ENABLED_PROTOCOLS.setString(StringUtils.join(acceptedProtocols, ",")); + + if (cipherSuites != null) + JAVAX_RMI_SSL_CLIENT_ENABLED_CIPHER_SUITES.setString(StringUtils.join(cipherSuites, ",")); + } +} diff --git a/src/java/org/apache/cassandra/service/CassandraDaemon.java b/src/java/org/apache/cassandra/service/CassandraDaemon.java index ef6c689edf47..360c26bdcc33 100644 --- a/src/java/org/apache/cassandra/service/CassandraDaemon.java +++ b/src/java/org/apache/cassandra/service/CassandraDaemon.java @@ -48,6 +48,7 @@ import org.apache.cassandra.concurrent.ScheduledExecutors; import org.apache.cassandra.config.CassandraRelevantProperties; import org.apache.cassandra.config.DatabaseDescriptor; +import org.apache.cassandra.config.JMXServerOptions; import org.apache.cassandra.cql3.QueryProcessor; import org.apache.cassandra.db.ColumnFamilyStore; import org.apache.cassandra.db.Keyspace; @@ -91,8 +92,6 @@ import static java.util.concurrent.TimeUnit.NANOSECONDS; import static org.apache.cassandra.config.CassandraRelevantProperties.CASSANDRA_FOREGROUND; -import static org.apache.cassandra.config.CassandraRelevantProperties.CASSANDRA_JMX_LOCAL_PORT; -import static org.apache.cassandra.config.CassandraRelevantProperties.CASSANDRA_JMX_REMOTE_PORT; import static org.apache.cassandra.config.CassandraRelevantProperties.CASSANDRA_PID_FILE; import static org.apache.cassandra.config.CassandraRelevantProperties.COM_SUN_MANAGEMENT_JMXREMOTE_PORT; import static org.apache.cassandra.config.CassandraRelevantProperties.JAVA_CLASS_PATH; @@ -153,42 +152,24 @@ private void maybeInitJmx() // then the JVM agent will have already started up a default JMX connector // server. This behaviour is deprecated, but some clients may be relying // on it, so log a warning and skip setting up the server with the settings - // as configured in cassandra-env.(sh|ps1) + // as configured in cassandra.yaml or cassandra-env.sh. // See: CASSANDRA-11540 & CASSANDRA-11725 if (COM_SUN_MANAGEMENT_JMXREMOTE_PORT.isPresent()) { - logger.warn("JMX settings in cassandra-env.sh have been bypassed as the JMX connector server is " + - "already initialized. Please refer to cassandra-env.(sh|ps1) for JMX configuration info"); + logger.warn("JMX settings in cassandra.yaml or cassandra-env.sh have been bypassed as the JMX connector server is " + + "already initialized. Please refer to cassandra.yaml or cassandra-env.sh for JMX configuration info"); return; } JAVA_RMI_SERVER_RANDOM_ID.setBoolean(true); - // If a remote port has been specified then use that to set up a JMX - // connector server which can be accessed remotely. Otherwise, look - // for the local port property and create a server which is bound - // only to the loopback address. Auth options are applied to both - // remote and local-only servers, but currently SSL is only - // available for remote. - // If neither is remote nor local port is set in cassandra-env.(sh|ps) - // then JMX is effectively disabled. - boolean localOnly = false; - String jmxPort = CASSANDRA_JMX_REMOTE_PORT.getString(); - - if (jmxPort == null) - { - localOnly = true; - jmxPort = CASSANDRA_JMX_LOCAL_PORT.getString(); - } - - if (jmxPort == null) + JMXServerOptions jmxServerOptions = DatabaseDescriptor.getJmxServerOptions(); + if (!jmxServerOptions.enabled) return; try { - jmxServer = JMXServerUtils.createJMXServer(Integer.parseInt(jmxPort), localOnly); - if (jmxServer == null) - return; + jmxServer = JMXServerUtils.createJMXServer(jmxServerOptions); } catch (IOException e) { diff --git a/src/java/org/apache/cassandra/service/StartupChecks.java b/src/java/org/apache/cassandra/service/StartupChecks.java index 91a95a4e1069..a16864cc2ae9 100644 --- a/src/java/org/apache/cassandra/service/StartupChecks.java +++ b/src/java/org/apache/cassandra/service/StartupChecks.java @@ -54,6 +54,7 @@ import org.apache.cassandra.config.CassandraRelevantProperties; import org.apache.cassandra.config.Config; import org.apache.cassandra.config.DatabaseDescriptor; +import org.apache.cassandra.config.JMXServerOptions; import org.apache.cassandra.config.StartupChecksOptions; import org.apache.cassandra.cql3.QueryProcessor; import org.apache.cassandra.cql3.UntypedResultSet; @@ -74,7 +75,6 @@ import org.apache.cassandra.utils.JavaUtils; import org.apache.cassandra.utils.NativeLibrary; -import static org.apache.cassandra.config.CassandraRelevantProperties.CASSANDRA_JMX_LOCAL_PORT; import static org.apache.cassandra.config.CassandraRelevantProperties.COM_SUN_MANAGEMENT_JMXREMOTE_PORT; import static org.apache.cassandra.config.CassandraRelevantProperties.IGNORE_KERNEL_BUG_1057843_CHECK; import static org.apache.cassandra.config.CassandraRelevantProperties.JAVA_VERSION; @@ -312,17 +312,21 @@ public void execute(StartupChecksOptions options) { if (options.isDisabled(getStartupCheckType())) return; - String jmxPort = CassandraRelevantProperties.CASSANDRA_JMX_REMOTE_PORT.getString(); - if (jmxPort == null) + + JMXServerOptions jmxServerOptions = DatabaseDescriptor.getJmxServerOptions(); + if (!jmxServerOptions.enabled) + { + logger.warn("JMX connection server is not enabled for either local or remote connections. " + + "Please see jmx_server_options in cassandra.yaml for more info"); + } + if (!jmxServerOptions.remote) { - logger.warn("JMX is not enabled to receive remote connections. Please see cassandra-env.sh for more info."); - jmxPort = CassandraRelevantProperties.CASSANDRA_JMX_LOCAL_PORT.toString(); - if (jmxPort == null) - logger.error(CASSANDRA_JMX_LOCAL_PORT.getKey() + " missing from cassandra-env.sh, unable to start local JMX service."); + logger.warn("JMX is not enabled to receive remote connections. " + + "Please see jmx_server_options in cassandra.yaml for more info."); } else { - logger.info("JMX is enabled to receive remote connections on port: {}", jmxPort); + logger.info("JMX is enabled to receive remote connections on port: {}", jmxServerOptions.jmx_port); } } }; diff --git a/src/java/org/apache/cassandra/utils/JMXServerUtils.java b/src/java/org/apache/cassandra/utils/JMXServerUtils.java index 43221f28bfb9..be8f943d2b45 100644 --- a/src/java/org/apache/cassandra/utils/JMXServerUtils.java +++ b/src/java/org/apache/cassandra/utils/JMXServerUtils.java @@ -33,7 +33,6 @@ import java.rmi.NotBoundException; import java.rmi.Remote; import java.rmi.RemoteException; -import java.rmi.registry.Registry; import java.rmi.server.RMIClientSocketFactory; import java.rmi.server.RMIServerSocketFactory; import java.rmi.server.UnicastRemoteObject; @@ -49,20 +48,17 @@ import javax.security.auth.Subject; import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Strings; import com.google.common.collect.ImmutableMap; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.apache.cassandra.auth.jmx.AuthenticationProxy; -import org.apache.cassandra.config.DatabaseDescriptor; +import org.apache.cassandra.config.CassandraRelevantProperties; +import org.apache.cassandra.config.JMXServerOptions; +import org.apache.cassandra.exceptions.ConfigurationException; import org.apache.cassandra.utils.jmx.DefaultJmxSocketFactory; -import static org.apache.cassandra.config.CassandraRelevantProperties.CASSANDRA_JMX_AUTHORIZER; -import static org.apache.cassandra.config.CassandraRelevantProperties.CASSANDRA_JMX_REMOTE_LOGIN_CONFIG; -import static org.apache.cassandra.config.CassandraRelevantProperties.COM_SUN_MANAGEMENT_JMXREMOTE_ACCESS_FILE; -import static org.apache.cassandra.config.CassandraRelevantProperties.COM_SUN_MANAGEMENT_JMXREMOTE_AUTHENTICATE; -import static org.apache.cassandra.config.CassandraRelevantProperties.COM_SUN_MANAGEMENT_JMXREMOTE_PASSWORD_FILE; -import static org.apache.cassandra.config.CassandraRelevantProperties.COM_SUN_MANAGEMENT_JMXREMOTE_RMI_PORT; import static org.apache.cassandra.config.CassandraRelevantProperties.JAVA_RMI_SERVER_HOSTNAME; public class JMXServerUtils @@ -74,13 +70,12 @@ public class JMXServerUtils * inaccessable. */ @VisibleForTesting - public static JMXConnectorServer createJMXServer(int port, String hostname, boolean local) - throws IOException + public static JMXConnectorServer createJMXServer(JMXServerOptions options, String hostname) throws IOException { Map env = new HashMap<>(); InetAddress serverAddress = null; - if (local) + if (!options.remote) { serverAddress = InetAddress.getLoopbackAddress(); JAVA_RMI_SERVER_HOSTNAME.setString(serverAddress.getHostAddress()); @@ -88,18 +83,18 @@ public static JMXConnectorServer createJMXServer(int port, String hostname, bool // Configure the RMI client & server socket factories, including SSL config. // CASSANDRA-18508: Make JMX SSL to be configured in cassandra.yaml - env.putAll(configureJmxSocketFactories(serverAddress, local)); + env.putAll(configureJmxSocketFactories(serverAddress, options)); // configure the RMI registry - Registry registry = new JmxRegistry(port, - (RMIClientSocketFactory) env.get(RMIConnectorServer.RMI_CLIENT_SOCKET_FACTORY_ATTRIBUTE), - (RMIServerSocketFactory) env.get(RMIConnectorServer.RMI_SERVER_SOCKET_FACTORY_ATTRIBUTE), - "jmxrmi"); + JmxRegistry registry = new JmxRegistry(options.jmx_port, + (RMIClientSocketFactory) env.get(RMIConnectorServer.RMI_CLIENT_SOCKET_FACTORY_ATTRIBUTE), + (RMIServerSocketFactory) env.get(RMIConnectorServer.RMI_SERVER_SOCKET_FACTORY_ATTRIBUTE), + "jmxrmi"); // Configure authn, using a JMXAuthenticator which either wraps a set log LoginModules configured // via a JAAS configuration entry, or one which delegates to the standard file based authenticator. // Authn is disabled if com.sun.management.jmxremote.authenticate=false - env.putAll(configureJmxAuthentication()); + env.putAll(configureJmxAuthentication(options)); // Secure credential passing to avoid deserialization attacks env.putAll(configureSecureCredentials()); @@ -107,7 +102,7 @@ public static JMXConnectorServer createJMXServer(int port, String hostname, bool // If not, but a location for the standard access file is set in system properties, the // return value is null, and an entry is added to the env map detailing that location // If neither method is specified, no access control is applied - MBeanServerForwarder authzProxy = configureJmxAuthorization(env); + MBeanServerForwarder authzProxy = configureJmxAuthorization(options, env); // Mark the JMX server as a permanently exported object. This allows the JVM to exit with the // server running and also exempts it from the distributed GC scheduler which otherwise would @@ -121,7 +116,7 @@ public static JMXConnectorServer createJMXServer(int port, String hostname, bool // Set the port used to create subsequent connections to exported objects over RMI. This simplifies // configuration in firewalled environments, but it can't be used in conjuction with SSL sockets. // See: CASSANDRA-7087 - int rmiPort = COM_SUN_MANAGEMENT_JMXREMOTE_RMI_PORT.getInt(); + int rmiPort = options.rmi_port; // We create the underlying RMIJRMPServerImpl so that we can manually bind it to the registry, // rather then specifying a binding address in the JMXServiceURL and letting it be done automatically @@ -142,14 +137,14 @@ public static JMXConnectorServer createJMXServer(int port, String hostname, bool jmxServer.setMBeanServerForwarder(authzProxy); jmxServer.start(); - ((JmxRegistry)registry).setRemoteServerStub(server.toStub()); - logJmxServiceUrl(serverAddress, port); + registry.setRemoteServerStub(server.toStub()); + logJmxServiceUrl(serverAddress, options.jmx_port); return jmxServer; } - public static JMXConnectorServer createJMXServer(int port, boolean local) throws IOException + public static JMXConnectorServer createJMXServer(JMXServerOptions serverOptions) throws IOException { - return createJMXServer(port, null, local); + return createJMXServer(serverOptions, null); } private static Map configureSecureCredentials() @@ -159,10 +154,10 @@ private static Map configureSecureCredentials() return env; } - private static Map configureJmxAuthentication() + private static Map configureJmxAuthentication(JMXServerOptions options) { Map env = new HashMap<>(); - if (!COM_SUN_MANAGEMENT_JMXREMOTE_AUTHENTICATE.getBoolean()) + if (!options.authenticate) return env; // If authentication is enabled, initialize the appropriate JMXAuthenticator @@ -176,14 +171,30 @@ private static Map configureJmxAuthentication() // before creating the authenticator. If no password file has been // explicitly set, it's read from the default location // $JAVA_HOME/lib/management/jmxremote.password - String configEntry = CASSANDRA_JMX_REMOTE_LOGIN_CONFIG.getString(); + String configEntry = options.login_config_name; if (configEntry != null) { + if (Strings.isNullOrEmpty(CassandraRelevantProperties.JAVA_SECURITY_AUTH_LOGIN_CONFIG.getString())) + { + if (Strings.isNullOrEmpty(options.login_config_file)) + { + throw new ConfigurationException(String.format("Login config name %s specified for JMX auth, but no " + + "configuration is available. Please set config " + + "location in cassandra.yaml or with the " + + "'%s' system property", + configEntry, + CassandraRelevantProperties.JAVA_SECURITY_AUTH_LOGIN_CONFIG.getKey())); + } + else + { + CassandraRelevantProperties.JAVA_SECURITY_AUTH_LOGIN_CONFIG.setString(options.login_config_file); + } + } env.put(JMXConnectorServer.AUTHENTICATOR, new AuthenticationProxy(configEntry)); } else { - String passwordFile = COM_SUN_MANAGEMENT_JMXREMOTE_PASSWORD_FILE.getString(); + String passwordFile = options.password_file; if (passwordFile != null) { // stash the password file location where JMXPluggableAuthenticator expects it @@ -195,14 +206,14 @@ private static Map configureJmxAuthentication() return env; } - private static MBeanServerForwarder configureJmxAuthorization(Map env) + private static MBeanServerForwarder configureJmxAuthorization(JMXServerOptions options, Map env) { // If a custom authz proxy is supplied (Cassandra ships with AuthorizationProxy, which // delegates to its own role based IAuthorizer), then instantiate and return one which // can be set as the JMXConnectorServer's MBeanServerForwarder. // If no custom proxy is supplied, check system properties for the location of the // standard access file & stash it in env - String authzProxyClass = CASSANDRA_JMX_AUTHORIZER.getString(); + String authzProxyClass = options.authorizer; if (authzProxyClass != null) { final InvocationHandler handler = FBUtilities.construct(authzProxyClass, "JMX authz proxy"); @@ -213,7 +224,7 @@ private static MBeanServerForwarder configureJmxAuthorization(Map configureJmxSocketFactories(InetAddress serverAddress, boolean localOnly) throws SSLException + public static Map configureJmxSocketFactories(InetAddress serverAddress, JMXServerOptions serverOptions) throws SSLException { - return new DefaultJmxSocketFactory().configure(serverAddress, localOnly, DatabaseDescriptor.getJmxEncryptionOptions()); + return new DefaultJmxSocketFactory().configure(serverAddress, serverOptions, serverOptions.jmx_encryption_options); } @VisibleForTesting diff --git a/src/java/org/apache/cassandra/utils/jmx/AbstractJmxSocketFactory.java b/src/java/org/apache/cassandra/utils/jmx/AbstractJmxSocketFactory.java index 6ee390ee93a7..3990c64ee7d4 100644 --- a/src/java/org/apache/cassandra/utils/jmx/AbstractJmxSocketFactory.java +++ b/src/java/org/apache/cassandra/utils/jmx/AbstractJmxSocketFactory.java @@ -24,19 +24,11 @@ import javax.net.ssl.SSLContext; import javax.net.ssl.SSLException; -import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.apache.cassandra.config.EncryptionOptions; -import org.apache.cassandra.exceptions.ConfigurationException; - -import static org.apache.cassandra.config.CassandraRelevantProperties.COM_SUN_MANAGEMENT_JMXREMOTE_SSL; -import static org.apache.cassandra.config.CassandraRelevantProperties.COM_SUN_MANAGEMENT_JMXREMOTE_SSL_ENABLED_CIPHER_SUITES; -import static org.apache.cassandra.config.CassandraRelevantProperties.COM_SUN_MANAGEMENT_JMXREMOTE_SSL_ENABLED_PROTOCOLS; -import static org.apache.cassandra.config.CassandraRelevantProperties.COM_SUN_MANAGEMENT_JMXREMOTE_SSL_NEED_CLIENT_AUTH; -import static org.apache.cassandra.config.CassandraRelevantProperties.JAVAX_RMI_SSL_CLIENT_ENABLED_CIPHER_SUITES; -import static org.apache.cassandra.config.CassandraRelevantProperties.JAVAX_RMI_SSL_CLIENT_ENABLED_PROTOCOLS; +import org.apache.cassandra.config.JMXServerOptions; /** * Abstracts out the most common workflow in setting up the SSL client and server socket factorires for JMX. @@ -66,8 +58,7 @@ abstract public class AbstractJmxSocketFactory * * * @param serverAddress the JMX server is bound to - * @param localOnly {@code true} if the JMX server only allows local connections; {@code false} if the JMX server - * allows the remote connections. + * @param serverOptions JMX server options * @param jmxEncryptionOptions {@link EncryptionOptions} used for the SSL configuration in case of the remote * connections. Could be {@code null} if system properties are * used instead as per Java Documentation @@ -75,67 +66,30 @@ abstract public class AbstractJmxSocketFactory * and {@code com.sun.jndi.rmi.factory.socket} properties for the client and server socket factories. * @throws SSLException if it fails to configure the socket factories with the given input */ - public Map configure(InetAddress serverAddress, boolean localOnly, + public Map configure(InetAddress serverAddress, + JMXServerOptions serverOptions, EncryptionOptions jmxEncryptionOptions) throws SSLException { Map env = new HashMap<>(); - boolean jmxRemoteSslSystemConfigProvided = COM_SUN_MANAGEMENT_JMXREMOTE_SSL.getBoolean(); + // We check for the enabled jmx_encryption_options here because in case of no configuration provided in cassandra.yaml // it will default to empty/non-null encryption options. Hence, we consider it set only if 'enabled' flag is set to true - boolean jmxEncryptionOptionsProvided = jmxEncryptionOptions != null - && jmxEncryptionOptions.getEnabled() != null - && jmxEncryptionOptions.getEnabled(); + boolean jmxEncryptionOptionsProvided = jmxEncryptionOptions != null && jmxEncryptionOptions.getEnabled() != null && jmxEncryptionOptions.getEnabled(); - if (jmxRemoteSslSystemConfigProvided && jmxEncryptionOptionsProvided) + if (jmxEncryptionOptionsProvided) { - throw new ConfigurationException("Please specify JMX SSL configuration in either cassandra-env.sh or " + - "cassandra.yaml, not in both locations"); - } - - boolean requireClientAuth = false; - String[] ciphers = null; - String[] protocols = null; - SSLContext sslContext = null; - - if (jmxRemoteSslSystemConfigProvided) - { - logger.info("Enabling JMX SSL using environment file properties"); - logger.warn("Consider using the jmx_encryption_options section of cassandra.yaml instead to prevent " + - "sensitive information being exposed"); - requireClientAuth = COM_SUN_MANAGEMENT_JMXREMOTE_SSL_NEED_CLIENT_AUTH.getBoolean(); - String protocolList = COM_SUN_MANAGEMENT_JMXREMOTE_SSL_ENABLED_PROTOCOLS.getString(); - if (protocolList != null) - { - JAVAX_RMI_SSL_CLIENT_ENABLED_PROTOCOLS.setString(protocolList); - protocols = StringUtils.split(protocolList, ','); - } - - String cipherList = COM_SUN_MANAGEMENT_JMXREMOTE_SSL_ENABLED_CIPHER_SUITES.getString(); - if (cipherList != null) - { - JAVAX_RMI_SSL_CLIENT_ENABLED_CIPHER_SUITES.setString(cipherList); - ciphers = StringUtils.split(cipherList, ','); - } - configureSslClientSocketFactory(env, serverAddress); - configureSslServerSocketFactory(env, serverAddress, ciphers, protocols, requireClientAuth); - } - else if (jmxEncryptionOptionsProvided) - { - logger.info("Enabling JMX SSL using jmx_encryption_options from cassandra.yaml"); - // Here we can continue to use the SslRMIClientSocketFactory for client sockets. - // However, we should still set System properties for cipher_suites and enabled_protocols - // to have the same behavior as cassandra-env.sh based JMX SSL settings - setJmxSystemProperties(jmxEncryptionOptions); - - requireClientAuth = jmxEncryptionOptions.getClientAuth() == EncryptionOptions.ClientAuth.REQUIRED; - ciphers = jmxEncryptionOptions.cipherSuitesArray(); - protocols = jmxEncryptionOptions.acceptedProtocolsArray(); - sslContext = jmxEncryptionOptions.sslContextFactoryInstance - .createJSSESslContext(jmxEncryptionOptions.getClientAuth()); + if (jmxEncryptionOptions.getEnabled()) + JMXServerOptions.setJmxSystemProperties(jmxEncryptionOptions.getAcceptedProtocols(), jmxEncryptionOptions.getCipherSuites()); + + logger.info("Enabling JMX SSL using jmx_encryption_options"); + boolean requireClientAuth = jmxEncryptionOptions.getClientAuth() == EncryptionOptions.ClientAuth.REQUIRED; + String[] ciphers = jmxEncryptionOptions.cipherSuitesArray(); + String[] protocols = jmxEncryptionOptions.acceptedProtocolsArray(); + SSLContext sslContext = jmxEncryptionOptions.sslContextFactoryInstance.createJSSESslContext(jmxEncryptionOptions.getClientAuth()); configureSslClientSocketFactory(env, serverAddress); configureSslServerSocketFactory(env, serverAddress, ciphers, protocols, requireClientAuth, sslContext); } - else if (localOnly) + else if (!serverOptions.remote) { configureLocalSocketFactories(env, serverAddress); } @@ -159,19 +113,6 @@ else if (localOnly) */ abstract public void configureSslClientSocketFactory(Map env, InetAddress serverAddress); - /** - * Configures SSL based server socket factory based on system config for key/trust stores. - * - * @param env output param containing the configured socket factories - * @param serverAddress the JMX server is bound to - * @param enabledCipherSuites for the SSL communication - * @param enabledProtocols for the SSL communication - * @param needClientAuth {@code true} if it requires the client-auth; {@code false} otherwise - */ - abstract public void configureSslServerSocketFactory(Map env, InetAddress serverAddress, - String[] enabledCipherSuites, String[] enabledProtocols, - boolean needClientAuth); - /** * Configures SSL based server socket factory based on custom SSLContext. * @@ -185,24 +126,4 @@ abstract public void configureSslServerSocketFactory(Map env, In abstract public void configureSslServerSocketFactory(Map env, InetAddress serverAddress, String[] enabledCipherSuites, String[] enabledProtocols, boolean needClientAuth, SSLContext sslContext); - - /** - * Sets the following JMX system properties. - *
-     *     com.sun.management.jmxremote.ssl=true
-     *     javax.rmi.ssl.client.enabledCipherSuites=<applicable cipher suites provided in the configuration>
-     *     javax.rmi.ssl.client.enabledProtocols=<applicable protocols provided in the configuration>
-     * 
- * - * @param jmxEncryptionOptions for the SSL communication - */ - private void setJmxSystemProperties(EncryptionOptions jmxEncryptionOptions) - { - COM_SUN_MANAGEMENT_JMXREMOTE_SSL.setBoolean(true); - if (jmxEncryptionOptions.getAcceptedProtocols() != null) - JAVAX_RMI_SSL_CLIENT_ENABLED_PROTOCOLS.setString(StringUtils.join(jmxEncryptionOptions.getAcceptedProtocols(), ",")); - - if (jmxEncryptionOptions.cipherSuitesArray() != null) - JAVAX_RMI_SSL_CLIENT_ENABLED_CIPHER_SUITES.setString(StringUtils.join(jmxEncryptionOptions.cipherSuitesArray(), ",")); - } } diff --git a/src/java/org/apache/cassandra/utils/jmx/DefaultJmxSocketFactory.java b/src/java/org/apache/cassandra/utils/jmx/DefaultJmxSocketFactory.java index 35cc92b731e3..45d4df72ddab 100644 --- a/src/java/org/apache/cassandra/utils/jmx/DefaultJmxSocketFactory.java +++ b/src/java/org/apache/cassandra/utils/jmx/DefaultJmxSocketFactory.java @@ -53,15 +53,6 @@ public void configureSslClientSocketFactory(Map env, InetAddress env.put("com.sun.jndi.rmi.factory.socket", clientFactory); } - @Override - public void configureSslServerSocketFactory(Map env, InetAddress serverAddress, String[] enabledCipherSuites, - String[] enabledProtocols, boolean needClientAuth) - { - SslRMIServerSocketFactory serverFactory = new SslRMIServerSocketFactory(enabledCipherSuites, enabledProtocols, needClientAuth); - env.put(RMIConnectorServer.RMI_SERVER_SOCKET_FACTORY_ATTRIBUTE, serverFactory); - logJmxSslConfig(serverFactory); - } - @Override public void configureSslServerSocketFactory(Map env, InetAddress serverAddress, String[] enabledCipherSuites, String[] enabledProtocols, boolean needClientAuth, SSLContext sslContext) diff --git a/test/conf/cassandra-jmx-disabled-sslconfig.yaml b/test/conf/cassandra-jmx-disabled-sslconfig.yaml index 2b6338992668..12baefb75f88 100644 --- a/test/conf/cassandra-jmx-disabled-sslconfig.yaml +++ b/test/conf/cassandra-jmx-disabled-sslconfig.yaml @@ -48,89 +48,91 @@ seed_provider: - seeds: "127.0.0.1:7012" endpoint_snitch: org.apache.cassandra.locator.SimpleSnitch dynamic_snitch: true -jmx_encryption_options: - enabled: false - cipher_suites: [TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256] - accepted_protocols: [TLSv1.2,TLSv1.3,TLSv1.1] - ssl_context_factory: - class_name: org.apache.cassandra.security.PEMBasedSslContextFactory - parameters: - private_key: | - -----BEGIN ENCRYPTED PRIVATE KEY----- - MIIE6jAcBgoqhkiG9w0BDAEDMA4ECOWqSzq5PBIdAgIFxQSCBMjXsCK30J0aT3J/ - g5kcbmevTOY1pIhJGbf5QYYrMUPiuDK2ydxIbiPzoTE4/S+OkCeHhlqwn/YydpBl - xgjZZ1Z5rLJHO27d2biuESqanDiBVXYuVmHmaifRnFy0uUTFkStB5mjVZEiJgO29 - L83hL60uWru71EVuVriC2WCfmZ/EXp6wyYszOqCFQ8Quk/rDO6XuaBl467MJbx5V - sucGT6E9XKNd9hB14/Izb2jtVM5kqKxoiHpz1na6yhEYJiE5D1uOonznWjBnjwB/ - f0x+acpDfVDoJKTlRdz+DEcbOF7mb9lBVVjP6P/AAsmQzz6JKwHjvCrjYfQmyyN8 - RI4KRQnWgm4L3dtByLqY8HFU4ogisCMCgI+hZQ+OKMz/hoRO540YGiPcTRY3EOUR - 0bd5JxU6tCJDMTqKP9aSL2KmLoiLowdMkSPz7TCzLsZ2bGJemuCfpAs4XT1vXCHs - evrUbOnh8et1IA8mZ9auThfqsZtNagJLEXA6hWIKp1FfVL3Q49wvMKZt4eTn/zwU - tLL0m5yPo6/HAaOA3hbm/oghZS0dseshXl7PZrmZQtvYnIvjyoxEL7ducYDQCDP6 - wZ7Nzyh1QZAauSS15hl3vLFRZCA9hWAVgwQAviTvhB342O0i9qI7TQkcHk+qcTPN - K+iGNbFZ8ma1izXNKSJ2PgI/QqFNIeJWvZrb9PhJRmaZVsTJ9fERm1ewpebZqkVv - zMqMhlKgx9ggAaSKgnGZkwXwB6GrSbbzUrwRCKm3FieD1QE4VVYevaadVUU75GG5 - mrFKorJEH7kFZlic8OTjDksYnHbcgU36XZrGEXa2+ldVeGKL3CsXWciaQRcJg8yo - WQDjZpcutGI0eMJWCqUkv8pYZC2/wZU4htCve5nVJUU4t9uuo9ex7lnwlLWPvheQ - jUBMgzSRsZ+zwaIusvufAAxiKK/cJm4ubZSZPIjBbfd4U7VPxtirP4Accydu7EK6 - eG/MZwtAMFNJxfxUR+/aYzJU/q1ePw7fWVHrpt58t/22CX2SJBEiUGmSmuyER4Ny - DPw6d6mhvPUS1jRhIZ9A81ht8MOX7VL5uVp307rt7o5vRpV1mo0iPiRHzGscMpJn - AP36klEAUNTf0uLTKZa7KHiwhn5iPmsCrENHkOKJjxhRrqHjD2wy3YHs3ow2voyY - Ua4Cids+c1hvRkNEDGNHm4+rKGFOGOsG/ZU7uj/6gflO4JXxNGiyTLflqMdWBvow - Zd7hk1zCaGAAn8nZ0hPweGxQ4Q30I9IBZrimGxB0vjiUqNio9+qMf33dCHFJEuut - ZGJMaUGVaPhXQcTy4uD5hzsPZV5xcsU4H3vBYyBcZgrusJ6OOgkuZQaU7p8rWQWr - bUEVbXuZdwEmxsCe7H/vEVv5+aA4sF4kWnMMFL7/LIYaiEzkTqdJlRv/KyJJgcAH - hg2BvR3XTAq8wiX0C98CdmTbsx2eyQdj5tCU606rEohFLKUxWkJYAKxCiUbxGGpI - RheVmxkef9ErxJiq7hsAsGrSJvMtJuDKIasnD14SOEwD/7jRAq6WdL9VLpxtzlOw - pWnIl8kUCO3WoaG9Jf+ZTIv2hnxJhaSzYrdXzGPNnaWKhBlwnXJRvQEdrIxZOimP - FujZhqbKUDbYAcqTkoQ= - -----END ENCRYPTED PRIVATE KEY----- - -----BEGIN CERTIFICATE----- - MIIDkTCCAnmgAwIBAgIETxH5JDANBgkqhkiG9w0BAQsFADB5MRAwDgYDVQQGEwdV - bmtub3duMRAwDgYDVQQIEwdVbmtub3duMRAwDgYDVQQHEwdVbmtub3duMRAwDgYD - VQQKEwdVbmtub3duMRQwEgYDVQQLDAtzc2xfdGVzdGluZzEZMBcGA1UEAxMQQXBh - Y2hlIENhc3NhbmRyYTAeFw0xNjAzMTgyMTI4MDJaFw0xNjA2MTYyMTI4MDJaMHkx - EDAOBgNVBAYTB1Vua25vd24xEDAOBgNVBAgTB1Vua25vd24xEDAOBgNVBAcTB1Vu - a25vd24xEDAOBgNVBAoTB1Vua25vd24xFDASBgNVBAsMC3NzbF90ZXN0aW5nMRkw - FwYDVQQDExBBcGFjaGUgQ2Fzc2FuZHJhMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A - MIIBCgKCAQEAjkmVX/HS49cS8Hn6o26IGwMIcEV3d7ZhH0GNcx8rnSRd10dU9F6d - ugSjbwGFMcWUQzYNejN6az0Wb8JIQyXRPTWjfgaWTyVGr0bGTnxg6vwhzfI/9jzy - q59xv29OuSY1dxmY31f0pZ9OOw3mabWksjoO2TexfKoxqsRHJ8PrM1f8E84Z4xo2 - TJXGzpuIxRkAJ+sVDqKEAhrKAfRYMSgdJ7zRt8VXv9ngjX20uA2m092NcH0Kmeto - TmuWUtK8E/qcN7ULN8xRWNUn4hu6mG6mayk4XliGRqI1VZupqh+MgNqHznuTd0bA - YrQsFPw9HaZ2hvVnJffJ5l7njAekZNOL+wIDAQABoyEwHzAdBgNVHQ4EFgQUcdiD - N6aylI91kAd34Hl2AzWY51QwDQYJKoZIhvcNAQELBQADggEBAG9q29ilUgCWQP5v - iHkZHj10gXGEoMkdfrPBf8grC7dpUcaw1Qfku/DJ7kPvMALeEsmFDk/t78roeNbh - IYBLJlzI1HZN6VPtpWQGsqxltAy5XN9Xw9mQM/tu70ShgsodGmE1UoW6eE5+/GMv - 6Fg+zLuICPvs2cFNmWUvukN5LW146tJSYCv0Q/rCPB3m9dNQ9pBxrzPUHXw4glwG - qGnGddXmOC+tSW5lDLLG1BRbKv4zxv3UlrtIjqlJtZb/sQMT6WtG2ihAz7SKOBHa - HOWUwuPTetWIuJCKP7P4mWWtmSmjLy+BFX5seNEngn3RzJ2L8uuTJQ/88OsqgGru - n3MVF9w= - -----END CERTIFICATE----- - private_key_password: "cassandra" - trusted_certificates: | - -----BEGIN CERTIFICATE----- - MIIDkTCCAnmgAwIBAgIETxH5JDANBgkqhkiG9w0BAQsFADB5MRAwDgYDVQQGEwdV - bmtub3duMRAwDgYDVQQIEwdVbmtub3duMRAwDgYDVQQHEwdVbmtub3duMRAwDgYD - VQQKEwdVbmtub3duMRQwEgYDVQQLDAtzc2xfdGVzdGluZzEZMBcGA1UEAxMQQXBh - Y2hlIENhc3NhbmRyYTAeFw0xNjAzMTgyMTI4MDJaFw0xNjA2MTYyMTI4MDJaMHkx - EDAOBgNVBAYTB1Vua25vd24xEDAOBgNVBAgTB1Vua25vd24xEDAOBgNVBAcTB1Vu - a25vd24xEDAOBgNVBAoTB1Vua25vd24xFDASBgNVBAsMC3NzbF90ZXN0aW5nMRkw - FwYDVQQDExBBcGFjaGUgQ2Fzc2FuZHJhMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A - MIIBCgKCAQEAjkmVX/HS49cS8Hn6o26IGwMIcEV3d7ZhH0GNcx8rnSRd10dU9F6d - ugSjbwGFMcWUQzYNejN6az0Wb8JIQyXRPTWjfgaWTyVGr0bGTnxg6vwhzfI/9jzy - q59xv29OuSY1dxmY31f0pZ9OOw3mabWksjoO2TexfKoxqsRHJ8PrM1f8E84Z4xo2 - TJXGzpuIxRkAJ+sVDqKEAhrKAfRYMSgdJ7zRt8VXv9ngjX20uA2m092NcH0Kmeto - TmuWUtK8E/qcN7ULN8xRWNUn4hu6mG6mayk4XliGRqI1VZupqh+MgNqHznuTd0bA - YrQsFPw9HaZ2hvVnJffJ5l7njAekZNOL+wIDAQABoyEwHzAdBgNVHQ4EFgQUcdiD - N6aylI91kAd34Hl2AzWY51QwDQYJKoZIhvcNAQELBQADggEBAG9q29ilUgCWQP5v - iHkZHj10gXGEoMkdfrPBf8grC7dpUcaw1Qfku/DJ7kPvMALeEsmFDk/t78roeNbh - IYBLJlzI1HZN6VPtpWQGsqxltAy5XN9Xw9mQM/tu70ShgsodGmE1UoW6eE5+/GMv - 6Fg+zLuICPvs2cFNmWUvukN5LW146tJSYCv0Q/rCPB3m9dNQ9pBxrzPUHXw4glwG - qGnGddXmOC+tSW5lDLLG1BRbKv4zxv3UlrtIjqlJtZb/sQMT6WtG2ihAz7SKOBHa - HOWUwuPTetWIuJCKP7P4mWWtmSmjLy+BFX5seNEngn3RzJ2L8uuTJQ/88OsqgGru - n3MVF9w= - -----END CERTIFICATE----- +jmx_server_options: + enabled: true + jmx_encryption_options: + enabled: false + cipher_suites: [TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256] + accepted_protocols: [TLSv1.2,TLSv1.3,TLSv1.1] + ssl_context_factory: + class_name: org.apache.cassandra.security.PEMBasedSslContextFactory + parameters: + private_key: | + -----BEGIN ENCRYPTED PRIVATE KEY----- + MIIE6jAcBgoqhkiG9w0BDAEDMA4ECOWqSzq5PBIdAgIFxQSCBMjXsCK30J0aT3J/ + g5kcbmevTOY1pIhJGbf5QYYrMUPiuDK2ydxIbiPzoTE4/S+OkCeHhlqwn/YydpBl + xgjZZ1Z5rLJHO27d2biuESqanDiBVXYuVmHmaifRnFy0uUTFkStB5mjVZEiJgO29 + L83hL60uWru71EVuVriC2WCfmZ/EXp6wyYszOqCFQ8Quk/rDO6XuaBl467MJbx5V + sucGT6E9XKNd9hB14/Izb2jtVM5kqKxoiHpz1na6yhEYJiE5D1uOonznWjBnjwB/ + f0x+acpDfVDoJKTlRdz+DEcbOF7mb9lBVVjP6P/AAsmQzz6JKwHjvCrjYfQmyyN8 + RI4KRQnWgm4L3dtByLqY8HFU4ogisCMCgI+hZQ+OKMz/hoRO540YGiPcTRY3EOUR + 0bd5JxU6tCJDMTqKP9aSL2KmLoiLowdMkSPz7TCzLsZ2bGJemuCfpAs4XT1vXCHs + evrUbOnh8et1IA8mZ9auThfqsZtNagJLEXA6hWIKp1FfVL3Q49wvMKZt4eTn/zwU + tLL0m5yPo6/HAaOA3hbm/oghZS0dseshXl7PZrmZQtvYnIvjyoxEL7ducYDQCDP6 + wZ7Nzyh1QZAauSS15hl3vLFRZCA9hWAVgwQAviTvhB342O0i9qI7TQkcHk+qcTPN + K+iGNbFZ8ma1izXNKSJ2PgI/QqFNIeJWvZrb9PhJRmaZVsTJ9fERm1ewpebZqkVv + zMqMhlKgx9ggAaSKgnGZkwXwB6GrSbbzUrwRCKm3FieD1QE4VVYevaadVUU75GG5 + mrFKorJEH7kFZlic8OTjDksYnHbcgU36XZrGEXa2+ldVeGKL3CsXWciaQRcJg8yo + WQDjZpcutGI0eMJWCqUkv8pYZC2/wZU4htCve5nVJUU4t9uuo9ex7lnwlLWPvheQ + jUBMgzSRsZ+zwaIusvufAAxiKK/cJm4ubZSZPIjBbfd4U7VPxtirP4Accydu7EK6 + eG/MZwtAMFNJxfxUR+/aYzJU/q1ePw7fWVHrpt58t/22CX2SJBEiUGmSmuyER4Ny + DPw6d6mhvPUS1jRhIZ9A81ht8MOX7VL5uVp307rt7o5vRpV1mo0iPiRHzGscMpJn + AP36klEAUNTf0uLTKZa7KHiwhn5iPmsCrENHkOKJjxhRrqHjD2wy3YHs3ow2voyY + Ua4Cids+c1hvRkNEDGNHm4+rKGFOGOsG/ZU7uj/6gflO4JXxNGiyTLflqMdWBvow + Zd7hk1zCaGAAn8nZ0hPweGxQ4Q30I9IBZrimGxB0vjiUqNio9+qMf33dCHFJEuut + ZGJMaUGVaPhXQcTy4uD5hzsPZV5xcsU4H3vBYyBcZgrusJ6OOgkuZQaU7p8rWQWr + bUEVbXuZdwEmxsCe7H/vEVv5+aA4sF4kWnMMFL7/LIYaiEzkTqdJlRv/KyJJgcAH + hg2BvR3XTAq8wiX0C98CdmTbsx2eyQdj5tCU606rEohFLKUxWkJYAKxCiUbxGGpI + RheVmxkef9ErxJiq7hsAsGrSJvMtJuDKIasnD14SOEwD/7jRAq6WdL9VLpxtzlOw + pWnIl8kUCO3WoaG9Jf+ZTIv2hnxJhaSzYrdXzGPNnaWKhBlwnXJRvQEdrIxZOimP + FujZhqbKUDbYAcqTkoQ= + -----END ENCRYPTED PRIVATE KEY----- + -----BEGIN CERTIFICATE----- + MIIDkTCCAnmgAwIBAgIETxH5JDANBgkqhkiG9w0BAQsFADB5MRAwDgYDVQQGEwdV + bmtub3duMRAwDgYDVQQIEwdVbmtub3duMRAwDgYDVQQHEwdVbmtub3duMRAwDgYD + VQQKEwdVbmtub3duMRQwEgYDVQQLDAtzc2xfdGVzdGluZzEZMBcGA1UEAxMQQXBh + Y2hlIENhc3NhbmRyYTAeFw0xNjAzMTgyMTI4MDJaFw0xNjA2MTYyMTI4MDJaMHkx + EDAOBgNVBAYTB1Vua25vd24xEDAOBgNVBAgTB1Vua25vd24xEDAOBgNVBAcTB1Vu + a25vd24xEDAOBgNVBAoTB1Vua25vd24xFDASBgNVBAsMC3NzbF90ZXN0aW5nMRkw + FwYDVQQDExBBcGFjaGUgQ2Fzc2FuZHJhMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A + MIIBCgKCAQEAjkmVX/HS49cS8Hn6o26IGwMIcEV3d7ZhH0GNcx8rnSRd10dU9F6d + ugSjbwGFMcWUQzYNejN6az0Wb8JIQyXRPTWjfgaWTyVGr0bGTnxg6vwhzfI/9jzy + q59xv29OuSY1dxmY31f0pZ9OOw3mabWksjoO2TexfKoxqsRHJ8PrM1f8E84Z4xo2 + TJXGzpuIxRkAJ+sVDqKEAhrKAfRYMSgdJ7zRt8VXv9ngjX20uA2m092NcH0Kmeto + TmuWUtK8E/qcN7ULN8xRWNUn4hu6mG6mayk4XliGRqI1VZupqh+MgNqHznuTd0bA + YrQsFPw9HaZ2hvVnJffJ5l7njAekZNOL+wIDAQABoyEwHzAdBgNVHQ4EFgQUcdiD + N6aylI91kAd34Hl2AzWY51QwDQYJKoZIhvcNAQELBQADggEBAG9q29ilUgCWQP5v + iHkZHj10gXGEoMkdfrPBf8grC7dpUcaw1Qfku/DJ7kPvMALeEsmFDk/t78roeNbh + IYBLJlzI1HZN6VPtpWQGsqxltAy5XN9Xw9mQM/tu70ShgsodGmE1UoW6eE5+/GMv + 6Fg+zLuICPvs2cFNmWUvukN5LW146tJSYCv0Q/rCPB3m9dNQ9pBxrzPUHXw4glwG + qGnGddXmOC+tSW5lDLLG1BRbKv4zxv3UlrtIjqlJtZb/sQMT6WtG2ihAz7SKOBHa + HOWUwuPTetWIuJCKP7P4mWWtmSmjLy+BFX5seNEngn3RzJ2L8uuTJQ/88OsqgGru + n3MVF9w= + -----END CERTIFICATE----- + private_key_password: "cassandra" + trusted_certificates: | + -----BEGIN CERTIFICATE----- + MIIDkTCCAnmgAwIBAgIETxH5JDANBgkqhkiG9w0BAQsFADB5MRAwDgYDVQQGEwdV + bmtub3duMRAwDgYDVQQIEwdVbmtub3duMRAwDgYDVQQHEwdVbmtub3duMRAwDgYD + VQQKEwdVbmtub3duMRQwEgYDVQQLDAtzc2xfdGVzdGluZzEZMBcGA1UEAxMQQXBh + Y2hlIENhc3NhbmRyYTAeFw0xNjAzMTgyMTI4MDJaFw0xNjA2MTYyMTI4MDJaMHkx + EDAOBgNVBAYTB1Vua25vd24xEDAOBgNVBAgTB1Vua25vd24xEDAOBgNVBAcTB1Vu + a25vd24xEDAOBgNVBAoTB1Vua25vd24xFDASBgNVBAsMC3NzbF90ZXN0aW5nMRkw + FwYDVQQDExBBcGFjaGUgQ2Fzc2FuZHJhMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A + MIIBCgKCAQEAjkmVX/HS49cS8Hn6o26IGwMIcEV3d7ZhH0GNcx8rnSRd10dU9F6d + ugSjbwGFMcWUQzYNejN6az0Wb8JIQyXRPTWjfgaWTyVGr0bGTnxg6vwhzfI/9jzy + q59xv29OuSY1dxmY31f0pZ9OOw3mabWksjoO2TexfKoxqsRHJ8PrM1f8E84Z4xo2 + TJXGzpuIxRkAJ+sVDqKEAhrKAfRYMSgdJ7zRt8VXv9ngjX20uA2m092NcH0Kmeto + TmuWUtK8E/qcN7ULN8xRWNUn4hu6mG6mayk4XliGRqI1VZupqh+MgNqHznuTd0bA + YrQsFPw9HaZ2hvVnJffJ5l7njAekZNOL+wIDAQABoyEwHzAdBgNVHQ4EFgQUcdiD + N6aylI91kAd34Hl2AzWY51QwDQYJKoZIhvcNAQELBQADggEBAG9q29ilUgCWQP5v + iHkZHj10gXGEoMkdfrPBf8grC7dpUcaw1Qfku/DJ7kPvMALeEsmFDk/t78roeNbh + IYBLJlzI1HZN6VPtpWQGsqxltAy5XN9Xw9mQM/tu70ShgsodGmE1UoW6eE5+/GMv + 6Fg+zLuICPvs2cFNmWUvukN5LW146tJSYCv0Q/rCPB3m9dNQ9pBxrzPUHXw4glwG + qGnGddXmOC+tSW5lDLLG1BRbKv4zxv3UlrtIjqlJtZb/sQMT6WtG2ihAz7SKOBHa + HOWUwuPTetWIuJCKP7P4mWWtmSmjLy+BFX5seNEngn3RzJ2L8uuTJQ/88OsqgGru + n3MVF9w= + -----END CERTIFICATE----- incremental_backups: true concurrent_compactors: 4 compaction_throughput: 0MiB/s diff --git a/test/conf/cassandra-jmx-pem-sslconfig.yaml b/test/conf/cassandra-jmx-pem-sslconfig.yaml index 45f58ffda272..55adfd87dd26 100644 --- a/test/conf/cassandra-jmx-pem-sslconfig.yaml +++ b/test/conf/cassandra-jmx-pem-sslconfig.yaml @@ -48,89 +48,91 @@ seed_provider: - seeds: "127.0.0.1:7012" endpoint_snitch: org.apache.cassandra.locator.SimpleSnitch dynamic_snitch: true -jmx_encryption_options: +jmx_server_options: enabled: true - cipher_suites: [TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256] - accepted_protocols: [TLSv1.2,TLSv1.3,TLSv1.1] - ssl_context_factory: - class_name: org.apache.cassandra.security.PEMBasedSslContextFactory - parameters: - private_key: | - -----BEGIN ENCRYPTED PRIVATE KEY----- - MIIE6jAcBgoqhkiG9w0BDAEDMA4ECOWqSzq5PBIdAgIFxQSCBMjXsCK30J0aT3J/ - g5kcbmevTOY1pIhJGbf5QYYrMUPiuDK2ydxIbiPzoTE4/S+OkCeHhlqwn/YydpBl - xgjZZ1Z5rLJHO27d2biuESqanDiBVXYuVmHmaifRnFy0uUTFkStB5mjVZEiJgO29 - L83hL60uWru71EVuVriC2WCfmZ/EXp6wyYszOqCFQ8Quk/rDO6XuaBl467MJbx5V - sucGT6E9XKNd9hB14/Izb2jtVM5kqKxoiHpz1na6yhEYJiE5D1uOonznWjBnjwB/ - f0x+acpDfVDoJKTlRdz+DEcbOF7mb9lBVVjP6P/AAsmQzz6JKwHjvCrjYfQmyyN8 - RI4KRQnWgm4L3dtByLqY8HFU4ogisCMCgI+hZQ+OKMz/hoRO540YGiPcTRY3EOUR - 0bd5JxU6tCJDMTqKP9aSL2KmLoiLowdMkSPz7TCzLsZ2bGJemuCfpAs4XT1vXCHs - evrUbOnh8et1IA8mZ9auThfqsZtNagJLEXA6hWIKp1FfVL3Q49wvMKZt4eTn/zwU - tLL0m5yPo6/HAaOA3hbm/oghZS0dseshXl7PZrmZQtvYnIvjyoxEL7ducYDQCDP6 - wZ7Nzyh1QZAauSS15hl3vLFRZCA9hWAVgwQAviTvhB342O0i9qI7TQkcHk+qcTPN - K+iGNbFZ8ma1izXNKSJ2PgI/QqFNIeJWvZrb9PhJRmaZVsTJ9fERm1ewpebZqkVv - zMqMhlKgx9ggAaSKgnGZkwXwB6GrSbbzUrwRCKm3FieD1QE4VVYevaadVUU75GG5 - mrFKorJEH7kFZlic8OTjDksYnHbcgU36XZrGEXa2+ldVeGKL3CsXWciaQRcJg8yo - WQDjZpcutGI0eMJWCqUkv8pYZC2/wZU4htCve5nVJUU4t9uuo9ex7lnwlLWPvheQ - jUBMgzSRsZ+zwaIusvufAAxiKK/cJm4ubZSZPIjBbfd4U7VPxtirP4Accydu7EK6 - eG/MZwtAMFNJxfxUR+/aYzJU/q1ePw7fWVHrpt58t/22CX2SJBEiUGmSmuyER4Ny - DPw6d6mhvPUS1jRhIZ9A81ht8MOX7VL5uVp307rt7o5vRpV1mo0iPiRHzGscMpJn - AP36klEAUNTf0uLTKZa7KHiwhn5iPmsCrENHkOKJjxhRrqHjD2wy3YHs3ow2voyY - Ua4Cids+c1hvRkNEDGNHm4+rKGFOGOsG/ZU7uj/6gflO4JXxNGiyTLflqMdWBvow - Zd7hk1zCaGAAn8nZ0hPweGxQ4Q30I9IBZrimGxB0vjiUqNio9+qMf33dCHFJEuut - ZGJMaUGVaPhXQcTy4uD5hzsPZV5xcsU4H3vBYyBcZgrusJ6OOgkuZQaU7p8rWQWr - bUEVbXuZdwEmxsCe7H/vEVv5+aA4sF4kWnMMFL7/LIYaiEzkTqdJlRv/KyJJgcAH - hg2BvR3XTAq8wiX0C98CdmTbsx2eyQdj5tCU606rEohFLKUxWkJYAKxCiUbxGGpI - RheVmxkef9ErxJiq7hsAsGrSJvMtJuDKIasnD14SOEwD/7jRAq6WdL9VLpxtzlOw - pWnIl8kUCO3WoaG9Jf+ZTIv2hnxJhaSzYrdXzGPNnaWKhBlwnXJRvQEdrIxZOimP - FujZhqbKUDbYAcqTkoQ= - -----END ENCRYPTED PRIVATE KEY----- - -----BEGIN CERTIFICATE----- - MIIDkTCCAnmgAwIBAgIETxH5JDANBgkqhkiG9w0BAQsFADB5MRAwDgYDVQQGEwdV - bmtub3duMRAwDgYDVQQIEwdVbmtub3duMRAwDgYDVQQHEwdVbmtub3duMRAwDgYD - VQQKEwdVbmtub3duMRQwEgYDVQQLDAtzc2xfdGVzdGluZzEZMBcGA1UEAxMQQXBh - Y2hlIENhc3NhbmRyYTAeFw0xNjAzMTgyMTI4MDJaFw0xNjA2MTYyMTI4MDJaMHkx - EDAOBgNVBAYTB1Vua25vd24xEDAOBgNVBAgTB1Vua25vd24xEDAOBgNVBAcTB1Vu - a25vd24xEDAOBgNVBAoTB1Vua25vd24xFDASBgNVBAsMC3NzbF90ZXN0aW5nMRkw - FwYDVQQDExBBcGFjaGUgQ2Fzc2FuZHJhMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A - MIIBCgKCAQEAjkmVX/HS49cS8Hn6o26IGwMIcEV3d7ZhH0GNcx8rnSRd10dU9F6d - ugSjbwGFMcWUQzYNejN6az0Wb8JIQyXRPTWjfgaWTyVGr0bGTnxg6vwhzfI/9jzy - q59xv29OuSY1dxmY31f0pZ9OOw3mabWksjoO2TexfKoxqsRHJ8PrM1f8E84Z4xo2 - TJXGzpuIxRkAJ+sVDqKEAhrKAfRYMSgdJ7zRt8VXv9ngjX20uA2m092NcH0Kmeto - TmuWUtK8E/qcN7ULN8xRWNUn4hu6mG6mayk4XliGRqI1VZupqh+MgNqHznuTd0bA - YrQsFPw9HaZ2hvVnJffJ5l7njAekZNOL+wIDAQABoyEwHzAdBgNVHQ4EFgQUcdiD - N6aylI91kAd34Hl2AzWY51QwDQYJKoZIhvcNAQELBQADggEBAG9q29ilUgCWQP5v - iHkZHj10gXGEoMkdfrPBf8grC7dpUcaw1Qfku/DJ7kPvMALeEsmFDk/t78roeNbh - IYBLJlzI1HZN6VPtpWQGsqxltAy5XN9Xw9mQM/tu70ShgsodGmE1UoW6eE5+/GMv - 6Fg+zLuICPvs2cFNmWUvukN5LW146tJSYCv0Q/rCPB3m9dNQ9pBxrzPUHXw4glwG - qGnGddXmOC+tSW5lDLLG1BRbKv4zxv3UlrtIjqlJtZb/sQMT6WtG2ihAz7SKOBHa - HOWUwuPTetWIuJCKP7P4mWWtmSmjLy+BFX5seNEngn3RzJ2L8uuTJQ/88OsqgGru - n3MVF9w= - -----END CERTIFICATE----- - private_key_password: "cassandra" - trusted_certificates: | - -----BEGIN CERTIFICATE----- - MIIDkTCCAnmgAwIBAgIETxH5JDANBgkqhkiG9w0BAQsFADB5MRAwDgYDVQQGEwdV - bmtub3duMRAwDgYDVQQIEwdVbmtub3duMRAwDgYDVQQHEwdVbmtub3duMRAwDgYD - VQQKEwdVbmtub3duMRQwEgYDVQQLDAtzc2xfdGVzdGluZzEZMBcGA1UEAxMQQXBh - Y2hlIENhc3NhbmRyYTAeFw0xNjAzMTgyMTI4MDJaFw0xNjA2MTYyMTI4MDJaMHkx - EDAOBgNVBAYTB1Vua25vd24xEDAOBgNVBAgTB1Vua25vd24xEDAOBgNVBAcTB1Vu - a25vd24xEDAOBgNVBAoTB1Vua25vd24xFDASBgNVBAsMC3NzbF90ZXN0aW5nMRkw - FwYDVQQDExBBcGFjaGUgQ2Fzc2FuZHJhMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A - MIIBCgKCAQEAjkmVX/HS49cS8Hn6o26IGwMIcEV3d7ZhH0GNcx8rnSRd10dU9F6d - ugSjbwGFMcWUQzYNejN6az0Wb8JIQyXRPTWjfgaWTyVGr0bGTnxg6vwhzfI/9jzy - q59xv29OuSY1dxmY31f0pZ9OOw3mabWksjoO2TexfKoxqsRHJ8PrM1f8E84Z4xo2 - TJXGzpuIxRkAJ+sVDqKEAhrKAfRYMSgdJ7zRt8VXv9ngjX20uA2m092NcH0Kmeto - TmuWUtK8E/qcN7ULN8xRWNUn4hu6mG6mayk4XliGRqI1VZupqh+MgNqHznuTd0bA - YrQsFPw9HaZ2hvVnJffJ5l7njAekZNOL+wIDAQABoyEwHzAdBgNVHQ4EFgQUcdiD - N6aylI91kAd34Hl2AzWY51QwDQYJKoZIhvcNAQELBQADggEBAG9q29ilUgCWQP5v - iHkZHj10gXGEoMkdfrPBf8grC7dpUcaw1Qfku/DJ7kPvMALeEsmFDk/t78roeNbh - IYBLJlzI1HZN6VPtpWQGsqxltAy5XN9Xw9mQM/tu70ShgsodGmE1UoW6eE5+/GMv - 6Fg+zLuICPvs2cFNmWUvukN5LW146tJSYCv0Q/rCPB3m9dNQ9pBxrzPUHXw4glwG - qGnGddXmOC+tSW5lDLLG1BRbKv4zxv3UlrtIjqlJtZb/sQMT6WtG2ihAz7SKOBHa - HOWUwuPTetWIuJCKP7P4mWWtmSmjLy+BFX5seNEngn3RzJ2L8uuTJQ/88OsqgGru - n3MVF9w= - -----END CERTIFICATE----- + jmx_encryption_options: + enabled: true + cipher_suites: [TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256] + accepted_protocols: [TLSv1.2,TLSv1.3,TLSv1.1] + ssl_context_factory: + class_name: org.apache.cassandra.security.PEMBasedSslContextFactory + parameters: + private_key: | + -----BEGIN ENCRYPTED PRIVATE KEY----- + MIIE6jAcBgoqhkiG9w0BDAEDMA4ECOWqSzq5PBIdAgIFxQSCBMjXsCK30J0aT3J/ + g5kcbmevTOY1pIhJGbf5QYYrMUPiuDK2ydxIbiPzoTE4/S+OkCeHhlqwn/YydpBl + xgjZZ1Z5rLJHO27d2biuESqanDiBVXYuVmHmaifRnFy0uUTFkStB5mjVZEiJgO29 + L83hL60uWru71EVuVriC2WCfmZ/EXp6wyYszOqCFQ8Quk/rDO6XuaBl467MJbx5V + sucGT6E9XKNd9hB14/Izb2jtVM5kqKxoiHpz1na6yhEYJiE5D1uOonznWjBnjwB/ + f0x+acpDfVDoJKTlRdz+DEcbOF7mb9lBVVjP6P/AAsmQzz6JKwHjvCrjYfQmyyN8 + RI4KRQnWgm4L3dtByLqY8HFU4ogisCMCgI+hZQ+OKMz/hoRO540YGiPcTRY3EOUR + 0bd5JxU6tCJDMTqKP9aSL2KmLoiLowdMkSPz7TCzLsZ2bGJemuCfpAs4XT1vXCHs + evrUbOnh8et1IA8mZ9auThfqsZtNagJLEXA6hWIKp1FfVL3Q49wvMKZt4eTn/zwU + tLL0m5yPo6/HAaOA3hbm/oghZS0dseshXl7PZrmZQtvYnIvjyoxEL7ducYDQCDP6 + wZ7Nzyh1QZAauSS15hl3vLFRZCA9hWAVgwQAviTvhB342O0i9qI7TQkcHk+qcTPN + K+iGNbFZ8ma1izXNKSJ2PgI/QqFNIeJWvZrb9PhJRmaZVsTJ9fERm1ewpebZqkVv + zMqMhlKgx9ggAaSKgnGZkwXwB6GrSbbzUrwRCKm3FieD1QE4VVYevaadVUU75GG5 + mrFKorJEH7kFZlic8OTjDksYnHbcgU36XZrGEXa2+ldVeGKL3CsXWciaQRcJg8yo + WQDjZpcutGI0eMJWCqUkv8pYZC2/wZU4htCve5nVJUU4t9uuo9ex7lnwlLWPvheQ + jUBMgzSRsZ+zwaIusvufAAxiKK/cJm4ubZSZPIjBbfd4U7VPxtirP4Accydu7EK6 + eG/MZwtAMFNJxfxUR+/aYzJU/q1ePw7fWVHrpt58t/22CX2SJBEiUGmSmuyER4Ny + DPw6d6mhvPUS1jRhIZ9A81ht8MOX7VL5uVp307rt7o5vRpV1mo0iPiRHzGscMpJn + AP36klEAUNTf0uLTKZa7KHiwhn5iPmsCrENHkOKJjxhRrqHjD2wy3YHs3ow2voyY + Ua4Cids+c1hvRkNEDGNHm4+rKGFOGOsG/ZU7uj/6gflO4JXxNGiyTLflqMdWBvow + Zd7hk1zCaGAAn8nZ0hPweGxQ4Q30I9IBZrimGxB0vjiUqNio9+qMf33dCHFJEuut + ZGJMaUGVaPhXQcTy4uD5hzsPZV5xcsU4H3vBYyBcZgrusJ6OOgkuZQaU7p8rWQWr + bUEVbXuZdwEmxsCe7H/vEVv5+aA4sF4kWnMMFL7/LIYaiEzkTqdJlRv/KyJJgcAH + hg2BvR3XTAq8wiX0C98CdmTbsx2eyQdj5tCU606rEohFLKUxWkJYAKxCiUbxGGpI + RheVmxkef9ErxJiq7hsAsGrSJvMtJuDKIasnD14SOEwD/7jRAq6WdL9VLpxtzlOw + pWnIl8kUCO3WoaG9Jf+ZTIv2hnxJhaSzYrdXzGPNnaWKhBlwnXJRvQEdrIxZOimP + FujZhqbKUDbYAcqTkoQ= + -----END ENCRYPTED PRIVATE KEY----- + -----BEGIN CERTIFICATE----- + MIIDkTCCAnmgAwIBAgIETxH5JDANBgkqhkiG9w0BAQsFADB5MRAwDgYDVQQGEwdV + bmtub3duMRAwDgYDVQQIEwdVbmtub3duMRAwDgYDVQQHEwdVbmtub3duMRAwDgYD + VQQKEwdVbmtub3duMRQwEgYDVQQLDAtzc2xfdGVzdGluZzEZMBcGA1UEAxMQQXBh + Y2hlIENhc3NhbmRyYTAeFw0xNjAzMTgyMTI4MDJaFw0xNjA2MTYyMTI4MDJaMHkx + EDAOBgNVBAYTB1Vua25vd24xEDAOBgNVBAgTB1Vua25vd24xEDAOBgNVBAcTB1Vu + a25vd24xEDAOBgNVBAoTB1Vua25vd24xFDASBgNVBAsMC3NzbF90ZXN0aW5nMRkw + FwYDVQQDExBBcGFjaGUgQ2Fzc2FuZHJhMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A + MIIBCgKCAQEAjkmVX/HS49cS8Hn6o26IGwMIcEV3d7ZhH0GNcx8rnSRd10dU9F6d + ugSjbwGFMcWUQzYNejN6az0Wb8JIQyXRPTWjfgaWTyVGr0bGTnxg6vwhzfI/9jzy + q59xv29OuSY1dxmY31f0pZ9OOw3mabWksjoO2TexfKoxqsRHJ8PrM1f8E84Z4xo2 + TJXGzpuIxRkAJ+sVDqKEAhrKAfRYMSgdJ7zRt8VXv9ngjX20uA2m092NcH0Kmeto + TmuWUtK8E/qcN7ULN8xRWNUn4hu6mG6mayk4XliGRqI1VZupqh+MgNqHznuTd0bA + YrQsFPw9HaZ2hvVnJffJ5l7njAekZNOL+wIDAQABoyEwHzAdBgNVHQ4EFgQUcdiD + N6aylI91kAd34Hl2AzWY51QwDQYJKoZIhvcNAQELBQADggEBAG9q29ilUgCWQP5v + iHkZHj10gXGEoMkdfrPBf8grC7dpUcaw1Qfku/DJ7kPvMALeEsmFDk/t78roeNbh + IYBLJlzI1HZN6VPtpWQGsqxltAy5XN9Xw9mQM/tu70ShgsodGmE1UoW6eE5+/GMv + 6Fg+zLuICPvs2cFNmWUvukN5LW146tJSYCv0Q/rCPB3m9dNQ9pBxrzPUHXw4glwG + qGnGddXmOC+tSW5lDLLG1BRbKv4zxv3UlrtIjqlJtZb/sQMT6WtG2ihAz7SKOBHa + HOWUwuPTetWIuJCKP7P4mWWtmSmjLy+BFX5seNEngn3RzJ2L8uuTJQ/88OsqgGru + n3MVF9w= + -----END CERTIFICATE----- + private_key_password: "cassandra" + trusted_certificates: | + -----BEGIN CERTIFICATE----- + MIIDkTCCAnmgAwIBAgIETxH5JDANBgkqhkiG9w0BAQsFADB5MRAwDgYDVQQGEwdV + bmtub3duMRAwDgYDVQQIEwdVbmtub3duMRAwDgYDVQQHEwdVbmtub3duMRAwDgYD + VQQKEwdVbmtub3duMRQwEgYDVQQLDAtzc2xfdGVzdGluZzEZMBcGA1UEAxMQQXBh + Y2hlIENhc3NhbmRyYTAeFw0xNjAzMTgyMTI4MDJaFw0xNjA2MTYyMTI4MDJaMHkx + EDAOBgNVBAYTB1Vua25vd24xEDAOBgNVBAgTB1Vua25vd24xEDAOBgNVBAcTB1Vu + a25vd24xEDAOBgNVBAoTB1Vua25vd24xFDASBgNVBAsMC3NzbF90ZXN0aW5nMRkw + FwYDVQQDExBBcGFjaGUgQ2Fzc2FuZHJhMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A + MIIBCgKCAQEAjkmVX/HS49cS8Hn6o26IGwMIcEV3d7ZhH0GNcx8rnSRd10dU9F6d + ugSjbwGFMcWUQzYNejN6az0Wb8JIQyXRPTWjfgaWTyVGr0bGTnxg6vwhzfI/9jzy + q59xv29OuSY1dxmY31f0pZ9OOw3mabWksjoO2TexfKoxqsRHJ8PrM1f8E84Z4xo2 + TJXGzpuIxRkAJ+sVDqKEAhrKAfRYMSgdJ7zRt8VXv9ngjX20uA2m092NcH0Kmeto + TmuWUtK8E/qcN7ULN8xRWNUn4hu6mG6mayk4XliGRqI1VZupqh+MgNqHznuTd0bA + YrQsFPw9HaZ2hvVnJffJ5l7njAekZNOL+wIDAQABoyEwHzAdBgNVHQ4EFgQUcdiD + N6aylI91kAd34Hl2AzWY51QwDQYJKoZIhvcNAQELBQADggEBAG9q29ilUgCWQP5v + iHkZHj10gXGEoMkdfrPBf8grC7dpUcaw1Qfku/DJ7kPvMALeEsmFDk/t78roeNbh + IYBLJlzI1HZN6VPtpWQGsqxltAy5XN9Xw9mQM/tu70ShgsodGmE1UoW6eE5+/GMv + 6Fg+zLuICPvs2cFNmWUvukN5LW146tJSYCv0Q/rCPB3m9dNQ9pBxrzPUHXw4glwG + qGnGddXmOC+tSW5lDLLG1BRbKv4zxv3UlrtIjqlJtZb/sQMT6WtG2ihAz7SKOBHa + HOWUwuPTetWIuJCKP7P4mWWtmSmjLy+BFX5seNEngn3RzJ2L8uuTJQ/88OsqgGru + n3MVF9w= + -----END CERTIFICATE----- incremental_backups: true concurrent_compactors: 4 compaction_throughput: 0MiB/s diff --git a/test/conf/cassandra-jmx-sslconfig.yaml b/test/conf/cassandra-jmx-sslconfig.yaml index 317d5236b62a..1a6ef9a9457f 100644 --- a/test/conf/cassandra-jmx-sslconfig.yaml +++ b/test/conf/cassandra-jmx-sslconfig.yaml @@ -48,14 +48,16 @@ seed_provider: - seeds: "127.0.0.1:7012" endpoint_snitch: org.apache.cassandra.locator.SimpleSnitch dynamic_snitch: true -jmx_encryption_options: +jmx_server_options: enabled: true - cipher_suites: [TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256] - accepted_protocols: [TLSv1.2,TLSv1.3,TLSv1.1] - keystore: test/conf/cassandra_ssl_test.keystore - keystore_password: cassandra - truststore: test/conf/cassandra_ssl_test.truststore - truststore_password: cassandra + jmx_encryption_options: + enabled: true + cipher_suites: [TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256] + accepted_protocols: [TLSv1.2,TLSv1.3,TLSv1.1] + keystore: test/conf/cassandra_ssl_test.keystore + keystore_password: cassandra + truststore: test/conf/cassandra_ssl_test.truststore + truststore_password: cassandra incremental_backups: true concurrent_compactors: 4 compaction_throughput: 0MiB/s diff --git a/test/distributed/org/apache/cassandra/distributed/impl/CollectingSslRMIServerSocketFactoryImpl.java b/test/distributed/org/apache/cassandra/distributed/impl/CollectingSslRMIServerSocketFactoryImpl.java index 01d051e4cf07..0d13aa6290cc 100644 --- a/test/distributed/org/apache/cassandra/distributed/impl/CollectingSslRMIServerSocketFactoryImpl.java +++ b/test/distributed/org/apache/cassandra/distributed/impl/CollectingSslRMIServerSocketFactoryImpl.java @@ -57,16 +57,6 @@ public CollectingSslRMIServerSocketFactoryImpl(InetAddress bindAddress, String[] this.sslSocketFactory = sslContext.getSocketFactory(); } - public CollectingSslRMIServerSocketFactoryImpl(InetAddress bindAddress, String[] enabledCipherSuites, - String[] enabledProtocols, boolean needClientAuth) - { - this.bindAddress = bindAddress; - this.enabledCipherSuites = enabledCipherSuites; - this.enabledProtocols = enabledProtocols; - this.needClientAuth = needClientAuth; - this.sslSocketFactory = getDefaultSSLSocketFactory(); - } - public String[] getEnabledCipherSuites() { return enabledCipherSuites; diff --git a/test/distributed/org/apache/cassandra/distributed/impl/IsolatedJmx.java b/test/distributed/org/apache/cassandra/distributed/impl/IsolatedJmx.java index 6a575972eb35..18eaeb85c532 100644 --- a/test/distributed/org/apache/cassandra/distributed/impl/IsolatedJmx.java +++ b/test/distributed/org/apache/cassandra/distributed/impl/IsolatedJmx.java @@ -35,6 +35,7 @@ import org.slf4j.Logger; import org.apache.cassandra.config.EncryptionOptions; +import org.apache.cassandra.config.JMXServerOptions; import org.apache.cassandra.distributed.api.IInstance; import org.apache.cassandra.distributed.api.IInstanceConfig; import org.apache.cassandra.distributed.shared.JMXUtil; @@ -91,12 +92,24 @@ public void startJmx() ((MBeanWrapper.DelegatingMbeanWrapper) MBeanWrapper.instance).setDelegate(wrapper); // CASSANDRA-18508: Sensitive JMX SSL configuration options can be easily exposed - Map encryptionOptionsMap = (Map) config.getParams().get("jmx_encryption_options"); - EncryptionOptions jmxEncryptionOptions = getJmxEncryptionOptions(encryptionOptionsMap); + Map jmxServerOptionsMap = (Map) config.getParams().get("jmx_server_options"); + EncryptionOptions jmxEncryptionOptions; + if (jmxServerOptionsMap == null) + { + JMXServerOptions parsingSystemProperties = JMXServerOptions.createParsingSystemProperties(); + jmxEncryptionOptions = parsingSystemProperties.jmx_encryption_options; + jmxEncryptionOptions.applyConfig(); + } + else + { + jmxEncryptionOptions = getJmxEncryptionOptions(jmxServerOptionsMap); + } + // Here the `localOnly` is always passed as true as it is for the local isolated JMX testing // However if the `jmxEncryptionOptions` are provided or JMX SSL configuration is set it will configure // the socket factories appropriately. - Map socketFactories = new IsolatedJmxSocketFactory().configure(addr, true, jmxEncryptionOptions); + JMXServerOptions jmxServerOptions = JMXServerOptions.create(true, true, jmxPort, jmxEncryptionOptions); + Map socketFactories = new IsolatedJmxSocketFactory().configure(addr, jmxServerOptions, jmxServerOptions.jmx_encryption_options); serverSocketFactory = (RMICloseableServerSocketFactory) socketFactories.get(RMIConnectorServer.RMI_SERVER_SOCKET_FACTORY_ATTRIBUTE); clientSocketFactory = (RMICloseableClientSocketFactory) socketFactories.get(RMIConnectorServer.RMI_CLIENT_SOCKET_FACTORY_ATTRIBUTE); Map env = new HashMap<>(socketFactories); @@ -148,12 +161,17 @@ public void startJmx() /** * Builds {@code EncryptionOptions} from the map based SSL configuration properties. * - * @param encryptionOptionsMap of SSL configuration properties + * @param jmxServerOptionsMap of jmx server configuration properties * @return EncryptionOptions built object */ @SuppressWarnings("unchecked") - private EncryptionOptions getJmxEncryptionOptions(Map encryptionOptionsMap) + private EncryptionOptions getJmxEncryptionOptions(Map jmxServerOptionsMap) { + if (jmxServerOptionsMap == null) + return null; + + Map encryptionOptionsMap = (Map) jmxServerOptionsMap.get("jmx_encryption_options"); + if (encryptionOptionsMap == null) { return null; diff --git a/test/distributed/org/apache/cassandra/distributed/impl/IsolatedJmxSocketFactory.java b/test/distributed/org/apache/cassandra/distributed/impl/IsolatedJmxSocketFactory.java index 868cb8ae4b28..2aa4415af929 100644 --- a/test/distributed/org/apache/cassandra/distributed/impl/IsolatedJmxSocketFactory.java +++ b/test/distributed/org/apache/cassandra/distributed/impl/IsolatedJmxSocketFactory.java @@ -22,16 +22,19 @@ import java.util.Arrays; import java.util.Map; import java.util.stream.Collectors; -import javax.management.remote.rmi.RMIConnectorServer; import javax.net.ssl.SSLContext; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.apache.cassandra.config.CassandraRelevantProperties; import org.apache.cassandra.utils.RMIClientSocketFactoryImpl; import org.apache.cassandra.utils.jmx.AbstractJmxSocketFactory; +import static javax.management.remote.rmi.RMIConnectorServer.RMI_CLIENT_SOCKET_FACTORY_ATTRIBUTE; +import static javax.management.remote.rmi.RMIConnectorServer.RMI_SERVER_SOCKET_FACTORY_ATTRIBUTE; +import static org.apache.cassandra.config.CassandraRelevantProperties.JAVAX_RMI_SSL_CLIENT_ENABLED_CIPHER_SUITES; +import static org.apache.cassandra.config.CassandraRelevantProperties.JAVAX_RMI_SSL_CLIENT_ENABLED_PROTOCOLS; + /** * JMX Socket factory used for the isolated JMX testing. */ @@ -43,35 +46,21 @@ public class IsolatedJmxSocketFactory extends AbstractJmxSocketFactory public void configureLocalSocketFactories(Map env, InetAddress serverAddress) { CollectingRMIServerSocketFactoryImpl serverSocketFactory = new CollectingRMIServerSocketFactoryImpl(serverAddress); - env.put(RMIConnectorServer.RMI_SERVER_SOCKET_FACTORY_ATTRIBUTE, - serverSocketFactory); RMIClientSocketFactoryImpl clientSocketFactory = new RMIClientSocketFactoryImpl(serverAddress); - env.put(RMIConnectorServer.RMI_CLIENT_SOCKET_FACTORY_ATTRIBUTE, - clientSocketFactory); + env.put(RMI_SERVER_SOCKET_FACTORY_ATTRIBUTE, serverSocketFactory); + env.put(RMI_CLIENT_SOCKET_FACTORY_ATTRIBUTE, clientSocketFactory); } @Override public void configureSslClientSocketFactory(Map env, InetAddress serverAddress) { RMISslClientSocketFactoryImpl clientFactory = new RMISslClientSocketFactoryImpl(serverAddress, - CassandraRelevantProperties.JAVAX_RMI_SSL_CLIENT_ENABLED_CIPHER_SUITES.getString(), - CassandraRelevantProperties.JAVAX_RMI_SSL_CLIENT_ENABLED_PROTOCOLS.getString()); - env.put(RMIConnectorServer.RMI_CLIENT_SOCKET_FACTORY_ATTRIBUTE, clientFactory); + JAVAX_RMI_SSL_CLIENT_ENABLED_CIPHER_SUITES.getString(), + JAVAX_RMI_SSL_CLIENT_ENABLED_PROTOCOLS.getString()); + env.put(RMI_CLIENT_SOCKET_FACTORY_ATTRIBUTE, clientFactory); env.put("com.sun.jndi.rmi.factory.socket", clientFactory); } - @Override - public void configureSslServerSocketFactory(Map env, InetAddress serverAddress, String[] enabledCipherSuites, - String[] enabledProtocols, boolean needClientAuth) - { - CollectingSslRMIServerSocketFactoryImpl serverFactory = new CollectingSslRMIServerSocketFactoryImpl(serverAddress, - enabledCipherSuites, - enabledProtocols, - needClientAuth); - env.put(RMIConnectorServer.RMI_SERVER_SOCKET_FACTORY_ATTRIBUTE, serverFactory); - logJmxSslConfig(serverFactory); - } - @Override public void configureSslServerSocketFactory(Map env, InetAddress serverAddress, String[] enabledCipherSuites, String[] enabledProtocols, boolean needClientAuth, SSLContext sslContext) @@ -81,7 +70,7 @@ public void configureSslServerSocketFactory(Map env, InetAddress enabledProtocols, needClientAuth, sslContext); - env.put(RMIConnectorServer.RMI_SERVER_SOCKET_FACTORY_ATTRIBUTE, serverFactory); + env.put(RMI_SERVER_SOCKET_FACTORY_ATTRIBUTE, serverFactory); logJmxSslConfig(serverFactory); } diff --git a/test/distributed/org/apache/cassandra/distributed/test/jmx/JMXSslConfigDistributedTest.java b/test/distributed/org/apache/cassandra/distributed/test/jmx/JMXSslConfigDistributedTest.java index 146f548eaf95..b923229ec043 100644 --- a/test/distributed/org/apache/cassandra/distributed/test/jmx/JMXSslConfigDistributedTest.java +++ b/test/distributed/org/apache/cassandra/distributed/test/jmx/JMXSslConfigDistributedTest.java @@ -37,7 +37,13 @@ import org.apache.cassandra.distributed.test.AbstractEncryptionOptionsImpl; import org.apache.cassandra.utils.jmx.JMXSslPropertiesUtil; +import static java.util.Map.of; +import static org.apache.cassandra.config.CassandraRelevantProperties.CASSANDRA_JMX_LOCAL_PORT; import static org.apache.cassandra.config.CassandraRelevantProperties.COM_SUN_MANAGEMENT_JMXREMOTE_SSL_ENABLED_CIPHER_SUITES; +import static org.apache.cassandra.config.CassandraRelevantProperties.JAVAX_NET_SSL_KEYSTORE; +import static org.apache.cassandra.config.CassandraRelevantProperties.JAVAX_NET_SSL_KEYSTOREPASSWORD; +import static org.apache.cassandra.config.CassandraRelevantProperties.JAVAX_NET_SSL_TRUSTSTORE; +import static org.apache.cassandra.config.CassandraRelevantProperties.JAVAX_NET_SSL_TRUSTSTOREPASSWORD; /** * Distributed tests for JMX SSL configuration via the system properties OR the encryption options in the cassandra.yaml. @@ -62,7 +68,9 @@ public void testDefaultEncryptionOptions() throws Throwable .build(); try (Cluster cluster = builder().withNodes(1).withConfig(c -> { - c.with(Feature.JMX).set("jmx_encryption_options", encryptionOptionsMap); + c.with(Feature.JMX).set("jmx_server_options", of("enabled", + true, + "jmx_encryption_options", encryptionOptionsMap)); }).start()) { Map jmxEnv = new HashMap<>(); @@ -85,7 +93,8 @@ public void testClientAuth() throws Throwable .build(); try (Cluster cluster = builder().withNodes(1).withConfig(c -> { - c.with(Feature.JMX).set("jmx_encryption_options", encryptionOptionsMap); + c.with(Feature.JMX).set("jmx_server_options", of("enabled", true, + "jmx_encryption_options", encryptionOptionsMap)); }).start()) { Map jmxEnv = new HashMap<>(); @@ -99,8 +108,8 @@ public void testClientAuth() throws Throwable public void testSystemSettings() throws Throwable { COM_SUN_MANAGEMENT_JMXREMOTE_SSL_ENABLED_CIPHER_SUITES.reset(); - try (WithProperties withProperties = JMXSslPropertiesUtil.use(true, false, - "TLSv1.2,TLSv1.3,TLSv1.1")) + try (WithProperties withProperties = JMXSslPropertiesUtil.use(true, false, "TLSv1.2,TLSv1.3,TLSv1.1") + .set(CASSANDRA_JMX_LOCAL_PORT, 7199)) { setKeystoreProperties(withProperties); try (Cluster cluster = builder().withNodes(1).withConfig(c -> { @@ -120,13 +129,11 @@ public void testSystemSettings() throws Throwable public void testInvalidKeystorePath() throws Throwable { try (Cluster cluster = builder().withNodes(1).withConfig(c -> { - c.with(Feature.JMX).set("jmx_encryption_options", - ImmutableMap.builder() - .put("enabled", true) - .put("keystore", "/path/to/bad/keystore/that/should/not/exist") - .put("keystore_password", "cassandra") - .put("accepted_protocols", Arrays.asList("TLSv1.2", "TLSv1.3", "TLSv1.1")) - .build()); + c.with(Feature.JMX).set("jmx_server_options", of("enabled", true, + "jmx_encryption_options", of("enabled", true, + "keystore", "/path/to/bad/keystore/that/should/not/exist", + "keystore_password", "cassandra", + "accepted_protocols", Arrays.asList("TLSv1.2", "TLSv1.3", "TLSv1.1")))); }).createWithoutStarting()) { assertCannotStartDueToConfigurationException(cluster); @@ -141,12 +148,11 @@ public void testInvalidKeystorePath() throws Throwable public void testDisabledEncryptionOptions() throws Throwable { try (Cluster cluster = builder().withNodes(1).withConfig(c -> { - c.with(Feature.JMX).set("jmx_encryption_options", - ImmutableMap.builder() - .put("enabled", false) - .put("keystore", "/path/to/bad/keystore/that/should/not/exist") - .put("keystore_password", "cassandra") - .build()); + c.with(Feature.JMX).set("jmx_server_options", of("enabled", true, + "jmx_encryption_options", + of("enabled", false, + "keystore", "/path/to/bad/keystore/that/should/not/exist", + "keystore_password", "cassandra"))); }).start()) { JMXTestsUtil.testAllValidGetters(cluster, null); @@ -155,10 +161,10 @@ public void testDisabledEncryptionOptions() throws Throwable private void setKeystoreProperties(WithProperties properties) { - properties.with("javax.net.ssl.trustStore", (String) validFileBasedKeystores.get("truststore"), - "javax.net.ssl.trustStorePassword", (String) validFileBasedKeystores.get("truststore_password"), - "javax.net.ssl.keyStore", (String) validFileBasedKeystores.get("keystore"), - "javax.net.ssl.keyStorePassword", (String) validFileBasedKeystores.get("keystore_password")); + properties.with(JAVAX_NET_SSL_TRUSTSTORE.getKey(), (String) validFileBasedKeystores.get("truststore"), + JAVAX_NET_SSL_TRUSTSTOREPASSWORD.getKey(), (String) validFileBasedKeystores.get("truststore_password"), + JAVAX_NET_SSL_KEYSTORE.getKey(), (String) validFileBasedKeystores.get("keystore"), + JAVAX_NET_SSL_KEYSTOREPASSWORD.getKey(), (String) validFileBasedKeystores.get("keystore_password")); } @SuppressWarnings("unchecked") diff --git a/test/resources/auth/cassandra-test-jaas.conf b/test/resources/auth/cassandra-test-jaas.conf index ccb8b6a90a01..59e00d291620 100644 --- a/test/resources/auth/cassandra-test-jaas.conf +++ b/test/resources/auth/cassandra-test-jaas.conf @@ -1,4 +1,4 @@ // Delegates authentication to a stub login module, hardcoded to authenticate as a particular user - see JMXAuthTest TestLogin { - org.apache.cassandra.auth.jmx.JMXAuthTest$StubLoginModule REQUIRED role_name=test_role; + org.apache.cassandra.auth.jmx.AbstractJMXAuthTest$StubLoginModule REQUIRED role_name=test_role; }; diff --git a/test/unit/org/apache/cassandra/auth/jmx/JMXAuthTest.java b/test/unit/org/apache/cassandra/auth/jmx/AbstractJMXAuthTest.java similarity index 87% rename from test/unit/org/apache/cassandra/auth/jmx/JMXAuthTest.java rename to test/unit/org/apache/cassandra/auth/jmx/AbstractJMXAuthTest.java index fece405f5f25..0d75ce6a6223 100644 --- a/test/unit/org/apache/cassandra/auth/jmx/JMXAuthTest.java +++ b/test/unit/org/apache/cassandra/auth/jmx/AbstractJMXAuthTest.java @@ -19,14 +19,16 @@ package org.apache.cassandra.auth.jmx; import java.lang.reflect.Field; -import java.nio.file.Paths; import java.rmi.server.RMISocketFactory; import java.util.HashMap; import java.util.Map; import javax.management.JMX; import javax.management.MBeanServerConnection; import javax.management.ObjectName; -import javax.management.remote.*; +import javax.management.remote.JMXConnector; +import javax.management.remote.JMXConnectorFactory; +import javax.management.remote.JMXConnectorServer; +import javax.management.remote.JMXServiceURL; import javax.security.auth.Subject; import javax.security.auth.callback.CallbackHandler; import javax.security.auth.login.LoginException; @@ -34,76 +36,35 @@ import com.google.common.collect.ImmutableSet; import org.junit.Before; -import org.junit.BeforeClass; +import org.junit.Ignore; import org.junit.Test; -import org.apache.cassandra.auth.*; +import org.apache.cassandra.auth.AuthenticatedUser; +import org.apache.cassandra.auth.CassandraPrincipal; +import org.apache.cassandra.auth.IAuthorizer; +import org.apache.cassandra.auth.JMXResource; +import org.apache.cassandra.auth.Permission; +import org.apache.cassandra.auth.RoleResource; +import org.apache.cassandra.auth.StubAuthorizer; import org.apache.cassandra.config.DatabaseDescriptor; +import org.apache.cassandra.config.JMXServerOptions; import org.apache.cassandra.cql3.CQLTester; import org.apache.cassandra.db.ColumnFamilyStoreMBean; import org.apache.cassandra.utils.JMXServerUtils; -import static org.apache.cassandra.config.CassandraRelevantProperties.CASSANDRA_JMX_AUTHORIZER; -import static org.apache.cassandra.config.CassandraRelevantProperties.CASSANDRA_JMX_REMOTE_LOGIN_CONFIG; -import static org.apache.cassandra.config.CassandraRelevantProperties.COM_SUN_MANAGEMENT_JMXREMOTE_AUTHENTICATE; -import static org.apache.cassandra.config.CassandraRelevantProperties.JAVA_SECURITY_AUTH_LOGIN_CONFIG; import static org.junit.Assert.assertEquals; import static org.junit.Assert.fail; -public class JMXAuthTest extends CQLTester +@Ignore +public abstract class AbstractJMXAuthTest extends CQLTester { private static JMXConnectorServer jmxServer; private static MBeanServerConnection connection; + private RoleResource role; private String tableName; private JMXResource tableMBean; - @FunctionalInterface - private interface MBeanAction - { - void execute(); - } - - @BeforeClass - public static void setupClass() throws Exception - { - setupAuthorizer(); - setupJMXServer(); - } - - private static void setupAuthorizer() - { - try - { - IAuthorizer authorizer = new StubAuthorizer(); - Field authorizerField = DatabaseDescriptor.class.getDeclaredField("authorizer"); - authorizerField.setAccessible(true); - authorizerField.set(null, authorizer); - DatabaseDescriptor.setPermissionsValidity(0); - } - catch (IllegalAccessException | NoSuchFieldException e) - { - throw new RuntimeException(e); - } - } - - private static void setupJMXServer() throws Exception - { - String config = Paths.get(ClassLoader.getSystemResource("auth/cassandra-test-jaas.conf").toURI()).toString(); - COM_SUN_MANAGEMENT_JMXREMOTE_AUTHENTICATE.setBoolean(true); - JAVA_SECURITY_AUTH_LOGIN_CONFIG.setString(config); - CASSANDRA_JMX_REMOTE_LOGIN_CONFIG.setString("TestLogin"); - CASSANDRA_JMX_AUTHORIZER.setString(NoSuperUserAuthorizationProxy.class.getName()); - jmxServer = JMXServerUtils.createJMXServer(9999, "localhost", true); - jmxServer.start(); - - JMXServiceURL jmxUrl = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://localhost:9999/jmxrmi"); - Map env = new HashMap<>(); - env.put("com.sun.jndi.rmi.factory.socket", RMISocketFactory.getDefaultSocketFactory()); - JMXConnector jmxc = JMXConnectorFactory.connect(jmxUrl, env); - connection = jmxc.getMBeanServerConnection(); - } - @Before public void setup() throws Throwable { @@ -193,6 +154,42 @@ public void executeMethod() throws Throwable assertPermissionOnResource(Permission.EXECUTE, JMXResource.root(), proxy::estimateKeys); } + + protected static void setupJMXServer(JMXServerOptions jmxServerOptions) throws Exception + { + jmxServerOptions.jmx_encryption_options.applyConfig(); + jmxServer = JMXServerUtils.createJMXServer(jmxServerOptions, "localhost"); + jmxServer.start(); + + JMXServiceURL jmxUrl = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://localhost:9999/jmxrmi"); + Map env = new HashMap<>(); + env.put("com.sun.jndi.rmi.factory.socket", RMISocketFactory.getDefaultSocketFactory()); + JMXConnector jmxc = JMXConnectorFactory.connect(jmxUrl, env); + connection = jmxc.getMBeanServerConnection(); + } + + protected static void setupAuthorizer() + { + try + { + IAuthorizer authorizer = new StubAuthorizer(); + Field authorizerField = DatabaseDescriptor.class.getDeclaredField("authorizer"); + authorizerField.setAccessible(true); + authorizerField.set(null, authorizer); + DatabaseDescriptor.setPermissionsValidity(0); + } + catch (IllegalAccessException | NoSuchFieldException e) + { + throw new RuntimeException(e); + } + } + + @FunctionalInterface + private interface MBeanAction + { + void execute(); + } + private void assertPermissionOnResource(Permission permission, JMXResource resource, MBeanAction action) @@ -238,12 +235,14 @@ public static class StubLoginModule implements LoginModule private CassandraPrincipal principal; private Subject subject; - public StubLoginModule(){} + public StubLoginModule() + { + } public void initialize(Subject subject, CallbackHandler callbackHandler, Map sharedState, Map options) { this.subject = subject; - principal = new CassandraPrincipal((String)options.get("role_name")); + principal = new CassandraPrincipal((String) options.get("role_name")); } public boolean login() throws LoginException diff --git a/test/unit/org/apache/cassandra/auth/jmx/JMXAuthJMXServerOptionsTest.java b/test/unit/org/apache/cassandra/auth/jmx/JMXAuthJMXServerOptionsTest.java new file mode 100644 index 000000000000..cb83a61eda17 --- /dev/null +++ b/test/unit/org/apache/cassandra/auth/jmx/JMXAuthJMXServerOptionsTest.java @@ -0,0 +1,48 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.cassandra.auth.jmx; + +import java.nio.file.Paths; + +import org.junit.BeforeClass; + +import org.apache.cassandra.config.EncryptionOptions; +import org.apache.cassandra.config.JMXServerOptions; + +/** + * Tests via server options normally constructed in cassandra.yaml. + */ +public class JMXAuthJMXServerOptionsTest extends AbstractJMXAuthTest +{ + @BeforeClass + public static void setupClass() throws Exception + { + setupAuthorizer(); + setupJMXServer(getJMXServerOptions()); + } + + private static JMXServerOptions getJMXServerOptions() throws Exception + { + String config = Paths.get(ClassLoader.getSystemResource("auth/cassandra-test-jaas.conf").toURI()).toString(); + + return new JMXServerOptions(true, false, 9999, 0, true, + new EncryptionOptions(), "TestLogin", config, null, null, + NoSuperUserAuthorizationProxy.class.getName()); + } +} diff --git a/test/unit/org/apache/cassandra/auth/jmx/JMXAuthSystemPropertiesTest.java b/test/unit/org/apache/cassandra/auth/jmx/JMXAuthSystemPropertiesTest.java new file mode 100644 index 000000000000..f527f2e609a3 --- /dev/null +++ b/test/unit/org/apache/cassandra/auth/jmx/JMXAuthSystemPropertiesTest.java @@ -0,0 +1,55 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.cassandra.auth.jmx; + +import java.nio.file.Paths; + +import org.junit.BeforeClass; + +import org.apache.cassandra.config.JMXServerOptions; + +import static org.apache.cassandra.config.CassandraRelevantProperties.CASSANDRA_JMX_AUTHORIZER; +import static org.apache.cassandra.config.CassandraRelevantProperties.CASSANDRA_JMX_LOCAL_PORT; +import static org.apache.cassandra.config.CassandraRelevantProperties.CASSANDRA_JMX_REMOTE_LOGIN_CONFIG; +import static org.apache.cassandra.config.CassandraRelevantProperties.COM_SUN_MANAGEMENT_JMXREMOTE_AUTHENTICATE; +import static org.apache.cassandra.config.CassandraRelevantProperties.JAVA_SECURITY_AUTH_LOGIN_CONFIG; + +/** + * Tests via system properties normally set in cassandra-env.sh + */ +public class JMXAuthSystemPropertiesTest extends AbstractJMXAuthTest +{ + @BeforeClass + public static void setupClass() throws Exception + { + setupAuthorizer(); + setupJMXServer(getJMXServerOptions()); + } + + private static JMXServerOptions getJMXServerOptions() throws Exception + { + String config = Paths.get(ClassLoader.getSystemResource("auth/cassandra-test-jaas.conf").toURI()).toString(); + COM_SUN_MANAGEMENT_JMXREMOTE_AUTHENTICATE.setBoolean(true); + JAVA_SECURITY_AUTH_LOGIN_CONFIG.setString(config); + CASSANDRA_JMX_REMOTE_LOGIN_CONFIG.setString("TestLogin"); + CASSANDRA_JMX_AUTHORIZER.setString(NoSuperUserAuthorizationProxy.class.getName()); + CASSANDRA_JMX_LOCAL_PORT.setInt(9999); + return JMXServerOptions.createParsingSystemProperties(); + } +} diff --git a/test/unit/org/apache/cassandra/config/DatabaseDescriptorRefTest.java b/test/unit/org/apache/cassandra/config/DatabaseDescriptorRefTest.java index dea0d867eefe..96b164a32256 100644 --- a/test/unit/org/apache/cassandra/config/DatabaseDescriptorRefTest.java +++ b/test/unit/org/apache/cassandra/config/DatabaseDescriptorRefTest.java @@ -144,6 +144,7 @@ public class DatabaseDescriptorRefTest "org.apache.cassandra.config.GuardrailsOptions$Config", "org.apache.cassandra.config.GuardrailsOptions$ConsistencyLevels", "org.apache.cassandra.config.GuardrailsOptions$TableProperties", + "org.apache.cassandra.config.JMXServerOptions", "org.apache.cassandra.config.ParameterizedClass", "org.apache.cassandra.config.RepairConfig", "org.apache.cassandra.config.RepairRetrySpec", diff --git a/test/unit/org/apache/cassandra/cql3/CQLTester.java b/test/unit/org/apache/cassandra/cql3/CQLTester.java index 2f5857ae9792..9410564b83dd 100644 --- a/test/unit/org/apache/cassandra/cql3/CQLTester.java +++ b/test/unit/org/apache/cassandra/cql3/CQLTester.java @@ -115,6 +115,7 @@ import org.apache.cassandra.config.DataStorageSpec; import org.apache.cassandra.config.DatabaseDescriptor; import org.apache.cassandra.config.EncryptionOptions; +import org.apache.cassandra.config.JMXServerOptions; import org.apache.cassandra.config.YamlConfigurationLoader; import org.apache.cassandra.cql3.functions.FunctionName; import org.apache.cassandra.cql3.functions.types.ParseUtils; @@ -190,7 +191,6 @@ import org.assertj.core.api.Assertions; import org.awaitility.Awaitility; -import static org.apache.cassandra.config.CassandraRelevantProperties.CASSANDRA_JMX_LOCAL_PORT; import static org.apache.cassandra.config.CassandraRelevantProperties.TEST_DRIVER_CONNECTION_TIMEOUT_MS; import static org.apache.cassandra.config.CassandraRelevantProperties.TEST_DRIVER_READ_TIMEOUT_MS; import static org.apache.cassandra.config.CassandraRelevantProperties.TEST_RANDOM_SEED; @@ -397,7 +397,7 @@ public static void startJMXServer() throws Exception InetAddress loopback = InetAddress.getLoopbackAddress(); jmxHost = loopback.getHostAddress(); jmxPort = getAutomaticallyAllocatedPort(loopback); - jmxServer = JMXServerUtils.createJMXServer(jmxPort, true); + jmxServer = JMXServerUtils.createJMXServer(JMXServerOptions.fromDescriptor(true, true, jmxPort)); jmxServer.start(); } @@ -518,7 +518,7 @@ protected void resetSchema() throws Throwable public static List buildNodetoolArgs(List args) { - int port = jmxPort == 0 ? CASSANDRA_JMX_LOCAL_PORT.getInt(7199) : jmxPort; + int port = jmxPort == 0 ? DatabaseDescriptor.getJmxServerOptions().jmx_port : jmxPort; String host = jmxHost == null ? "127.0.0.1" : jmxHost; List allArgs = new ArrayList<>(); allArgs.add("bin/nodetool"); diff --git a/test/unit/org/apache/cassandra/db/virtual/SettingsTableTest.java b/test/unit/org/apache/cassandra/db/virtual/SettingsTableTest.java index 1645e3150e59..71b9172da798 100644 --- a/test/unit/org/apache/cassandra/db/virtual/SettingsTableTest.java +++ b/test/unit/org/apache/cassandra/db/virtual/SettingsTableTest.java @@ -32,6 +32,7 @@ import org.apache.cassandra.config.Config; import org.apache.cassandra.config.DurationSpec; import org.apache.cassandra.config.EncryptionOptions.ServerEncryptionOptions.InternodeEncryption; +import org.apache.cassandra.config.JMXServerOptions; import org.apache.cassandra.config.ParameterizedClass; import org.apache.cassandra.cql3.CQLTester; import org.apache.cassandra.security.SSLFactory; @@ -52,7 +53,8 @@ public void config() config = new Config(); config.client_encryption_options.applyConfig(); config.server_encryption_options.applyConfig(); - config.jmx_encryption_options.applyConfig(); + config.jmx_server_options = new JMXServerOptions(); + config.jmx_server_options.jmx_encryption_options.applyConfig(); config.sstable_preemptive_open_interval = null; config.index_summary_resize_interval = null; config.cache_load_timeout = new DurationSpec.IntSecondsBound(0); diff --git a/test/unit/org/apache/cassandra/tools/ToolsEnvsConfigsTest.java b/test/unit/org/apache/cassandra/tools/ToolsEnvsConfigsTest.java index 6e593ccb9b71..1ee7192478e7 100644 --- a/test/unit/org/apache/cassandra/tools/ToolsEnvsConfigsTest.java +++ b/test/unit/org/apache/cassandra/tools/ToolsEnvsConfigsTest.java @@ -21,9 +21,9 @@ import java.util.Collections; import com.google.common.collect.ImmutableMap; - import org.junit.Test; +import org.apache.cassandra.config.DatabaseDescriptor; import org.apache.cassandra.cql3.CQLTester; import org.apache.cassandra.tools.ToolRunner.ToolResult; @@ -35,6 +35,7 @@ public class ToolsEnvsConfigsTest @Test public void testJDKEnvInfoDefaultCleaners() { + DatabaseDescriptor.daemonInitialization(); ToolResult tool = ToolRunner.invoke(ImmutableMap.of("_JAVA_OPTIONS", "-Djava.net.preferIPv4Stack=true"), null, CQLTester.buildNodetoolArgs(Collections.emptyList())); diff --git a/test/unit/org/apache/cassandra/tools/nodetool/SjkTest.java b/test/unit/org/apache/cassandra/tools/nodetool/SjkTest.java index 9812ef250bf6..65dcbede9555 100644 --- a/test/unit/org/apache/cassandra/tools/nodetool/SjkTest.java +++ b/test/unit/org/apache/cassandra/tools/nodetool/SjkTest.java @@ -19,6 +19,7 @@ import org.junit.Test; +import org.apache.cassandra.config.DatabaseDescriptor; import org.apache.cassandra.tools.ToolRunner; public class SjkTest @@ -26,6 +27,7 @@ public class SjkTest @Test public void sjkHelpReturnsRc0() { + DatabaseDescriptor.daemonInitialization(); ToolRunner.ToolResult tool = ToolRunner.invokeNodetool("sjk", "--help"); tool.assertOnExitCode(); } diff --git a/test/unit/org/apache/cassandra/utils/jmx/DuplicateJMXConfigurationTest.java b/test/unit/org/apache/cassandra/utils/jmx/DuplicateJMXConfigurationTest.java new file mode 100644 index 000000000000..976507badb3b --- /dev/null +++ b/test/unit/org/apache/cassandra/utils/jmx/DuplicateJMXConfigurationTest.java @@ -0,0 +1,67 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.cassandra.utils.jmx; + +import org.junit.Test; + +import org.apache.cassandra.config.DatabaseDescriptor; +import org.apache.cassandra.distributed.shared.WithProperties; +import org.apache.cassandra.exceptions.ConfigurationException; + +import static org.apache.cassandra.config.CassandraRelevantProperties.CASSANDRA_CONFIG; +import static org.apache.cassandra.config.CassandraRelevantProperties.CASSANDRA_JMX_REMOTE_PORT; +import static org.apache.cassandra.config.CassandraRelevantProperties.COM_SUN_MANAGEMENT_JMXREMOTE_AUTHENTICATE; +import static org.apache.cassandra.config.CassandraRelevantProperties.COM_SUN_MANAGEMENT_JMXREMOTE_SSL; +import static org.apache.cassandra.config.CassandraRelevantProperties.COM_SUN_MANAGEMENT_JMXREMOTE_SSL_ENABLED_CIPHER_SUITES; +import static org.apache.cassandra.config.CassandraRelevantProperties.COM_SUN_MANAGEMENT_JMXREMOTE_SSL_ENABLED_PROTOCOLS; +import static org.apache.cassandra.config.CassandraRelevantProperties.COM_SUN_MANAGEMENT_JMXREMOTE_SSL_NEED_CLIENT_AUTH; +import static org.apache.cassandra.config.CassandraRelevantProperties.JAVAX_NET_SSL_KEYSTORE; +import static org.apache.cassandra.config.CassandraRelevantProperties.JAVAX_NET_SSL_KEYSTOREPASSWORD; +import static org.apache.cassandra.config.CassandraRelevantProperties.JAVAX_NET_SSL_TRUSTSTORE; +import static org.apache.cassandra.config.CassandraRelevantProperties.JAVAX_NET_SSL_TRUSTSTOREPASSWORD; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +public class DuplicateJMXConfigurationTest +{ + @Test + public void testDuplicateConfiguration() + { + String enabledProtocols = "TLSv1.2,TLSv1.3,TLSv1.1"; + String cipherSuites = "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256"; + + try (WithProperties props = new WithProperties().set(CASSANDRA_CONFIG, "cassandra-jmx-sslconfig.yaml") + .set(CASSANDRA_JMX_REMOTE_PORT, 7199) + .set(COM_SUN_MANAGEMENT_JMXREMOTE_AUTHENTICATE, true) + .set(COM_SUN_MANAGEMENT_JMXREMOTE_SSL, true) + .set(COM_SUN_MANAGEMENT_JMXREMOTE_SSL_NEED_CLIENT_AUTH, true) + .set(COM_SUN_MANAGEMENT_JMXREMOTE_SSL_ENABLED_PROTOCOLS, enabledProtocols) + .set(COM_SUN_MANAGEMENT_JMXREMOTE_SSL_ENABLED_CIPHER_SUITES, cipherSuites) + .set(JAVAX_NET_SSL_KEYSTORE, "test/conf/cassandra_ssl_test.keystore") + .set(JAVAX_NET_SSL_TRUSTSTORE, "test/conf/cassandra_ssl_test.truststore") + .set(JAVAX_NET_SSL_KEYSTOREPASSWORD, "cassandra") + .set(JAVAX_NET_SSL_TRUSTSTOREPASSWORD, "cassandra")) + { + assertThatThrownBy(DatabaseDescriptor::daemonInitialization) + .isInstanceOf(ConfigurationException.class) + .hasMessageContaining("Configure either jmx_server_options in cassandra.yaml and comment out configure_jmx function " + + "call in cassandra-env.sh or keep cassandra-env.sh to call configure_jmx function but you have to keep " + + "jmx_server_options in cassandra.yaml commented out."); + } + } +} diff --git a/test/unit/org/apache/cassandra/utils/jmx/JMXSslConfigTest.java b/test/unit/org/apache/cassandra/utils/jmx/JMXSslConfigTest.java index 2e739c558ba5..fb6a248dab96 100644 --- a/test/unit/org/apache/cassandra/utils/jmx/JMXSslConfigTest.java +++ b/test/unit/org/apache/cassandra/utils/jmx/JMXSslConfigTest.java @@ -30,10 +30,15 @@ import org.junit.Test; import org.apache.cassandra.config.DatabaseDescriptor; +import org.apache.cassandra.config.JMXServerOptions; import org.apache.cassandra.distributed.shared.WithProperties; import org.apache.cassandra.utils.JMXServerUtils; import static org.apache.cassandra.config.CassandraRelevantProperties.CASSANDRA_CONFIG; +import static org.apache.cassandra.config.CassandraRelevantProperties.JAVAX_NET_SSL_KEYSTORE; +import static org.apache.cassandra.config.CassandraRelevantProperties.JAVAX_NET_SSL_KEYSTOREPASSWORD; +import static org.apache.cassandra.config.CassandraRelevantProperties.JAVAX_NET_SSL_TRUSTSTORE; +import static org.apache.cassandra.config.CassandraRelevantProperties.JAVAX_NET_SSL_TRUSTSTOREPASSWORD; import static org.apache.cassandra.config.CassandraRelevantProperties.JAVAX_RMI_SSL_CLIENT_ENABLED_CIPHER_SUITES; import static org.apache.cassandra.config.CassandraRelevantProperties.JAVAX_RMI_SSL_CLIENT_ENABLED_PROTOCOLS; @@ -68,10 +73,15 @@ public void testRemoteJmxSystemConfig() throws SSLException String enabledProtocols = "TLSv1.2,TLSv1.3,TLSv1.1"; String cipherSuites = "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256"; - try (WithProperties ignored = JMXSslPropertiesUtil.use(true, true, enabledProtocols, - cipherSuites)) + try (WithProperties ignored = JMXSslPropertiesUtil.use(true, true, enabledProtocols, cipherSuites) + .set(JAVAX_NET_SSL_KEYSTORE, "test/conf/cassandra_ssl_test.keystore") + .set(JAVAX_NET_SSL_TRUSTSTORE, "test/conf/cassandra_ssl_test.truststore") + .set(JAVAX_NET_SSL_KEYSTOREPASSWORD, "cassandra") + .set(JAVAX_NET_SSL_TRUSTSTOREPASSWORD, "cassandra")) { - Map env = JMXServerUtils.configureJmxSocketFactories(serverAddress, false); + JMXServerOptions options = JMXServerOptions.createParsingSystemProperties(); + options.jmx_encryption_options.applyConfig(); + Map env = JMXServerUtils.configureJmxSocketFactories(serverAddress, options); Assert.assertNotNull("ServerSocketFactory must not be null", env.get(RMIConnectorServer.RMI_SERVER_SOCKET_FACTORY_ATTRIBUTE)); Assert.assertTrue("RMI_SERVER_SOCKET_FACTORY must be of SslRMIServerSocketFactory type", env.get(RMIConnectorServer.RMI_SERVER_SOCKET_FACTORY_ATTRIBUTE) instanceof SslRMIServerSocketFactory); Assert.assertNotNull("ClientSocketFactory must not be null", env.get(RMIConnectorServer.RMI_CLIENT_SOCKET_FACTORY_ATTRIBUTE)); @@ -90,7 +100,8 @@ public void testLocalJmxServer() throws SSLException InetAddress serverAddress = InetAddress.getLoopbackAddress(); try (WithProperties ignored = JMXSslPropertiesUtil.use(false)) { - Map env = JMXServerUtils.configureJmxSocketFactories(serverAddress, true); + JMXServerOptions options = JMXServerOptions.fromDescriptor(true, true, 7199); + Map env = JMXServerUtils.configureJmxSocketFactories(serverAddress, options); Assert.assertNull("ClientSocketFactory must be null", env.get(RMIConnectorServer.RMI_CLIENT_SOCKET_FACTORY_ATTRIBUTE)); Assert.assertNull("com.sun.jndi.rmi.factory.socket must not be set in the env", env.get("com.sun.jndi.rmi.factory.socket")); diff --git a/test/unit/org/apache/cassandra/utils/jmx/JMXSslConfiguredWithYamlFileOptionsTest.java b/test/unit/org/apache/cassandra/utils/jmx/JMXSslConfiguredWithYamlFileOptionsTest.java index 3855183a9259..c9d2d9f09184 100644 --- a/test/unit/org/apache/cassandra/utils/jmx/JMXSslConfiguredWithYamlFileOptionsTest.java +++ b/test/unit/org/apache/cassandra/utils/jmx/JMXSslConfiguredWithYamlFileOptionsTest.java @@ -31,9 +31,8 @@ import org.junit.Test; import org.apache.cassandra.config.DatabaseDescriptor; -import org.apache.cassandra.config.EncryptionOptions; +import org.apache.cassandra.config.JMXServerOptions; import org.apache.cassandra.distributed.shared.WithProperties; -import org.apache.cassandra.exceptions.ConfigurationException; import org.apache.cassandra.utils.JMXServerUtils; import static org.apache.cassandra.config.CassandraRelevantProperties.CASSANDRA_CONFIG; @@ -66,15 +65,15 @@ public static void tearDownDatabaseDescriptor() @Test public void testYamlFileJmxEncryptionOptions() throws SSLException { - EncryptionOptions jmxEncryptionOptions = DatabaseDescriptor.getJmxEncryptionOptions(); - String expectedProtocols = StringUtils.join(jmxEncryptionOptions.getAcceptedProtocols(), ","); - String expectedCipherSuites = StringUtils.join(jmxEncryptionOptions.cipherSuitesArray(), ","); + JMXServerOptions serverOptions = DatabaseDescriptor.getJmxServerOptions(); + String expectedProtocols = StringUtils.join(serverOptions.jmx_encryption_options.getAcceptedProtocols(), ","); + String expectedCipherSuites = StringUtils.join(serverOptions.jmx_encryption_options.cipherSuitesArray(), ","); InetAddress serverAddress = InetAddress.getLoopbackAddress(); try (WithProperties ignored = JMXSslPropertiesUtil.use(false)) { - Map env = JMXServerUtils.configureJmxSocketFactories(serverAddress, false); + Map env = JMXServerUtils.configureJmxSocketFactories(serverAddress, serverOptions); Assert.assertTrue("com.sun.management.jmxremote.ssl must be true", COM_SUN_MANAGEMENT_JMXREMOTE_SSL.getBoolean()); Assert.assertNotNull("ServerSocketFactory must not be null", env.get(RMIConnectorServer.RMI_SERVER_SOCKET_FACTORY_ATTRIBUTE)); Assert.assertTrue("RMI_SERVER_SOCKET_FACTORY must be of JMXSslRMIServerSocketFactory type", env.get(RMIConnectorServer.RMI_SERVER_SOCKET_FACTORY_ATTRIBUTE) instanceof SslRMIServerSocketFactory); @@ -84,21 +83,4 @@ public void testYamlFileJmxEncryptionOptions() throws SSLException Assert.assertEquals("javax.rmi.ssl.client.enabledCipherSuites must match", expectedCipherSuites, JAVAX_RMI_SSL_CLIENT_ENABLED_CIPHER_SUITES.getString()); } } - - /** - * Tests for the error scenario when the JMX SSL configuration is provided as - * system configuration as well as encryption_options. - * - * @throws SSLException - */ - @Test(expected = ConfigurationException.class) - public void testDuplicateConfig() throws SSLException - { - InetAddress serverAddress = InetAddress.getLoopbackAddress(); - - try (WithProperties ignored = JMXSslPropertiesUtil.use(true)) - { - JMXServerUtils.configureJmxSocketFactories(serverAddress, false); - } - } } diff --git a/test/unit/org/apache/cassandra/utils/jmx/JMXSslDisabledEncryptionOptionsTest.java b/test/unit/org/apache/cassandra/utils/jmx/JMXSslDisabledEncryptionOptionsTest.java index ef2070f2aa20..841a93357fc1 100644 --- a/test/unit/org/apache/cassandra/utils/jmx/JMXSslDisabledEncryptionOptionsTest.java +++ b/test/unit/org/apache/cassandra/utils/jmx/JMXSslDisabledEncryptionOptionsTest.java @@ -29,6 +29,7 @@ import org.junit.Test; import org.apache.cassandra.config.DatabaseDescriptor; +import org.apache.cassandra.config.JMXServerOptions; import org.apache.cassandra.distributed.shared.WithProperties; import org.apache.cassandra.utils.JMXServerUtils; @@ -71,7 +72,7 @@ public void testDisabledJmxSslConfigs() throws SSLException try (WithProperties ignored = JMXSslPropertiesUtil.use(false)) { - Map env = JMXServerUtils.configureJmxSocketFactories(serverAddress, false); + Map env = JMXServerUtils.configureJmxSocketFactories(serverAddress, JMXServerOptions.fromDescriptor(true, false, 7199)); Assert.assertTrue("no properties must be set", env.isEmpty()); Assert.assertFalse("com.sun.management.jmxremote.ssl must be false", COM_SUN_MANAGEMENT_JMXREMOTE_SSL.getBoolean()); Assert.assertNull("javax.rmi.ssl.client.enabledProtocols must be null", JAVAX_RMI_SSL_CLIENT_ENABLED_PROTOCOLS.getString()); @@ -90,7 +91,7 @@ public void testFallbackToLocalJmxServer() throws SSLException try (WithProperties ignored = JMXSslPropertiesUtil.use(false)) { - Map env = JMXServerUtils.configureJmxSocketFactories(serverAddress, true); + Map env = JMXServerUtils.configureJmxSocketFactories(serverAddress, JMXServerOptions.fromDescriptor(true, true, 7199)); Assert.assertFalse("com.sun.management.jmxremote.ssl must be false", COM_SUN_MANAGEMENT_JMXREMOTE_SSL.getBoolean()); Assert.assertNull("com.sun.jndi.rmi.factory.socket must be null", env.get("com.sun.jndi.rmi.factory.socket")); Assert.assertNotNull("ServerSocketFactory must not be null", env.get(RMIConnectorServer.RMI_SERVER_SOCKET_FACTORY_ATTRIBUTE)); diff --git a/test/unit/org/apache/cassandra/utils/jmx/JMXSslPEMConfigTest.java b/test/unit/org/apache/cassandra/utils/jmx/JMXSslPEMConfigTest.java index c7db7b2c724b..01459954e61d 100644 --- a/test/unit/org/apache/cassandra/utils/jmx/JMXSslPEMConfigTest.java +++ b/test/unit/org/apache/cassandra/utils/jmx/JMXSslPEMConfigTest.java @@ -31,7 +31,7 @@ import org.junit.Test; import org.apache.cassandra.config.DatabaseDescriptor; -import org.apache.cassandra.config.EncryptionOptions; +import org.apache.cassandra.config.JMXServerOptions; import org.apache.cassandra.distributed.shared.WithProperties; import org.apache.cassandra.utils.JMXServerUtils; @@ -63,15 +63,15 @@ public static void tearDownDatabaseDescriptor() @Test public void testPEMBasedJmxSslConfig() throws SSLException { - EncryptionOptions jmxEncryptionOptions = DatabaseDescriptor.getJmxEncryptionOptions(); - String expectedProtocols = StringUtils.join(jmxEncryptionOptions.getAcceptedProtocols(), ","); - String expectedCipherSuites = StringUtils.join(jmxEncryptionOptions.cipherSuitesArray(), ","); + JMXServerOptions serverOptions = DatabaseDescriptor.getJmxServerOptions(); + String expectedProtocols = StringUtils.join(serverOptions.jmx_encryption_options.getAcceptedProtocols(), ","); + String expectedCipherSuites = StringUtils.join(serverOptions.jmx_encryption_options.cipherSuitesArray(), ","); InetAddress serverAddress = InetAddress.getLoopbackAddress(); try (WithProperties ignored = JMXSslPropertiesUtil.use(false)) { - Map env = JMXServerUtils.configureJmxSocketFactories(serverAddress, false); + Map env = JMXServerUtils.configureJmxSocketFactories(serverAddress, serverOptions); Assert.assertTrue("com.sun.management.jmxremote.ssl must be true", COM_SUN_MANAGEMENT_JMXREMOTE_SSL.getBoolean()); Assert.assertNotNull("ServerSocketFactory must not be null", env.get(RMIConnectorServer.RMI_SERVER_SOCKET_FACTORY_ATTRIBUTE)); Assert.assertTrue("RMI_SERVER_SOCKET_FACTORY must be of JMXSslRMIServerSocketFactory type", env.get(RMIConnectorServer.RMI_SERVER_SOCKET_FACTORY_ATTRIBUTE) instanceof SslRMIServerSocketFactory);