Enable JMX server configuration to be in cassandra.yaml

patch by Zhongxiang Zheng; reviewed by Stefan Miklosovic, Maulin Vasavada, Cheng Wang, Jordan West for CASSANDRA-11695

Co-authored-by: Stefan Miklosovic <smiklosovic@apache.org>
Co-authored-by: Sam Tunnicliffe <samt@apache.org>
This commit is contained in:
Zhongxiang Zheng 2016-06-30 18:17:49 +09:00 committed by Stefan Miklosovic
parent 54e4688069
commit 2ff41551a6
No known key found for this signature in database
GPG Key ID: 32F35CB2F546D93E
38 changed files with 1041 additions and 573 deletions

View File

@ -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)

View File

@ -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

View File

@ -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=""

View File

@ -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.
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=<enabled-protocols>"
#JVM_OPTS="$JVM_OPTS -Dcom.sun.management.jmxremote.ssl.enabled.cipher.suites=<enabled-cipher-suites>"
#JVM_OPTS="$JVM_OPTS -Djavax.net.ssl.keyStore=/path/to/keystore"
#JVM_OPTS="$JVM_OPTS -Djavax.net.ssl.keyStorePassword=<keystore-password>"
#JVM_OPTS="$JVM_OPTS -Djavax.net.ssl.trustStore=/path/to/truststore"
#JVM_OPTS="$JVM_OPTS -Djavax.net.ssl.trustStorePassword=<truststore-password>"
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"
}
# 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.
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=<enabled-protocols>"
#JVM_OPTS="$JVM_OPTS -Dcom.sun.management.jmxremote.ssl.enabled.cipher.suites=<enabled-cipher-suites>"
#JVM_OPTS="$JVM_OPTS -Djavax.net.ssl.keyStore=/path/to/keystore"
#JVM_OPTS="$JVM_OPTS -Djavax.net.ssl.keyStorePassword=<keystore-password>"
#JVM_OPTS="$JVM_OPTS -Djavax.net.ssl.trustStore=/path/to/truststore"
#JVM_OPTS="$JVM_OPTS -Djavax.net.ssl.trustStorePassword=<truststore-password>"
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"
configure_jmx 7199
# To use mx4j, an HTML interface for JMX, add mx4j-tools.jar to the lib/
# directory.

View File

@ -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.

View File

@ -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.

View File

@ -49,7 +49,7 @@ COMPLEX_OPTIONS = (
'hints_compression',
'server_encryption_options',
'client_encryption_options',
'jmx_encryption_options',
'jmx_server_options',
'transparent_data_encryption_options',
'hinted_handoff_disabled_datacenters',
'startup_checks',

View File

@ -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. */

View File

@ -434,7 +434,8 @@ public class Config
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 class Config
private static final Set<String> SENSITIVE_KEYS = new HashSet<String>() {{
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)

View File

@ -960,8 +960,19 @@ public class DatabaseDescriptor
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 class DatabaseDescriptor
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 class DatabaseDescriptor
return conf.client_encryption_options;
}
public static EncryptionOptions getJmxEncryptionOptions()
public static JMXServerOptions getJmxServerOptions()
{
return conf.jmx_encryption_options;
return conf.jmx_server_options;
}
@VisibleForTesting

View File

@ -470,7 +470,12 @@ public class EncryptionOptions
public String[] acceptedProtocolsArray()
{
List<String> ap = getAcceptedProtocols();
return ap == null ? new String[0] : ap.toArray(new String[0]);
return ap == null ? null : ap.toArray(new String[0]);
}
public List<String> getCipherSuites()
{
return sslContextFactoryInstance == null ? null : sslContextFactoryInstance.getCipherSuites();
}
public String[] cipherSuitesArray()

View File

@ -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<String> cipherSuites = null;
if (rawCipherSuites != null)
cipherSuites = List.of(StringUtils.split(rawCipherSuites, ","));
String rawSslProtocols = COM_SUN_MANAGEMENT_JMXREMOTE_SSL_ENABLED_PROTOCOLS.getString();
List<String> 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.
* <pre>
* com.sun.management.jmxremote.ssl=true
* javax.rmi.ssl.client.enabledCipherSuites=&lt;applicable cipher suites provided in the configuration&gt;
* javax.rmi.ssl.client.enabledProtocols=&lt;applicable protocols provided in the configuration&gt;
* </pre>
*
* @param acceptedProtocols for the SSL communication
* @param cipherSuites for the SSL communication
*/
public static void setJmxSystemProperties(List<String> acceptedProtocols, List<String> 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, ","));
}
}

