diff --git a/channelz/service/service.go b/channelz/service/service.go index 342c836e72b6..2da73b9e984f 100644 --- a/channelz/service/service.go +++ b/channelz/service/service.go @@ -32,12 +32,16 @@ import ( "google.golang.org/grpc/channelz" pb "google.golang.org/grpc/channelz/service_proto" "google.golang.org/grpc/connectivity" + "google.golang.org/grpc/credentials" ) -const ( - secToNano = 1e9 - usecToNano = 1e3 -) +func secToNano(i int64) int64 { + return i * 1e9 +} + +func usecToNano(i int64) int64 { + return i * 1e3 +} // RegisterChannelzServiceToServer registers the channelz service to the given server. func RegisterChannelzServiceToServer(s *grpc.Server) { @@ -135,31 +139,25 @@ func subChannelMetricToProto(cm *channelz.SubChannelMetric) *pb.Subchannel { return sc } -func securityToProto(se channelz.SecurityValue) *pb.Security { +func securityToProto(se credentials.SecurityValue) *pb.Security { switch v := se.(type) { - case *channelz.TLSSecurityValue: + case *credentials.TLSSecurityValue: return &pb.Security{Model: &pb.Security_Tls_{Tls: &pb.Security_Tls{ CipherSuite: &pb.Security_Tls_StandardName{StandardName: v.StandardName}, LocalCertificate: v.LocalCertificate, RemoteCertificate: v.RemoteCertificate, - }, - }, - } - case *channelz.OtherSecurityValue: + }}} + case *credentials.OtherSecurityValue: anyval, err := ptypes.MarshalAny(v.Value) if err != nil { return &pb.Security{Model: &pb.Security_Other{Other: &pb.Security_OtherSecurity{ Name: v.Name, - }, - }, - } + }}} } return &pb.Security{Model: &pb.Security_Other{Other: &pb.Security_OtherSecurity{ Name: v.Name, Value: anyval, - }, - }, - } + }}} } return nil } @@ -167,19 +165,19 @@ func securityToProto(se channelz.SecurityValue) *pb.Security { func sockoptToProto(skopts *channelz.SocketOptionData) []*pb.SocketOption { var opts []*pb.SocketOption if skopts.Linger != nil { - additional, err := ptypes.MarshalAny(&pb.SocketOptionLinger{Active: skopts.Linger.Onoff != 0, Duration: ptypes.DurationProto(time.Duration(int64(skopts.Linger.Linger) * secToNano))}) + additional, err := ptypes.MarshalAny(&pb.SocketOptionLinger{Active: skopts.Linger.Onoff != 0, Duration: ptypes.DurationProto(time.Duration(secToNano(int64(skopts.Linger.Linger))))}) if err == nil { opts = append(opts, &pb.SocketOption{Name: "SO_LINGER", Additional: additional}) } } if skopts.RecvTimeout != nil { - additional, err := ptypes.MarshalAny(&pb.SocketOptionTimeout{Duration: ptypes.DurationProto(time.Duration(skopts.RecvTimeout.Sec*secToNano + skopts.RecvTimeout.Usec*usecToNano))}) + additional, err := ptypes.MarshalAny(&pb.SocketOptionTimeout{Duration: ptypes.DurationProto(time.Duration(secToNano(int64(skopts.RecvTimeout.Sec)) + usecToNano(int64(skopts.RecvTimeout.Usec))))}) if err == nil { opts = append(opts, &pb.SocketOption{Name: "SO_RCVTIMEO", Additional: additional}) } } if skopts.SendTimeout != nil { - additional, err := ptypes.MarshalAny(&pb.SocketOptionTimeout{Duration: ptypes.DurationProto(time.Duration(skopts.SendTimeout.Sec*secToNano + skopts.SendTimeout.Usec*usecToNano))}) + additional, err := ptypes.MarshalAny(&pb.SocketOptionTimeout{Duration: ptypes.DurationProto(time.Duration(secToNano(int64(skopts.SendTimeout.Sec)) + usecToNano(int64(skopts.SendTimeout.Usec))))}) if err == nil { opts = append(opts, &pb.SocketOption{Name: "SO_SNDTIMEO", Additional: additional}) } diff --git a/channelz/service/service_test.go b/channelz/service/service_test.go index 2dcbc6027033..a5848812562b 100644 --- a/channelz/service/service_test.go +++ b/channelz/service/service_test.go @@ -34,10 +34,11 @@ import ( "google.golang.org/grpc/channelz" pb "google.golang.org/grpc/channelz/service_proto" "google.golang.org/grpc/connectivity" + "google.golang.org/grpc/credentials" ) func init() { - proto.RegisterType((*OtherSecurityValue)(nil), "grpc.channelz.OtherSecurityValue") + proto.RegisterType((*OtherSecurityValue)(nil), "grpc.credentials.OtherSecurityValue") channelz.TurnOn() } @@ -100,7 +101,7 @@ type dummySocket struct { SocketOptions *channelz.SocketOptionData localAddr net.Addr remoteAddr net.Addr - Security channelz.SecurityValue + Security credentials.SecurityValue remoteName string } @@ -193,12 +194,12 @@ func protoToTime(protoTime *pb.SocketOptionTimeout) *unix.Timeval { return timeout } -func protoToSecurity(protoSecurity *pb.Security) channelz.SecurityValue { +func protoToSecurity(protoSecurity *pb.Security) credentials.SecurityValue { switch v := protoSecurity.Model.(type) { case *pb.Security_Tls_: - return &channelz.TLSSecurityValue{StandardName: v.Tls.GetStandardName(), LocalCertificate: v.Tls.GetLocalCertificate(), RemoteCertificate: v.Tls.GetRemoteCertificate()} + return &credentials.TLSSecurityValue{StandardName: v.Tls.GetStandardName(), LocalCertificate: v.Tls.GetLocalCertificate(), RemoteCertificate: v.Tls.GetRemoteCertificate()} case *pb.Security_Other: - sv := &channelz.OtherSecurityValue{Name: v.Other.GetName()} + sv := &credentials.OtherSecurityValue{Name: v.Other.GetName()} var x ptypes.DynamicAny if err := ptypes.UnmarshalAny(v.Other.GetValue(), &x); err == nil { sv.Value = x.Message @@ -588,18 +589,18 @@ func TestGetSocket(t *testing.T) { }, }, { - Security: &channelz.TLSSecurityValue{ + Security: &credentials.TLSSecurityValue{ StandardName: "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", RemoteCertificate: []byte{48, 130, 2, 156, 48, 130, 2, 5, 160}, }, }, { - Security: &channelz.OtherSecurityValue{ + Security: &credentials.OtherSecurityValue{ Name: "XXXX", }, }, { - Security: &channelz.OtherSecurityValue{ + Security: &credentials.OtherSecurityValue{ Name: "YYYY", Value: &OtherSecurityValue{LocalCertificate: []byte{1, 2, 3}, RemoteCertificate: []byte{4, 5, 6}}, }, diff --git a/channelz/types.go b/channelz/types.go index cc70040e90d7..c213036027ce 100644 --- a/channelz/types.go +++ b/channelz/types.go @@ -22,8 +22,8 @@ import ( "net" "time" - "github.com/golang/protobuf/proto" "google.golang.org/grpc/connectivity" + "google.golang.org/grpc/credentials" "google.golang.org/grpc/grpclog" ) @@ -284,7 +284,7 @@ type SocketInternalMetric struct { // the original target name. RemoteName string SocketOptions *SocketOptionData - Security SecurityValue + Security credentials.SecurityValue } // Socket is the interface that should be satisfied in order to be tracked by @@ -417,35 +417,3 @@ func (s *server) deleteSelfIfReady() { } s.cm.deleteEntry(s.id) } - -// Security defines the interface that security protocols should implement in order -// to provide security info to channelz. -type Security interface { - GetSecurityValue() SecurityValue -} - -// SecurityValue defines the interface that GetSecurityValue() return value should -// satisfy. This interface should only be satisfied by *TLSSecurityValue and -// *OtherSecurityValue. -type SecurityValue interface { - isSecurityValue() -} - -// TLSSecurityValue defines the struct that TLS protocol should return from GetSecurityValue(), -// containing security info like cipher and certificate used. -type TLSSecurityValue struct { - StandardName string - LocalCertificate []byte - RemoteCertificate []byte -} - -func (*TLSSecurityValue) isSecurityValue() {} - -// OtherSecurityValue defines the struct that non-TLS protocol should return from -// GetSecurityValue(), which contains protocol specific security info. -type OtherSecurityValue struct { - Name string - Value proto.Message -} - -func (*OtherSecurityValue) isSecurityValue() {} diff --git a/channelz/types_linux.go b/channelz/types_linux.go deleted file mode 100644 index 13cbbacbbe51..000000000000 --- a/channelz/types_linux.go +++ /dev/null @@ -1,52 +0,0 @@ -/* - * - * Copyright 2018 gRPC 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 channelz - -import ( - "syscall" - - "golang.org/x/sys/unix" -) - -// SocketOptionData defines the struct to hold socket option data, and related -// getter function to obtain info from fd. -type SocketOptionData struct { - Linger *unix.Linger - RecvTimeout *unix.Timeval - SendTimeout *unix.Timeval - TCPInfo *unix.TCPInfo -} - -// Getsockopt defines the function to get socket options requested by channelz. -// It is to be passed to syscall.RawConn.Control(). -func (s *SocketOptionData) Getsockopt(fd uintptr) { - if v, err := unix.GetsockoptLinger(int(fd), syscall.SOL_SOCKET, syscall.SO_LINGER); err == nil { - s.Linger = v - } - if v, err := unix.GetsockoptTimeval(int(fd), syscall.SOL_SOCKET, syscall.SO_RCVTIMEO); err == nil { - s.RecvTimeout = v - } - if v, err := unix.GetsockoptTimeval(int(fd), syscall.SOL_SOCKET, syscall.SO_SNDTIMEO); err == nil { - s.SendTimeout = v - } - if v, err := unix.GetsockoptTCPInfo(int(fd), syscall.SOL_TCP, syscall.TCP_INFO); err == nil { - s.TCPInfo = v - } - return -} diff --git a/channelz/types_windows.go b/channelz/types_windows.go deleted file mode 100644 index bab7d83432f4..000000000000 --- a/channelz/types_windows.go +++ /dev/null @@ -1,29 +0,0 @@ -/* - * - * Copyright 2018 gRPC 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 channelz - -// SocketOptionData defines the struct to hold socket option data, and related -// getter function to obtain info from fd. -// Windows OS doesn't support Socket Option -type SocketOptionData struct{} - -// Getsockopt defines the function to get socket options requested by channelz. -// It is to be passed to syscall.RawConn.Control(). -// Windows OS doesn't support Socket Option -func (s *SocketOptionData) Getsockopt(fd uintptr) {} diff --git a/channelz/util_default.go b/channelz/util_default.go deleted file mode 100644 index f634fe09a6c4..000000000000 --- a/channelz/util_default.go +++ /dev/null @@ -1,26 +0,0 @@ -// +build !darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd,!solaris !go1.9 - -/* - * - * Copyright 2018 gRPC 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 channelz - -// GetSocketOption gets the socket option info of the conn. -func GetSocketOption(c interface{}) *SocketOptionData { - return nil -} diff --git a/credentials/credentials.go b/credentials/credentials.go index 7ceff93dd782..2a5ed52a546c 100644 --- a/credentials/credentials.go +++ b/credentials/credentials.go @@ -31,8 +31,7 @@ import ( "net" "strings" - "google.golang.org/grpc/channelz" - + "github.com/golang/protobuf/proto" "golang.org/x/net/context" ) @@ -121,8 +120,8 @@ func (t TLSInfo) AuthType() string { } // GetSecurityValue returns security info requested by channelz. -func (t TLSInfo) GetSecurityValue() channelz.SecurityValue { - v := &channelz.TLSSecurityValue{ +func (t TLSInfo) GetSecurityValue() SecurityValue { + v := &TLSSecurityValue{ StandardName: cipherSuiteLookup[t.State.CipherSuite], } // Currently there's no way to get LocalCertificate info from tls package. @@ -169,7 +168,7 @@ func (c *tlsCreds) ClientHandshake(ctx context.Context, authority string, rawCon case <-ctx.Done(): return nil, nil, ctx.Err() } - return tlsConn{conn, rawConn}, TLSInfo{conn.ConnectionState()}, nil + return tlsConn{Conn: conn, rawConn: rawConn}, TLSInfo{conn.ConnectionState()}, nil } func (c *tlsCreds) ServerHandshake(rawConn net.Conn) (net.Conn, AuthInfo, error) { @@ -177,7 +176,7 @@ func (c *tlsCreds) ServerHandshake(rawConn net.Conn) (net.Conn, AuthInfo, error) if err := conn.Handshake(); err != nil { return nil, nil, err } - return tlsConn{conn, rawConn}, TLSInfo{conn.ConnectionState()}, nil + return tlsConn{Conn: conn, rawConn: rawConn}, TLSInfo{conn.ConnectionState()}, nil } func (c *tlsCreds) Clone() TransportCredentials { @@ -232,3 +231,35 @@ func NewServerTLSFromFile(certFile, keyFile string) (TransportCredentials, error } return NewTLS(&tls.Config{Certificates: []tls.Certificate{cert}}), nil } + +// Security defines the interface that security protocols should implement in order +// to provide security info to channelz. +type Security interface { + GetSecurityValue() SecurityValue +} + +// SecurityValue defines the interface that GetSecurityValue() return value should +// satisfy. This interface should only be satisfied by *TLSSecurityValue and +// *OtherSecurityValue. +type SecurityValue interface { + isSecurityValue() +} + +// TLSSecurityValue defines the struct that TLS protocol should return from GetSecurityValue(), +// containing security info like cipher and certificate used. +type TLSSecurityValue struct { + StandardName string + LocalCertificate []byte + RemoteCertificate []byte +} + +func (*TLSSecurityValue) isSecurityValue() {} + +// OtherSecurityValue defines the struct that non-TLS protocol should return from +// GetSecurityValue(), which contains protocol specific security info. +type OtherSecurityValue struct { + Name string + Value proto.Message +} + +func (*OtherSecurityValue) isSecurityValue() {} diff --git a/credentials/credentials_util_go19.go b/credentials/credentials_util_go19.go index 85345e656d83..2577c16f61f0 100644 --- a/credentials/credentials_util_go19.go +++ b/credentials/credentials_util_go19.go @@ -2,7 +2,7 @@ /* * - * Copyright 2014 gRPC authors. + * Copyright 2018 gRPC authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/credentials/credentials_util_pre_go19.go b/credentials/credentials_util_pre_go19.go index 773dfdeed3ac..9466e1955801 100644 --- a/credentials/credentials_util_pre_go19.go +++ b/credentials/credentials_util_pre_go19.go @@ -2,7 +2,7 @@ /* * - * Copyright 2014 gRPC authors. + * Copyright 2018 gRPC authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/test/channelz_go19_test.go b/test/channelz_go19_test.go deleted file mode 100644 index 66871bed9fe8..000000000000 --- a/test/channelz_go19_test.go +++ /dev/null @@ -1,100 +0,0 @@ -// +build go1.10 - -/* - * - * Copyright 2018 gRPC 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 test - -import ( - "testing" - "time" - - "google.golang.org/grpc/channelz" - testpb "google.golang.org/grpc/test/grpc_testing" - "google.golang.org/grpc/test/leakcheck" -) - -func init() { - channelz.TurnOn() -} - -func TestCZSocketMetricsSocketOption(t *testing.T) { - envs := []env{tcpClearRREnv, tcpTLSRREnv} - for _, e := range envs { - testCZSocketMetricsSocketOption(t, e) - } -} - -func testCZSocketMetricsSocketOption(t *testing.T, e env) { - defer leakcheck.Check(t) - channelz.NewChannelzStorage() - te := newTest(t, e) - te.startServer(&testServer{security: e.security}) - defer te.tearDown() - cc := te.clientConn() - tc := testpb.NewTestServiceClient(cc) - doSuccessfulUnaryCall(tc, t) - - time.Sleep(10 * time.Millisecond) - ss, _ := channelz.GetServers(0) - if len(ss) != 1 { - t.Fatalf("There should be one server, not %d", len(ss)) - } - if len(ss[0].ListenSockets) != 1 { - t.Fatalf("There should be one listen socket, not %d", len(ss[0].ListenSockets)) - } - for id := range ss[0].ListenSockets { - sm := channelz.GetSocket(id) - if sm == nil || sm.SocketData == nil || sm.SocketData.SocketOptions == nil { - t.Fatalf("Unable to get server listen socket options") - } - } - ns, _ := channelz.GetServerSockets(ss[0].ID, 0) - if len(ns) != 1 { - t.Fatalf("There should be one server normal socket, not %d", len(ns)) - } - if ns[0] == nil || ns[0].SocketData == nil || ns[0].SocketData.SocketOptions == nil { - t.Fatalf("Unable to get server normal socket options") - } - - tchan, _ := channelz.GetTopChannels(0) - if len(tchan) != 1 { - t.Fatalf("There should only be one top channel, not %d", len(tchan)) - } - if len(tchan[0].SubChans) != 1 { - t.Fatalf("There should only be one subchannel under top channel %d, not %d", tchan[0].ID, len(tchan[0].SubChans)) - } - var id int64 - for id = range tchan[0].SubChans { - break - } - sc := channelz.GetSubChannel(id) - if sc == nil { - t.Fatalf("There should only be one socket under subchannel %d, not 0", id) - } - if len(sc.Sockets) != 1 { - t.Fatalf("There should only be one socket under subchannel %d, not %d", sc.ID, len(sc.Sockets)) - } - for id = range sc.Sockets { - break - } - skt := channelz.GetSocket(id) - if skt == nil || skt.SocketData == nil || skt.SocketData.SocketOptions == nil { - t.Fatalf("Unable to get client normal socket options") - } -} diff --git a/test/channelz_test.go b/test/channelz_test.go index 0db4cba2f8b8..86ec3f102075 100644 --- a/test/channelz_test.go +++ b/test/channelz_test.go @@ -122,7 +122,6 @@ func TestCZTopChannelRegistrationAndDeletion(t *testing.T) { te.srvAddr = "" ccs = append(ccs, cc) } - if err := verifyResultWithDelay(func() (bool, error) { if tcs, end := channelz.GetTopChannels(c.start); len(tcs) != c.length || end != c.end { return false, fmt.Errorf("GetTopChannels(%d) = %+v (len of which: %d), end: %+v, want len(GetTopChannels(%d)) = %d, end: %+v", c.start, tcs, len(tcs), end, c.start, c.length, c.end) diff --git a/transport/http2_client.go b/transport/http2_client.go index 4ecd7c598d5d..c4b463553cfa 100644 --- a/transport/http2_client.go +++ b/transport/http2_client.go @@ -1220,7 +1220,7 @@ func (t *http2Client) ChannelzMetric() *channelz.SocketInternalMetric { RemoteAddr: t.remoteAddr, // RemoteName : } - if au, ok := t.authInfo.(channelz.Security); ok { + if au, ok := t.authInfo.(credentials.Security); ok { s.Security = au.GetSecurityValue() } t.czmu.RUnlock() diff --git a/transport/http2_server.go b/transport/http2_server.go index 9d027c91b544..006ea8181f30 100644 --- a/transport/http2_server.go +++ b/transport/http2_server.go @@ -1057,7 +1057,7 @@ func (t *http2Server) ChannelzMetric() *channelz.SocketInternalMetric { RemoteAddr: t.remoteAddr, // RemoteName : } - if au, ok := t.authInfo.(channelz.Security); ok { + if au, ok := t.authInfo.(credentials.Security); ok { s.Security = au.GetSecurityValue() } t.czmu.RUnlock()