blob: ee9c6104c879b71f55d6ef42cdf8a9525ef768d0 [file] [log] [blame]
/*
* 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.io.IOException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import javax.net.ssl.TrustManagerFactory;
import org.apache.commons.lang3.StringUtils;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import io.netty.handler.ssl.OpenSsl;
import io.netty.handler.ssl.OpenSslContext;
import io.netty.handler.ssl.SslContext;
import io.netty.handler.ssl.SslProvider;
import org.apache.cassandra.config.EncryptionOptions;
import org.apache.cassandra.config.ParameterizedClass;
import org.apache.cassandra.distributed.shared.WithProperties;
import static org.apache.cassandra.config.CassandraRelevantProperties.DISABLE_TCACTIVE_OPENSSL;
import static org.apache.cassandra.security.PEMBasedSslContextFactory.ConfigKey.ENCODED_CERTIFICATES;
import static org.apache.cassandra.security.PEMBasedSslContextFactory.ConfigKey.ENCODED_KEY;
import static org.apache.cassandra.security.PEMBasedSslContextFactory.ConfigKey.KEY_PASSWORD;
public class PEMBasedSslContextFactoryTest
{
private static final String private_key =
"-----BEGIN ENCRYPTED PRIVATE KEY-----\n" +
"MIIE6jAcBgoqhkiG9w0BDAEDMA4ECOWqSzq5PBIdAgIFxQSCBMjXsCK30J0aT3J/\n" +
"g5kcbmevTOY1pIhJGbf5QYYrMUPiuDK2ydxIbiPzoTE4/S+OkCeHhlqwn/YydpBl\n" +
"xgjZZ1Z5rLJHO27d2biuESqanDiBVXYuVmHmaifRnFy0uUTFkStB5mjVZEiJgO29\n" +
"L83hL60uWru71EVuVriC2WCfmZ/EXp6wyYszOqCFQ8Quk/rDO6XuaBl467MJbx5V\n" +
"sucGT6E9XKNd9hB14/Izb2jtVM5kqKxoiHpz1na6yhEYJiE5D1uOonznWjBnjwB/\n" +
"f0x+acpDfVDoJKTlRdz+DEcbOF7mb9lBVVjP6P/AAsmQzz6JKwHjvCrjYfQmyyN8\n" +
"RI4KRQnWgm4L3dtByLqY8HFU4ogisCMCgI+hZQ+OKMz/hoRO540YGiPcTRY3EOUR\n" +
"0bd5JxU6tCJDMTqKP9aSL2KmLoiLowdMkSPz7TCzLsZ2bGJemuCfpAs4XT1vXCHs\n" +
"evrUbOnh8et1IA8mZ9auThfqsZtNagJLEXA6hWIKp1FfVL3Q49wvMKZt4eTn/zwU\n" +
"tLL0m5yPo6/HAaOA3hbm/oghZS0dseshXl7PZrmZQtvYnIvjyoxEL7ducYDQCDP6\n" +
"wZ7Nzyh1QZAauSS15hl3vLFRZCA9hWAVgwQAviTvhB342O0i9qI7TQkcHk+qcTPN\n" +
"K+iGNbFZ8ma1izXNKSJ2PgI/QqFNIeJWvZrb9PhJRmaZVsTJ9fERm1ewpebZqkVv\n" +
"zMqMhlKgx9ggAaSKgnGZkwXwB6GrSbbzUrwRCKm3FieD1QE4VVYevaadVUU75GG5\n" +
"mrFKorJEH7kFZlic8OTjDksYnHbcgU36XZrGEXa2+ldVeGKL3CsXWciaQRcJg8yo\n" +
"WQDjZpcutGI0eMJWCqUkv8pYZC2/wZU4htCve5nVJUU4t9uuo9ex7lnwlLWPvheQ\n" +
"jUBMgzSRsZ+zwaIusvufAAxiKK/cJm4ubZSZPIjBbfd4U7VPxtirP4Accydu7EK6\n" +
"eG/MZwtAMFNJxfxUR+/aYzJU/q1ePw7fWVHrpt58t/22CX2SJBEiUGmSmuyER4Ny\n" +
"DPw6d6mhvPUS1jRhIZ9A81ht8MOX7VL5uVp307rt7o5vRpV1mo0iPiRHzGscMpJn\n" +
"AP36klEAUNTf0uLTKZa7KHiwhn5iPmsCrENHkOKJjxhRrqHjD2wy3YHs3ow2voyY\n" +
"Ua4Cids+c1hvRkNEDGNHm4+rKGFOGOsG/ZU7uj/6gflO4JXxNGiyTLflqMdWBvow\n" +
"Zd7hk1zCaGAAn8nZ0hPweGxQ4Q30I9IBZrimGxB0vjiUqNio9+qMf33dCHFJEuut\n" +
"ZGJMaUGVaPhXQcTy4uD5hzsPZV5xcsU4H3vBYyBcZgrusJ6OOgkuZQaU7p8rWQWr\n" +
"bUEVbXuZdwEmxsCe7H/vEVv5+aA4sF4kWnMMFL7/LIYaiEzkTqdJlRv/KyJJgcAH\n" +
"hg2BvR3XTAq8wiX0C98CdmTbsx2eyQdj5tCU606rEohFLKUxWkJYAKxCiUbxGGpI\n" +
"RheVmxkef9ErxJiq7hsAsGrSJvMtJuDKIasnD14SOEwD/7jRAq6WdL9VLpxtzlOw\n" +
"pWnIl8kUCO3WoaG9Jf+ZTIv2hnxJhaSzYrdXzGPNnaWKhBlwnXJRvQEdrIxZOimP\n" +
"FujZhqbKUDbYAcqTkoQ=\n" +
"-----END ENCRYPTED PRIVATE KEY-----\n" +
"-----BEGIN CERTIFICATE-----\n" +
"MIIDkTCCAnmgAwIBAgIETxH5JDANBgkqhkiG9w0BAQsFADB5MRAwDgYDVQQGEwdV\n" +
"bmtub3duMRAwDgYDVQQIEwdVbmtub3duMRAwDgYDVQQHEwdVbmtub3duMRAwDgYD\n" +
"VQQKEwdVbmtub3duMRQwEgYDVQQLDAtzc2xfdGVzdGluZzEZMBcGA1UEAxMQQXBh\n" +
"Y2hlIENhc3NhbmRyYTAeFw0xNjAzMTgyMTI4MDJaFw0xNjA2MTYyMTI4MDJaMHkx\n" +
"EDAOBgNVBAYTB1Vua25vd24xEDAOBgNVBAgTB1Vua25vd24xEDAOBgNVBAcTB1Vu\n" +
"a25vd24xEDAOBgNVBAoTB1Vua25vd24xFDASBgNVBAsMC3NzbF90ZXN0aW5nMRkw\n" +
"FwYDVQQDExBBcGFjaGUgQ2Fzc2FuZHJhMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A\n" +
"MIIBCgKCAQEAjkmVX/HS49cS8Hn6o26IGwMIcEV3d7ZhH0GNcx8rnSRd10dU9F6d\n" +
"ugSjbwGFMcWUQzYNejN6az0Wb8JIQyXRPTWjfgaWTyVGr0bGTnxg6vwhzfI/9jzy\n" +
"q59xv29OuSY1dxmY31f0pZ9OOw3mabWksjoO2TexfKoxqsRHJ8PrM1f8E84Z4xo2\n" +
"TJXGzpuIxRkAJ+sVDqKEAhrKAfRYMSgdJ7zRt8VXv9ngjX20uA2m092NcH0Kmeto\n" +
"TmuWUtK8E/qcN7ULN8xRWNUn4hu6mG6mayk4XliGRqI1VZupqh+MgNqHznuTd0bA\n" +
"YrQsFPw9HaZ2hvVnJffJ5l7njAekZNOL+wIDAQABoyEwHzAdBgNVHQ4EFgQUcdiD\n" +
"N6aylI91kAd34Hl2AzWY51QwDQYJKoZIhvcNAQELBQADggEBAG9q29ilUgCWQP5v\n" +
"iHkZHj10gXGEoMkdfrPBf8grC7dpUcaw1Qfku/DJ7kPvMALeEsmFDk/t78roeNbh\n" +
"IYBLJlzI1HZN6VPtpWQGsqxltAy5XN9Xw9mQM/tu70ShgsodGmE1UoW6eE5+/GMv\n" +
"6Fg+zLuICPvs2cFNmWUvukN5LW146tJSYCv0Q/rCPB3m9dNQ9pBxrzPUHXw4glwG\n" +
"qGnGddXmOC+tSW5lDLLG1BRbKv4zxv3UlrtIjqlJtZb/sQMT6WtG2ihAz7SKOBHa\n" +
"HOWUwuPTetWIuJCKP7P4mWWtmSmjLy+BFX5seNEngn3RzJ2L8uuTJQ/88OsqgGru\n" +
"n3MVF9w=\n" +
"-----END CERTIFICATE-----";
private static final String unencrypted_private_key =
"-----BEGIN PRIVATE KEY-----\n" +
"MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCOSZVf8dLj1xLw\n" +
"efqjbogbAwhwRXd3tmEfQY1zHyudJF3XR1T0Xp26BKNvAYUxxZRDNg16M3prPRZv\n" +
"wkhDJdE9NaN+BpZPJUavRsZOfGDq/CHN8j/2PPKrn3G/b065JjV3GZjfV/Sln047\n" +
"DeZptaSyOg7ZN7F8qjGqxEcnw+szV/wTzhnjGjZMlcbOm4jFGQAn6xUOooQCGsoB\n" +
"9FgxKB0nvNG3xVe/2eCNfbS4DabT3Y1wfQqZ62hOa5ZS0rwT+pw3tQs3zFFY1Sfi\n" +
"G7qYbqZrKTheWIZGojVVm6mqH4yA2ofOe5N3RsBitCwU/D0dpnaG9Wcl98nmXueM\n" +
"B6Rk04v7AgMBAAECggEAYnxIKjrFz/JkJ5MmiszM5HV698r9YB0aqHnFIHPoykIL\n" +
"uiCjiumantDrFsCkosixULwvI/BRwbxstTpyrheU9psT6P1CONICVPvV8ylgJAYU\n" +
"l+ofn56cEXKxVuICSWFLDH7pM1479g+IJJQAchbKQpqxAGTuMu3SpvJolfuj5srt\n" +
"bM7/RYhJFLwDuvHNA3ivlogMneItP03+C25aaxstM+lBuBf68+n78zMgSvt6J/6Y\n" +
"G2TOMKnxveMlG2qu9l2lAw/2i8daG/qre08nTH7wpRx0gZLZqNpe45exkrzticzF\n" +
"FgWYjG2K2brX21jqHroFgMhdXF7zhhRgLoIeC0BrIQKBgQDCfGfWrJESKBbVai5u\n" +
"7wqD9nlzjv6N6FXfTDOPXO1vz5frdvtLVWbs0SMPy+NglkaZK0iqHvb9mf2of8eC\n" +
"0D5cmewjn7WCDBQMypIMYgT912ak/BBVuGXcxb6UgD+xARfSARo2C8NG1hfprw1W\n" +
"ad14CjS5xhFMs44HpVYhI7iPYwKBgQC7SqVG/b37vZ7CINemdvoMujLvvYXDJJM8\n" +
"N21LqNJfVXdukdH3T0xuLnh9Z/wPHjJDMF/9+1foxSEPHijtyz5P19EilNEC/3qw\n" +
"fI19+VZoY0mdhPtXSGzy+rbTE2v71QgwFLizSos14Gr+eNiIjF7FYccK05++K/zk\n" +
"cd8ZA3bwiQKBgQCl+HTFBs9mpz+VMOAfW2+l3hkXPNiPUc62mNkHZ05ZNNd44jjh\n" +
"uSf0wSUiveR08MmevQlt5K7zDQ8jVKh2QjB15gVXAVxsdtJFeDnax2trFP9LnLBz\n" +
"9sE2/qn9INU5wK0LUlWD+dXUBbCyg+jl7cJKRqtoPldVFYYHkFlIPqup8QKBgHXv\n" +
"hyuw1FUVDkdHzwOvn70r8q8sNHKxMVWVwWkHIZGOi+pAQGrusD4hXRX6yKnsZdIR\n" +
"QCD6iFy25R5T64nxlYdJaxPPid3NakB/7ckJnPOWseBSwMIxhQlr/nvjmve1Kba9\n" +
"FaEwq4B9lGIxToiNe4/nBiM3JzvlDxX67nUdzWOhAoGAdFvriyvjshSJ4JHgIY9K\n" +
"37BVB0VKMcFV2P8fLVWO5oyRtE1bJhU4QVpQmauABU4RGSojJ3NPIVH1wxmJeYtj\n" +
"Q3b7EZaqI6ovna2eK2qtUx4WwxhRaXTT8xueBI2lgL6sBSTGG+K69ZOzGQzG/Mfr\n" +
"RXKInnLInFD9JD94VqmMozo=\n" +
"-----END PRIVATE KEY-----\n" +
"-----BEGIN CERTIFICATE-----\n" +
"MIIDkTCCAnmgAwIBAgIETxH5JDANBgkqhkiG9w0BAQsFADB5MRAwDgYDVQQGEwdV\n" +
"bmtub3duMRAwDgYDVQQIEwdVbmtub3duMRAwDgYDVQQHEwdVbmtub3duMRAwDgYD\n" +
"VQQKEwdVbmtub3duMRQwEgYDVQQLDAtzc2xfdGVzdGluZzEZMBcGA1UEAxMQQXBh\n" +
"Y2hlIENhc3NhbmRyYTAeFw0xNjAzMTgyMTI4MDJaFw0xNjA2MTYyMTI4MDJaMHkx\n" +
"EDAOBgNVBAYTB1Vua25vd24xEDAOBgNVBAgTB1Vua25vd24xEDAOBgNVBAcTB1Vu\n" +
"a25vd24xEDAOBgNVBAoTB1Vua25vd24xFDASBgNVBAsMC3NzbF90ZXN0aW5nMRkw\n" +
"FwYDVQQDExBBcGFjaGUgQ2Fzc2FuZHJhMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A\n" +
"MIIBCgKCAQEAjkmVX/HS49cS8Hn6o26IGwMIcEV3d7ZhH0GNcx8rnSRd10dU9F6d\n" +
"ugSjbwGFMcWUQzYNejN6az0Wb8JIQyXRPTWjfgaWTyVGr0bGTnxg6vwhzfI/9jzy\n" +
"q59xv29OuSY1dxmY31f0pZ9OOw3mabWksjoO2TexfKoxqsRHJ8PrM1f8E84Z4xo2\n" +
"TJXGzpuIxRkAJ+sVDqKEAhrKAfRYMSgdJ7zRt8VXv9ngjX20uA2m092NcH0Kmeto\n" +
"TmuWUtK8E/qcN7ULN8xRWNUn4hu6mG6mayk4XliGRqI1VZupqh+MgNqHznuTd0bA\n" +
"YrQsFPw9HaZ2hvVnJffJ5l7njAekZNOL+wIDAQABoyEwHzAdBgNVHQ4EFgQUcdiD\n" +
"N6aylI91kAd34Hl2AzWY51QwDQYJKoZIhvcNAQELBQADggEBAG9q29ilUgCWQP5v\n" +
"iHkZHj10gXGEoMkdfrPBf8grC7dpUcaw1Qfku/DJ7kPvMALeEsmFDk/t78roeNbh\n" +
"IYBLJlzI1HZN6VPtpWQGsqxltAy5XN9Xw9mQM/tu70ShgsodGmE1UoW6eE5+/GMv\n" +
"6Fg+zLuICPvs2cFNmWUvukN5LW146tJSYCv0Q/rCPB3m9dNQ9pBxrzPUHXw4glwG\n" +
"qGnGddXmOC+tSW5lDLLG1BRbKv4zxv3UlrtIjqlJtZb/sQMT6WtG2ihAz7SKOBHa\n" +
"HOWUwuPTetWIuJCKP7P4mWWtmSmjLy+BFX5seNEngn3RzJ2L8uuTJQ/88OsqgGru\n" +
"n3MVF9w=\n" +
"-----END CERTIFICATE-----";
private static final String trusted_certificates =
"-----BEGIN CERTIFICATE-----\n" +
"MIIDkTCCAnmgAwIBAgIETxH5JDANBgkqhkiG9w0BAQsFADB5MRAwDgYDVQQGEwdV\n" +
"bmtub3duMRAwDgYDVQQIEwdVbmtub3duMRAwDgYDVQQHEwdVbmtub3duMRAwDgYD\n" +
"VQQKEwdVbmtub3duMRQwEgYDVQQLDAtzc2xfdGVzdGluZzEZMBcGA1UEAxMQQXBh\n" +
"Y2hlIENhc3NhbmRyYTAeFw0xNjAzMTgyMTI4MDJaFw0xNjA2MTYyMTI4MDJaMHkx\n" +
"EDAOBgNVBAYTB1Vua25vd24xEDAOBgNVBAgTB1Vua25vd24xEDAOBgNVBAcTB1Vu\n" +
"a25vd24xEDAOBgNVBAoTB1Vua25vd24xFDASBgNVBAsMC3NzbF90ZXN0aW5nMRkw\n" +
"FwYDVQQDExBBcGFjaGUgQ2Fzc2FuZHJhMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A\n" +
"MIIBCgKCAQEAjkmVX/HS49cS8Hn6o26IGwMIcEV3d7ZhH0GNcx8rnSRd10dU9F6d\n" +
"ugSjbwGFMcWUQzYNejN6az0Wb8JIQyXRPTWjfgaWTyVGr0bGTnxg6vwhzfI/9jzy\n" +
"q59xv29OuSY1dxmY31f0pZ9OOw3mabWksjoO2TexfKoxqsRHJ8PrM1f8E84Z4xo2\n" +
"TJXGzpuIxRkAJ+sVDqKEAhrKAfRYMSgdJ7zRt8VXv9ngjX20uA2m092NcH0Kmeto\n" +
"TmuWUtK8E/qcN7ULN8xRWNUn4hu6mG6mayk4XliGRqI1VZupqh+MgNqHznuTd0bA\n" +
"YrQsFPw9HaZ2hvVnJffJ5l7njAekZNOL+wIDAQABoyEwHzAdBgNVHQ4EFgQUcdiD\n" +
"N6aylI91kAd34Hl2AzWY51QwDQYJKoZIhvcNAQELBQADggEBAG9q29ilUgCWQP5v\n" +
"iHkZHj10gXGEoMkdfrPBf8grC7dpUcaw1Qfku/DJ7kPvMALeEsmFDk/t78roeNbh\n" +
"IYBLJlzI1HZN6VPtpWQGsqxltAy5XN9Xw9mQM/tu70ShgsodGmE1UoW6eE5+/GMv\n" +
"6Fg+zLuICPvs2cFNmWUvukN5LW146tJSYCv0Q/rCPB3m9dNQ9pBxrzPUHXw4glwG\n" +
"qGnGddXmOC+tSW5lDLLG1BRbKv4zxv3UlrtIjqlJtZb/sQMT6WtG2ihAz7SKOBHa\n" +
"HOWUwuPTetWIuJCKP7P4mWWtmSmjLy+BFX5seNEngn3RzJ2L8uuTJQ/88OsqgGru\n" +
"n3MVF9w=\n" +
"-----END CERTIFICATE-----";
private final Map<String, Object> commonConfig = new HashMap<>();
@Before
public void setup()
{
commonConfig.put(ENCODED_CERTIFICATES.getKeyName(), trusted_certificates);
commonConfig.put("require_client_auth", Boolean.FALSE);
commonConfig.put("cipher_suites", Arrays.asList("TLS_RSA_WITH_AES_128_CBC_SHA"));
}
private void addKeyStoreOptions(Map<String, Object> config)
{
config.put(ENCODED_KEY.getKeyName(), private_key);
config.put(KEY_PASSWORD.getKeyName(), "cassandra");
}
private void addUnencryptedKeyStoreOptions(Map<String, Object> config)
{
config.put(ENCODED_KEY.getKeyName(), unencrypted_private_key);
}
private void addFileBaseTrustStoreOptions(Map<String, Object> config)
{
config.put("truststore", "test/conf/cassandra_ssl_test.truststore.pem");
}
private void addFileBaseKeyStoreOptions(Map<String, Object> config)
{
config.put("keystore", "test/conf/cassandra_ssl_test.keystore.pem");
config.put("keystore_password", "cassandra");
}
private void addFileBaseUnencryptedKeyStoreOptions(Map<String, Object> config)
{
config.put("keystore", "test/conf/cassandra_ssl_test.unencrypted_keystore.pem");
}
@Test
public void getSslContextOpenSSL() throws IOException
{
ParameterizedClass sslContextFactory = new ParameterizedClass(PEMBasedSslContextFactory.class.getSimpleName()
, new HashMap<>());
EncryptionOptions options = new EncryptionOptions().withTrustStore("test/conf/cassandra_ssl_test.truststore.pem")
.withKeyStore("test/conf/cassandra_ssl_test.keystore.pem")
.withKeyStorePassword("cassandra")
.withRequireClientAuth(false)
.withCipherSuites("TLS_RSA_WITH_AES_128_CBC_SHA")
.withSslContextFactory(sslContextFactory);
SslContext sslContext = SSLFactory.getOrCreateSslContext(options, true, ISslContextFactory.SocketType.SERVER);
Assert.assertNotNull(sslContext);
if (OpenSsl.isAvailable())
Assert.assertTrue(sslContext instanceof OpenSslContext);
else
Assert.assertTrue(sslContext instanceof SslContext);
}
@Test
public void getSslContextOpenSSLOutboundKeystore() throws IOException
{
ParameterizedClass sslContextFactory = new ParameterizedClass(PEMBasedSslContextFactory.class.getSimpleName()
, new HashMap<>());
EncryptionOptions.ServerEncryptionOptions options = new EncryptionOptions.ServerEncryptionOptions().withTrustStore("test/conf/cassandra_ssl_test.truststore.pem")
.withKeyStore("test/conf/cassandra_ssl_test.keystore.pem")
.withKeyStorePassword("cassandra")
.withOutboundKeystore("test/conf/cassandra_ssl_test.keystore.pem")
.withOutboundKeystorePassword("cassandra")
.withRequireClientAuth(false)
.withCipherSuites("TLS_RSA_WITH_AES_128_CBC_SHA")
.withSslContextFactory(sslContextFactory);
SslContext sslContext = SSLFactory.getOrCreateSslContext(options, true, ISslContextFactory.SocketType.CLIENT);
Assert.assertNotNull(sslContext);
if (OpenSsl.isAvailable())
Assert.assertTrue(sslContext instanceof OpenSslContext);
else
Assert.assertTrue(sslContext instanceof SslContext);
}
@Test(expected = IOException.class)
public void buildTrustManagerFactoryWithInvalidTruststoreFile() throws IOException
{
Map<String, Object> config = new HashMap<>();
config.putAll(commonConfig);
config.remove("encoded_certificates");
config.put("truststore", "/this/is/probably/not/a/file/on/your/test/machine");
DefaultSslContextFactory defaultSslContextFactoryImpl = new DefaultSslContextFactory(config);
defaultSslContextFactoryImpl.keystoreContext.checkedExpiry = false;
defaultSslContextFactoryImpl.buildTrustManagerFactory();
}
@Test
public void buildTrustManagerFactoryHappyPath() throws IOException
{
Map<String, Object> config = new HashMap<>();
config.putAll(commonConfig);
PEMBasedSslContextFactory sslContextFactory = new PEMBasedSslContextFactory(config);
sslContextFactory.keystoreContext.checkedExpiry = false;
TrustManagerFactory trustManagerFactory = sslContextFactory.buildTrustManagerFactory();
Assert.assertNotNull(trustManagerFactory);
}
@Test
public void buildFileBasedTrustManagerFactoryHappyPath() throws IOException
{
Map<String, Object> config = new HashMap<>();
config.putAll(commonConfig);
config.remove(ENCODED_CERTIFICATES.getKeyName());
addFileBaseTrustStoreOptions(config);
PEMBasedSslContextFactory sslContextFactory = new PEMBasedSslContextFactory(config);
sslContextFactory.keystoreContext.checkedExpiry = false;
TrustManagerFactory trustManagerFactory = sslContextFactory.buildTrustManagerFactory();
Assert.assertNotNull(trustManagerFactory);
}
@Test(expected = IOException.class)
public void buildKeyManagerFactoryWithInvalidKeystoreFile() throws IOException
{
Map<String, Object> config = new HashMap<>();
config.putAll(commonConfig);
config.put("keystore", "/this/is/probably/not/a/file/on/your/test/machine");
PEMBasedSslContextFactory sslContextFactory = new PEMBasedSslContextFactory(config);
sslContextFactory.keystoreContext.checkedExpiry = false;
sslContextFactory.buildKeyManagerFactory();
}
@Test(expected = IOException.class)
public void buildKeyManagerFactoryWithBadPassword() throws IOException
{
Map<String, Object> config = new HashMap<>();
config.putAll(commonConfig);
addKeyStoreOptions(config);
config.put("keystore_password", "HomeOfBadPasswords");
DefaultSslContextFactory defaultSslContextFactoryImpl = new DefaultSslContextFactory(config);
defaultSslContextFactoryImpl.buildKeyManagerFactory();
}
@Test
public void buildKeyManagerFactoryHappyPath() throws IOException
{
Map<String, Object> config = new HashMap<>();
config.putAll(commonConfig);
PEMBasedSslContextFactory sslContextFactory1 = new PEMBasedSslContextFactory(config);
// Make sure the exiry check didn't happen so far for the private key
Assert.assertFalse(sslContextFactory1.keystoreContext.checkedExpiry);
addKeyStoreOptions(config);
PEMBasedSslContextFactory sslContextFactory2 = new PEMBasedSslContextFactory(config);
// Trigger the private key loading. That will also check for expired private key
sslContextFactory2.buildKeyManagerFactory();
// Now we should have checked the private key's expiry
Assert.assertTrue(sslContextFactory2.keystoreContext.checkedExpiry);
// Make sure that new factory object preforms the fresh private key expiry check
PEMBasedSslContextFactory sslContextFactory3 = new PEMBasedSslContextFactory(config);
Assert.assertFalse(sslContextFactory3.keystoreContext.checkedExpiry);
sslContextFactory3.buildKeyManagerFactory();
Assert.assertTrue(sslContextFactory3.keystoreContext.checkedExpiry);
}
@Test(expected = IllegalArgumentException.class)
public void buildKeyManagerFactoryWithConflictingPasswordConfigs() throws IOException
{
Map<String, Object> config = new HashMap<>();
config.putAll(commonConfig);
addKeyStoreOptions(config);
config.put("keystore_password", config.get("keyPassword") + "-conflict");
PEMBasedSslContextFactory sslContextFactory = new PEMBasedSslContextFactory(config);
sslContextFactory.buildKeyManagerFactory();
}
@Test
public void buildKeyManagerFactoryWithMatchingPasswordConfigs() throws IOException
{
Map<String, Object> config = new HashMap<>();
config.putAll(commonConfig);
addKeyStoreOptions(config);
config.put("keystore_password", config.get("keyPassword"));
PEMBasedSslContextFactory sslContextFactory = new PEMBasedSslContextFactory(config);
sslContextFactory.buildKeyManagerFactory();
}
@Test
public void buildFileBasedKeyManagerFactoryHappyPath() throws IOException
{
Map<String, Object> config = new HashMap<>();
config.putAll(commonConfig);
PEMBasedSslContextFactory sslContextFactory1 = new PEMBasedSslContextFactory(config);
// Make sure the expiry check didn't happen so far for the private key
Assert.assertFalse(sslContextFactory1.keystoreContext.checkedExpiry);
addFileBaseKeyStoreOptions(config);
PEMBasedSslContextFactory sslContextFactory2 = new PEMBasedSslContextFactory(config);
// Trigger the private key loading. That will also check for expired private key
sslContextFactory2.buildKeyManagerFactory();
// Now we should have checked the private key's expiry
Assert.assertTrue(sslContextFactory2.keystoreContext.checkedExpiry);
// Make sure that new factory object preforms the fresh private key expiry check
PEMBasedSslContextFactory sslContextFactory3 = new PEMBasedSslContextFactory(config);
Assert.assertFalse(sslContextFactory3.keystoreContext.checkedExpiry);
sslContextFactory3.buildKeyManagerFactory();
Assert.assertTrue(sslContextFactory3.keystoreContext.checkedExpiry);
}
@Test
public void buildKeyManagerFactoryWithUnencryptedKey() throws IOException
{
Map<String, Object> config = new HashMap<>();
config.putAll(commonConfig);
addUnencryptedKeyStoreOptions(config);
Assert.assertTrue("Unencrypted Key test must not specify a key password",
StringUtils.isEmpty((String) config.get(KEY_PASSWORD.getKeyName())));
PEMBasedSslContextFactory sslContextFactory = new PEMBasedSslContextFactory(config);
sslContextFactory.buildKeyManagerFactory();
}
@Test
public void buildKeyManagerFactoryWithFileBasedUnencryptedKey() throws IOException
{
Map<String, Object> config = new HashMap<>();
config.putAll(commonConfig);
addFileBaseUnencryptedKeyStoreOptions(config);
Assert.assertTrue("Unencrypted Key test must not specify a key password",
StringUtils.isEmpty((String) config.get(KEY_PASSWORD.getKeyName())));
PEMBasedSslContextFactory sslContextFactory = new PEMBasedSslContextFactory(config);
sslContextFactory.buildKeyManagerFactory();
}
@Test
public void testDisableOpenSslForInJvmDtests()
{
// The configuration name below is hard-coded intentionally to make sure we don't break the contract without
// changing the documentation appropriately
try (WithProperties properties = new WithProperties().set(DISABLE_TCACTIVE_OPENSSL, true))
{
Map<String, Object> config = new HashMap<>();
config.putAll(commonConfig);
PEMBasedSslContextFactory sslContextFactory = new PEMBasedSslContextFactory(config);
Assert.assertEquals(SslProvider.JDK, sslContextFactory.getSslProvider());
}
}
@Test(expected = IllegalArgumentException.class)
public void testMultiplePrivateKeySources()
{
Map<String, Object> config = new HashMap<>();
config.putAll(commonConfig);
addUnencryptedKeyStoreOptions(config);
// Check with a valid file path for the keystore
addFileBaseUnencryptedKeyStoreOptions(config);
new PEMBasedSslContextFactory(config);
}
@Test
public void testMultiplePrivateKeySourcesWithInvalidKeystorePath()
{
Map<String, Object> config = new HashMap<>();
config.putAll(commonConfig);
addUnencryptedKeyStoreOptions(config);
// Check with an invalid file path for the keystore
config.put("keystore", "/path/to/nowhere");
new PEMBasedSslContextFactory(config);
}
@Test(expected = IllegalArgumentException.class)
public void testMultipleTrustedCertificatesSources()
{
Map<String, Object> config = new HashMap<>();
config.putAll(commonConfig);
// Check with a valid file path for the truststore
addFileBaseTrustStoreOptions(config);
new PEMBasedSslContextFactory(config);
}
@Test
public void testMultipleTrustedCertificatesSourcesWithInvalidTruststorePath()
{
Map<String, Object> config = new HashMap<>();
config.putAll(commonConfig);
// Check with an invalid file path for the truststore
config.put("truststore", "/path/to/nowhere");
new PEMBasedSslContextFactory(config);
}
}