diff --git a/zrpc/client.go b/zrpc/client.go index f671d2e7..e8a679b4 100644 --- a/zrpc/client.go +++ b/zrpc/client.go @@ -18,6 +18,12 @@ var ( WithRetry = internal.WithRetry // WithUnaryClientInterceptor is an alias of internal.WithUnaryClientInterceptor. WithUnaryClientInterceptor = internal.WithUnaryClientInterceptor + // WithInsecure is an alias of internal.WithInsecure. + WithInsecure = internal.WithInsecure + // WithTlsClientFromUnilateralism is an alias of internal.WithTlsClientFromUnilateralism + WithTlsClientFromUnilateralism = internal.WithTlsClientFromUnilateralism + // WithTlsClientFromMutual is an alias of internal.WithTlsClientFromMutual + WithTlsClientFromMutual = internal.WithTlsClientFromMutual ) type ( @@ -58,6 +64,9 @@ func NewClient(c RpcClientConf, options ...ClientOption) (Client, error) { opts = append(opts, WithRetry()) } opts = append(opts, options...) + if !c.HasSslVerify() { + opts = append(opts, WithInsecure()) + } var target string var err error diff --git a/zrpc/client_test.go b/zrpc/client_test.go index d9b05bb4..c42931c7 100644 --- a/zrpc/client_test.go +++ b/zrpc/client_test.go @@ -76,7 +76,6 @@ func TestDepositServer_Deposit(t *testing.T) { Token: "bar", Timeout: 1000, }, - WithDialOption(grpc.WithInsecure()), WithDialOption(grpc.WithContextDialer(dialer())), WithUnaryClientInterceptor(func(ctx context.Context, method string, req, reply interface{}, cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error { diff --git a/zrpc/config.go b/zrpc/config.go index 07b72724..0b05df84 100644 --- a/zrpc/config.go +++ b/zrpc/config.go @@ -30,6 +30,7 @@ type ( Token string `json:",optional"` Retry bool `json:",optional"` // grpc auto retry Timeout int64 `json:",default=2000"` + InsecureVerify bool `json:",default=false"` } ) @@ -72,3 +73,8 @@ func (sc RpcServerConf) Validate() error { func (cc RpcClientConf) HasCredential() bool { return len(cc.App) > 0 && len(cc.Token) > 0 } + +//HasTls checks if there is a SSL in config. +func (cc RpcClientConf) HasSslVerify() bool { + return cc.InsecureVerify +} diff --git a/zrpc/config_test.go b/zrpc/config_test.go index 67d2a4b3..45a366d7 100644 --- a/zrpc/config_test.go +++ b/zrpc/config_test.go @@ -14,6 +14,11 @@ func TestRpcClientConf(t *testing.T) { assert.True(t, conf.HasCredential()) conf = NewEtcdClientConf([]string{"localhost:1234", "localhost:5678"}, "key", "foo", "bar") assert.True(t, conf.HasCredential()) + // ssl on + conf = NewDirectClientConf([]string{"localhost:1234", "localhost:5678"}, "foo", "bar") + assert.False(t, conf.HasSslVerify()) + conf.InsecureVerify = true + assert.True(t, conf.HasSslVerify()) } func TestRpcServerConf(t *testing.T) { diff --git a/zrpc/internal/client.go b/zrpc/internal/client.go index 861982ef..cad7c53e 100644 --- a/zrpc/internal/client.go +++ b/zrpc/internal/client.go @@ -2,8 +2,12 @@ package internal import ( "context" + "crypto/tls" + "crypto/x509" "errors" "fmt" + "io/ioutil" + "log" "strings" "time" @@ -11,6 +15,7 @@ import ( "github.com/tal-tech/go-zero/zrpc/internal/clientinterceptors" "github.com/tal-tech/go-zero/zrpc/internal/resolver" "google.golang.org/grpc" + "google.golang.org/grpc/credentials" ) const ( @@ -65,7 +70,6 @@ func (c *client) buildDialOptions(opts ...ClientOption) []grpc.DialOption { } options := []grpc.DialOption{ - grpc.WithInsecure(), grpc.WithBlock(), WithUnaryClientInterceptors( clientinterceptors.UnaryTracingInterceptor, @@ -112,6 +116,13 @@ func WithDialOption(opt grpc.DialOption) ClientOption { } } +// WithInsecure returns a func to customize a ClientOptions with secure option. +func WithInsecure() ClientOption { + return func(options *ClientOptions) { + options.DialOptions = append(options.DialOptions, grpc.WithInsecure()) + } +} + // WithTimeout returns a func to customize a ClientOptions with given timeout. func WithTimeout(timeout time.Duration) ClientOption { return func(options *ClientOptions) { @@ -132,3 +143,40 @@ func WithUnaryClientInterceptor(interceptor grpc.UnaryClientInterceptor) ClientO options.DialOptions = append(options.DialOptions, WithUnaryClientInterceptors(interceptor)) } } + +// WithTlsClientFromUnilateralism return a func to customize a ClientOptions Verify with Unilateralism authentication. +func WithTlsClientFromUnilateralism(crt, domainName string) ClientOption { + return func(options *ClientOptions) { + c, err := credentials.NewClientTLSFromFile(crt, domainName) + if err != nil { + log.Fatalf("credentials.NewClientTLSFromFile err: %v", err) + } + options.DialOptions = append(options.DialOptions, grpc.WithTransportCredentials(c)) + } +} + +// WithTlsClientFromMutual return a func to customize a ClientOptions Verify with mutual authentication. +func WithTlsClientFromMutual(crtFile, keyFile, caFile string) ClientOption { + return func(options *ClientOptions) { + cert, err := tls.LoadX509KeyPair(crtFile, keyFile) + if err != nil { + log.Fatalf("tls.LoadX509KeyPair err: %v", err) + } + certPool := x509.NewCertPool() + ca, err := ioutil.ReadFile(caFile) + if err != nil { + log.Fatalf("credentials: failed to ReadFile CA certificates err: %v", err) + } + + if !certPool.AppendCertsFromPEM(ca) { + log.Fatalf("credentials: failed to append certificates err: %v", err) + } + + config := &tls.Config{ + Certificates: []tls.Certificate{cert}, + RootCAs: certPool, + } + + options.DialOptions = append(options.DialOptions, grpc.WithTransportCredentials(credentials.NewTLS(config))) + } +}