Merge branch 'cassandra-4.1' into trunk

This commit is contained in:
Stefan Miklosovic 2023-04-17 10:22:31 +02:00
commit 531b4cde43
No known key found for this signature in database
GPG Key ID: 32F35CB2F546D93E
17 changed files with 755 additions and 47 deletions

View File

@ -129,6 +129,7 @@
* Rename DisableFlag class to EnableFlag on guardrails (CASSANDRA-17544)
4.1.2
* Allow keystore and trustrore passwords to be nullable (CASSANDRA-18124)
* Return snapshots with dots in their name in nodetool listsnapshots (CASSANDRA-18371)
* Fix NPE when loading snapshots and data directory is one directory from root (CASSANDRA-18359)
* Do not submit hints when hinted_handoff_enabled=false (CASSANDRA-18304)

View File

@ -161,6 +161,10 @@ Upgrading
`toTimestamp` and `toUnixTimestamp` in Cassandra 2.2.
- Hadoop integration is no longer available (CASSANDRA-18323). If you want to process Cassandra data by big data frameworks,
please upgrade your infrastructure to use Cassandra Spark connector.
- Keystore/truststore password configurations are nullable now and the code defaults of those passwords to 'cassandra' are
removed. Any deployments that depend upon the code default to this password value without explicitly specifying
it in cassandra.yaml will fail on upgrade. Please specify your keystore_password and truststore_password elements in cassandra.yaml with appropriate
values to prevent this failure.
Deprecation
-----------

View File

@ -1361,7 +1361,12 @@ server_encryption_options:
legacy_ssl_storage_port_enabled: false
# Set to a valid keystore if internode_encryption is dc, rack or all
keystore: conf/.keystore
keystore_password: cassandra
#keystore_password: cassandra
# Configure the way Cassandra creates SSL contexts.
# To use PEM-based key material, see org.apache.cassandra.security.PEMBasedSslContextFactory
# ssl_context_factory:
# # Must be an instance of org.apache.cassandra.security.ISslContextFactory
# class_name: org.apache.cassandra.security.DefaultSslContextFactory
# During internode mTLS authentication, inbound connections (acting as servers) use keystore, keystore_password
# containing server certificate to create SSLContext and
# outbound connections (acting as clients) use outbound_keystore & outbound_keystore_password with client certificates
@ -1372,7 +1377,7 @@ server_encryption_options:
require_client_auth: false
# Set to a valid trustore if require_client_auth is true
truststore: conf/.truststore
truststore_password: cassandra
#truststore_password: cassandra
# Verify that the host name in the certificate matches the connected host
require_endpoint_verification: false
# More advanced defaults:
@ -1406,7 +1411,12 @@ client_encryption_options:
# optional: true
# Set keystore and keystore_password to valid keystores if enabled is true
keystore: conf/.keystore
keystore_password: cassandra
#keystore_password: cassandra
# Configure the way Cassandra creates SSL contexts.
# To use PEM-based key material, see org.apache.cassandra.security.PEMBasedSslContextFactory
# ssl_context_factory:
# # Must be an instance of org.apache.cassandra.security.ISslContextFactory
# class_name: org.apache.cassandra.security.DefaultSslContextFactory
# Verify client certificates
require_client_auth: false
# require_endpoint_verification: false

View File

