liveBook · Manning

TLS

As explained in gRPC Microservices in Go

SSL/TLS is a family of cryptographic communication protocols that authenticates peers and encrypts data exchanged over a network.

Transport Layer Security (TLS) protects communication between microservices. gRPC uses HTTP/2 over SSL/TLS to authenticate peers and encrypt data exchanged between a client and server. This matters when a network call replaces an in-process call: service boundaries introduce both communication failures and a need to protect data in transit. TLS succeeds SSL. section 1.1 section 1.1.4 section 6.3

For a gRPC connection using client and server certificates, each side needs its own certificate and key, plus a certificate pool for the CA certificate. The server loads its certificate, configures client-certificate requirements and passes TLS transport credentials into gRPC server initialization. The client loads its certificate, sets a server name and trusted roots, and supplies TLS credentials when connecting. Certificate-loading and pool errors must be handled before accepting or making calls. section 6.3.3

Listing 6.8 gRPC TLS configuration
...
func getTlsCredentials() (credentials.TransportCredentials, error) {
    serverCert, serverCertErr := tls.LoadX509KeyPair("cert/server.crt", 
     "cert/server.key")                                         #1
    // handle serverCertErr
    certPool := x509.NewCertPool()                                #2
    caCert, caCertErr := ioutil.ReadFile("cert/ca.crt")
    // handle caCertErr
 
    if ok := certPool.AppendCertsFromPEM(caCert); !ok {           #3
        return nil, errors.New("failed to append the CA certs")
    }
 
    return credentials.NewTLS(
        &tls.Config{
            ClientAuth:   tls.RequireAnyClientCert,               #4
            Certificates: []tls.Certificate{serverCert},          #5
            ClientCAs:    certPool,                               #6
        }), nil
}
...
func main() {
 
    listener, err := net.Listen("tcp", fmt.Sprintf(":%d", 8080))
    // handle err
    tlsCredentials, tlsCredentialsErr := getTlsCredentials()
    // handle tlsCredentialsErr
    var opts []grpc.ServerOption
    opts = append(opts, grpc.Creds(tlsCredentials))               #7
 
    grpcServer := grpc.NewServer(opts...)
    ...
}

The Go server listing shows certificate loading, a CA certificate pool and credentials.NewTLS applied to the gRPC server. section 6.3.3

func getTlsCredentials() (credentials.TransportCredentials, error) {
    clientCert, clientCertErr := tls.LoadX509KeyPair("cert/client.crt", 
     "cert/client.key")                                                 #1
    // handle clientCertErr
 
    certPool := x509.NewCertPool()                                        #2
    caCert, caCertErr := ioutil.ReadFile("cert/ca.crt")
    // handle caCertErr
 
    if ok := certPool.AppendCertsFromPEM(caCert); !ok {                   #3
        return nil, errors.New("failed to append CA cert.")
    }
 
    return credentials.NewTLS(&tls.Config{
        ServerName:   "*.microservices.dev",                              #4
        Certificates: []tls.Certificate{clientCert},                      #5
        RootCAs:      certPool,                                           #6
    }), nil
}
...
func main() {
    tlsCredentials, tlsCredentialsErr := getTlsCredentials()
    // handle tlsCredentialsErr
    var opts []grpc.DialOption
 
    opts = append(opts, grpc.WithTransportCredentials(tlsCredentials))    #7
    conn, err := grpc.Dial("localhost:8080", opts...)
    // handle err
}
...

The companion client listing shows its certificate, RootCAs and ServerName configuration. section 6.3.3

Local certificate setup is useful for development, not a complete production certificate-management plan. In a larger microservice deployment, delegate certificate generation and management to a third party. TLS also needs attention at the deployment boundary: a Kubernetes Ingress can be configured with a TLS host and certificate-issuer annotation for a gRPC service, but its certificate is not automatically available to clients. The self-signed ingress.local certificate is intended only for local development. section 6.3 section 6.3.3 section 8.3.3

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  annotations:
    kubernetes.io/ingress.class: nginx
    nginx.ingress.kubernetes.io/backend-protocol: GRPC
    nginx.ingress.kubernetes.io/ssl-redirect: "true"
    cert-manager.io/cluster-issuer: selfsigned-issuer    #1
  name: order
spec:
  rules:
    - http:
        paths:
          - path: /Order
            pathType: Prefix
            backend:
              service:
                name: order
                port:
                  number: 8080
  tls:
    - hosts:
           - ingress.local                               #2

The Ingress manifest shows the gRPC backend, HTTPS redirect, certificate issuer and TLS host together. section 8.3.3

How gRPC Microservices in Go covers it

How deep it goes
Works through Go client and server credential configuration and Ingress setup, while deferring production certificate management and omitting certificate-password encryption.
Examples
Uses Go transport-credential listings for both peers and a Kubernetes Ingress manifest for a locally signed certificate.
What it assumes
Assumes gRPC client-server communication and service deployment context; introduces TLS’s purpose before showing certificate configuration.
What you can do after
Operate/configure TLS credentials for Go gRPC peers and TLS settings for a Kubernetes Ingress.
How it connects
Connects TLS to gRPC, HTTP/2, certificate authorities, mutual TLS, Kubernetes Ingress and certificate management.

Also explained in

Compare how 15 books explain TLS →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of gRPC Microservices in Go. The section links point to the parts of the book it draws on.