Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

grpc-node TLS sample code is not complete. #273

Open
GingerMoon opened this issue Apr 12, 2018 · 17 comments
Open

grpc-node TLS sample code is not complete. #273

GingerMoon opened this issue Apr 12, 2018 · 17 comments

Comments

@GingerMoon
Copy link

Hi gurus,
I am a newbee to node.js and grpc. So a good sample code is really appreciated.

The grpc-node TLS sample code is in https://grpc.io/docs/guides/auth.html#nodejs not complete.
For example, no sample code for TLS client side.
The strange thing is,
https://grpc.io/grpc/node/grpc.credentials.html
createSsl( [root_certs] [, private_key] [, cert_chain])
Create an SSL Credentials object. If using a client-side certificate, both the second and third arguments must be passed.
Why are private key and cert chain needed for client side?
They are not needed for grpc-go TLS client side.
grpc/grpc-go#1980

@marzolfb
Copy link

There is some confusion here and I'm not certain if you are trying to initiate a "normal" TLS connection to a server from the client side or if you are instead trying to connect to a server that performs client authentication via certs ("mutual TLS").

If it is the latter ("mutual TLS"), then you do need to pass the client cert (cert_chain) and private key for the cert (private_key) because the server you are connecting to requires it. Furthermore, the go example you point to (which I think is more pointing to the example here) is not doing mutual TLS (which requires providing a client-side cert/key) but rather it is just initiating a "normal" TLS connection to the server.

If it is the former (you are not doing mutual TLS), the optional [, private_key] [, cert_chain] parts would be omitted when making the call (which would match the go example you link to).

Hopefully that helps. I stumbled on this issue looking for other issues here and thought I would try to help clear things up.

@celesteking
Copy link

celesteking commented Sep 17, 2020

grpc nodejs docs are appalling. What shall I supply in root_certs? Buffer of what?

@gja
Copy link

gja commented Sep 20, 2020

@celesteking were you able to figure that out? We are having the same issue. In particular, node's root certs (require("tls").rootCertificates) are an array of strings

@murgatroid99
Copy link
Member

The root certs is supposed to be a Buffer loaded from a root certificates file. If you want to use the default public root certificates, just omit that argument. It is supposed to be used with self-signed certificates, or certificates that otherwise don't have a signing chain that includes one of the main root certificate authorities.

An example of self-signed certificates can be found in this directory: https://github.com/grpc/grpc-node/tree/master/test/data. The ca.pem file contains the root certificate.

@gja
Copy link

gja commented Sep 23, 2020

@murgatroid99 I don't believe the code works like that. The following example from the grpc-js, but I believe the native version works the same way. If ssl is missing, it looks for an environment variable called GRPC_DEFAULT_SSL_ROOTS_FILE_PATH (which is still a single .pem I believe).

defaultRootsData = fs.readFileSync(DEFAULT_ROOTS_FILE_PATH);

@murgatroid99
Copy link
Member

If that environment variable is not set, it defaults to using the built in root certificates.

Also, I'm not sure if this is clear: one .pem file can contain information for multiple certificates.

@GingerMoon
Copy link
Author

Thank you guys for the time on this ticket.
Since I am not working on this anymore, please feel free to close the ticket if needed.

@yellowandy
Copy link

Was also looking at just doing a TLS client connection from node (not mutual TLS) and couldn't get it working. The Java and Go equivalent are fairly straightforward but was unable to get it working in node.

@sourinMT
Copy link

Using credentials.createSsl() as credentials for a client side TLS connection(without any authentication) worked for me.

@njavilas2015
Copy link

it is super easy to create a grpc ssl server you only have to import the certificates in my case with letsencrypt

let credentials = grpc.ServerCredentials.createSsl(null
/fs.readFileSync('./certs/ca.crt')/, [{
cert_chain: fs.readFileSync('/etc/letsencrypt/fullchain.pem'),
private_key: fs.readFileSync('/etc/letsencrypt/privkey.pem')
}], false);

await server.bindAsync("0.0.0.0:50051", credentials, (error, port) => {
if (error) console.log(error)
console.log("listening grpc on *:50051");
server.start()
});

@nandor-magyar
Copy link

nandor-magyar commented Nov 19, 2021

Creating a server is straightforward based on the docs, it is the client-side what is lacking docs and possibly features.

I have managed to create server-side with a Node server, connecting golang clients, but I cannot add Node clients the same manner as with golang.

I would like to achieve server-side TLS.
The same way as it is done in golang example & mentioned by the OP:
https://grpc.io/docs/guides/auth/#with-server-authentication-ssltls

credentials.createSsl() is not working, and I see no option to provide the public key alone.

Authenticate using a public key, not using a CA, is this feature missing?

@murgatroid99
Copy link
Member

On the server side, you need to use ServerCredentials.createSsl().

@nandor-magyar
Copy link

Server-side, the node component being the client, ServerCredentials.createSsl() will work if the system already trusts the servers public key, otherwise it is to be set up.
Providing the public cert file into the rootCert/first param works with a generated private/public key-pair.

@ragauskl
Copy link

ragauskl commented Feb 23, 2022

I had a use case where I needed to test minimal setup of gRPC SSL on LAN with Node.js across multiple devices and without being familiar in detail with gRPC and SSL (plus everyone names root and intermediate certificates differently making it confusing sometimes) It took me couple days of frustration with lack of examples for server setup, so I made small server-client example for localhost in case anyone finds it useful: sample-grpc-ssl. It uses selfsigned certs with node-forge (Alternative with openssl here) or can replace them with letsencrypt or other

@vthakuri
Copy link

@murgatroid99 can you please give some sample code in nodejs for server to apply TLS

ServerCredentials.createSsl(). for this thing it will be really helpful or any link where in nodejs server side and client side TLS is setup sir please

@xmlking
Copy link

xmlking commented Oct 1, 2022

Example, if you have to use combine systemRootCerts and self-signed root cert as trust certs when gRPC client has to connect to both production server endpoint (server cert signed by public CA) as well as developoment server endpoint (server cert signed by self-signed CA)

import grpc from '@grpc/grpc-js';
import { readFileSync } from 'node:fs';
import tls from 'node:tls';
import { EOL } from 'node:os';
import type { ClientOptions } from '@grpc/grpc-js';
import type {VerifyOptions} from "@grpc/grpc-js/src/channel-credentials";

const systemRootCerts = Buffer.from(tls.rootCertificates.join(EOL));
const myRootCert = readFileSync('config/certs/ca-cert.pem')
const rootCerts  =  Buffer.concat([myRootCert, systemRootCerts])
const privateKey = readFileSync('config/certs/client-key.pem')
const certChain =	readFileSync('config/certs/client-cert.pem')
const verifyOptions: VerifyOptions = {}

const channelCredentials = grpc.credentials.createSsl(rootCerts, privateKey, certChain, verifyOptions)

console.debug('endpoints', endpoints);
// If no ServerName is set, infer the ServerName from the hostname we're connecting to.
const hostname = endpoints.engine?.split(':')[0] ?? 'localhost';
console.debug('engine hostname:', hostname);

const clientOptions: ClientOptions = {
	'grpc.ssl_target_name_override': hostname,
	'grpc.default_authority': hostname
};

const transport = new GrpcTransport({ host: endpoints.engine, channelCredentials, clientOptions });

const engineServiceClient = new EngineServiceClient(transport);

@notmedia
Copy link

notmedia commented Oct 2, 2022

I wrote an article about it - https://itnext.io/how-to-setup-and-test-tls-in-grpc-grpc-web-1b67cc4413e6

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests