Skip to Content
🎉 gRPCity 3.0 is released. Read more →

Credentials

gRPC runs over HTTP/2, so TLS is a natural fit. By default gRPCity does not require certificates and traffic flows in plaintext — fine for trusted internal links, risky on shared networks. Turn on TLS when you need confidentiality, integrity, or peer authentication.

TLS adds CPU cost on both ends. For very-high-QPS internal services, weigh that against the threat model.

Generating certificates

Use OpenSSL to mint a self-signed CA plus a server and client certificate signed by it. The shell snippets below stash common parameters in a few variables and produce the certs in a certs/ directory.

# Create the certs directory mkdir -p certs && cd certs # Set password variable password="grpcity" # Set certificate validity period variable days=365

CA certificate

# Set CA-related variables ca_key="ca.key" ca_crt="ca.crt" ca_subject="/C=CN/ST=GD/L=Guangzhou/O=gRPCity/OU=gRPCity/CN=ca" # Generate CA key and certificate openssl genrsa -passout pass:$password -des3 -out $ca_key 4096 openssl req -passin pass:$password -new -x509 -days $days -key $ca_key -out $ca_crt -subj "$ca_subject"

Server certificate

# Set server-related variables server_key="server.key" server_csr="server.csr" server_crt="server.crt" server_subject="/C=CN/ST=GD/L=Guangzhou/O=gRPCity/OU=Server/CN=localhost" # Generate server key and certificate openssl genrsa -passout pass:$password -des3 -out $server_key 4096 openssl req -passin pass:$password -new -key $server_key -out $server_csr -subj "$server_subject" openssl x509 -req -passin pass:$password -days $days -in $server_csr -CA $ca_crt -CAkey $ca_key -set_serial 01 -out $server_crt openssl rsa -passin pass:$password -in $server_key -out $server_key

Client certificate

# Set client-related variables client_key="client.key" client_csr="client.csr" client_crt="client.crt" client_subject="/C=CN/ST=GD/L=Guangzhou/O=gRPCity/OU=Client/CN=localhost" # Generate client key and certificate openssl genrsa -passout pass:$password -des3 -out $client_key 4096 openssl req -passin pass:$password -new -key $client_key -out $client_csr -subj "$client_subject" openssl x509 -passin pass:$password -req -days $days -in $client_csr -CA $ca_crt -CAkey $ca_key -set_serial 01 -out $client_crt openssl rsa -passin pass:$password -in $client_key -out $client_key

In the end, we have the following certificate directory:

Terminal
. └── certs ├── ca.crt ├── ca.key ├── client.crt ├── client.csr ├── client.key ├── server.crt ├── server.csr └── server.key

Building credentials manually

loader.makeServerCredentials() and loader.makeClientCredentials() cover the common path. When you need finer control — createFromSecureContext, Google ADC, composed credentials — gRPCity also re-exports the credentials namespace and the ChannelCredentials / ServerCredentials types, so you don’t have to depend on @grpc/grpc-js:

import { credentials } from 'grpcity' const insecure = credentials.createInsecure()

Server configuration

Use loader.makeServerCredentials() to wire up certificates on the server side.

The parameters for loader.makeServerCredentials(rootCerts, keyCertPairs, checkClientCertificate) are as follows:

  • rootCerts: Root certificate, usually the CA certificate;
  • keyCertPairs: Certificate pair, key and crt, must be an array;
  • checkClientCertificate: Whether to check the client certificate;

Example:

import fs from 'node:fs' import loader from './loader.js' const credentials = loader.makeServerCredentials( fs.readFileSync(path.resolve(__dirname, 'certs/ca.crt')), [{ private_key: fs.readFileSync(path.resolve(__dirname, 'certs/server.key')), cert_chain: fs.readFileSync(path.resolve(__dirname, 'certs/server.crt')) }], true)

Certificates can be loaded into the server in two ways:

  1. During initialization
const server = await loader.initServer({ credentials })
  1. During listening startup
await server.listen(addr, credentials)

Priority: listen() takes precedence over initServer()

After using certificates, the server cannot be started using an IP address; you can use localhost or a domain name instead.

Client configuration

Let’s start the client certificate configuration. Use loader.makeCredentials() to load the certificates.

import fs from 'node:fs' import path from 'node:path' const credentials = loader.makeClientCredentials( fs.readFileSync(path.resolve(__dirname, 'certs/ca.crt')), fs.readFileSync(path.resolve(__dirname, 'certs/client.key')), fs.readFileSync(path.resolve(__dirname, 'certs/client.crt')) )

After obtaining credentials, there are two ways to load them, as shown below:

  1. Loading during initClients()
const clients = await loader.initClients({ services: { 'test.helloworld.Greeter': addr, 'test.helloworld.Hellor': addr }, credentials })
  1. Loading during get() or getReal()
const greeterClient = clients.get('test.helloworld.Greeter', { credentials }) const result = await greeterClient.sayHello({ name: 'greeter' })
  • initClients() is suitable for scenarios where all servers use the same certificate.
  • get() is suitable for scenarios where different servers have different certificates.
Last updated on