grpcurl icon indicating copy to clipboard operation
grpcurl copied to clipboard

Wrong error message if a server requires client certificates

Open TENX-S opened this issue 5 months ago • 0 comments

We can ask a gRPC server to verify client certificates like below (tweaked from grpc-go routeguide example):

		clientCA := data.Path("x509/client_ca_cert.pem")
		b, err := os.ReadFile(clientCA)
		if err != nil {
			log.Fatalf("failed to read client ca cert: %v", err)
		}

		certPool := x509.NewCertPool()
		if !certPool.AppendCertsFromPEM(b) {
			log.Fatalf("failed to load add client CA")
		}

		serverCert, err := tls.LoadX509KeyPair(*certFile, *keyFile)
		if err != nil {
			log.Fatalf("failed to laod serverCert: %v", err)
		}

		config := &tls.Config{
			Certificates: []tls.Certificate{serverCert},
			ClientAuth:   tls.RequireAndVerifyClientCert,
			ClientCAs:    certPool,
		}

		opts = []grpc.ServerOption{grpc.Creds(credentials.NewTLS(config))}

On the client side, if we only load server cert (from grpc-go routeguide example):

		if *caFile == "" {
			*caFile = data.Path("x509/ca_cert.pem")
		}
		creds, err := credentials.NewClientTLSFromFile(*caFile, *serverHostOverride)
		if err != nil {
			log.Fatalf("Failed to create TLS credentials: %v", err)
		}
		opts = append(opts, grpc.WithTransportCredentials(creds))

Then invoking a gRPC request by using the above TLS config will get the following error immediately:

$ go run route_guide/client/client.go -tls
2024/01/19 11:33:31 Getting feature for point (409146138, -746188906)
2024/01/19 11:33:31 client.GetFeature failed: rpc error: code = Unavailable desc = connection error: desc = "error reading server preface: remote error: tls: certificate required"
exit status 1

And if there is nothing wrong with my understanding, the above client call is equivalent to the following command:

$ grpcurl  \
-cacert "D:\Developer\Projects\grpc-go\examples\data\x509\ca_cert.pem" \
-authority "x.test.example.com" \
-d "{\"latitude\": 10,\"longitude\": 10}" \
 localhost:50051 GetFeature

But this command has the following error message after 10 seconds:

Failed to dial target host "localhost:50051": context deadline exceeded

Which is not like the one that gRPC server has returned:

rpc error: code = Unavailable desc = connection error: desc = "error reading server preface: remote error: tls: certificate required"

TENX-S avatar Jan 19 '24 04:01 TENX-S