Does Go gRPC support mutual TLS using self-signed client certs? I'm trying to get mutual TLS working on Go gRPC, and I generated self-signed certs for the server and client using src/crypto/tls/generate_cert.go
, and the client is failing to connect with the server stating it's a bad cert.
Here's the relevant server code:
// load server cert/key, cacert
srvcert, err := tls.LoadX509KeyPair("server.pem", "key.pem")
if err != nil {
log.Fatalf("SERVER: unable to read server key pair: %v", err)
}
pem, err := ioutil.ReadFile("../client/client.pem")
if err != nil {
log.Fatalf("SERVER: unable to read client pem: %v", err)
}
certPool := x509.NewCertPool()
if ok := certPool.AppendCertsFromPEM(pem); !ok {
log.Fatalf("SERVER: unable to add client cert to pool: %v", err)
}
ta := credentials.NewTLS(&tls.Config{
Certificates: []tls.Certificate{srvcert},
ClientCAs: certPool,
ClientAuth: tls.RequireAndVerifyClientCert,
})
lis, err := net.Listen("tcp", ":51150")
if err != nil {
log.Fatalf("SERVER: unable to listen: %v", err)
}
s := grpc.NewServer(grpc.Creds(ta))
pb.RegisterExpoServer(s, &server{})
if err := s.Serve(lis); err != nil {
log.Fatalf("SERVER: failed to serve: %v", err)
}
And the relevant client code:
// load client cert/key, cacert
clcert, err := tls.LoadX509KeyPair("client.pem", "key.pem")
if err != nil {
log.Fatalf("CLIENT: unable to load client pem: %v", err)
}
srvcert, err := ioutil.ReadFile("../server/server.pem")
if err != nil {
log.Fatalf("CLIENT: unable to load server cert: %v", err)
}
caCertPool := x509.NewCertPool()
if ok := caCertPool.AppendCertsFromPEM(srvcert); !ok {
log.Fatalf("CLIENT: unable to load server cert pool: %v", err)
}
ta := credentials.NewTLS(&tls.Config{
Certificates: []tls.Certificate{clcert},
RootCAs: caCertPool,
})
conn, err := grpc.Dial("localhost:51150", grpc.WithTransportCredentials(ta))
if err != nil {
log.Fatalf("CLIENT: unable to dial: %v", err)
}
c := pb.NewExpoClient(conn)
The client is able to dial okay, but the error comes when trying to call an RPC on the client:
2018/07/28 19:32:18 CLIENT: unable to checkin: rpc error: code = Unavailable desc = all SubConns are in TransientFailure, latest connection error: connection error: desc = "transport: authentication handshake failed: remote error: tls: bad certificate"