grpcurl
grpcurl copied to clipboard
Wrong error message if a server requires client certificates
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"