今天會接續 [Go] 用 Go 建立 gRPC 的 Server 與 Client 的範例,將 Server/Client 之間加入 TLS 加密通道。
在開始之前要先準備好憑證,建立憑證的方式可以參考 [Go] 使用 Go Tool 建立 SSL 自簽憑證 。
Server 端設定憑證 今天的目標是,用 grpc/credentials 建立 grpc credentials.TransportCredentials ,便且將此憑證傳入grpc.NewServer()
。
可以參考下方的程式碼,設定 TLS 最重要的 2 行就是 creds, err := credentials.NewServerTLSFromFile("cert.pem", "key.pem")
與 s := grpc.NewServer(grpc.Creds(creds))
。
Set TLS to Server 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 package mainimport ( "google.golang.org/grpc" "google.golang.org/grpc/credentials" "log" "net" "trygrpc/pb" "trygrpc/service" ) const ( port = ":50051" ) func main () { lis, err := net.Listen("tcp" , port) if err != nil { log.Fatalf("failed to listen: %v" , err) } creds, err := credentials.NewServerTLSFromFile("cert.pem" , "key.pem" ) if err != nil { log.Fatalf("failed to create credentials: %v" , err) } s := grpc.NewServer(grpc.Creds(creds)) log.Println("gRPC server is running." ) pb.RegisterGreeterServer(s, &service.MessageService{}) if err := s.Serve(lis); err != nil { log.Fatalf("failed to serve: %v" , err) } }
Client 端設定憑證 Client 在讀取的時候,也要設定好憑證,這樣 Server 端在使用 key.pem
解密的時候才能夠正常運作。 而 Client 加入憑證的方式也很簡單。 最重要的 2 行是 creds, err := credentials.NewClientTLSFromFile("../cert.pem", "")
與 conn, err := grpc.Dial(address, grpc.WithTransportCredentials(creds), grpc.WithBlock())
。 其實跟 Server 大同小異。
Set TLS to Client 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 package mainimport ( "context" "google.golang.org/grpc" "google.golang.org/grpc/credentials" "log" "time" "trygrpc/pb" ) const ( address = "localhost:50051" ) func main () { creds, err := credentials.NewClientTLSFromFile("../cert.pem" , "" ) if err != nil { log.Fatalf("failed to load credentials: %v" , err) } conn, err := grpc.Dial(address, grpc.WithTransportCredentials(creds), grpc.WithBlock()) if err != nil { log.Fatalf("did not connect: %v" , err) } defer conn.Close() c := pb.NewGreeterClient(conn) name := "Miles" 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()) }
小結 最後可以參考此 commit ,比較使用 TLS 與不使用 TLS 的程式碼差異,就可以知道使用 TLS 並不會太難。
延伸閱讀 [grpc-go/examples/features/encryption ] [Enhancing Application Communication with gRPC ]