@ -125,6 +125,8 @@ public class KubernetesSecretsPEMSslContextFactory extends KubernetesSecretsSslC
private String pemEncodedCertificates;
private PEMBasedSslContextFactory pemBasedSslContextFactory;
public boolean checkedExpiry = false;
public KubernetesSecretsPEMSslContextFactory()
{
pemBasedSslContextFactory = new PEMBasedSslContextFactory();
@ -165,7 +167,7 @@ public class KubernetesSecretsPEMSslContextFactory extends KubernetesSecretsSslC
protected KeyManagerFactory buildKeyManagerFactory() throws SSLException
{
KeyManagerFactory kmf = pemBasedSslContextFactory.buildKeyManagerFactory();
checkedExpiry = pemBasedSslContextFactory.checkedExpiry;
checkedExpiry = pemBasedSslContextFactory.keystoreContext.checkedExpiry;
return kmf;
}

View File

@ -149,12 +149,12 @@ public class KubernetesSecretsSslContextFactory extends FileBasedSslContextFacto
public KubernetesSecretsSslContextFactory()
{
keystore = getString(EncryptionOptions.ConfigKey.KEYSTORE.toString(), KEYSTORE_PATH_VALUE);
keystore_password = getValueFromEnv(KEYSTORE_PASSWORD_ENV_VAR_NAME,
DEFAULT_KEYSTORE_PASSWORD);
truststore = getString(EncryptionOptions.ConfigKey.TRUSTSTORE.toString(), TRUSTSTORE_PATH_VALUE);
truststore_password = getValueFromEnv(TRUSTSTORE_PASSWORD_ENV_VAR_NAME,
DEFAULT_TRUSTSTORE_PASSWORD);
keystoreContext = new FileBasedStoreContext(getString(EncryptionOptions.ConfigKey.KEYSTORE.toString(), KEYSTORE_PATH_VALUE),
getValueFromEnv(KEYSTORE_PASSWORD_ENV_VAR_NAME, DEFAULT_KEYSTORE_PASSWORD));
trustStoreContext = new FileBasedStoreContext(getString(EncryptionOptions.ConfigKey.TRUSTSTORE.toString(), TRUSTSTORE_PATH_VALUE),
getValueFromEnv(TRUSTSTORE_PASSWORD_ENV_VAR_NAME, DEFAULT_TRUSTSTORE_PASSWORD));
keystoreLastUpdatedTime = System.nanoTime();
keystoreUpdatedTimeSecretKeyPath = getString(ConfigKeys.KEYSTORE_UPDATED_TIMESTAMP_PATH,
KEYSTORE_UPDATED_TIMESTAMP_PATH_VALUE);
@ -166,12 +166,13 @@ public class KubernetesSecretsSslContextFactory extends FileBasedSslContextFacto
public KubernetesSecretsSslContextFactory(Map<String, Object> parameters)
{
super(parameters);
keystore = getString(EncryptionOptions.ConfigKey.KEYSTORE.toString(), KEYSTORE_PATH_VALUE);
keystore_password = getValueFromEnv(getString(ConfigKeys.KEYSTORE_PASSWORD_ENV_VAR,
KEYSTORE_PASSWORD_ENV_VAR_NAME), DEFAULT_KEYSTORE_PASSWORD);
truststore = getString(EncryptionOptions.ConfigKey.TRUSTSTORE.toString(), TRUSTSTORE_PATH_VALUE);
truststore_password = getValueFromEnv(getString(ConfigKeys.TRUSTSTORE_PASSWORD_ENV_VAR,
TRUSTSTORE_PASSWORD_ENV_VAR_NAME), DEFAULT_TRUSTSTORE_PASSWORD);
keystoreContext = new FileBasedStoreContext(getString(EncryptionOptions.ConfigKey.KEYSTORE.toString(), KEYSTORE_PATH_VALUE),
getValueFromEnv(getString(ConfigKeys.KEYSTORE_PASSWORD_ENV_VAR,
KEYSTORE_PASSWORD_ENV_VAR_NAME), DEFAULT_KEYSTORE_PASSWORD));
trustStoreContext = new FileBasedStoreContext(getString(EncryptionOptions.ConfigKey.TRUSTSTORE.toString(), TRUSTSTORE_PATH_VALUE),
getValueFromEnv(getString(ConfigKeys.TRUSTSTORE_PASSWORD_ENV_VAR,
TRUSTSTORE_PASSWORD_ENV_VAR_NAME), DEFAULT_TRUSTSTORE_PASSWORD));
keystoreLastUpdatedTime = System.nanoTime();
keystoreUpdatedTimeSecretKeyPath = getString(ConfigKeys.KEYSTORE_UPDATED_TIMESTAMP_PATH,
KEYSTORE_UPDATED_TIMESTAMP_PATH_VALUE);

View File

@ -147,7 +147,7 @@ public class KubernetesSecretsPEMSslContextFactoryTest
KubernetesSecretsPEMSslContextFactory kubernetesSecretsSslContextFactory =
new KubernetesSecretsPEMSslContextFactoryForTestOnly(config);
kubernetesSecretsSslContextFactory.checkedExpiry = false;
kubernetesSecretsSslContextFactory.trustStoreContext.checkedExpiry = false;
kubernetesSecretsSslContextFactory.buildTrustManagerFactory();
}
@ -158,7 +158,7 @@ public class KubernetesSecretsPEMSslContextFactoryTest
config.putAll(commonConfig);
KubernetesSecretsPEMSslContextFactory kubernetesSecretsSslContextFactory = new KubernetesSecretsPEMSslContextFactoryForTestOnly(config);
kubernetesSecretsSslContextFactory.checkedExpiry = false;
kubernetesSecretsSslContextFactory.trustStoreContext.checkedExpiry = false;
TrustManagerFactory trustManagerFactory = kubernetesSecretsSslContextFactory.buildTrustManagerFactory();
Assert.assertNotNull(trustManagerFactory);
}
@ -172,7 +172,7 @@ public class KubernetesSecretsPEMSslContextFactoryTest
KubernetesSecretsPEMSslContextFactory kubernetesSecretsSslContextFactory =
new KubernetesSecretsPEMSslContextFactoryForTestOnly(config);
kubernetesSecretsSslContextFactory.checkedExpiry = false;
kubernetesSecretsSslContextFactory.keystoreContext.checkedExpiry = false;
kubernetesSecretsSslContextFactory.buildKeyManagerFactory();
}
@ -262,7 +262,7 @@ public class KubernetesSecretsPEMSslContextFactoryTest
addKeystoreOptions(config);
KubernetesSecretsPEMSslContextFactory kubernetesSecretsSslContextFactory = new KubernetesSecretsPEMSslContextFactoryForTestOnly(config);
kubernetesSecretsSslContextFactory.checkedExpiry = false;
kubernetesSecretsSslContextFactory.trustStoreContext.checkedExpiry = false;
TrustManagerFactory trustManagerFactory = kubernetesSecretsSslContextFactory.buildTrustManagerFactory();
Assert.assertNotNull(trustManagerFactory);
Assert.assertFalse(kubernetesSecretsSslContextFactory.shouldReload());
@ -282,7 +282,7 @@ public class KubernetesSecretsPEMSslContextFactoryTest
addKeystoreOptions(config);
KubernetesSecretsPEMSslContextFactory kubernetesSecretsSslContextFactory = new KubernetesSecretsPEMSslContextFactoryForTestOnly(config);
kubernetesSecretsSslContextFactory.checkedExpiry = false;
kubernetesSecretsSslContextFactory.keystoreContext.checkedExpiry = false;
KeyManagerFactory keyManagerFactory = kubernetesSecretsSslContextFactory.buildKeyManagerFactory();
Assert.assertNotNull(keyManagerFactory);
Assert.assertFalse(kubernetesSecretsSslContextFactory.shouldReload());

