💬
错觉。
💻
介绍完 grpc tls 证书认证,接下来继续介绍如何在 go-zero zrpc 中如何配置,关于 go-zero zrpc 的简单使用见 zrpc demo
服务端
AddOptions 即可,这里使用了 go1.16 的特性 embed 加载证书
import _ "embed"
var (
configFile = flag.String("f", "etc/hello.yaml", "the config file")
//go:embed tls/server.pem
serverPem []byte
//go:embed tls/server.key
serverKey []byte
//go:embed tls/ca.pem
caPem []byte
)
//getCreds 添加凭证
func getCreds() credentials.TransportCredentials {
// cert, err := tls.LoadX509KeyPair("../../tls/server.pem", "../../tls/server.key")
cert, err := tls.X509KeyPair(serverPem, serverKey)
if err != nil {
log.Fatalf("tls.LoadX509KeyPair err: %v", err)
}
certPool := x509.NewCertPool()
// ca, err := os.ReadFile("../../tls/ca.pem")
// if err != nil {
// log.Fatalf("ioutil.ReadFile err: %v", err)
// }
if ok := certPool.AppendCertsFromPEM(caPem); !ok {
log.Fatalf("certPool.AppendCertsFromPEM err")
}
creds := credentials.NewTLS(&tls.Config{
Certificates: []tls.Certificate{cert},
ClientAuth: tls.RequireAndVerifyClientCert,
ClientCAs: certPool,
})
return creds
}
func main() {
flag.Parse()
var c config.Config
conf.MustLoad(*configFile, &c)
ctx := svc.NewServiceContext(c)
srv := server.NewHelloServer(ctx)
s := zrpc.MustNewServer(c.RpcServerConf, func(grpcServer *grpc.Server) {
hello.RegisterHelloServer(grpcServer, srv)
})
// 添加证书设置
cred := getCreds()
s.AddOptions(grpc.Creds(cred))
defer s.Stop()
fmt.Printf("Starting rpc server at %s...\n", c.ListenOn)
s.Start()
}
ronething at ronething-dell-ubuntu in ~/Documents/grpc-sample/go-zero-tls (master●●)
$ ./main
Starting rpc server at 127.0.0.1:9999...
{"@timestamp":"2021-04-15T00:33:50.129+08","level":"stat","content":"(rpc) shedding_stat [1m], cpu: 254, total: 0, pass: 0, drop: 0"}
{"@timestamp":"2021-04-15T00:33:50.130+08","level":"stat","content":"CPU: 242m, MEMORY: Alloc=2.6Mi, TotalAlloc=6.0Mi, Sys=71.1Mi, NumGC=2"}
{"@timestamp":"2021-04-15T00:34:50.129+08","level":"stat","content":"(rpc) shedding_stat [1m], cpu: 143, total: 0, pass: 0, drop: 0"}
客户端
因为 zrpc newClient 写死了 dialoptions WithInsecure 如果直接使用原先的 test client 会报错
// https://github.com/tal-tech/go-zero/blob/5aded99df53c6f3eb0de896c213b65a4d6478b83/zrpc/internal/client.go#L67
func (c *client) buildDialOptions(opts ...ClientOption) []grpc.DialOption {
var cliOpts ClientOptions
for _, opt := range opts {
opt(&cliOpts)
}
options := []grpc.DialOption{
grpc.WithInsecure(), // 这里设置了 WithInsecure
grpc.WithBlock(),
WithUnaryClientInterceptors(
clientinterceptors.TracingInterceptor,
clientinterceptors.DurationInterceptor,
clientinterceptors.BreakerInterceptor,
clientinterceptors.PrometheusInterceptor,
clientinterceptors.TimeoutInterceptor(cliOpts.Timeout),
),
}
return append(options, cliOpts.DialOptions...)
}
ronething at ronething-dell-ubuntu in ~/Documents/grpc-sample/go-zero-tls/helloclient (master●●)
$ go test -v -run TestPing
=== RUN TestPing
2021/04/15 00:36:19 rpc dial: discov://127.0.0.1:2379/hello.rpc, error: context deadline exceeded, make sure rpc service "hello.rpc" is alread started
exit status 1
FAIL grpc-sample/go-zero-tls/helloclient 3.007s
两种解决方案:
1、不用 zrpc 的 client 使用原生 grpc client 进行连接
2、修改相关代码,其实我也已经提了 issue 不过官方暂时没有回复
临时修改一下看一下效果
首先将 go-zero zrpc client 连接选项 WithInsecure 注释
package helloclient
import (
"context"
"crypto/tls"
"crypto/x509"
"log"
"os"
"testing"
"github.com/tal-tech/go-zero/core/discov"
"github.com/tal-tech/go-zero/zrpc"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials"
)
func TestPing(t *testing.T) {
// 添加证书设置
cred := getCreds()
client := zrpc.MustNewClient(
zrpc.RpcClientConf{
Etcd: discov.EtcdConf{
Hosts: []string{"127.0.0.1:2379"},
Key: "hello.rpc",
},
},
zrpc.WithDialOption(grpc.WithTransportCredentials(cred)), // 证书认证
)
h := NewHello(client)
resp, err := h.Ping(context.TODO(), &Request{
Ping: "ashing",
})
if err != nil {
t.Error(err)
return
}
t.Log(resp.GetPong())
}
//getCreds 添加凭证
func getCreds() credentials.TransportCredentials {
cert, err := tls.LoadX509KeyPair("../tls/client.pem", "../tls/client.key")
if err != nil {
log.Fatalf("tls.LoadX509KeyPair err: %v", err)
}
certPool := x509.NewCertPool()
ca, err := os.ReadFile("../tls/ca.pem")
if err != nil {
log.Fatalf("ioutil.ReadFile err: %v", err)
}
if ok := certPool.AppendCertsFromPEM(ca); !ok {
log.Fatalf("certPool.AppendCertsFromPEM err")
}
creds := credentials.NewTLS(&tls.Config{
Certificates: []tls.Certificate{cert},
ServerName: "localhost",
RootCAs: certPool,
})
return creds
}
ronething at ronething-dell-ubuntu in ~/Documents/grpc-sample/go-zero-tls/helloclient (master●●)
$ go test -v -run TestPing
=== RUN TestPing
2021/04/15 01:01:16 {"@timestamp":"2021-04-15T01:01:16.963+08","level":"stat","content":"p2c - conn: 127.0.0.1:9999, load: 670, reqs: 1"}
hello_test.go:40: hello: ashing
--- PASS: TestPing (0.01s)
PASS
ok grpc-sample/go-zero-tls/helloclient 0.013s
返回正常。完整代码见 go-zero-tls
🌞
嗯 早点睡。
写于 2021-04-14 夜晚