Update JDK SSL Tests to use SSL Context Builder.

Motivation:

Use new / non-deprecated APIs for creating SSL Context
in tests, in order to be able to implement OpenSsl
tests with maximum code reuse.

Modifications:

Use `SslContextBuilder.(forServer|forClient)` instead
of deprecated `JdkSslServerContext` constructor.
Use `ApplicationProtocolConfig` instead of Protocol
Negotiator.
Use custom exception type for skipping tests to avoid
swallowing exceptions arising from tests.

Result:

Exceptions from tests aren't swallowed.
Using new APIs allows reusing same test code for
OpenSsl tests.
This commit is contained in:
Alex Petrov 2015-11-26 08:45:56 +01:00 committed by Scott Mitchell
parent 61b5792340
commit 38838b807d
3 changed files with 112 additions and 47 deletions

View File

@ -31,6 +31,9 @@ import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel; import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.ssl.JdkApplicationProtocolNegotiator.ProtocolSelector; import io.netty.handler.ssl.JdkApplicationProtocolNegotiator.ProtocolSelector;
import io.netty.handler.ssl.JdkApplicationProtocolNegotiator.ProtocolSelectorFactory; import io.netty.handler.ssl.JdkApplicationProtocolNegotiator.ProtocolSelectorFactory;
import io.netty.handler.ssl.ApplicationProtocolConfig.Protocol;
import io.netty.handler.ssl.ApplicationProtocolConfig.SelectedListenerFailureBehavior;
import io.netty.handler.ssl.ApplicationProtocolConfig.SelectorFailureBehavior;
import io.netty.handler.ssl.util.InsecureTrustManagerFactory; import io.netty.handler.ssl.util.InsecureTrustManagerFactory;
import io.netty.handler.ssl.util.SelfSignedCertificate; import io.netty.handler.ssl.util.SelfSignedCertificate;
import io.netty.util.NetUtil; import io.netty.util.NetUtil;
@ -59,13 +62,13 @@ public class JdkSslEngineTest extends SSLEngineTest {
// Check in this test just in case we have multiple tests that just the class and we already ignored the // Check in this test just in case we have multiple tests that just the class and we already ignored the
// initialization error. // initialization error.
if (!JdkNpnSslEngine.isAvailable()) { if (!JdkNpnSslEngine.isAvailable()) {
throw new RuntimeException("NPN not on classpath"); throw tlsExtensionNotFound(Protocol.NPN);
} }
JdkApplicationProtocolNegotiator apn = new JdkNpnApplicationProtocolNegotiator(true, true, ApplicationProtocolConfig apn = failingNegotiator(Protocol.NPN,
PREFERRED_APPLICATION_LEVEL_PROTOCOL); PREFERRED_APPLICATION_LEVEL_PROTOCOL);
mySetup(apn); mySetup(apn);
runTest(); runTest();
} catch (RuntimeException e) { } catch (SkipTestException e) {
// NPN availability is dependent on the java version. If NPN is not available because of // NPN availability is dependent on the java version. If NPN is not available because of
// java version incompatibility don't fail the test, but instead just skip the test // java version incompatibility don't fail the test, but instead just skip the test
assumeNoException(e); assumeNoException(e);
@ -79,15 +82,15 @@ public class JdkSslEngineTest extends SSLEngineTest {
// Check in this test just in case we have multiple tests that just the class and we already ignored the // Check in this test just in case we have multiple tests that just the class and we already ignored the
// initialization error. // initialization error.
if (!JdkNpnSslEngine.isAvailable()) { if (!JdkNpnSslEngine.isAvailable()) {
throw new RuntimeException("NPN not on classpath"); throw tlsExtensionNotFound(Protocol.NPN);
} }
JdkApplicationProtocolNegotiator clientApn = new JdkNpnApplicationProtocolNegotiator(false, false, ApplicationProtocolConfig clientApn = acceptingNegotiator(Protocol.NPN,
PREFERRED_APPLICATION_LEVEL_PROTOCOL); PREFERRED_APPLICATION_LEVEL_PROTOCOL);
JdkApplicationProtocolNegotiator serverApn = new JdkNpnApplicationProtocolNegotiator(false, false, ApplicationProtocolConfig serverApn = acceptingNegotiator(Protocol.NPN,
APPLICATION_LEVEL_PROTOCOL_NOT_COMPATIBLE); APPLICATION_LEVEL_PROTOCOL_NOT_COMPATIBLE);
mySetup(serverApn, clientApn); mySetup(serverApn, clientApn);
runTest(null); runTest(null);
} catch (Exception e) { } catch (SkipTestException e) {
// ALPN availability is dependent on the java version. If ALPN is not available because of // ALPN availability is dependent on the java version. If ALPN is not available because of
// java version incompatibility don't fail the test, but instead just skip the test // java version incompatibility don't fail the test, but instead just skip the test
assumeNoException(e); assumeNoException(e);
@ -101,16 +104,16 @@ public class JdkSslEngineTest extends SSLEngineTest {
// Check in this test just in case we have multiple tests that just the class and we already ignored the // Check in this test just in case we have multiple tests that just the class and we already ignored the
// initialization error. // initialization error.
if (!JdkNpnSslEngine.isAvailable()) { if (!JdkNpnSslEngine.isAvailable()) {
throw new RuntimeException("NPN not on classpath"); throw tlsExtensionNotFound(Protocol.NPN);
} }
JdkApplicationProtocolNegotiator clientApn = new JdkNpnApplicationProtocolNegotiator(true, true, ApplicationProtocolConfig clientApn = failingNegotiator(Protocol.NPN,
PREFERRED_APPLICATION_LEVEL_PROTOCOL); PREFERRED_APPLICATION_LEVEL_PROTOCOL);
JdkApplicationProtocolNegotiator serverApn = new JdkNpnApplicationProtocolNegotiator(false, false, ApplicationProtocolConfig serverApn = acceptingNegotiator(Protocol.NPN,
APPLICATION_LEVEL_PROTOCOL_NOT_COMPATIBLE); APPLICATION_LEVEL_PROTOCOL_NOT_COMPATIBLE);
mySetup(serverApn, clientApn); mySetup(serverApn, clientApn);
assertTrue(clientLatch.await(2, TimeUnit.SECONDS)); assertTrue(clientLatch.await(2, TimeUnit.SECONDS));
assertTrue(clientException instanceof SSLHandshakeException); assertTrue(clientException instanceof SSLHandshakeException);
} catch (RuntimeException e) { } catch (SkipTestException e) {
// NPN availability is dependent on the java version. If NPN is not available because of // NPN availability is dependent on the java version. If NPN is not available because of
// java version incompatibility don't fail the test, but instead just skip the test // java version incompatibility don't fail the test, but instead just skip the test
assumeNoException(e); assumeNoException(e);
@ -124,16 +127,16 @@ public class JdkSslEngineTest extends SSLEngineTest {
// Check in this test just in case we have multiple tests that just the class and we already ignored the // Check in this test just in case we have multiple tests that just the class and we already ignored the
// initialization error. // initialization error.
if (!JdkNpnSslEngine.isAvailable()) { if (!JdkNpnSslEngine.isAvailable()) {
throw new RuntimeException("NPN not on classpath"); throw tlsExtensionNotFound(Protocol.NPN);
} }
JdkApplicationProtocolNegotiator clientApn = new JdkNpnApplicationProtocolNegotiator(false, false, ApplicationProtocolConfig clientApn = acceptingNegotiator(Protocol.NPN,
PREFERRED_APPLICATION_LEVEL_PROTOCOL); PREFERRED_APPLICATION_LEVEL_PROTOCOL);
JdkApplicationProtocolNegotiator serverApn = new JdkNpnApplicationProtocolNegotiator(true, true, ApplicationProtocolConfig serverApn = failingNegotiator(Protocol.NPN,
APPLICATION_LEVEL_PROTOCOL_NOT_COMPATIBLE); APPLICATION_LEVEL_PROTOCOL_NOT_COMPATIBLE);
mySetup(serverApn, clientApn); mySetup(serverApn, clientApn);
assertTrue(serverLatch.await(2, TimeUnit.SECONDS)); assertTrue(serverLatch.await(2, TimeUnit.SECONDS));
assertTrue(serverException instanceof SSLHandshakeException); assertTrue(serverException instanceof SSLHandshakeException);
} catch (RuntimeException e) { } catch (SkipTestException e) {
// NPN availability is dependent on the java version. If NPN is not available because of // NPN availability is dependent on the java version. If NPN is not available because of
// java version incompatibility don't fail the test, but instead just skip the test // java version incompatibility don't fail the test, but instead just skip the test
assumeNoException(e); assumeNoException(e);
@ -147,13 +150,13 @@ public class JdkSslEngineTest extends SSLEngineTest {
// Check in this test just in case we have multiple tests that just the class and we already ignored the // Check in this test just in case we have multiple tests that just the class and we already ignored the
// initialization error. // initialization error.
if (!JdkAlpnSslEngine.isAvailable()) { if (!JdkAlpnSslEngine.isAvailable()) {
throw new RuntimeException("ALPN not on classpath"); throw tlsExtensionNotFound(Protocol.ALPN);
} }
JdkApplicationProtocolNegotiator apn = new JdkAlpnApplicationProtocolNegotiator(true, true, ApplicationProtocolConfig apn = failingNegotiator(Protocol.ALPN,
PREFERRED_APPLICATION_LEVEL_PROTOCOL); PREFERRED_APPLICATION_LEVEL_PROTOCOL);
mySetup(apn); mySetup(apn);
runTest(); runTest();
} catch (Exception e) { } catch (SkipTestException e) {
// ALPN availability is dependent on the java version. If ALPN is not available because of // ALPN availability is dependent on the java version. If ALPN is not available because of
// java version incompatibility don't fail the test, but instead just skip the test // java version incompatibility don't fail the test, but instead just skip the test
assumeNoException(e); assumeNoException(e);
@ -167,15 +170,15 @@ public class JdkSslEngineTest extends SSLEngineTest {
// Check in this test just in case we have multiple tests that just the class and we already ignored the // Check in this test just in case we have multiple tests that just the class and we already ignored the
// initialization error. // initialization error.
if (!JdkAlpnSslEngine.isAvailable()) { if (!JdkAlpnSslEngine.isAvailable()) {
throw new RuntimeException("ALPN not on classpath"); throw tlsExtensionNotFound(Protocol.ALPN);
} }
JdkApplicationProtocolNegotiator clientApn = new JdkAlpnApplicationProtocolNegotiator(false, false, ApplicationProtocolConfig clientApn = acceptingNegotiator(Protocol.ALPN,
PREFERRED_APPLICATION_LEVEL_PROTOCOL); PREFERRED_APPLICATION_LEVEL_PROTOCOL);
JdkApplicationProtocolNegotiator serverApn = new JdkAlpnApplicationProtocolNegotiator(false, false, ApplicationProtocolConfig serverApn = acceptingNegotiator(Protocol.ALPN,
APPLICATION_LEVEL_PROTOCOL_NOT_COMPATIBLE); APPLICATION_LEVEL_PROTOCOL_NOT_COMPATIBLE);
mySetup(serverApn, clientApn); mySetup(serverApn, clientApn);
runTest(null); runTest(null);
} catch (Exception e) { } catch (SkipTestException e) {
// ALPN availability is dependent on the java version. If ALPN is not available because of // ALPN availability is dependent on the java version. If ALPN is not available because of
// java version incompatibility don't fail the test, but instead just skip the test // java version incompatibility don't fail the test, but instead just skip the test
assumeNoException(e); assumeNoException(e);
@ -189,16 +192,16 @@ public class JdkSslEngineTest extends SSLEngineTest {
// Check in this test just in case we have multiple tests that just the class and we already ignored the // Check in this test just in case we have multiple tests that just the class and we already ignored the
// initialization error. // initialization error.
if (!JdkAlpnSslEngine.isAvailable()) { if (!JdkAlpnSslEngine.isAvailable()) {
throw new RuntimeException("ALPN not on classpath"); throw tlsExtensionNotFound(Protocol.ALPN);
} }
JdkApplicationProtocolNegotiator clientApn = new JdkAlpnApplicationProtocolNegotiator(false, false, ApplicationProtocolConfig clientApn = acceptingNegotiator(Protocol.ALPN,
PREFERRED_APPLICATION_LEVEL_PROTOCOL); PREFERRED_APPLICATION_LEVEL_PROTOCOL);
JdkApplicationProtocolNegotiator serverApn = new JdkAlpnApplicationProtocolNegotiator(true, true, ApplicationProtocolConfig serverApn = failingNegotiator(Protocol.ALPN,
APPLICATION_LEVEL_PROTOCOL_NOT_COMPATIBLE); APPLICATION_LEVEL_PROTOCOL_NOT_COMPATIBLE);
mySetup(serverApn, clientApn); mySetup(serverApn, clientApn);
assertTrue(serverLatch.await(2, TimeUnit.SECONDS)); assertTrue(serverLatch.await(2, TimeUnit.SECONDS));
assertTrue(serverException instanceof SSLHandshakeException); assertTrue(serverException instanceof SSLHandshakeException);
} catch (Exception e) { } catch (SkipTestException e) {
// ALPN availability is dependent on the java version. If ALPN is not available because of // ALPN availability is dependent on the java version. If ALPN is not available because of
// java version incompatibility don't fail the test, but instead just skip the test // java version incompatibility don't fail the test, but instead just skip the test
assumeNoException(e); assumeNoException(e);
@ -212,18 +215,18 @@ public class JdkSslEngineTest extends SSLEngineTest {
// Check in this test just in case we have multiple tests that just the class and we already ignored the // Check in this test just in case we have multiple tests that just the class and we already ignored the
// initialization error. // initialization error.
if (!JdkAlpnSslEngine.isAvailable()) { if (!JdkAlpnSslEngine.isAvailable()) {
throw new RuntimeException("ALPN not on classpath"); throw tlsExtensionNotFound(Protocol.ALPN);
} }
// Even the preferred application protocol appears second in the client's list, it will be picked // Even the preferred application protocol appears second in the client's list, it will be picked
// because it's the first one on server's list. // because it's the first one on server's list.
JdkApplicationProtocolNegotiator clientApn = new JdkAlpnApplicationProtocolNegotiator(false, false, ApplicationProtocolConfig clientApn = acceptingNegotiator(Protocol.ALPN,
FALLBACK_APPLICATION_LEVEL_PROTOCOL, PREFERRED_APPLICATION_LEVEL_PROTOCOL); FALLBACK_APPLICATION_LEVEL_PROTOCOL, PREFERRED_APPLICATION_LEVEL_PROTOCOL);
JdkApplicationProtocolNegotiator serverApn = new JdkAlpnApplicationProtocolNegotiator(true, true, ApplicationProtocolConfig serverApn = failingNegotiator(Protocol.ALPN,
PREFERRED_APPLICATION_LEVEL_PROTOCOL, FALLBACK_APPLICATION_LEVEL_PROTOCOL); PREFERRED_APPLICATION_LEVEL_PROTOCOL, FALLBACK_APPLICATION_LEVEL_PROTOCOL);
mySetup(serverApn, clientApn); mySetup(serverApn, clientApn);
assertNull(serverException); assertNull(serverException);
runTest(PREFERRED_APPLICATION_LEVEL_PROTOCOL); runTest(PREFERRED_APPLICATION_LEVEL_PROTOCOL);
} catch (Exception e) { } catch (SkipTestException e) {
// ALPN availability is dependent on the java version. If ALPN is not available because of // ALPN availability is dependent on the java version. If ALPN is not available because of
// java version incompatibility don't fail the test, but instead just skip the test // java version incompatibility don't fail the test, but instead just skip the test
assumeNoException(e); assumeNoException(e);
@ -237,8 +240,9 @@ public class JdkSslEngineTest extends SSLEngineTest {
// Check in this test just in case we have multiple tests that just the class and we already ignored the // Check in this test just in case we have multiple tests that just the class and we already ignored the
// initialization error. // initialization error.
if (!JdkAlpnSslEngine.isAvailable()) { if (!JdkAlpnSslEngine.isAvailable()) {
throw new RuntimeException("ALPN not on classpath"); throw tlsExtensionNotFound(Protocol.ALPN);
} }
SelfSignedCertificate ssc = new SelfSignedCertificate();
JdkApplicationProtocolNegotiator clientApn = new JdkAlpnApplicationProtocolNegotiator(true, true, JdkApplicationProtocolNegotiator clientApn = new JdkAlpnApplicationProtocolNegotiator(true, true,
PREFERRED_APPLICATION_LEVEL_PROTOCOL); PREFERRED_APPLICATION_LEVEL_PROTOCOL);
JdkApplicationProtocolNegotiator serverApn = new JdkAlpnApplicationProtocolNegotiator( JdkApplicationProtocolNegotiator serverApn = new JdkAlpnApplicationProtocolNegotiator(
@ -258,28 +262,54 @@ public class JdkSslEngineTest extends SSLEngineTest {
} }
}, JdkBaseApplicationProtocolNegotiator.FAIL_SELECTION_LISTENER_FACTORY, }, JdkBaseApplicationProtocolNegotiator.FAIL_SELECTION_LISTENER_FACTORY,
APPLICATION_LEVEL_PROTOCOL_NOT_COMPATIBLE); APPLICATION_LEVEL_PROTOCOL_NOT_COMPATIBLE);
mySetup(serverApn, clientApn);
SslContext serverSslCtx = new JdkSslServerContext(ssc.certificate(), ssc.privateKey(), null, null,
IdentityCipherSuiteFilter.INSTANCE, serverApn, 0, 0);
SslContext clientSslCtx = new JdkSslClientContext(null, InsecureTrustManagerFactory.INSTANCE, null,
IdentityCipherSuiteFilter.INSTANCE, clientApn, 0, 0);
mySetup(serverSslCtx, clientSslCtx);
assertTrue(clientLatch.await(2, TimeUnit.SECONDS)); assertTrue(clientLatch.await(2, TimeUnit.SECONDS));
assertTrue(clientException instanceof SSLHandshakeException); assertTrue(clientException instanceof SSLHandshakeException);
} catch (Exception e) { } catch (SkipTestException e) {
// ALPN availability is dependent on the java version. If ALPN is not available because of // ALPN availability is dependent on the java version. If ALPN is not available because of
// java version incompatibility don't fail the test, but instead just skip the test // java version incompatibility don't fail the test, but instead just skip the test
assumeNoException(e); assumeNoException(e);
} }
} }
private void mySetup(JdkApplicationProtocolNegotiator apn) throws InterruptedException, SSLException, private void mySetup(ApplicationProtocolConfig apn) throws InterruptedException, SSLException,
CertificateException { CertificateException {
mySetup(apn, apn); mySetup(apn, apn);
} }
private void mySetup(JdkApplicationProtocolNegotiator serverApn, JdkApplicationProtocolNegotiator clientApn) private void mySetup(ApplicationProtocolConfig serverApn, ApplicationProtocolConfig clientApn)
throws InterruptedException, SSLException, CertificateException { throws InterruptedException, SSLException, CertificateException {
SelfSignedCertificate ssc = new SelfSignedCertificate(); SelfSignedCertificate ssc = new SelfSignedCertificate();
serverSslCtx = new JdkSslServerContext(ssc.certificate(), ssc.privateKey(), null, null,
IdentityCipherSuiteFilter.INSTANCE, serverApn, 0, 0); mySetup(SslContextBuilder.forServer(ssc.certificate(), ssc.privateKey(), null)
clientSslCtx = new JdkSslClientContext(null, InsecureTrustManagerFactory.INSTANCE, null, .sslProvider(sslProvider())
IdentityCipherSuiteFilter.INSTANCE, clientApn, 0, 0); .ciphers(null, IdentityCipherSuiteFilter.INSTANCE)
.applicationProtocolConfig(serverApn)
.sessionCacheSize(0)
.sessionTimeout(0)
.build(),
SslContextBuilder.forClient()
.sslProvider(sslProvider())
.applicationProtocolConfig(clientApn)
.trustManager(InsecureTrustManagerFactory.INSTANCE)
.ciphers(null, IdentityCipherSuiteFilter.INSTANCE)
.sessionCacheSize(0)
.sessionTimeout(0)
.build());
}
private void mySetup(SslContext serverCtx, SslContext clientCtx)
throws InterruptedException, SSLException, CertificateException {
serverSslCtx = serverCtx;
clientSslCtx = clientCtx;
serverConnectedChannel = null; serverConnectedChannel = null;
sb = new ServerBootstrap(); sb = new ServerBootstrap();
@ -346,4 +376,30 @@ public class JdkSslEngineTest extends SSLEngineTest {
protected SslProvider sslProvider() { protected SslProvider sslProvider() {
return SslProvider.JDK; return SslProvider.JDK;
} }
private ApplicationProtocolConfig failingNegotiator(Protocol protocol,
String... supportedProtocols) {
return new ApplicationProtocolConfig(protocol,
SelectorFailureBehavior.FATAL_ALERT,
SelectedListenerFailureBehavior.FATAL_ALERT,
supportedProtocols);
}
private ApplicationProtocolConfig acceptingNegotiator(Protocol protocol,
String... supportedProtocols) {
return new ApplicationProtocolConfig(protocol,
SelectorFailureBehavior.NO_ADVERTISE,
SelectedListenerFailureBehavior.ACCEPT,
supportedProtocols);
}
private SkipTestException tlsExtensionNotFound(Protocol protocol) {
throw new SkipTestException(protocol + " not on classpath");
}
private static final class SkipTestException extends RuntimeException {
public SkipTestException(String message) {
super(message);
}
}
} }

View File

@ -180,13 +180,22 @@ public abstract class SSLEngineTest {
File servertTrustCrtFile, File serverKeyFile, File serverCrtFile, String serverKeyPassword, File servertTrustCrtFile, File serverKeyFile, File serverCrtFile, String serverKeyPassword,
File clientTrustCrtFile, File clientKeyFile, File clientCrtFile, String clientKeyPassword) File clientTrustCrtFile, File clientKeyFile, File clientCrtFile, String clientKeyPassword)
throws InterruptedException, SSLException { throws InterruptedException, SSLException {
serverSslCtx = SslContext.newServerContext(sslProvider(), servertTrustCrtFile, null, serverSslCtx = SslContextBuilder.forServer(serverCrtFile, serverKeyFile, serverKeyPassword)
serverCrtFile, serverKeyFile, serverKeyPassword, null, .sslProvider(sslProvider())
null, IdentityCipherSuiteFilter.INSTANCE, null, 0, 0); .trustManager(servertTrustCrtFile)
clientSslCtx = SslContext.newClientContext(sslProvider(), clientTrustCrtFile, null, .ciphers(null, IdentityCipherSuiteFilter.INSTANCE)
clientCrtFile, clientKeyFile, clientKeyPassword, null, .sessionCacheSize(0)
null, IdentityCipherSuiteFilter.INSTANCE, .sessionTimeout(0)
null, 0, 0); .build();
clientSslCtx = SslContextBuilder.forClient()
.sslProvider(sslProvider())
.trustManager(clientTrustCrtFile)
.keyManager(clientCrtFile, clientKeyFile, clientKeyPassword)
.ciphers(null, IdentityCipherSuiteFilter.INSTANCE)
.sessionCacheSize(0)
.sessionTimeout(0)
.build();
serverConnectedChannel = null; serverConnectedChannel = null;
sb = new ServerBootstrap(); sb = new ServerBootstrap();

View File

@ -34,7 +34,7 @@ public class SniHandlerTest {
File keyFile = new File(SniHandlerTest.class.getResource("test_encrypted.pem").getFile()); File keyFile = new File(SniHandlerTest.class.getResource("test_encrypted.pem").getFile());
File crtFile = new File(SniHandlerTest.class.getResource("test.crt").getFile()); File crtFile = new File(SniHandlerTest.class.getResource("test.crt").getFile());
return new JdkSslServerContext(crtFile, keyFile, "12345"); return SslContextBuilder.forServer(crtFile, keyFile, "12345").build();
} }
@Test @Test