View File

@ -20,8 +20,8 @@ package org.apache.cassandra.security;
import java.io.IOException;
import java.io.OutputStream;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.HashMap;
@ -38,7 +38,6 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.apache.cassandra.config.EncryptionOptions;
import org.apache.cassandra.io.util.PathUtils;
import static org.apache.cassandra.security.KubernetesSecretsSslContextFactory.ConfigKeys.KEYSTORE_PASSWORD_ENV_VAR;
import static org.apache.cassandra.security.KubernetesSecretsSslContextFactory.ConfigKeys.KEYSTORE_UPDATED_TIMESTAMP_PATH;
@ -63,11 +62,10 @@ public class KubernetesSecretsSslContextFactoryTest
private static void deleteFileIfExists(String file)
{
Path filePath = Paths.get(file);
boolean deleted = PathUtils.tryDelete(filePath);
boolean deleted = new File(file).delete();
if (!deleted)
{
logger.warn("File {} could not be deleted.", filePath);
logger.warn("File {} could not be deleted.", file);
}
}
@ -106,7 +104,7 @@ public class KubernetesSecretsSslContextFactoryTest
config.put(TRUSTSTORE_PATH, "/this/is/probably/not/a/file/on/your/test/machine");
KubernetesSecretsSslContextFactory kubernetesSecretsSslContextFactory = new KubernetesSecretsSslContextFactoryForTestOnly(config);
kubernetesSecretsSslContextFactory.checkedExpiry = false;
kubernetesSecretsSslContextFactory.trustStoreContext.checkedExpiry = false;
kubernetesSecretsSslContextFactory.buildTrustManagerFactory();
}
@ -119,7 +117,7 @@ public class KubernetesSecretsSslContextFactoryTest
config.put(KubernetesSecretsSslContextFactory.DEFAULT_TRUSTSTORE_PASSWORD_ENV_VAR_NAME, "HomeOfBadPasswords");
KubernetesSecretsSslContextFactory kubernetesSecretsSslContextFactory = new KubernetesSecretsSslContextFactoryForTestOnly(config);
kubernetesSecretsSslContextFactory.checkedExpiry = false;
kubernetesSecretsSslContextFactory.trustStoreContext.checkedExpiry = false;
kubernetesSecretsSslContextFactory.buildTrustManagerFactory();
}
@ -133,7 +131,7 @@ public class KubernetesSecretsSslContextFactoryTest
config.put(KubernetesSecretsSslContextFactory.DEFAULT_TRUSTSTORE_PASSWORD_ENV_VAR_NAME, "");
KubernetesSecretsSslContextFactory kubernetesSecretsSslContextFactory = new KubernetesSecretsSslContextFactoryForTestOnly(config);
kubernetesSecretsSslContextFactory.checkedExpiry = false;
kubernetesSecretsSslContextFactory.trustStoreContext.checkedExpiry = false;
kubernetesSecretsSslContextFactory.buildTrustManagerFactory();
}
@ -144,7 +142,7 @@ public class KubernetesSecretsSslContextFactoryTest
config.putAll(commonConfig);
KubernetesSecretsSslContextFactory kubernetesSecretsSslContextFactory = new KubernetesSecretsSslContextFactoryForTestOnly(config);
kubernetesSecretsSslContextFactory.checkedExpiry = false;
kubernetesSecretsSslContextFactory.trustStoreContext.checkedExpiry = false;
TrustManagerFactory trustManagerFactory = kubernetesSecretsSslContextFactory.buildTrustManagerFactory();
Assert.assertNotNull(trustManagerFactory);
}
@ -155,9 +153,11 @@ public class KubernetesSecretsSslContextFactoryTest
Map<String, Object> config = new HashMap<>();
config.putAll(commonConfig);
config.put(KEYSTORE_PATH, "/this/is/probably/not/a/file/on/your/test/machine");
config.put(KEYSTORE_PASSWORD_ENV_VAR, "MY_KEYSTORE_PASSWORD");
config.put("MY_KEYSTORE_PASSWORD","ThisWontMatter");
KubernetesSecretsSslContextFactory kubernetesSecretsSslContextFactory = new KubernetesSecretsSslContextFactoryForTestOnly(config);
kubernetesSecretsSslContextFactory.checkedExpiry = false;
kubernetesSecretsSslContextFactory.keystoreContext.checkedExpiry = false;
kubernetesSecretsSslContextFactory.buildKeyManagerFactory();
}
@ -181,20 +181,20 @@ public class KubernetesSecretsSslContextFactoryTest
KubernetesSecretsSslContextFactory kubernetesSecretsSslContextFactory1 = new KubernetesSecretsSslContextFactoryForTestOnly(config);
// Make sure the exiry check didn't happen so far for the private key
Assert.assertFalse(kubernetesSecretsSslContextFactory1.checkedExpiry);
Assert.assertFalse(kubernetesSecretsSslContextFactory1.keystoreContext.checkedExpiry);
addKeystoreOptions(config);
KubernetesSecretsSslContextFactory kubernetesSecretsSslContextFactory2 = new KubernetesSecretsSslContextFactoryForTestOnly(config);
// Trigger the private key loading. That will also check for expired private key
kubernetesSecretsSslContextFactory2.buildKeyManagerFactory();
// Now we should have checked the private key's expiry
Assert.assertTrue(kubernetesSecretsSslContextFactory2.checkedExpiry);
Assert.assertTrue(kubernetesSecretsSslContextFactory2.keystoreContext.checkedExpiry);
// Make sure that new factory object preforms the fresh private key expiry check
KubernetesSecretsSslContextFactory kubernetesSecretsSslContextFactory3 = new KubernetesSecretsSslContextFactoryForTestOnly(config);
Assert.assertFalse(kubernetesSecretsSslContextFactory3.checkedExpiry);
Assert.assertFalse(kubernetesSecretsSslContextFactory3.keystoreContext.checkedExpiry);
kubernetesSecretsSslContextFactory3.buildKeyManagerFactory();
Assert.assertTrue(kubernetesSecretsSslContextFactory3.checkedExpiry);
Assert.assertTrue(kubernetesSecretsSslContextFactory3.keystoreContext.checkedExpiry);
}
@Test
@ -205,7 +205,7 @@ public class KubernetesSecretsSslContextFactoryTest
addKeystoreOptions(config);
KubernetesSecretsSslContextFactory kubernetesSecretsSslContextFactory = new KubernetesSecretsSslContextFactoryForTestOnly(config);
kubernetesSecretsSslContextFactory.checkedExpiry = false;
kubernetesSecretsSslContextFactory.trustStoreContext.checkedExpiry = false;
TrustManagerFactory trustManagerFactory = kubernetesSecretsSslContextFactory.buildTrustManagerFactory();
Assert.assertNotNull(trustManagerFactory);
Assert.assertFalse(kubernetesSecretsSslContextFactory.shouldReload());
@ -225,7 +225,7 @@ public class KubernetesSecretsSslContextFactoryTest
addKeystoreOptions(config);
KubernetesSecretsSslContextFactory kubernetesSecretsSslContextFactory = new KubernetesSecretsSslContextFactoryForTestOnly(config);
kubernetesSecretsSslContextFactory.checkedExpiry = false;
kubernetesSecretsSslContextFactory.keystoreContext.checkedExpiry = false;
KeyManagerFactory keyManagerFactory = kubernetesSecretsSslContextFactory.buildKeyManagerFactory();
Assert.assertNotNull(keyManagerFactory);
Assert.assertFalse(kubernetesSecretsSslContextFactory.shouldReload());

