Credentials
gRPC is built on top of the HTTP/2 protocol and provides excellent support for TLS. When certificate authentication is not required, gRPCity
by default skips the validation of server certificates. gRPC communication without certificates enables plaintext communication, exposing information to the risk of being intercepted by any third party.
To ensure that gRPC communication is not intercepted, tampered with, or forged by third parties, TLS encryption feature can be enabled on the server.
Note: Enabling TLS will increase CPU resource consumption. If your business scenario involves high QPS (Queries Per Second), it is not recommended to enable TLS.
Generate Certificates
Create your own SSL certificates. First, we need to create SSL certificates for both the server and the client. OpenSSL commands can be used to generate your own certificates.
We use a bash
script to generate certificates, setting global variables such as passwords and certificate validity period.
# Create the certs directory
mkdir -p certs && cd certs
# Set password variable
password="grpcity"
# Set certificate validity period variable
days=365
The 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"
The 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
The 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:
.
βββ certs
βββ ca.crt
βββ ca.key
βββ client.crt
βββ client.csr
βββ client.key
βββ server.crt
βββ server.csr
βββ server.key
Server Configuration
Letβs start the server certificate configuration. Use loader.makeServerCredentials()
to load the certificates.
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:
- During initialization
const server = await loader.initServer({ credentials })
- 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:
- Loading during
initClients()
const clients = await loader.initClients({
services: {
'test.helloworld.Greeter': addr,
'test.helloworld.Hellor': addr
},
credentials
})
- Loading during
get()
orgetReal()
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.