Should gRPC use the trust-store for client-side SSL?

1,469 views
Skip to first unread message

Mark Nuttall-Smith

unread,
Oct 29, 2018, 3:25:28 PM10/29/18
to grpc.io
Hi,

I have a gRPC client (C# and Python) using client-side SSL which is terminated in an Istio ingress gateway (envoy) before reaching the service.

When using a genuine certificate from LetsEncrypt everything works fine.

However, when the ingress gateway is configured with a self signed SSL certificate, generated from a root CA which has been added to the trust store (keychain/cert-manager) on the client machine, the connection fails:

E1029 17:01:45.274918000 123145515409408 ssl_transport_security.cc:1229] Handshake failed with fatal error SSL_ERROR_SSL: error:1000007d:SSL routines:OPENSSL_internal:CERTIFICATE_VERIFY_FAILED.

Chrome/curl etc will connect to the http services behind the same ingress gateway without SSL warnings (given that the root CA certificate has been added to the trust store).

My question is: should gRPC also be using the trust store for client-side SSL? If so, any ideas what I might be doing wrong. 

Thanks,
Mark

li...@google.com

unread,
Oct 29, 2018, 3:43:59 PM10/29/18
to grpc.io
Hi Mark,

Can you try to add the root certificates to the gRPC client, and see if the warning go away?

Lidi

Mark Nuttall-Smith

unread,
Oct 29, 2018, 5:02:41 PM10/29/18
to grpc.io
Hi Lidi,

Yep, that works too - eg. for the Python client:

with open('ca.crt', 'rb') as f:
    creds
= grpc.ssl_channel_credentials(f.read())
channel
= secure_channel(host, creds)

Where ca.crt is the same certificate that I imported into the trust store. 

However, I don't want to distribute the client certificate with the application. In a corporate environment I'd expect a sysadmin to push the corporate CA root certificate to the trust store... right?

Cheers, Mark

jian...@google.com

unread,
Oct 29, 2018, 5:43:36 PM10/29/18
to grpc.io
Which platform does your client run? Looks like MacOS.

For Linux, we support read from grpc system root store. For MacOS, it is not support yet -- grpc only reads default root from root pem certificates shipped with grpc.

However, there are a few other ways to load root certificates. E.g., you can pass root certificate file through env var "GRPC_DEFAULT_SSL_ROOTS_FILE_PATH". Or you can specify grpc_set_ssl_roots_override_callback().

Mark Nuttall-Smith

unread,
Oct 29, 2018, 5:47:27 PM10/29/18
to jian...@google.com, grp...@googlegroups.com
Hi,
Indeed I'm running these tests on Mac OS, but in reality the deployed environment is Windows. Is the system trust store supported there?
Thanks

--
You received this message because you are subscribed to a topic in the Google Groups "grpc.io" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/grpc-io/xtSG6QGP640/unsubscribe.
To unsubscribe from this group and all its topics, send an email to grpc-io+u...@googlegroups.com.
To post to this group, send email to grp...@googlegroups.com.
Visit this group at https://groups.google.com/group/grpc-io.
To view this discussion on the web visit https://groups.google.com/d/msgid/grpc-io/2f088a10-21a4-459d-bf80-a749f120d22a%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Jiangtao Li

unread,
Oct 29, 2018, 5:53:32 PM10/29/18
to marknutt...@gmail.com, grp...@googlegroups.com
Here are complexity and technical challenges of loading system root store on MacOS and Windows. On MacOS, keychain APIs cannot be easily accessed by grpc c core. On Windows, the initial system root store could be empty, which cause negative user experience. There are performance penalty as well.
We can put these into feature requests, but we do not resource at this moment to implement in the near term.

Thanks,
Jiangtao

Mark Nuttall-Smith

unread,
Oct 30, 2018, 1:38:38 PM10/30/18
to grpc.io
Thanks for the info, Jingtao.

In case of interest to anyone in future, on Windows, something like the following works for loading a certificate from the system store:

var certStore = new X509Store(StoreName.Root, StoreLocation.CurrentUser);
certStore
.Open(OpenFlags.ReadOnly);
var caCert = certStore.Certificates.Find(X509FindType.FindBySubjectName, "xxx.yyyy.zzz", true)[0];

var rootCertificates = string.Join(Environment.NewLine,
   
"-----BEGIN CERTIFICATE-----",
   
Convert.ToBase64String(caCert.RawData, Base64FormattingOptions.InsertLineBreaks),
   
"-----END CERTIFICATE-----");

var channelCredentials = new SslCredentials(rootCertificates);
var channel = new Channel("xxx.yyyy.zzz", channelCredentials);
var client = new Greeter.GreeterClient(channel);

Hacky, but it works for now...
Reply all
Reply to author
Forward
0 new messages