View File

@ -25,6 +25,8 @@ import java.util.Map;
import java.util.Objects;
import java.util.Set;
import javax.annotation.Nullable;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableList;
@ -72,8 +74,10 @@ public class EncryptionOptions
*/
public final ParameterizedClass ssl_context_factory;
public final String keystore;
@Nullable
public final String keystore_password;
public final String truststore;
@Nullable
public final String truststore_password;
public final List<String> cipher_suites;
protected String protocol;
@ -147,9 +151,9 @@ public class EncryptionOptions
ssl_context_factory = new ParameterizedClass("org.apache.cassandra.security.DefaultSslContextFactory",
new HashMap<>());
keystore = "conf/.keystore";
keystore_password = "cassandra";
keystore_password = null;
truststore = "conf/.truststore";
truststore_password = "cassandra";
truststore_password = null;
cipher_suites = null;
protocol = null;
accepted_protocols = null;
@ -608,6 +612,7 @@ public class EncryptionOptions
@Replaces(oldName = "enable_legacy_ssl_storage_port", deprecated = true)
public final boolean legacy_ssl_storage_port_enabled;
public final String outbound_keystore;
@Nullable
public final String outbound_keystore_password;
public ServerEncryptionOptions()

View File

@ -123,22 +123,52 @@ public abstract class FileBasedSslContextFactory extends AbstractSslContextFacto
}
}
/**
* Validates the given keystore password.
*
* @param isOutboundKeystore {@code true} for the {@code outbound_keystore_password};{@code false} otherwise
* @param password value
* @throws IllegalArgumentException if the {@code password} is empty as per the definition of {@link StringUtils#isEmpty(CharSequence)}
*/
protected void validatePassword(boolean isOutboundKeystore, String password)
{
boolean keystorePasswordEmpty = StringUtils.isEmpty(password);
if (keystorePasswordEmpty)
{
String keyName = isOutboundKeystore ? "outbound_" : "";
final String msg = String.format("'%skeystore_password' must be specified", keyName);
throw new IllegalArgumentException(msg);
}
}
/**
* Builds required KeyManagerFactory from the file based keystore. It also checks for the PrivateKey's certificate's
* expiry and logs {@code warning} for each expired PrivateKey's certitificate.
*
* @return KeyManagerFactory built from the file based keystore.
* @throws SSLException if any issues encountered during the build process
* @throws IllegalArgumentException if the validation for the {@code keystore_password} fails
* @see #validatePassword(boolean, String)
*/
@Override
protected KeyManagerFactory buildKeyManagerFactory() throws SSLException
{
/*
* Validation of the password is delayed until this point to allow nullable keystore passwords
* for other use-cases (CASSANDRA-18124).
*/
validatePassword(false, keystoreContext.password);
return getKeyManagerFactory(keystoreContext);
}
@Override
protected KeyManagerFactory buildOutboundKeyManagerFactory() throws SSLException
{
/*
* Validation of the password is delayed until this point to allow nullable keystore passwords
* for other use-cases (CASSANDRA-18124).
*/
validatePassword(true, outboundKeystoreContext.password);
return getKeyManagerFactory(outboundKeystoreContext);
}
@ -156,7 +186,9 @@ public abstract class FileBasedSslContextFactory extends AbstractSslContextFacto
final String algorithm = this.algorithm == null ? TrustManagerFactory.getDefaultAlgorithm() : this.algorithm;
TrustManagerFactory tmf = TrustManagerFactory.getInstance(algorithm);
KeyStore ts = KeyStore.getInstance(store_type);
ts.load(tsf, trustStoreContext.password.toCharArray());
final char[] truststorePassword = StringUtils.isEmpty(trustStoreContext.password) ? null : trustStoreContext.password.toCharArray();
ts.load(tsf, truststorePassword);
tmf.init(ts);
return tmf;
}