View File

@ -48,6 +48,7 @@ import org.apache.cassandra.auth.AuthCacheService;
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 org.apache.cassandra.utils.logging.VirtualTableAppender;
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 @@ public class CassandraDaemon
// 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)
{

View File

@ -54,6 +54,7 @@ import net.jpountz.lz4.LZ4Factory;
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.FBUtilities;
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 class StartupChecks
{
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 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 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 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);
}
}
};

View File

@ -33,7 +33,6 @@ import java.rmi.NoSuchObjectException;
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.net.ssl.SSLException;
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<String, Object> 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 class JMXServerUtils
// 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 class JMXServerUtils
// 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 class JMXServerUtils
// 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 class JMXServerUtils
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<String, Object> configureSecureCredentials()
@ -159,10 +154,10 @@ public class JMXServerUtils
return env;
}
private static Map<String, Object> configureJmxAuthentication()
private static Map<String, Object> configureJmxAuthentication(JMXServerOptions options)
{
Map<String, Object> 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 @@ public class JMXServerUtils
// 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 @@ public class JMXServerUtils
return env;
}
private static MBeanServerForwarder configureJmxAuthorization(Map<String, Object> env)
private static MBeanServerForwarder configureJmxAuthorization(JMXServerOptions options, Map<String, Object> 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 @@ public class JMXServerUtils
}
else
{
String accessFile = COM_SUN_MANAGEMENT_JMXREMOTE_ACCESS_FILE.getString();
String accessFile = options.access_file;
if (accessFile != null)
{
env.put("jmx.remote.x.access.file", accessFile);
@ -227,18 +238,16 @@ public class JMXServerUtils
* for configuring this.
*
* @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 options for JMX server, either from {@code cassandra.yaml} or parsed as system properties from {@code cassandra-env.sh}.
* @return Map&lt;String, Object@gt; containing {@code jmx.remote.rmi.client.socket.factory}, {@code jmx.remote.rmi.server.socket.factory}
* 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
*
* @see DefaultJmxSocketFactory
*/
@VisibleForTesting
public static Map<String, Object> configureJmxSocketFactories(InetAddress serverAddress, boolean localOnly) throws SSLException
public static Map<String, Object> 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

View File

@ -24,19 +24,11 @@ import java.util.Map;
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
* </pre>
*
* @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 <a href="https://docs.oracle.com/en/java/javase/17/management/monitoring-and-management-using-jmx-technology.html#GUID-F08985BB-629A-4FBF-A0CB-8762DF7590E0">Java Documentation</a>
@ -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<String, Object> configure(InetAddress serverAddress, boolean localOnly,
public Map<String, Object> configure(InetAddress serverAddress,
JMXServerOptions serverOptions,
EncryptionOptions jmxEncryptionOptions) throws SSLException
{
Map<String, Object> 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");
}
if (jmxEncryptionOptions.getEnabled())
JMXServerOptions.setJmxSystemProperties(jmxEncryptionOptions.getAcceptedProtocols(), jmxEncryptionOptions.getCipherSuites());
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());
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 @@ abstract public class AbstractJmxSocketFactory
*/
abstract public void configureSslClientSocketFactory(Map<String, Object> 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<String, Object> 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 class AbstractJmxSocketFactory
abstract public void configureSslServerSocketFactory(Map<String, Object> env, InetAddress serverAddress,
String[] enabledCipherSuites, String[] enabledProtocols,
boolean needClientAuth, SSLContext sslContext);
/**
* Sets the following JMX system properties.
* <pre>
* com.sun.management.jmxremote.ssl=true
* javax.rmi.ssl.client.enabledCipherSuites=&lt;applicable cipher suites provided in the configuration&gt;
* javax.rmi.ssl.client.enabledProtocols=&lt;applicable protocols provided in the configuration&gt;
* </pre>
*
* @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(), ","));
}
}

View File

@ -53,15 +53,6 @@ public final class DefaultJmxSocketFactory extends AbstractJmxSocketFactory
env.put("com.sun.jndi.rmi.factory.socket", clientFactory);
}
@Override
public void configureSslServerSocketFactory(Map<String, Object> 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<String, Object> env, InetAddress serverAddress, String[] enabledCipherSuites,
String[] enabledProtocols, boolean needClientAuth, SSLContext sslContext)

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -57,16 +57,6 @@ class CollectingSslRMIServerSocketFactoryImpl implements RMICloseableServerSocke
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;

View File

@ -35,6 +35,7 @@ import com.google.common.util.concurrent.Uninterruptibles;
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 class IsolatedJmx
((MBeanWrapper.DelegatingMbeanWrapper) MBeanWrapper.instance).setDelegate(wrapper);
// CASSANDRA-18508: Sensitive JMX SSL configuration options can be easily exposed
Map<String, Object> encryptionOptionsMap = (Map<String, Object>) config.getParams().get("jmx_encryption_options");
EncryptionOptions jmxEncryptionOptions = getJmxEncryptionOptions(encryptionOptionsMap);
Map<String, Object> jmxServerOptionsMap = (Map<String, Object>) 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<String, Object> socketFactories = new IsolatedJmxSocketFactory().configure(addr, true, jmxEncryptionOptions);
JMXServerOptions jmxServerOptions = JMXServerOptions.create(true, true, jmxPort, jmxEncryptionOptions);
Map<String, Object> 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<String, Object> env = new HashMap<>(socketFactories);
@ -148,12 +161,17 @@ public class IsolatedJmx
/**
* 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<String, Object> encryptionOptionsMap)
private EncryptionOptions getJmxEncryptionOptions(Map<String, Object> jmxServerOptionsMap)
{
if (jmxServerOptionsMap == null)
return null;
Map<String, Object> encryptionOptionsMap = (Map<String, Object>) jmxServerOptionsMap.get("jmx_encryption_options");
if (encryptionOptionsMap == null)
{
return null;

View File

@ -22,16 +22,19 @@ import java.net.InetAddress;
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<String, Object> 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<String, Object> 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<String, Object> 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<String, Object> env, InetAddress serverAddress, String[] enabledCipherSuites,
String[] enabledProtocols, boolean needClientAuth, SSLContext sslContext)
@ -81,7 +70,7 @@ public class IsolatedJmxSocketFactory extends AbstractJmxSocketFactory
enabledProtocols,
needClientAuth,
sslContext);
env.put(RMIConnectorServer.RMI_SERVER_SOCKET_FACTORY_ATTRIBUTE, serverFactory);
env.put(RMI_SERVER_SOCKET_FACTORY_ATTRIBUTE, serverFactory);
logJmxSslConfig(serverFactory);
}

View File

@ -37,7 +37,13 @@ import org.apache.cassandra.distributed.shared.WithProperties;
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 class JMXSslConfigDistributedTest extends AbstractEncryptionOptionsImpl
.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<String, Object> jmxEnv = new HashMap<>();
@ -85,7 +93,8 @@ public class JMXSslConfigDistributedTest extends AbstractEncryptionOptionsImpl
.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<String, Object> jmxEnv = new HashMap<>();
@ -99,8 +108,8 @@ public class JMXSslConfigDistributedTest extends AbstractEncryptionOptionsImpl
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 class JMXSslConfigDistributedTest extends AbstractEncryptionOptionsImpl
public void testInvalidKeystorePath() throws Throwable
{
try (Cluster cluster = builder().withNodes(1).withConfig(c -> {
c.with(Feature.JMX).set("jmx_encryption_options",
ImmutableMap.<String, Object>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 class JMXSslConfigDistributedTest extends AbstractEncryptionOptionsImpl
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 class JMXSslConfigDistributedTest extends AbstractEncryptionOptionsImpl
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")

View File

@ -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;
};

View File

@ -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 javax.security.auth.spi.LoginModule;
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<String, Object> 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 class JMXAuthTest extends CQLTester
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<String, Object> 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 class JMXAuthTest extends CQLTester
private CassandraPrincipal principal;
private Subject subject;
public StubLoginModule(){}
public StubLoginModule()
{
}
public void initialize(Subject subject, CallbackHandler callbackHandler, Map<String, ?> sharedState, Map<String, ?> 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

View File

@ -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());
}
}

View File

@ -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();
}
}

View File

@ -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",

View File

@ -115,6 +115,7 @@ import org.apache.cassandra.config.Config;
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.apache.cassandra.utils.TimeUUID;
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 abstract class CQLTester
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 @@ public abstract class CQLTester
public static List<String> buildNodetoolArgs(List<String> 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<String> allArgs = new ArrayList<>();
allArgs.add("bin/nodetool");

View File

@ -32,6 +32,7 @@ import com.datastax.driver.core.Row;
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 class SettingsTableTest extends CQLTester
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);

View File

@ -21,9 +21,9 @@ package org.apache.cassandra.tools;
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()));

View File

@ -19,6 +19,7 @@ package org.apache.cassandra.tools.nodetool;
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();
}

View File

@ -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.");
}
}
}

View File

@ -30,10 +30,15 @@ import org.junit.BeforeClass;
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 class JMXSslConfigTest
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<String, Object> env = JMXServerUtils.configureJmxSocketFactories(serverAddress, false);
JMXServerOptions options = JMXServerOptions.createParsingSystemProperties();
options.jmx_encryption_options.applyConfig();
Map<String, Object> 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 class JMXSslConfigTest
InetAddress serverAddress = InetAddress.getLoopbackAddress();
try (WithProperties ignored = JMXSslPropertiesUtil.use(false))
{
Map<String, Object> env = JMXServerUtils.configureJmxSocketFactories(serverAddress, true);
JMXServerOptions options = JMXServerOptions.fromDescriptor(true, true, 7199);
Map<String, Object> 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"));

View File

@ -31,9 +31,8 @@ import org.junit.BeforeClass;
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 class JMXSslConfiguredWithYamlFileOptionsTest
@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<String, Object> env = JMXServerUtils.configureJmxSocketFactories(serverAddress, false);
Map<String, Object> 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 class JMXSslConfiguredWithYamlFileOptionsTest
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);
}
}
}

View File

@ -29,6 +29,7 @@ import org.junit.BeforeClass;
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 class JMXSslDisabledEncryptionOptionsTest
try (WithProperties ignored = JMXSslPropertiesUtil.use(false))
{
Map<String, Object> env = JMXServerUtils.configureJmxSocketFactories(serverAddress, false);
Map<String, Object> 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 class JMXSslDisabledEncryptionOptionsTest
try (WithProperties ignored = JMXSslPropertiesUtil.use(false))
{
Map<String, Object> env = JMXServerUtils.configureJmxSocketFactories(serverAddress, true);
Map<String, Object> 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));

View File

@ -31,7 +31,7 @@ import org.junit.BeforeClass;
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 class JMXSslPEMConfigTest
@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<String, Object> env = JMXServerUtils.configureJmxSocketFactories(serverAddress, false);
Map<String, Object> 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);