blob: 5bb56e1c9ac24f3d7915d52718ab8e663b48442f [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.omid.tls;
import io.netty.buffer.ByteBufAllocator;
import io.netty.handler.ssl.SslContext;
import org.apache.omid.tls.KeyStoreFileType;
import org.apache.omid.tls.X509Exception;
import org.junit.After;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import java.security.Security;
import java.util.*;
import static org.junit.Assert.*;
import static org.mockito.Mockito.mock;
/**
* This file has is based on the one in HBase project.
* @see <a href=
* "https://github.com/apache/hbase/blob/d2b0074f7ad4c43d31a1a511a0d74feda72451d1/hbase-common/src/test/java/org/apache/hadoop/hbase/io/crypto/tls/TestX509Util.java">Base
* revision</a>
*/
@RunWith(Parameterized.class)
public class TestX509Util extends BaseX509ParameterizedTestCase {
@Parameterized.Parameter()
public X509KeyType caKeyType;
@Parameterized.Parameter(value = 1)
public X509KeyType certKeyType;
@Parameterized.Parameter(value = 2)
public String keyPassword;
@Parameterized.Parameter(value = 3)
public Integer paramIndex;
@Parameterized.Parameters(
name = "{index}: caKeyType={0}, certKeyType={1}, keyPassword={2}, paramIndex={3}")
public static Collection<Object[]> data() {
List<Object[]> params = new ArrayList<>();
int paramIndex = 0;
for (X509KeyType caKeyType : X509KeyType.values()) {
for (X509KeyType certKeyType : X509KeyType.values()) {
for (String keyPassword : new String[] { KEY_EMPTY_PASSWORD, KEY_NON_EMPTY_PASSWORD }) {
params.add(new Object[] { caKeyType, certKeyType, keyPassword, paramIndex++ });
}
}
}
return params;
}
private String tlsConfigKeystoreLocation;
private String tlsConfigKeystorePassword;
private String tlsConfigKeystoreType;
private String tlsConfigTrustLocation;
private String tlsConfigTrustPassword;
private String tlsConfigTrustType;
@Override
public void init(X509KeyType caKeyType, X509KeyType certKeyType, String keyPassword,
Integer paramIndex) throws Exception {
super.init(caKeyType, certKeyType, keyPassword, paramIndex);
x509TestContext.setSystemProperties(KeyStoreFileType.JKS, KeyStoreFileType.JKS);
tlsConfigKeystoreLocation = x509TestContext.getTlsConfigKeystoreLocation();
tlsConfigKeystorePassword = x509TestContext.getTlsConfigKeystorePassword();
tlsConfigKeystoreType = x509TestContext.getTlsConfigKeystoreType();
tlsConfigTrustLocation = x509TestContext.getTlsConfigTrustLocation();
tlsConfigTrustPassword = x509TestContext.getTlsConfigTrustPassword();
tlsConfigTrustType = x509TestContext.getTlsConfigTrustType();
}
@After
public void cleanUp() {
x509TestContext.clearSystemProperties();
System.clearProperty("com.sun.net.ssl.checkRevocation");
System.clearProperty("com.sun.security.enableCRLDP");
Security.setProperty("ocsp.enable", Boolean.FALSE.toString());
Security.setProperty("com.sun.security.enableCRLDP", Boolean.FALSE.toString());
}
@Test
public void testCreateSSLContextWithoutCustomProtocol() throws Exception {
init(caKeyType, certKeyType, keyPassword, paramIndex);
SslContext sslContext = X509Util.createSslContextForClient(tlsConfigKeystoreLocation, tlsConfigKeystorePassword.toCharArray(), tlsConfigKeystoreType, tlsConfigTrustLocation, tlsConfigTrustPassword.toCharArray(), tlsConfigTrustType, false, false, null, null, X509Util.DEFAULT_PROTOCOL);
ByteBufAllocator byteBufAllocatorMock = mock(ByteBufAllocator.class);
assertEquals(new String[] { X509Util.DEFAULT_PROTOCOL },
sslContext.newEngine(byteBufAllocatorMock).getEnabledProtocols());
}
@Test
public void testCreateSSLContextWithCustomProtocol() throws Exception {
final String protocol = "TLSv1.1";
init(caKeyType, certKeyType, keyPassword, paramIndex);
ByteBufAllocator byteBufAllocatorMock = mock(ByteBufAllocator.class);
SslContext sslContext = X509Util.createSslContextForClient(tlsConfigKeystoreLocation, tlsConfigKeystorePassword.toCharArray(), tlsConfigKeystoreType, tlsConfigTrustLocation, tlsConfigTrustPassword.toCharArray(), tlsConfigTrustType, false, false, protocol, null, X509Util.DEFAULT_PROTOCOL);
assertEquals(Collections.singletonList(protocol),
Arrays.asList(sslContext.newEngine(byteBufAllocatorMock).getEnabledProtocols()));
}
@Test(expected = X509Exception.SSLContextException.class)
public void testCreateSSLContextWithoutKeyStoreLocationServer() throws Exception {
init(caKeyType, certKeyType, keyPassword, paramIndex);
tlsConfigKeystoreLocation = "";
SslContext sslContext = X509Util.createSslContextForServer(tlsConfigKeystoreLocation, tlsConfigKeystorePassword.toCharArray(), tlsConfigKeystoreType, tlsConfigTrustLocation, tlsConfigTrustPassword.toCharArray(), tlsConfigTrustType, false, false, null, null, X509Util.DEFAULT_PROTOCOL);
}
@Test
public void testCreateSSLContextWithoutKeyStoreLocationClient() throws Exception {
init(caKeyType, certKeyType, keyPassword, paramIndex);
tlsConfigKeystoreLocation = "";
SslContext sslContext = X509Util.createSslContextForClient(tlsConfigKeystoreLocation, tlsConfigKeystorePassword.toCharArray(), tlsConfigKeystoreType, tlsConfigTrustLocation, tlsConfigTrustPassword.toCharArray(), tlsConfigTrustType, false, false, null, null, X509Util.DEFAULT_PROTOCOL);
}
@Test(expected = X509Exception.class)
public void testCreateSSLContextWithoutKeyStorePassword() throws Exception {
init(caKeyType, certKeyType, keyPassword, paramIndex);
if (!x509TestContext.isKeyStoreEncrypted()) {
throw new X509Exception.SSLContextException("");
}
tlsConfigKeystorePassword = "";
SslContext sslContext = X509Util.createSslContextForServer(tlsConfigKeystoreLocation, tlsConfigKeystorePassword.toCharArray(), tlsConfigKeystoreType, tlsConfigTrustLocation, tlsConfigTrustPassword.toCharArray(), tlsConfigTrustType, false, false, null, null, X509Util.DEFAULT_PROTOCOL);
}
@Test
public void testCreateSSLContextWithoutTrustStoreLocationClient() throws Exception {
init(caKeyType, certKeyType, keyPassword, paramIndex);
tlsConfigTrustLocation = "";
SslContext sslContext = X509Util.createSslContextForClient(tlsConfigKeystoreLocation, tlsConfigKeystorePassword.toCharArray(), tlsConfigKeystoreType, tlsConfigTrustLocation, tlsConfigTrustPassword.toCharArray(), tlsConfigTrustType, false, false, null, null, X509Util.DEFAULT_PROTOCOL);
}
@Test
public void testCreateSSLContextWithoutTrustStoreLocationServer() throws Exception {
init(caKeyType, certKeyType, keyPassword, paramIndex);
tlsConfigTrustLocation = "";
SslContext sslContext = X509Util.createSslContextForServer(tlsConfigKeystoreLocation, tlsConfigKeystorePassword.toCharArray(), tlsConfigKeystoreType, tlsConfigTrustLocation, tlsConfigTrustPassword.toCharArray(), tlsConfigTrustType, false, false, null, null, X509Util.DEFAULT_PROTOCOL);
}
// It would be great to test the value of PKIXBuilderParameters#setRevocationEnabled,
// but it does not appear to be possible
@Test
public void testCRLEnabled() throws Exception {
init(caKeyType, certKeyType, keyPassword, paramIndex);
SslContext sslContext = X509Util.createSslContextForServer(tlsConfigKeystoreLocation, tlsConfigKeystorePassword.toCharArray(), tlsConfigKeystoreType, tlsConfigTrustLocation, tlsConfigTrustPassword.toCharArray(), tlsConfigTrustType, true, false, null, null, X509Util.DEFAULT_PROTOCOL);
assertTrue(Boolean.valueOf(System.getProperty("com.sun.net.ssl.checkRevocation")));
assertTrue(Boolean.valueOf(System.getProperty("com.sun.security.enableCRLDP")));
assertFalse(Boolean.valueOf(Security.getProperty("ocsp.enable")));
}
@Test
public void testCRLDisabled() throws Exception {
init(caKeyType, certKeyType, keyPassword, paramIndex);
SslContext sslContext = X509Util.createSslContextForServer(tlsConfigKeystoreLocation, tlsConfigKeystorePassword.toCharArray(), tlsConfigKeystoreType, tlsConfigTrustLocation, tlsConfigTrustPassword.toCharArray(), tlsConfigTrustType, false, false, null, null, X509Util.DEFAULT_PROTOCOL);
assertFalse(Boolean.valueOf(System.getProperty("com.sun.net.ssl.checkRevocation")));
assertFalse(Boolean.valueOf(System.getProperty("com.sun.security.enableCRLDP")));
assertFalse(Boolean.valueOf(Security.getProperty("ocsp.enable")));
}
@Test
public void testLoadJKSKeyStore() throws Exception {
init(caKeyType, certKeyType, keyPassword, paramIndex);
// Make sure we can instantiate a key manager from the JKS file on disk
X509Util.createKeyManager(
x509TestContext.getKeyStoreFile(KeyStoreFileType.JKS).getAbsolutePath(),
x509TestContext.getKeyStorePassword().toCharArray(), KeyStoreFileType.JKS.getPropertyValue());
}
@Test
public void testLoadJKSKeyStoreNullPassword() throws Exception {
init(caKeyType, certKeyType, keyPassword, paramIndex);
if (!x509TestContext.getKeyStorePassword().isEmpty()) {
return;
}
// Make sure that empty password and null password are treated the same
X509Util.createKeyManager(
x509TestContext.getKeyStoreFile(KeyStoreFileType.JKS).getAbsolutePath(), null,
KeyStoreFileType.JKS.getPropertyValue());
}
@Test
public void testLoadJKSKeyStoreFileTypeDefaultToJks() throws Exception {
init(caKeyType, certKeyType, keyPassword, paramIndex);
// Make sure we can instantiate a key manager from the JKS file on disk
X509Util.createKeyManager(
x509TestContext.getKeyStoreFile(KeyStoreFileType.JKS).getAbsolutePath(),
x509TestContext.getKeyStorePassword().toCharArray(),
null /* null StoreFileType means 'autodetect from file extension' */);
}
@Test
public void testLoadJKSKeyStoreWithWrongPassword() throws Exception {
init(caKeyType, certKeyType, keyPassword, paramIndex);
assertThrows(X509Exception.KeyManagerException.class, () -> {
// Attempting to load with the wrong key password should fail
X509Util.createKeyManager(
x509TestContext.getKeyStoreFile(KeyStoreFileType.JKS).getAbsolutePath(), "wrong password".toCharArray(),
KeyStoreFileType.JKS.getPropertyValue());
});
}
@Test
public void testLoadJKSTrustStore() throws Exception {
init(caKeyType, certKeyType, keyPassword, paramIndex);
// Make sure we can instantiate a trust manager from the JKS file on disk
X509Util.createTrustManager(
x509TestContext.getTrustStoreFile(KeyStoreFileType.JKS).getAbsolutePath(),
x509TestContext.getTrustStorePassword().toCharArray(), KeyStoreFileType.JKS.getPropertyValue(), true, true);
}
@Test
public void testLoadJKSTrustStoreNullPassword() throws Exception {
init(caKeyType, certKeyType, keyPassword, paramIndex);
if (!x509TestContext.getTrustStorePassword().isEmpty()) {
return;
}
// Make sure that empty password and null password are treated the same
X509Util.createTrustManager(
x509TestContext.getTrustStoreFile(KeyStoreFileType.JKS).getAbsolutePath(), null,
KeyStoreFileType.JKS.getPropertyValue(), false, false);
}
@Test
public void testLoadJKSTrustStoreFileTypeDefaultToJks() throws Exception {
init(caKeyType, certKeyType, keyPassword, paramIndex);
// Make sure we can instantiate a trust manager from the JKS file on disk
X509Util.createTrustManager(
x509TestContext.getTrustStoreFile(KeyStoreFileType.JKS).getAbsolutePath(),
x509TestContext.getTrustStorePassword().toCharArray(), null, // null StoreFileType means 'autodetect from
// file extension'
true, true);
}
@Test
public void testLoadJKSTrustStoreWithWrongPassword() throws Exception {
init(caKeyType, certKeyType, keyPassword, paramIndex);
assertThrows(X509Exception.TrustManagerException.class, () -> {
// Attempting to load with the wrong key password should fail
X509Util.createTrustManager(
x509TestContext.getTrustStoreFile(KeyStoreFileType.JKS).getAbsolutePath(), "wrong password".toCharArray(),
KeyStoreFileType.JKS.getPropertyValue(), true, true);
});
}
@Test
public void testLoadPKCS12KeyStore() throws Exception {
init(caKeyType, certKeyType, keyPassword, paramIndex);
// Make sure we can instantiate a key manager from the PKCS12 file on disk
X509Util.createKeyManager(
x509TestContext.getKeyStoreFile(KeyStoreFileType.PKCS12).getAbsolutePath(),
x509TestContext.getKeyStorePassword().toCharArray(), KeyStoreFileType.PKCS12.getPropertyValue());
}
@Test
public void testLoadPKCS12KeyStoreNullPassword() throws Exception {
init(caKeyType, certKeyType, keyPassword, paramIndex);
if (!x509TestContext.getKeyStorePassword().isEmpty()) {
return;
}
// Make sure that empty password and null password are treated the same
X509Util.createKeyManager(
x509TestContext.getKeyStoreFile(KeyStoreFileType.PKCS12).getAbsolutePath(), null,
KeyStoreFileType.PKCS12.getPropertyValue());
}
@Test
public void testLoadPKCS12KeyStoreWithWrongPassword() throws Exception {
init(caKeyType, certKeyType, keyPassword, paramIndex);
assertThrows(X509Exception.KeyManagerException.class, () -> {
// Attempting to load with the wrong key password should fail
X509Util.createKeyManager(
x509TestContext.getKeyStoreFile(KeyStoreFileType.PKCS12).getAbsolutePath(),
"wrong password".toCharArray(), KeyStoreFileType.PKCS12.getPropertyValue());
});
}
@Test
public void testLoadPKCS12TrustStore() throws Exception {
init(caKeyType, certKeyType, keyPassword, paramIndex);
// Make sure we can instantiate a trust manager from the PKCS12 file on disk
X509Util.createTrustManager(
x509TestContext.getTrustStoreFile(KeyStoreFileType.PKCS12).getAbsolutePath(),
x509TestContext.getTrustStorePassword().toCharArray(), KeyStoreFileType.PKCS12.getPropertyValue(), true,
true);
}
@Test
public void testLoadPKCS12TrustStoreNullPassword() throws Exception {
init(caKeyType, certKeyType, keyPassword, paramIndex);
if (!x509TestContext.getTrustStorePassword().isEmpty()) {
return;
}
// Make sure that empty password and null password are treated the same
X509Util.createTrustManager(
x509TestContext.getTrustStoreFile(KeyStoreFileType.PKCS12).getAbsolutePath(), null,
KeyStoreFileType.PKCS12.getPropertyValue(), false, false);
}
@Test
public void testLoadPKCS12TrustStoreWithWrongPassword() throws Exception {
init(caKeyType, certKeyType, keyPassword, paramIndex);
assertThrows(X509Exception.TrustManagerException.class, () -> {
// Attempting to load with the wrong key password should fail
X509Util.createTrustManager(
x509TestContext.getTrustStoreFile(KeyStoreFileType.PKCS12).getAbsolutePath(),
"wrong password".toCharArray(), KeyStoreFileType.PKCS12.getPropertyValue(), true, true);
});
}
@Test
public void testGetDefaultCipherSuitesJava8() throws Exception {
init(caKeyType, certKeyType, keyPassword, paramIndex);
String[] cipherSuites = X509Util.getDefaultCipherSuitesForJavaVersion("1.8");
// Java 8 default should have the CBC suites first
assertTrue(cipherSuites[0].contains("CBC"));
}
@Test
public void testGetDefaultCipherSuitesJava9() throws Exception {
init(caKeyType, certKeyType, keyPassword, paramIndex);
String[] cipherSuites = X509Util.getDefaultCipherSuitesForJavaVersion("9");
// Java 9+ default should have the GCM suites first
assertTrue(cipherSuites[0].contains("GCM"));
}
@Test
public void testGetDefaultCipherSuitesJava10() throws Exception {
init(caKeyType, certKeyType, keyPassword, paramIndex);
String[] cipherSuites = X509Util.getDefaultCipherSuitesForJavaVersion("10");
// Java 9+ default should have the GCM suites first
assertTrue(cipherSuites[0].contains("GCM"));
}
@Test
public void testGetDefaultCipherSuitesJava11() throws Exception {
init(caKeyType, certKeyType, keyPassword, paramIndex);
String[] cipherSuites = X509Util.getDefaultCipherSuitesForJavaVersion("11");
// Java 9+ default should have the GCM suites first
assertTrue(cipherSuites[0].contains("GCM"));
}
@Test
public void testGetDefaultCipherSuitesUnknownVersion() throws Exception {
init(caKeyType, certKeyType, keyPassword, paramIndex);
String[] cipherSuites = X509Util.getDefaultCipherSuitesForJavaVersion("notaversion");
// If version can't be parsed, use the more conservative Java 8 default
assertTrue(cipherSuites[0].contains("CBC"));
}
@Test
public void testGetDefaultCipherSuitesNullVersion() throws Exception {
init(caKeyType, certKeyType, keyPassword, paramIndex);
assertThrows(NullPointerException.class, () -> {
X509Util.getDefaultCipherSuitesForJavaVersion(null);
});
}
}