View File

@ -109,11 +109,6 @@ public final class PEMBasedSslContextFactory extends FileBasedSslContextFactory
final String msg = String.format("'%skeystore_password' and '%skey_password' both configurations are given and the values do not match", keyName, keyName);
throw new IllegalArgumentException(msg);
}
else
{
logger.warn("'{}keystore_password' and '{}key_password' both are configured but since the values match it's " +
"okay. Ideally you should only specify one of them.", keyName, keyName);
}
}
public PEMBasedSslContextFactory(Map<String, Object> parameters)

View File

@ -42,6 +42,7 @@ import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;
import com.google.common.collect.ImmutableSet;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -100,7 +101,7 @@ public final class PEMReader
String base64EncodedKey = extractBase64EncodedKey(pemKey);
byte[] derKeyBytes = decodeBase64(base64EncodedKey);
if (keyPassword != null)
if (!StringUtils.isEmpty(keyPassword))
{
logger.debug("Encrypted key's length: {}, key's password length: {}",
derKeyBytes.length, keyPassword.length());

View File

@ -0,0 +1,154 @@
#
# 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.
#
#
# Testing for pluggable ssl_context_factory option for client and server encryption options with a valid and a missing
# implementation classes.
#
cluster_name: Test Cluster
# memtable_allocation_type: heap_buffers
memtable_allocation_type: offheap_objects
commitlog_sync: batch
commitlog_segment_size: 5MiB
commitlog_directory: build/test/cassandra/commitlog
# commitlog_compression:
# - class_name: LZ4Compressor
cdc_raw_directory: build/test/cassandra/cdc_raw
cdc_enabled: false
hints_directory: build/test/cassandra/hints
partitioner: org.apache.cassandra.dht.ByteOrderedPartitioner
listen_address: 127.0.0.1
storage_port: 7012
ssl_storage_port: 17012
start_native_transport: true
native_transport_port: 9042
column_index_size: 4KiB
saved_caches_directory: build/test/cassandra/saved_caches
data_file_directories:
- build/test/cassandra/data
disk_access_mode: mmap
seed_provider:
- class_name: org.apache.cassandra.locator.SimpleSeedProvider
parameters:
- seeds: "127.0.0.1:7012"
endpoint_snitch: org.apache.cassandra.locator.SimpleSnitch
dynamic_snitch: true
client_encryption_options:
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-----
keystore_password: cassandra-abracadbra
server_encryption_options:
ssl_context_factory:
class_name: org.apache.cassandra.security.PEMBasedSslContextFactory
parameters:
private_key_password: "cassandra-abracadbra"
internode_encryption: none
keystore: test/conf/cassandra_ssl_test.keystore.pem
keystore_password: cassandra
truststore: test/conf/cassandra_ssl_test.truststore.pem
incremental_backups: true
concurrent_compactors: 4
compaction_throughput: 0MiB/s
row_cache_class_name: org.apache.cassandra.cache.OHCProvider
row_cache_size: 16MiB
user_defined_functions_enabled: true
scripted_user_defined_functions_enabled: false
prepared_statements_cache_size: 1MiB
corrupted_tombstone_strategy: exception
stream_entire_sstables: true
stream_throughput_outbound: 24MiB/s
sasi_indexes_enabled: true
materialized_views_enabled: true
file_cache_enabled: true

View File

@ -0,0 +1,148 @@
#
# 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.
#
#
# Testing for pluggable ssl_context_factory option for client and server encryption options with a valid and a missing
# implementation classes.
#
cluster_name: Test Cluster
# memtable_allocation_type: heap_buffers
memtable_allocation_type: offheap_objects
commitlog_sync: batch
commitlog_segment_size: 5MiB
commitlog_directory: build/test/cassandra/commitlog
# commitlog_compression:
# - class_name: LZ4Compressor
cdc_raw_directory: build/test/cassandra/cdc_raw
cdc_enabled: false
hints_directory: build/test/cassandra/hints
partitioner: org.apache.cassandra.dht.ByteOrderedPartitioner
listen_address: 127.0.0.1
storage_port: 7012
ssl_storage_port: 17012
start_native_transport: true
native_transport_port: 9042
column_index_size: 4KiB
saved_caches_directory: build/test/cassandra/saved_caches
data_file_directories:
- build/test/cassandra/data
disk_access_mode: mmap
seed_provider:
- class_name: org.apache.cassandra.locator.SimpleSeedProvider
parameters:
- seeds: "127.0.0.1:7012"
endpoint_snitch: org.apache.cassandra.locator.SimpleSnitch
dynamic_snitch: true
client_encryption_options:
ssl_context_factory:
class_name: org.apache.cassandra.security.PEMBasedSslContextFactory
parameters:
private_key: |
-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCOSZVf8dLj1xLw
efqjbogbAwhwRXd3tmEfQY1zHyudJF3XR1T0Xp26BKNvAYUxxZRDNg16M3prPRZv
wkhDJdE9NaN+BpZPJUavRsZOfGDq/CHN8j/2PPKrn3G/b065JjV3GZjfV/Sln047
DeZptaSyOg7ZN7F8qjGqxEcnw+szV/wTzhnjGjZMlcbOm4jFGQAn6xUOooQCGsoB
9FgxKB0nvNG3xVe/2eCNfbS4DabT3Y1wfQqZ62hOa5ZS0rwT+pw3tQs3zFFY1Sfi
G7qYbqZrKTheWIZGojVVm6mqH4yA2ofOe5N3RsBitCwU/D0dpnaG9Wcl98nmXueM
B6Rk04v7AgMBAAECggEAYnxIKjrFz/JkJ5MmiszM5HV698r9YB0aqHnFIHPoykIL
uiCjiumantDrFsCkosixULwvI/BRwbxstTpyrheU9psT6P1CONICVPvV8ylgJAYU
l+ofn56cEXKxVuICSWFLDH7pM1479g+IJJQAchbKQpqxAGTuMu3SpvJolfuj5srt
bM7/RYhJFLwDuvHNA3ivlogMneItP03+C25aaxstM+lBuBf68+n78zMgSvt6J/6Y
G2TOMKnxveMlG2qu9l2lAw/2i8daG/qre08nTH7wpRx0gZLZqNpe45exkrzticzF
FgWYjG2K2brX21jqHroFgMhdXF7zhhRgLoIeC0BrIQKBgQDCfGfWrJESKBbVai5u
7wqD9nlzjv6N6FXfTDOPXO1vz5frdvtLVWbs0SMPy+NglkaZK0iqHvb9mf2of8eC
0D5cmewjn7WCDBQMypIMYgT912ak/BBVuGXcxb6UgD+xARfSARo2C8NG1hfprw1W
ad14CjS5xhFMs44HpVYhI7iPYwKBgQC7SqVG/b37vZ7CINemdvoMujLvvYXDJJM8
N21LqNJfVXdukdH3T0xuLnh9Z/wPHjJDMF/9+1foxSEPHijtyz5P19EilNEC/3qw
fI19+VZoY0mdhPtXSGzy+rbTE2v71QgwFLizSos14Gr+eNiIjF7FYccK05++K/zk
cd8ZA3bwiQKBgQCl+HTFBs9mpz+VMOAfW2+l3hkXPNiPUc62mNkHZ05ZNNd44jjh
uSf0wSUiveR08MmevQlt5K7zDQ8jVKh2QjB15gVXAVxsdtJFeDnax2trFP9LnLBz
9sE2/qn9INU5wK0LUlWD+dXUBbCyg+jl7cJKRqtoPldVFYYHkFlIPqup8QKBgHXv
hyuw1FUVDkdHzwOvn70r8q8sNHKxMVWVwWkHIZGOi+pAQGrusD4hXRX6yKnsZdIR
QCD6iFy25R5T64nxlYdJaxPPid3NakB/7ckJnPOWseBSwMIxhQlr/nvjmve1Kba9
FaEwq4B9lGIxToiNe4/nBiM3JzvlDxX67nUdzWOhAoGAdFvriyvjshSJ4JHgIY9K
37BVB0VKMcFV2P8fLVWO5oyRtE1bJhU4QVpQmauABU4RGSojJ3NPIVH1wxmJeYtj
Q3b7EZaqI6ovna2eK2qtUx4WwxhRaXTT8xueBI2lgL6sBSTGG+K69ZOzGQzG/Mfr
RXKInnLInFD9JD94VqmMozo=
-----END 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-----
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-----
server_encryption_options:
ssl_context_factory:
class_name: org.apache.cassandra.security.PEMBasedSslContextFactory
internode_encryption: none
keystore: test/conf/cassandra_ssl_test.unencrypted_keystore.pem
truststore: test/conf/cassandra_ssl_test.truststore.pem
incremental_backups: true
concurrent_compactors: 4
compaction_throughput: 0MiB/s
row_cache_class_name: org.apache.cassandra.cache.OHCProvider
row_cache_size: 16MiB
user_defined_functions_enabled: true
scripted_user_defined_functions_enabled: false
prepared_statements_cache_size: 1MiB
corrupted_tombstone_strategy: exception
stream_entire_sstables: true
stream_throughput_outbound: 24MiB/s
sasi_indexes_enabled: true
materialized_views_enabled: true
file_cache_enabled: true

View File

@ -120,6 +120,7 @@ public class DefaultSslContextFactoryTest
Map<String,Object> config = new HashMap<>();
config.putAll(commonConfig);
config.put("keystore", "/this/is/probably/not/a/file/on/your/test/machine");
config.put("keystore_password", "ThisWontMatter");
DefaultSslContextFactory defaultSslContextFactoryImpl = new DefaultSslContextFactory(config);
defaultSslContextFactoryImpl.keystoreContext.checkedExpiry = false;
@ -168,6 +169,7 @@ public class DefaultSslContextFactoryTest
Map<String, Object> config = new HashMap<>();
config.putAll(commonConfig);
config.put("outbound_keystore", "/this/is/probably/not/a/file/on/your/test/machine");
config.put("outbound_keystore_password", "ThisWontMatter");
DefaultSslContextFactory defaultSslContextFactoryImpl = new DefaultSslContextFactory(config);
defaultSslContextFactoryImpl.outboundKeystoreContext.checkedExpiry = false;
@ -183,7 +185,7 @@ public class DefaultSslContextFactoryTest
config.put("outbound_keystore_password", "HomeOfBadPasswords");
DefaultSslContextFactory defaultSslContextFactoryImpl = new DefaultSslContextFactory(config);
defaultSslContextFactoryImpl.buildKeyManagerFactory();
defaultSslContextFactoryImpl.buildOutboundKeyManagerFactory();
}
@Test

