Swap to Netty's SslContextBuilder

We provide a utility to configure the SslContext for our usage, which we
can change as necessary.
This commit is contained in:
Eric Anderson 2015-03-20 09:32:15 -07:00
parent fd0aed22ce
commit e05885d2aa
10 changed files with 108 additions and 13 deletions

View File

@ -65,6 +65,7 @@ import io.grpc.Channel;
import io.grpc.ChannelImpl; import io.grpc.ChannelImpl;
import io.grpc.Status; import io.grpc.Status;
import io.grpc.stub.StreamObserver; import io.grpc.stub.StreamObserver;
import io.grpc.transport.netty.GrpcSslContexts;
import io.grpc.transport.netty.NegotiationType; import io.grpc.transport.netty.NegotiationType;
import io.grpc.transport.netty.NettyChannelBuilder; import io.grpc.transport.netty.NettyChannelBuilder;
import io.grpc.transport.okhttp.OkHttpChannelBuilder; import io.grpc.transport.okhttp.OkHttpChannelBuilder;
@ -184,7 +185,7 @@ public class AsyncClient {
// Force the hostname to match the cert the server uses. // Force the hostname to match the cert the server uses.
address = InetAddress.getByAddress("foo.test.google.fr", address.getAddress()); address = InetAddress.getByAddress("foo.test.google.fr", address.getAddress());
File cert = loadCert("ca.pem"); File cert = loadCert("ca.pem");
context = SslContext.newClientContext(cert); context = GrpcSslContexts.forClient().trustManager(cert).build();
} }
return NettyChannelBuilder return NettyChannelBuilder
.forAddress(new InetSocketAddress(address, config.port)) .forAddress(new InetSocketAddress(address, config.port))

View File

