Ingress gateways allow you to configure Google Remote Procedure Call (gRPC) services that are based on the mutual TLS (mTLS) protocol. This security mechanism ensures that only authorized clients can access gRPC services. End-to-end encryption and two-way authentication are implemented throughout the data transmission process to effectively protect information from eavesdropping, tampering, and unauthorized access.
Background information
You can route traffic to gRPC services in an ASM instance by using an ingress gateway.Service Mesh gRPC services are built on top of the HTTP/2 protocol. This allows you to use the TLS or mTLS protocol to encrypt transmitted data to ensure data security. Ingress gateways support gRPC with TLS or mTLS. TLS termination is performed on encrypted TCP data streams when they pass through ingress gateways. You do not need to configure TLS for applications in the ASM instance.
Procedure
Step 1: Deploy a sample application
Log on to the ACK console. In the left-side navigation pane, click Clusters.
On the Clusters page, click the name of the cluster that you want to manage and choose in the left-side navigation pane.
In the upper part of the Deployments page, select a namespace from the Namespace drop-down list and click Create from YAML.
On the Create page, copy the following YAML code to the code editor and click Create.
Expand to view the YAML code
apiVersion: apps/v1
kind: Deployment
metadata:
name: istio-grpc-server-v1
labels:
app: istio-grpc-server
version: v1
spec:
replicas: 1
selector:
matchLabels:
app: istio-grpc-server
version: v1
template:
metadata:
labels:
app: istio-grpc-server
version: v1
spec:
containers:
- args:
- --address=0.0.0.0:8080
image: registry.cn-hangzhou.aliyuncs.com/aliacs-app-catalog/istio-grpc-server
imagePullPolicy: Always
livenessProbe:
exec:
command:
- /bin/grpc_health_probe
- -addr=:8080
initialDelaySeconds: 2
name: istio-grpc-server
ports:
- containerPort: 8080
readinessProbe:
exec:
command:
- /bin/grpc_health_probe
- -addr=:8080
initialDelaySeconds: 2
---
apiVersion: v1
kind: Service
metadata:
name: istio-grpc-server
labels:
app: istio-grpc-server
spec:
ports:
- name: grpc-backend
port: 8080
protocol: TCP
selector:
app: istio-grpc-server
type: ClusterIP
---
Note
The name
parameter of the ports
field in the service configuration must start with http2-
or grpc-
. Otherwise, Istio cannot identify the service protocol.
Step 2: Create an ingress gateway
In this example, the default port 443 is used to expose the service. For more information, see Create an ingress gateway.
Step 3: Configure an Istio gateway and a virtual service
Log on to the ASM console. In the left-side navigation pane, choose .
On the Mesh Management page, find the ASM instance that you want to configure, and click the instance name or click Manage in the Actions column.
Create an Istio gateway.
On the details page of the ASM instance, choose in the left-side navigation pane.
On the Gateway page, click Create from YAML.
On the Create page, select default from the Namespace drop-down list, copy the following YAML code to the code editor, and then click Create.
apiVersion: networking.istio.io/v1beta1
kind: Gateway
metadata:
name: gw-grpc-443
namespace: default
spec:
selector:
istio: ingressgateway
servers:
- hosts:
- '*'
port:
name: https
number: 443
protocol: HTTPS
tls:
credentialName: example-credential
mode: MUTUAL
Create a virtual service.
On the details page of the ASM instance, choose in the left-side navigation pane.
On the VirtualService page, click Create from YAML.
On the Create page, select default from the Namespace drop-down list, copy the following YAML code to the code editor, and then click Create.
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: grpc-vs
spec:
hosts:
- "*"
gateways:
- gw-grpc-443
http:
- match:
- port: 443
route:
- destination:
host: istio-grpc-server
Step 4: Mount a certificate
Typically, a gRPC client requires a Subject Alternative Name (SAN) certificate. We recommend that you use the certificates listed in grpc-go. Mount the certificate to the istio-system namespace of the ACK cluster because the ingress gateway requires the certificate.
For an ASM instance of a version earlier than 1.17
Run the following command to create a secret in the istio-system namespace:
kubectl create -n istio-system secret generic example-credential --from-file=tls.key=server_key.pem --from-file=tls.crt=server_cert.pem --from-file=ca.crt=client_ca_cert.pem
Note
The secret name must be the same as the credentialName that is configured in the Istio gateway.
For an ASM instance of version 1.17 or later
Log on to the ASM console. In the left-side navigation pane, choose .
On the Mesh Management page, click the name of the ASM instance. In the left-side navigation pane, choose .
On the Certificate Management page, click Create. In the Certificate Information panel, configure the required parameters and click OK.
Step 5: Start the gRPC client
In this example, a gRPC client that uses mTLS is started. For more information, see the official gRPC website.
Install dependencies. For more information, see Quick start of gRPC in Go.
Clone the gRPC-go code repository. For more information, see gRPC-go.
Replace the content of the main.go file in the /grpc-go/examples/helloworld/greeter_client/ path with the following code and change the address
value to ${IP address of the ingress gateway}:443
:
Expand to view the sample code
package main
import (
"context"
"crypto/tls"
"crypto/x509"
"flag"
"io/ioutil"
"log"
"time"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials"
pb "google.golang.org/grpc/examples/helloworld/helloworld"
)
const (
defaultName = "world"
)
var (
addr = flag.String("addr", "localhost:50051", "the address to connect to")
name = flag.String("name", defaultName, "Name to greet")
cert = flag.String("cert", "./data/x509/client_cert.pem", "server cert for mTLS")
key = flag.String("key", "./data/x509/client_key.pem", "server key for mTLS")
cacert = flag.String("cacert", "./data/x509/ca_cert.pem", "ca cert for mTLS")
servername = flag.String("servername", "x.test.example.com", "the cert name of server")
)
func main() {
flag.Parse()
certPair, err := tls.LoadX509KeyPair(*cert, *key)
if err != nil {
log.Fatalf("failed to load client cert: %v", err)
}
ca := x509.NewCertPool()
caFilePath := *cacert
caBytes, err := ioutil.ReadFile(caFilePath)
if err != nil {
log.Fatalf("failed to read ca cert %q: %v", caFilePath, err)
}
if ok := ca.AppendCertsFromPEM(caBytes); !ok {
log.Fatalf("failed to parse %q", caFilePath)
}
tlsConfig := &tls.Config{
ServerName: *servername,
Certificates: []tls.Certificate{certPair},
RootCAs: ca,
}
conn, err := grpc.Dial(*addr, grpc.WithTransportCredentials(credentials.NewTLS(tlsConfig)))
if err != nil {
log.Fatalf("did not connect: %v", err)
}
defer conn.Close()
c := pb.NewGreeterClient(conn)
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
defer cancel()
r, err := c.SayHello(ctx, &pb.HelloRequest{Name: *name})
if err != nil {
log.Fatalf("could not greet: %v", err)
}
log.Printf("Greeting: %s", r.GetMessage())
}
Go to the examples path and run the following command:
go run helloworld/greeter_client/main.go
Expected result:
If the error shown in the following figure is returned, the certificate is invalid. Perform the preceding steps to mount the certificate again.