View File

@ -0,0 +1,182 @@
/*
* 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.security;
import java.util.HashMap;
import java.util.Map;
import javax.net.ssl.SSLException;
import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.apache.cassandra.config.EncryptionOptions;
import org.apache.cassandra.config.ParameterizedClass;
public class FileBasedSslContextFactoryTest
{
private static final Logger logger = LoggerFactory.getLogger(FileBasedSslContextFactoryTest.class);
private EncryptionOptions.ServerEncryptionOptions encryptionOptions;
@BeforeClass
public static void setupDatabaseDescriptor()
{
System.setProperty("cassandra.config", "cassandra.yaml");
}
@AfterClass
public static void tearDownDatabaseDescriptor()
{
System.clearProperty("cassandra.config");
}
@Before
public void setup()
{
encryptionOptions = new EncryptionOptions.ServerEncryptionOptions()
.withSslContextFactory(new ParameterizedClass(TestFileBasedSSLContextFactory.class.getName(),
new HashMap<>()))
.withTrustStore("test/conf/cassandra_ssl_test.truststore")
.withTrustStorePassword("cassandra")
.withRequireClientAuth(false)
.withCipherSuites("TLS_RSA_WITH_AES_128_CBC_SHA")
.withKeyStore("test/conf/cassandra_ssl_test.keystore")
.withKeyStorePassword("cassandra")
.withOutboundKeystore("test/conf/cassandra_ssl_test_outbound.keystore")
.withOutboundKeystorePassword("cassandra");
}
@Test
public void testHappyPath() throws SSLException
{
EncryptionOptions.ServerEncryptionOptions localEncryptionOptions = encryptionOptions;
Assert.assertEquals("org.apache.cassandra.security.FileBasedSslContextFactoryTest$TestFileBasedSSLContextFactory",
localEncryptionOptions.ssl_context_factory.class_name);
Assert.assertNotNull("keystore_password must not be null", localEncryptionOptions.keystore_password);
Assert.assertNotNull("outbound_keystore_password must not be null", localEncryptionOptions.outbound_keystore_password);
TestFileBasedSSLContextFactory sslContextFactory =
(TestFileBasedSSLContextFactory) localEncryptionOptions.sslContextFactoryInstance;
sslContextFactory.buildKeyManagerFactory();
sslContextFactory.buildTrustManagerFactory();
}
/**
* Tests for empty {@code keystore_password} and empty {@code outbound_keystore_password} configurations.
*/
@Test(expected = IllegalArgumentException.class)
public void testEmptyKeystorePasswords() throws SSLException
{
EncryptionOptions.ServerEncryptionOptions localEncryptionOptions = encryptionOptions.withKeyStorePassword(null).withOutboundKeystorePassword(null);
Assert.assertEquals("org.apache.cassandra.security.FileBasedSslContextFactoryTest$TestFileBasedSSLContextFactory",
localEncryptionOptions.ssl_context_factory.class_name);
Assert.assertNull("keystore_password must be null", localEncryptionOptions.keystore_password);
Assert.assertNull("outbound_keystore_password must be null", localEncryptionOptions.outbound_keystore_password);
TestFileBasedSSLContextFactory sslContextFactory =
(TestFileBasedSSLContextFactory) localEncryptionOptions.sslContextFactoryInstance;
try
{
sslContextFactory.buildKeyManagerFactory();
sslContextFactory.buildTrustManagerFactory();
}
catch (Exception e)
{
Assert.assertEquals("'keystore_password' must be specified", e.getMessage());
throw e;
}
}
/**
* Tests for the empty password for the {@code keystore} used for the client communication.
*/
@Test(expected = IllegalArgumentException.class)
public void testEmptyKeystorePassword() throws SSLException
{
EncryptionOptions.ServerEncryptionOptions localEncryptionOptions = encryptionOptions.withKeyStorePassword(null);
Assert.assertEquals("org.apache.cassandra.security.FileBasedSslContextFactoryTest$TestFileBasedSSLContextFactory",
localEncryptionOptions.ssl_context_factory.class_name);
Assert.assertNull("keystore_password must be null", localEncryptionOptions.keystore_password);
Assert.assertNotNull("outbound_keystore_password must not be null", localEncryptionOptions.outbound_keystore_password);
TestFileBasedSSLContextFactory sslContextFactory =
(TestFileBasedSSLContextFactory) localEncryptionOptions.sslContextFactoryInstance;
try
{
sslContextFactory.buildKeyManagerFactory();
sslContextFactory.buildTrustManagerFactory();
}
catch (Exception e)
{
Assert.assertEquals("'keystore_password' must be specified", e.getMessage());
throw e;
}
}
/**
* Tests for the empty password for the {@code outbound_keystore}. Since the {@code outbound_keystore_password} defaults
* to the {@code keystore_password}, this test should pass without exceptions.
*/
@Test
public void testOnlyEmptyOutboundKeystorePassword() throws SSLException
{
EncryptionOptions.ServerEncryptionOptions localEncryptionOptions = encryptionOptions.withOutboundKeystorePassword(null);
Assert.assertEquals("org.apache.cassandra.security.FileBasedSslContextFactoryTest$TestFileBasedSSLContextFactory",
localEncryptionOptions.ssl_context_factory.class_name);
Assert.assertNotNull("keystore_password must not be null", localEncryptionOptions.keystore_password);
Assert.assertNull("outbound_keystore_password must be null", localEncryptionOptions.outbound_keystore_password);
TestFileBasedSSLContextFactory sslContextFactory =
(TestFileBasedSSLContextFactory) localEncryptionOptions.sslContextFactoryInstance;
sslContextFactory.buildKeyManagerFactory();
sslContextFactory.buildTrustManagerFactory();
}
@Test
public void testEmptyTruststorePassword() throws SSLException
{
EncryptionOptions.ServerEncryptionOptions localEncryptionOptions = encryptionOptions.withTrustStorePassword(null);
Assert.assertEquals("org.apache.cassandra.security.FileBasedSslContextFactoryTest$TestFileBasedSSLContextFactory",
localEncryptionOptions.ssl_context_factory.class_name);
Assert.assertNotNull("keystore_password must not be null", localEncryptionOptions.keystore_password);
Assert.assertNotNull("outbound_keystore_password must not be null", localEncryptionOptions.outbound_keystore_password);
Assert.assertNull("truststore_password must be null", localEncryptionOptions.truststore_password);
TestFileBasedSSLContextFactory sslContextFactory =
(TestFileBasedSSLContextFactory) localEncryptionOptions.sslContextFactoryInstance;
sslContextFactory.buildTrustManagerFactory();
}
public static class TestFileBasedSSLContextFactory extends FileBasedSslContextFactory
{
public TestFileBasedSSLContextFactory(Map<String, Object> parameters)
{
super(parameters);
}
}
}

