March 25, 2021

gRPC and SSL/TLS Ciphers and Protocol Version

Documentation

https://grpc.io/docs/guides/auth/

https://github.com/grpc/grpc-java/blob/master/SECURITY.md

Setup

Generate a self-signed server certificate in PEM format.

$ keytool -genkeypair -alias localhost -keyalg RSA -keysize 2048 -dname "CN=localhost,O=Antigo,ST=Stockholm,C=SE" -validity 720 -storetype PKCS12 -keystore localhost.p12 -storepass changeit -keypass changeit -v
Generating 2,048 bit RSA key pair and self-signed certificate (SHA256withRSA) with a validity of 720 days
	for: CN=localhost, O=Antigo, ST=Stockholm, C=SE
[Storing localhost.p12]

$ openssl pkcs12 -in localhost.p12 -out localhost.pem -nodes
Enter Import Password:

Then manually split pem file into a .crt.pem and .key.pem file.

Java

Server

package se.magnuskkarlsson.example_grpc.server;

import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
import java.util.List;

import io.grpc.Server;
import io.grpc.netty.shaded.io.grpc.netty.GrpcSslContexts;
import io.grpc.netty.shaded.io.grpc.netty.NettyServerBuilder;

public class HelloServer {

    public static void main(String[] args) throws IOException, InterruptedException {
        System.out.println("Starting Server ...");

        InputStream certChainFile = HelloServer.class.getClassLoader().getResourceAsStream("localhost.crt.pem");
        InputStream privateKeyFile = HelloServer.class.getClassLoader().getResourceAsStream("localhost.key.pem");
//        final Server server = ServerBuilder //
//                .forPort(50051) //
////                https://grpc.io/docs/guides/auth/#java
//                .useTransportSecurity(certChainFile, privateKeyFile) //
//                .addService(new HelloServiceImpl()) //
//                .build();

        Listlt;Stringgt; ciphers = Arrays.asList(/* "TLS_DHE_RSA_WITH_AES_256_GCM_SHA384", */
                "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384", /* "TLS_DHE_RSA_WITH_AES_128_GCM_SHA256", */
                "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256");

//        https://github.com/grpc/grpc-java/blob/master/SECURITY.md
        final Server server = NettyServerBuilder //
                .forPort(50051) //
                .sslContext( //
                        GrpcSslContexts //
                                .forServer(certChainFile, privateKeyFile) //
                                .protocols("TLSv1.2") //
                                .ciphers(ciphers)
//                                .trustManager(clientCAsFile) //
//                                .clientAuth(ClientAuth.REQUIRE) //
                                .build()) //
                .addService(new HelloServiceImpl()) //
                .build();

        server.start();

        Runtime.getRuntime().addShutdownHook(new Thread(() -gt; {
            System.out.println("Shutting down Server ....");
            server.shutdown();
            System.out.println("Successfully stopped Server");
        }));

        server.awaitTermination();
    }

}

Client

package se.magnuskkarlsson.example_grpc.client;

import java.io.InputStream;
import java.util.Iterator;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

import example_grpc.HelloServiceGrpc;
import example_grpc.HelloServiceGrpc.HelloServiceBlockingStub;
import example_grpc.HelloServiceGrpc.HelloServiceStub;
import example_grpc.HelloServiceOuterClass.HelloBiDirectionalStreamingRequest;
import example_grpc.HelloServiceOuterClass.HelloBiDirectionalStreamingResponse;
import example_grpc.HelloServiceOuterClass.HelloClientStreamingRequest;
import example_grpc.HelloServiceOuterClass.HelloClientStreamingResponse;
import example_grpc.HelloServiceOuterClass.HelloRequest;
import example_grpc.HelloServiceOuterClass.HelloResponse;
import example_grpc.HelloServiceOuterClass.HelloServerStreamingRequest;
import example_grpc.HelloServiceOuterClass.HelloServerStreamingResponse;
import io.grpc.ManagedChannel;
import io.grpc.netty.shaded.io.grpc.netty.GrpcSslContexts;
import io.grpc.netty.shaded.io.grpc.netty.NettyChannelBuilder;
import io.grpc.stub.StreamObserver;

// https://github.com/grpc/grpc-java/blob/master/examples/src/main/java/io/grpc/examples/routeguide/RouteGuideClient.java
public class HelloClient {

    public static void main(String[] args) throws Exception {
        System.out.println("Starting Client ...");

//        ManagedChannel channel = ManagedChannelBuilder //
//                .forAddress("localhost", 50051) //
//                .usePlaintext() //
//                .build();

        // https://grpc.io/docs/guides/auth/#java
        InputStream truststore = HelloClient.class.getClassLoader().getResourceAsStream("localhost.crt.pem");
        ManagedChannel channel = NettyChannelBuilder //
                .forAddress("localhost", 50051) //
                .sslContext(GrpcSslContexts.forClient().trustManager(truststore).build()) //
                .build();

        new HelloClient().unary(channel);
//        new HelloClient().serverStreaming(channel);
//        new HelloClient().clientStreaming(channel);
//        new HelloClient().biDirectionalStreaming(channel);

        System.out.println("Shutting down Client");
        channel.shutdown();
    }

    private void unary(ManagedChannel channel) {
        HelloServiceBlockingStub syncClient = HelloServiceGrpc.newBlockingStub(channel);
//        HelloServiceStub asyncClient = HelloServiceGrpc.newStub(channel);

        HelloRequest req1 = HelloRequest.newBuilder().setName("Magnus").build();
        HelloResponse resp1 = syncClient.hello(req1);
        System.out.println("[Async] " + resp1);

        HelloRequest req2 = HelloRequest.newBuilder().setName("John Doe").build();
        HelloResponse resp2 = syncClient.hello(req2);
        System.out.println("[Async] " + resp2);
    }
    
}

No comments: