Search code examples
javasslnettygrpcgrpc-java

gRPC: How to configure SSL in client?


Its new topic for me. I'm able to connect as plaintext.

public ManagedChannel getChannel(String serviceName){
    TSServiceClientManager scm = TSServiceManagementFactory.getInstance().getServiceClientManager();
    TSServiceConnectionInfo connInfo = scm.getServiceConnectionInfo(serviceName);
    if(channel == null){
        channel = ManagedChannelBuilder.forAddress(connInfo.getHost(), connInfo.getPort())
                .usePlaintext(true) //need help here for SSL code 
                .build();
    }

    return channel;
}

I was told to enable client-side SSL. I know how to generate, keystore, truststore, pem, CA etc. I need help in :

How to enable SSL instead of .usePlaintext(true) as shown in above code?

(Kindly rewrite the code considering the cert file, keystore, truststore and .pem file exist)

And

I want to know is there anything to do with server to make SSL connection work?


Solution

  • Since grpc-java 1.37.0 it is possible for most users to configure TLS without using transport-specific APIs. This leverages the ChannelCredentials concept introduced in 1.34.0.

    ChannelCredentials creds = TlsChannelCredentials.newBuilder()
        // if server's cert doesn't chain to a standard root
        .trustManager(caFile)
        .keyManager(clientCertFile, keyFile) // client cert
        .build();
    channel = Grpc.newChannelBuilderForAddress(serverHost, serverPort, creds)
        .build();
    

    TlsServerCredentials and Grpc.newServerBuilderForPort() would be used on server-side.

    Advanced use cases may need to use transport-specific APIs like GrpcSslContexts and NettyChannelBuilder.sslContext().


    Original answer: You need to use a transport-specific API. You're likely using Netty today. For Netty, you need to configure Netty's SslContext and pass it to gRPC. Your usage may look something like this:

    SslContext sslcontext = GrpcSslContexts.forClient()
        // if server's cert doesn't chain to a standard root
        .trustManager(caFile)
        .keyManager(clientCertFile, keyFile) // client cert
        .build();
    channel = NettyChannelBuilder.forAddress(serverHost, serverPort)
        .sslContext(sslContext)
        .build();
    

    If you need server-side configuration, it would use the similar NettyServerBuilder.sslContext(). But the context itself would be different.