Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test: add kitex grpc client with gPRC server TLS test #47

Open
wants to merge 7 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions common/common.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// Copyright 2024 CloudWeGo Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package common

import (
"net"
"time"

"github.com/cloudwego/kitex/pkg/klog"
)

func WaitServer(hostPort string) {
for begin := time.Now(); time.Since(begin) < time.Second; {
if _, err := net.Dial("tcp", hostPort); err == nil {
klog.Infof("server %s is up", hostPort)
return
}
time.Sleep(time.Millisecond * 10)
}
}
55 changes: 55 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
module github.com/cloudwego/kitex-tests

go 1.17

require (
github.com/apache/thrift v0.13.0
github.com/bytedance/gopkg v0.0.0-20230728082804-614d0af6619b
github.com/cloudwego/fastpb v0.0.4
github.com/cloudwego/kitex v0.8.1-0.20240108100713-a6d5d904434d
github.com/cloudwego/netpoll v0.5.1
google.golang.org/grpc v1.36.1
google.golang.org/protobuf v1.28.1
)

require (
github.com/bytedance/sonic v1.10.2 // indirect
github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d // indirect
github.com/chenzhuoyu/iasm v0.9.1 // indirect
github.com/choleraehyq/pid v0.0.17 // indirect
github.com/cloudwego/configmanager v0.2.0 // indirect
github.com/cloudwego/dynamicgo v0.1.6 // indirect
github.com/cloudwego/frugal v0.1.12 // indirect
github.com/cloudwego/localsession v0.0.2 // indirect
github.com/cloudwego/thriftgo v0.3.5 // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/fatih/structtag v1.2.0 // indirect
github.com/golang/protobuf v1.5.2 // indirect
github.com/google/pprof v0.0.0-20220608213341-c488b8fa1db3 // indirect
github.com/iancoleman/strcase v0.2.0 // indirect
github.com/jhump/protoreflect v1.8.2 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/klauspost/cpuid/v2 v2.2.4 // indirect
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 // indirect
github.com/modern-go/gls v0.0.0-20220109145502-612d0167dce5 // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/oleiade/lane v1.0.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/stretchr/testify v1.8.2 // indirect
github.com/tidwall/gjson v1.9.3 // indirect
github.com/tidwall/match v1.1.1 // indirect
github.com/tidwall/pretty v1.2.0 // indirect
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
golang.org/x/arch v0.2.0 // indirect
golang.org/x/net v0.0.0-20221014081412-f15817d10f9b // indirect
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4 // indirect
golang.org/x/sys v0.0.0-20220817070843-5a390386f1f2 // indirect
golang.org/x/text v0.6.0 // indirect
google.golang.org/genproto v0.0.0-20210513213006-bf773b8c8384 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)

replace (
github.com/apache/thrift => github.com/apache/thrift v0.13.0
github.com/cloudwego/kitex => github.com/felix021/kitex v0.8.1-0.20240111074411-c4fd7c65edf8
)
43 changes: 43 additions & 0 deletions grpc/tls/cert/gen.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
#! /bin/bash
# Copyright 2024 CloudWeGo Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

set -e
ppzqh marked this conversation as resolved.
Show resolved Hide resolved

rm -f *.pem
rm -f *.srl

# 1. Generate CA's private key and self-signed certificate
openssl req -x509 -newkey rsa:4096 -days 365 -nodes -keyout ca-key.pem -out ca-cert.pem -subj "/C=FR/ST=Occitanie/L=Toulouse/O=Tech School/OU=Education/CN=*.techschool.guru/[email protected]"

echo "CA's self-signed certificate"
openssl x509 -in ca-cert.pem -noout -text

# 2. Generate web server's private key and certificate signing request (CSR)
openssl req -newkey rsa:4096 -nodes -keyout server-key.pem -out server-req.pem -subj "/C=FR/ST=Ile de France/L=Paris/O=PC Book/OU=Computer/CN=*.pcbook.com/[email protected]"

# 3. Use CA's private key to sign web server's CSR and get back the signed certificate
openssl x509 -req -in server-req.pem -days 60 -CA ca-cert.pem -CAkey ca-key.pem -CAcreateserial -out server-cert.pem

