How to configure gRPC Client communicating over TLS transport layer without server certificate? - ssl

Currently I want to expose a gRPC Method as Public API and protected by Auth0 (JWT Token), with Istio(Envoy Proxy) will help validating the token on server side. Since the JWT Token is not encrypted by the standard (it is only used to end-user authentication and authorization layer), I want to encrypt the communication using TLS. Also, my public server already have valid certificate.
The problem is on the gRPC Client side. Every example I look, the gRPC Client have to initialize the TLS Connection with server cert pem file. Is it really necessary? Because it adds operational burden and complexity, where we have to distribute our server pem file everytime we renew the certificate AND/OR the client side has to restart the application.
Thanks,
Agung

If you are using a self signed certificate, then yes you must explicitly trust it in your client. If you use a publicly signed certificate on your Server, gRPC will use the Operating System's certificate authorities to verify the cert. (In the case of Java, it uses the JVMs cert authorities.)

If you are using a self-signed certificate you need to specify the server's root certificates in the pem_root_certs member of the SslCredentialsOptions struct passed in when creating a channel, as Carl says.
However if you are using a CA issued certificate, leaving the pem_root_certs member empty will cause gRPC to default to its own master list (reviewable online), not any OS-specific list.

Related

How to set client certificate chain in WinHttp

I am working on a client-server application where server is a web server which performs client validation based on SSL certificate. Server trust a Root CA certificate. Client is a windows application developed in C++ which has a certificate signed by intermediate CA which in turn signed by Root CA.
I am able to set client certificate during https connection by calling WinHttpSetOption api with WINHTTP_OPTION_CLIENT_CERT_CONTEXT as option. However this will set only client certificate but not the entire chain. Server does not have intermediate CA in its store hence it is not able to authenticate the client.
Is there a way to set the full client certificate chain in WinHttp, provided the full chain is already present in certificate store of client?
The server has to have the CA certificate beforehand, it's not going to trust the root CA the client hands it. (I'm not sure about whether it (the server-side) would trust an intermediate CA signed by a trusted CA but my inclination says no).
Trusting some random CA a client sends would break the entire point of certificate verification, you would have no idea of whether the data the client submits is actually meaningful. So add the root and intermediate CA certificates to the server's certificate stores. (If you don't have access to that you'll have to talk to an admin and have them do it).
I'm not really seeing anything wrong with what you are doing.
You are implementing mTLS. The client side has a private key that it uses to validate itself to the Server. Most times the client will generate this private key itself and just send it to the server via CSR. In your case you have some CA generate it for you.
mTLS is used in place of some other sort of login a client might do to a server. The client itself doesnt care about the cert chain. The client doesnt need to validate itself. It just sends a token encoded via its private key. The server DOES need the root or intermediate cert in order to validate the key the client has sent. Usually you just install this root into your normal cert store (server side) so the server can validate the client.
Only I could find was to Add Sub CA to system store. During service startup or installation, open the CA certificate store and Add certificate context to it.

How secure is the https connection if the client not passes certificate

We have a web server running on linux machine where we configured 'SSLVerifyClient' as 'require' in ssl.conf file.
Does this needs client who is utilizing the service from web browser(like firefox or chrome) needs a certificate.
If yes, then it is not possible to distribute client certificate to every user as there can be some thousands of users, how to overcome this problem.
If no, then how the data passed over network is secure? I know that certificate helps in encrypting data so that no one who don't have certificate can read data.
Please help me in clarifying my doubts
If you don't use client certificate, the https connection is still safe:
Only the client and the server can read/write the content
The identity of the server is assured by a certificate authority
Client certificate only give you client authentication in the beginning of the connection. To encrypt the data, the public key of the server is used in the beginning (See public key encryption).
If you identify the client with cookies set after login/password submit, it is still safe: you have identify the client.
When SSLVerifyClient is set to require, the client MUST pass a client certificate. You would generate these via OpenSSL, and sign them with a certificate authority that you install via SSLCACertificateFile.
How you distribute those certificates is an issue you'll have to solve yourself.

How can I use a self-signed client certificate in a WCF call with transport security?

I have a WCF service (authored in-house) using a WS-HTTP binding and transport security (SSL). We are authenticating callers with client certificates and a whitelist of acceptable certificates (certs are provided to us out-of-band). So we're using a custom validator (e.g. a class deriving from System.IdentityModel.Selectors.X509CertificateValidator) to do a database query to check the whitelist.
It works in the following case: We have a root certificate used in development, issued by the development team (using OpenSSL). This root is trusted (e.g. installed in the Trusted Third-Party CA cert store) on the server hosting our WCF service. The test client is configured to present a certificate signed by this root. This case behaves as expected.
It does not work in the following case: The client presents a self-signed certificate to the service. In this case the client receives the error message "The HTTP request was forbidden with client authentication scheme 'Anonymous'", and-- here's the odd part-- the service's certificate validator doesn't even run. We don't get any chance to give the thumbs-up. The client cert is rejected by a layer lower than our validator.
How can I use a self-signed client certificate with my service?
You can't. In WCF, WS-HTTP transport security is SSL. My error results from a failure in the SSL negotiation between the parties.
The normal case of this negotiation is as follows: The service sends the client a list of root certificates that it trusts. The client examines this list and finds a certificate that the server will find trustworthy and sends it.
In my error case, the client is examining the server's list and determining that its cert will not be trusted. At this point the client will normally attempt to negotiate down to anonymous access, which is forbidden in my case, so the negotiation fails.
WCF does not support self-signed client certificates, or certs issued by an untrusted CA, in WS-HTTP binding + transport security scenarios, even if you use custom validation mode. It does support this scenario in message security. I suspect that Net.TCP supports this scenario, but haven't tested that.