View File

@ -0,0 +1,92 @@
/*
* 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.security;
import javax.net.ssl.SSLException;
import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
import org.apache.cassandra.config.Config;
import org.apache.cassandra.config.DatabaseDescriptor;
import org.apache.cassandra.exceptions.ConfigurationException;
public class PEMBasedSslContextFactoryConfigWithMismatchingPasswordsTest
{
@BeforeClass
public static void setupDatabaseDescriptor()
{
System.setProperty("cassandra.config", "cassandra-pem-sslcontextfactory-mismatching-passwords.yaml");
}
@AfterClass
public static void tearDownDatabaseDescriptor()
{
System.clearProperty("cassandra.config");
}
@Test(expected = ConfigurationException.class)
public void testInLinePEMConfiguration() throws SSLException
{
Config config = DatabaseDescriptor.loadConfig();
try
{
config.client_encryption_options.applyConfig();
}
catch (ConfigurationException e)
{
assertErrorMessageAndRethrow(e);
}
}
@Test(expected = ConfigurationException.class)
public void testFileBasedPEMConfiguration() throws SSLException
{
Config config = DatabaseDescriptor.loadConfig();
try
{
config.server_encryption_options.applyConfig();
}
catch (ConfigurationException e)
{
assertErrorMessageAndRethrow(e);
}
}
private void assertErrorMessageAndRethrow(ConfigurationException e) throws ConfigurationException
{
String expectedMessage = "'keystore_password' and 'key_password' both configurations are given and the values do not match";
Throwable rootCause = getRootCause(e);
String actualMessage = rootCause.getMessage();
Assert.assertEquals(expectedMessage, actualMessage);
throw e;
}
private Throwable getRootCause(Throwable e)
{
Throwable rootCause = e;
while (rootCause.getCause() != null && rootCause.getCause() != rootCause)
{
rootCause = rootCause.getCause();
}
return rootCause;
}
}

View File

@ -0,0 +1,79 @@
/*
* 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.security;
import javax.net.ssl.SSLException;
import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
import org.apache.cassandra.config.Config;
import org.apache.cassandra.config.DatabaseDescriptor;
public class PEMBasedSslContextFactoryConfigWithUnencryptedKeysTest
{
@BeforeClass
public static void setupDatabaseDescriptor()
{
System.setProperty("cassandra.config", "cassandra-pem-sslcontextfactory-unencryptedkeys.yaml");
System.setProperty("cassandra.disable_tcactive_openssl", "true");
}
@AfterClass
public static void tearDownDatabaseDescriptor()
{
System.clearProperty("cassandra.config");
}
@Test
public void testHappyPathInlinePEM() throws SSLException
{
Config config = DatabaseDescriptor.loadConfig();
config.client_encryption_options.applyConfig();
Assert.assertEquals("org.apache.cassandra.security.PEMBasedSslContextFactory",
config.client_encryption_options.ssl_context_factory.class_name);
Assert.assertEquals(config.client_encryption_options.ssl_context_factory.class_name,
config.client_encryption_options.sslContextFactoryInstance.getClass().getName());
PEMBasedSslContextFactory sslContextFactory =
(PEMBasedSslContextFactory) config.client_encryption_options.sslContextFactoryInstance;
sslContextFactory.buildKeyManagerFactory();
sslContextFactory.buildTrustManagerFactory();
}
@Test
public void testHappyPathFileBasedPEM() throws SSLException
{
Config config = DatabaseDescriptor.loadConfig();
config.server_encryption_options.applyConfig();
Assert.assertEquals("org.apache.cassandra.security.PEMBasedSslContextFactory",
config.server_encryption_options.ssl_context_factory.class_name);
Assert.assertEquals(config.server_encryption_options.ssl_context_factory.class_name,
config.server_encryption_options.sslContextFactoryInstance.getClass().getName());
PEMBasedSslContextFactory sslContextFactory =
(PEMBasedSslContextFactory) config.server_encryption_options.sslContextFactoryInstance;
sslContextFactory.buildKeyManagerFactory();
sslContextFactory.buildTrustManagerFactory();
}
}