@ -45,6 +45,7 @@ import grpc.testing.TestServiceGrpc;
import io.grpc.ServerImpl; import io.grpc.ServerImpl;
import io.grpc.Status; import io.grpc.Status;
import io.grpc.stub.StreamObserver; import io.grpc.stub.StreamObserver;
import io.grpc.transport.netty.GrpcSslContexts;
import io.grpc.transport.netty.NettyServerBuilder; import io.grpc.transport.netty.NettyServerBuilder;
import io.netty.handler.ssl.SslContext; import io.netty.handler.ssl.SslContext;
@ -82,7 +83,7 @@ public class AsyncServer {
File cert = loadCert("server1.pem"); File cert = loadCert("server1.pem");
File key = loadCert("server1.key"); File key = loadCert("server1.key");
sslContext = SslContext.newServerContext(cert, key); sslContext = GrpcSslContexts.forServer(cert, key).build();
} }
if (port == 0) { if (port == 0) {

View File

@ -39,6 +39,7 @@ import com.google.protobuf.ByteString;
import grpc.testing.Qpstest; import grpc.testing.Qpstest;
import grpc.testing.Qpstest.SimpleRequest; import grpc.testing.Qpstest.SimpleRequest;
import io.grpc.Channel; import io.grpc.Channel;
import io.grpc.transport.netty.GrpcSslContexts;
import io.grpc.transport.netty.NegotiationType; import io.grpc.transport.netty.NegotiationType;
import io.grpc.transport.netty.NettyChannelBuilder; import io.grpc.transport.netty.NettyChannelBuilder;
import io.grpc.transport.okhttp.OkHttpChannelBuilder; import io.grpc.transport.okhttp.OkHttpChannelBuilder;
@ -91,7 +92,7 @@ final class ClientUtil {
// Force the hostname to match the cert the server uses. // Force the hostname to match the cert the server uses.
address = InetAddress.getByAddress("foo.test.google.fr", address.getAddress()); address = InetAddress.getByAddress("foo.test.google.fr", address.getAddress());
File cert = loadCert("ca.pem"); File cert = loadCert("ca.pem");
context = SslContext.newClientContext(cert); context = GrpcSslContexts.forClient().trustManager(cert).build();
} }
return NettyChannelBuilder return NettyChannelBuilder
.forAddress(new InetSocketAddress(address, config.port)) .forAddress(new InetSocketAddress(address, config.port))

View File

@ -32,6 +32,7 @@
package io.grpc.testing.integration; package io.grpc.testing.integration;
import io.grpc.ChannelImpl; import io.grpc.ChannelImpl;
import io.grpc.transport.netty.GrpcSslContexts;
import io.grpc.transport.netty.NegotiationType; import io.grpc.transport.netty.NegotiationType;
import io.grpc.transport.netty.NettyChannelBuilder; import io.grpc.transport.netty.NettyChannelBuilder;
import io.grpc.transport.okhttp.OkHttpChannelBuilder; import io.grpc.transport.okhttp.OkHttpChannelBuilder;
@ -224,7 +225,7 @@ public class TestServiceClient {
SslContext sslContext = null; SslContext sslContext = null;
if (useTestCa) { if (useTestCa) {
try { try {
sslContext = SslContext.newClientContext(Util.loadCert("ca.pem")); sslContext = GrpcSslContexts.forClient().trustManager(Util.loadCert("ca.pem")).build();
} catch (Exception ex) { } catch (Exception ex) {
throw new RuntimeException(ex); throw new RuntimeException(ex);
} }

View File

@ -36,6 +36,7 @@ import com.google.common.util.concurrent.MoreExecutors;
import io.grpc.ServerImpl; import io.grpc.ServerImpl;
import io.grpc.ServerInterceptors; import io.grpc.ServerInterceptors;
import io.grpc.testing.TestUtils; import io.grpc.testing.TestUtils;
import io.grpc.transport.netty.GrpcSslContexts;
import io.grpc.transport.netty.NettyServerBuilder; import io.grpc.transport.netty.NettyServerBuilder;
import io.netty.handler.ssl.SslContext; import io.netty.handler.ssl.SslContext;
@ -133,8 +134,8 @@ public class TestServiceServer {
executor = Executors.newSingleThreadScheduledExecutor(); executor = Executors.newSingleThreadScheduledExecutor();
SslContext sslContext = null; SslContext sslContext = null;
if (useTls) { if (useTls) {
sslContext = SslContext.newServerContext(Util.loadCert("server1.pem"), sslContext = GrpcSslContexts.forServer(
Util.loadCert("server1.key")); Util.loadCert("server1.pem"), Util.loadCert("server1.key")).build();
} }
server = NettyServerBuilder.forPort(port) server = NettyServerBuilder.forPort(port)
.sslContext(sslContext) .sslContext(sslContext)

View File

@ -32,9 +32,9 @@
package io.grpc.testing.integration; package io.grpc.testing.integration;
import io.grpc.ChannelImpl; import io.grpc.ChannelImpl;
import io.grpc.transport.netty.GrpcSslContexts;
import io.grpc.transport.netty.NettyChannelBuilder; import io.grpc.transport.netty.NettyChannelBuilder;
import io.grpc.transport.netty.NettyServerBuilder; import io.grpc.transport.netty.NettyServerBuilder;
import io.netty.handler.ssl.SslContext;
import org.junit.AfterClass; import org.junit.AfterClass;
import org.junit.BeforeClass; import org.junit.BeforeClass;
@ -57,8 +57,8 @@ public class Http2NettyTest extends AbstractTransportTest {
public static void startServer() { public static void startServer() {
try { try {
startStaticServer(NettyServerBuilder.forPort(serverPort) startStaticServer(NettyServerBuilder.forPort(serverPort)
.sslContext(SslContext.newServerContext( .sslContext(GrpcSslContexts.forServer(
Util.loadCert("server1.pem"), Util.loadCert("server1.key")))); Util.loadCert("server1.pem"), Util.loadCert("server1.key")).build()));
} catch (IOException ex) { } catch (IOException ex) {
throw new RuntimeException(ex); throw new RuntimeException(ex);
} }
@ -76,7 +76,7 @@ public class Http2NettyTest extends AbstractTransportTest {
= InetAddress.getByAddress("foo.test.google.fr", new byte[] {127, 0, 0, 1}); = InetAddress.getByAddress("foo.test.google.fr", new byte[] {127, 0, 0, 1});
return NettyChannelBuilder return NettyChannelBuilder
.forAddress(new InetSocketAddress(address, serverPort)) .forAddress(new InetSocketAddress(address, serverPort))
.sslContext(SslContext.newClientContext(Util.loadCert("ca.pem"))) .sslContext(GrpcSslContexts.forClient().trustManager(Util.loadCert("ca.pem")).build())
.build(); .build();
} catch (Exception ex) { } catch (Exception ex) {
throw new RuntimeException(ex); throw new RuntimeException(ex);

View File

@ -0,0 +1,86 @@
/*
* Copyright 2015, Google Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package io.grpc.transport.netty;
import io.netty.handler.codec.http2.Http2SecurityUtil;
import io.netty.handler.ssl.SslContextBuilder;
import io.netty.handler.ssl.SupportedCipherSuiteFilter;
import java.io.File;
/**
* Utility for configuring SslContext for gRPC.
*/
public class GrpcSslContexts {
private GrpcSslContexts() {}
/**
* Creates a SslContextBuilder with ciphers and APN appropriate for gRPC.
*
* @see SslContextBuilder#forClient()
* @see #configure(SslContextBuilder)
*/
public static SslContextBuilder forClient() {
return configure(SslContextBuilder.forClient());
}
/**
* Creates a SslContextBuilder with ciphers and APN appropriate for gRPC.
*
* @see SslContextBuilder#forServer(File, File)
* @see #configure(SslContextBuilder)
*/
public static SslContextBuilder forServer(File keyCertChainFile, File keyFile) {
return configure(SslContextBuilder.forServer(keyCertChainFile, keyFile));
}
/**
* Creates a SslContextBuilder with ciphers and APN appropriate for gRPC.
*
* @see SslContextBuilder#forServer(File, File, String)
* @see #configure(SslContextBuilder)
*/
public static SslContextBuilder forServer(
File keyCertChainFile, File keyFile, String keyPassword) {
return configure(SslContextBuilder.forServer(keyCertChainFile, keyFile, keyPassword));
}
/**
* Set ciphers and APN appropriate for gRPC. Precisely what is set is permitted to change, so if
* an application requires particular settings it should override the options set here.
*/
public static SslContextBuilder configure(SslContextBuilder builder) {
return builder.ciphers(Http2SecurityUtil.CIPHERS, SupportedCipherSuiteFilter.INSTANCE)
// We currently handle ALPN ourselves, so we require ALPN in Netty disabled.
.applicationProtocolConfig(null);
}
}

View File

@ -111,7 +111,10 @@ public final class NettyChannelBuilder extends AbstractChannelBuilder<NettyChann
return this; return this;
} }
/** SSL/TLS context to use instead of the system default. */ /**
* SSL/TLS context to use instead of the system default. It must have been configured with {@link
* GrpcSslContexts}, but options could have been overridden.
*/
public NettyChannelBuilder sslContext(SslContext sslContext) { public NettyChannelBuilder sslContext(SslContext sslContext) {
this.sslContext = sslContext; this.sslContext = sslContext;
return this; return this;

View File

@ -142,7 +142,7 @@ class NettyClientTransport implements ClientTransport {
case TLS: case TLS:
if (sslContext == null) { if (sslContext == null) {
try { try {
sslContext = SslContext.newClientContext(); sslContext = GrpcSslContexts.forClient().build();
} catch (SSLException ex) { } catch (SSLException ex) {
throw new RuntimeException(ex); throw new RuntimeException(ex);
} }

View File

@ -161,7 +161,8 @@ public final class NettyServerBuilder extends AbstractServerBuilder<NettyServerB
} }
/** /**
* Sets the TLS context to use for encryption. Providing a context enables encryption. * Sets the TLS context to use for encryption. Providing a context enables encryption. It must
* have been configured with {@link GrpcSslContexts}, but options could have been overridden.
*/ */
public NettyServerBuilder sslContext(SslContext sslContext) { public NettyServerBuilder sslContext(SslContext sslContext) {
this.sslContext = sslContext; this.sslContext = sslContext;