Two-way SSL clarification

I am somewhat confused as to how two-way SSL works. How does the client create its certificate to send to the server? Is it generated from the server and distributed to the client?
Also, what is the advantage of two-way SSL over one-way SSL?
Both certificates should exist prior to the connection. They're usually created by Certification Authorities (not necessarily the same). (There are alternative cases where verification can be done differently, but some verification will need to be made.)
The server certificate should be created by a CA that the client trusts (and following the naming conventions defined in RFC 6125).
The client certificate should be created by a CA that the server trusts.
It's up to each party to choose what it trusts.
There are online CA tools that will allow you to apply for a certificate within your browser and get it installed there once the CA has issued it. They need not be on the server that requests client-certificate authentication.
The certificate distribution and trust management is the role of the Public Key Infrastructure (PKI), implemented via the CAs. The SSL/TLS client and servers and then merely users of that PKI.
When the client connects to a server that requests client-certificate authentication, the server sends a list of CAs it's willing to accept as part of the client-certificate request. The client is then able to send its client certificate, if it wishes to and a suitable one is available.
The main advantages of client-certificate authentication are:
The private information (the private key) is never sent to the server. The client doesn't let its secret out at all during the authentication.
A server that doesn't know a user with that certificate can still authenticate that user, provided it trusts the CA that issued the certificate (and that the certificate is valid). This is very similar to the way passports are used: you may have never met a person showing you a passport, but because you trust the issuing authority, you're able to link the identity to the person.
You may be interested in Advantages of client certificates for client authentication? (on Security.SE).
What you call "Two-Way SSL" is usually called TLS/SSL with client certificate authentication.
In a "normal" TLS connection to example.com only the client verifies that it is indeed communicating with the server for example.com. The server doesn't know who the client is. If the server wants to authenticate the client the usual thing is to use passwords, so a client needs to send a user name and password to the server, but this happens inside the TLS connection as part of an inner protocol (e.g. HTTP) it's not part of the TLS protocol itself. The disadvantage is that you need a separate password for every site because you send the password to the server. So if you use the same password on for example PayPal and MyPonyForum then every time you log into MyPonyForum you send this password to the server of MyPonyForum so the operator of this server could intercept it and try it on PayPal and can issue payments in your name.
Client certificate authentication offers another way to authenticate the client in a TLS connection. In contrast to password login, client certificate authentication is specified as part of the TLS protocol. It works analogous to the way the client authenticates the server: The client generates a public private key pair and submits the public key to a trusted CA for signing. The CA returns a client certificate that can be used to authenticate the client. The client can now use the same certificate to authenticate to different servers (i.e. you could use the same certificate for PayPal and MyPonyForum without risking that it can be abused). The way it works is that after the server has sent its certificate it asks the client to provide a certificate too. Then some public key magic happens (if you want to know the details read RFC 5246) and now the client knows it communicates with the right server, the server knows it communicates with the right client and both have some common key material to encrypt and verify the connection.
In two way ssl the client asks for servers digital certificate and server ask for the same from the client. It is more secured as it is both ways, although its bit slow. Generally we dont follow it as the server doesnt care about the identity of the client, but a client needs to make sure about the integrity of server it is connecting to.

WCF Client Certificate Authentication

We have a typical client-server WCF service and I would like the following:
Client passes a certificate to the Server through the ClientCredentials property
Server looks at the certificate and see's that it has been issued by our trusted certificate authority
The client is rejected if they use a certificate that is not issued by our CA.
The client has a clientAuthentication certificate installed, along with our trusted CA.
The server has our trusted CA certificate installed. I dont want to install any other certificates.
I am flexible on the binding, however it does need to work in a web scenerio.
I thought about using BasicHttpBinding with TransportCredentialOnly, however it doesnt support certificates :(.
Ive tried using wsHttpBinding in Message mode, however that requires a ServerCertificate to perform server authentication and message encryption... which I dont want!
Is there any built-in way to achieve this?
All build in bindings allow using client certificates only when server certificate is used - mutal certificate authentication and security. To support your scenario you will have to handle it completely yourselves. If you want to inject your authentication mechanism to WCF you will have to do custom token and custom credentials.