echo "Server's signed certificate"
openssl x509 -in server-cert.pem -noout -text

# 4. Generate client's private key and certificate signing request (CSR)
openssl req -newkey rsa:4096 -nodes -keyout client-key.pem -out client-req.pem -subj "/C=FR/ST=Alsace/L=Strasbourg/O=PC Client/OU=Computer/CN=*.pcclient.com/[email protected]"

# 5. Use CA's private key to sign client's CSR and get back the signed certificate
openssl x509 -req -in client-req.pem -days 60 -CA ca-cert.pem -CAkey ca-key.pem -CAcreateserial -out client-cert.pem

echo "Client's signed certificate"
openssl x509 -in client-cert.pem -noout -text
130 changes: 130 additions & 0 deletions grpc/tls/grpc_server.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
// Copyright 2024 CloudWeGo Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package tls

import (
"context"
"crypto/tls"
"crypto/x509"
"fmt"
"io"
"io/ioutil"
"net"
"strings"

"google.golang.org/grpc"
"google.golang.org/grpc/credentials"

grpc_demo "github.com/cloudwego/kitex-tests/grpc_gen/protobuf/grpc_demo_2"
)

func RunGRPCTLSServer(hostport string) (*grpc.Server, error) {
tlsCredentials, err := serverLoadTLSCredentials()
if err != nil {
return nil, err
}
cred := grpc.Creds(tlsCredentials)

svr := grpc.NewServer(cred)
ms := &GrpcServiceA{}
grpc_demo.RegisterServiceAServer(svr, ms)
listener, err := net.Listen("tcp", hostport)
if err != nil {
return nil, err
}
go svr.Serve(listener)
return svr, nil
}

type GrpcServiceA struct {
grpc_demo.UnimplementedServiceAServer
}

func (s *GrpcServiceA) CallUnary(ctx context.Context, req *grpc_demo.Request) (*grpc_demo.Reply, error) {
res := &grpc_demo.Reply{Message: req.Name + " Hello!"}
return res, nil
}

func (s *GrpcServiceA) CallClientStream(stream grpc_demo.ServiceA_CallClientStreamServer) error {
var msgs []string
for {
req, err := stream.Recv()
if err != nil {
if err == io.EOF {
break
}
return err
}
msgs = append(msgs, req.Name)
}
return stream.SendAndClose(&grpc_demo.Reply{Message: "all message: " + strings.Join(msgs, ", ")})
}
func (s *GrpcServiceA) CallServerStream(req *grpc_demo.Request, stream grpc_demo.ServiceA_CallServerStreamServer) error {
resp := &grpc_demo.Reply{}
for i := 0; i < 3; i++ {
resp.Message = fmt.Sprintf("%v-%d", req.Name, i)
err := stream.Send(resp)
if err != nil {
return err
}
}
return nil
}
func (s *GrpcServiceA) CallBidiStream(stream grpc_demo.ServiceA_CallBidiStreamServer) error {
for {
recv, err := stream.Recv()
if err != nil {
if err == io.EOF {
break
}
return err
}
resp := &grpc_demo.Reply{}
resp.Message = recv.Name
err = stream.Send(resp)
if err != nil {
return err
}
}
return nil
}

func serverLoadTLSCredentials() (credentials.TransportCredentials, error) {
// Load certificate of the CA who signed client's certificate
pemClientCA, err := ioutil.ReadFile("cert/ca-cert.pem")
if err != nil {
return nil, err
}

certPool := x509.NewCertPool()
if !certPool.AppendCertsFromPEM(pemClientCA) {
return nil, fmt.Errorf("failed to add client CA's certificate")
}

// Load server's certificate and private key
serverCert, err := tls.LoadX509KeyPair("cert/server-cert.pem", "cert/server-key.pem")
if err != nil {
return nil, err
}

// Create the credentials and return it
config := &tls.Config{
Certificates: []tls.Certificate{serverCert},
ClientAuth: tls.RequireAndVerifyClientCert, // mTLS
ClientCAs: certPool,
}

return credentials.NewTLS(config), nil
}
Loading
Loading