I'm trying to create a GRPC service to authenticate users. The back end server will be written in Go and the front end will be in Javascript. The connection between client and server must be secure, so I will use SSL/TLS on the server side.
My question has to do with the GRPC client API. When creating a GRPC client to make the request, I need to specify a credentials object:
var ssl_creds = grpc.credentials.createSsl(root_certs);
var stub = new helloworld.Greeter('myservice.example.com', ssl_creds);
There are a number of different credentials objects I can supply, but they all seem to require having the public key for the server present on the client side. How do I get the public key from the server to the client to create the credentials object? Do I have to do any sort of verification myself to ensure that the cert is trusted?
For libraries used to make REST HTTP requests, this step seemingly happens in the background, as I do not have to specify the key. Often you can supply the key as an optional parameter, which is only necessary when the SSL cert is not verified by some certificate authority. How are these libraries (e.g. jQuery or Python's requests library) fetching the necessary public key and performing verification? Is there similar functionality in the GRPC library which I can use for this purpose?
Related
I'm working with an old legacy app at work that's written in ASP.NET 4. We recently started migrating to the cloud and we had to expose one of the endpoints so that our api gateway (Apigee) can call it. What is the correct way to restrict this endpoint so that it only allows calls from Apigee? I'm aware 2-way-ssl should solve this issue but that requires changes on the Apigee side and we don't have control over that. Is there something I can do on the API side to confirm that the certificate in the request is specifically from Apigee?
You're describing the need for what is sometimes called 'southbound' authentication. Specifically mutual-TLS sometimes called client authentication, as opposed to standard (or one-way) TLS where only the server is being authenticated by the calling client. You're right: mTLS (a.k.a., "two-way SSL") is one means to allow your back-end server to authenticate the calling Apigee-layer 'client'.
When you want client authentication via TLS (mTLS) you need to configure your back-end server endpoint to require mTLS at the time of the handshake, and to have stored in its Truststore the signing CA certificate of the client certificate you expect to see offered up by the calling client at time of connection. Done right, your server
requires mTLS and shuts down the handshake if the client won't
offer a client cert,
validates the client cert is authentic as being issued by a recognized signing CA (Truststore), and
is the actual client cert expected to be seen (e.g., by matching the expected distinguished name).
Here's an authoritative support-community article about doing all this, within Apigee: https://community.apigee.com/questions/63337/mutual-tls-between-client-to-edge-and-edge-to-back.html
Hopefully I can make this clear enough.
Goal:
Client Certificate-Authenticated Azure Function
Scenario:
Azure Function App with:
HTTPS Only: set to Yes
Client certificate mode: set to Require
HTTP-triggered Azure Function (Python) which:
Loads client certificate from X-ARR-ClientCert header
Pulls a pre-shared client cert from a database and compares:
Issuer
CommonName
Not Valid Before/After
Hits the listed OCSP endpoint to see if cert is revoked
If properties from each cert match and the certificate has not been revoked, the Function will generate a SAS token for the requestor and send it in the response.
Question:
How is the cryptographic part of client cert auth handled in this scenario?
According to this (great) blog post, there is a CertificateVerify step where...
"The client is authenticated by using its private key to sign a
hash of all the messages up to this point. The recipient verifies
the signature using the public key of the signer, thus ensuring it
was signed with the client’s private key."
I don't see a way to access ...all the messages up to this point. to validate this has occured using the Function (Python) code.
Is this something Microsoft handles automagically (similar to how they forward client certs via the X-ARR-ClientCert header)? Or is this not possible?
From what I implemented in a similar case:
Your app received the certificate via the header and must:
load the certificate (using the library cryptography in python for example)
verify the signature of the certificate with you certificate authority
verify the date of validity
verify that it has not been revoked
Using web app (but the same would apply to functions), the Azure frontend seems to just launch authentication protocol to verify that the client that send the certificate has the private key associated (and launch the mutual auth protocol as described in the blog post). But it does not verify the validity or signature of the certificate.
The CertificateVerify step you're mentionning seems to be handled by the Azure Frontend, I don't think your need to worry about this process.
Hopes this helps !
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.
Is there a Groovy way to open a SSL connection to a server with client side authentification without using the JVM keystore?
I want to enable users to upload a public key over a website and then access a REST API on their server in a secure way. So I can have a lot of different keys which have to be loaded during runtime. I don't know if this is even possible using keystores.
I am looking for a solution, where I can just provide the keystring on connection initialization.
I am implementing an app where I don't have a system requiring username and password. What I do require is a name and a phone number.
The scenario is like this:
1) user opens the app for the first time
2)app makes a request to my server and gets a unique UserKey
3)from now one any request the app makes to my REST service also has a signature. The signature is actually a SHA(UserKey:the data provided in the request Base64Encoded)
4)The server also performs the same hash to check the signature
Why I don't use SSH:
not willing to pay for the certificate
I don't need to send sensitive data like passwords, so I don't see the benefit of using it
I just need a simple way to call my own WCF REST services from own app
I understand that there is a flow of security at step2 when the UserKey comes in cleartext, but this happens only once when the app is first opened. How dangerous do you think this is?
What would you recommend? Is there any .NET library that could help me?
Actually, there are several problems with that approach. Suppose there's man-in-the-middle whenever you make a request to the server. By analyzing, for example, 100 sent packets he would recognize similar pattern with signature in your requests. Then he would forge his own request and add your signature. The server checks the hash - everything's alright, it's you and your unique user key. But it's not.
There's a notion of asymmetric keys in cryptography which currently is really popular and provides tough security service. Main concept is the following: server generates two keys - public and private; public key is used to encode texts; they can be decoded only with the use of private key, which is kept by the server in secure location. So server gives client the public key to encode his messages. It may be made double: client generates public key and gives it to the server. Then server generates keys and gives encoded with client's public key his own public key. This way it's almost impossible for man-in-the-middle to make an attack.
Better yet, since the problem is really common, you could use OAuth to authorize users on your website. It is secure, widely used (facebook, g+, twitter, you name them) and has implementations already in variety of languages.
Since you control both the application itself and the webservices, you can do this with SSL (which gets rid of the problems with your current approach) without paying for anything. You can create a self-signed certificate and install that on your webserver; configure the SSL context of your client application to only trust that one certificate. Then, create a client-side self-signed certificate and install that within your application. Set the server up to require mutually-authenticated SSL and only allow your self-signed certificate for access.
Done. You client will only talk to your legitimate server (so no one can spoof your server and trick the client in to talking to it) and your server will only talk to your legitimate clients (so no one can steal information, ID, etc). And it's all protected with the strong cryptography used within SSL.