From 6c45ffa421876704fa6c24f2570d49ed79005ab8 Mon Sep 17 00:00:00 2001 From: Gari Singh Date: Wed, 7 Dec 2016 09:51:52 -0500 Subject: [PATCH] FAB-1259 Create Basic Common GRPC Server This is the initial phase of creating a common GRPC server object to handle common operations such as TLS. This change set provides a basic GRPC server object and functions to create plain and TLS enabled GRPC servers Fixes FAB-1259 Change-Id: Ic63bec9e8747083016dbcddab06f1061903d5a59 Signed-off-by: Gari Singh --- core/comm/server.go | 200 +++++++++ core/comm/server_test.go | 409 ++++++++++++++++++ core/comm/testdata/grpc/test.pb.go | 130 ++++++ core/comm/testdata/grpc/test.proto | 25 ++ .../comm/testdata/prime256v1-openssl-cert.pem | 15 + core/comm/testdata/prime256v1-openssl-key.pem | 8 + 6 files changed, 787 insertions(+) create mode 100644 core/comm/server.go create mode 100644 core/comm/server_test.go create mode 100644 core/comm/testdata/grpc/test.pb.go create mode 100644 core/comm/testdata/grpc/test.proto create mode 100644 core/comm/testdata/prime256v1-openssl-cert.pem create mode 100644 core/comm/testdata/prime256v1-openssl-key.pem diff --git a/core/comm/server.go b/core/comm/server.go new file mode 100644 index 00000000000..fc8cc8a356c --- /dev/null +++ b/core/comm/server.go @@ -0,0 +1,200 @@ +/* +Copyright IBM Corp. 2016 All Rights Reserved. + +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 comm + +import ( + "crypto/tls" + "crypto/x509" + "errors" + "net" + + "google.golang.org/grpc" + "google.golang.org/grpc/credentials" +) + +//GRPCServer defines an interface representing a GRPC-based server +type GRPCServer interface { + //Address returns the listen address for the GRPCServer + Address() string + //Start starts the underlying grpc.Server + Start() error + //Stop stops the underlying grpc.Server + Stop() + //Server returns the grpc.Server instance for the GRPCServer + Server() *grpc.Server + //Listener returns the net.Listener instance for the GRPCServer + Listener() net.Listener + //ServerCertificate returns the tls.Certificate used by the grpc.Server + ServerCertificate() tls.Certificate + //TLSEnabled is a flag indicating whether or not TLS is enabled for this GRPCServer instance + TLSEnabled() bool +} + +type grpcServerImpl struct { + //Listen address for the server specified as hostname:port + address string + //Listener for handling network requests + listener net.Listener + //GRPC server + server *grpc.Server + //Certificate presented by the server for TLS communication + serverCertificate tls.Certificate + //Key used by the server for TLS communication + serverKeyPEM []byte + //List of certificate authorities to optionally pass to the client during the TLS handshake + serverRootCAs []tls.Certificate + //List of certificate authorities to be used to authenticate clients if client authentication is required + clientRootCAs *x509.CertPool + //Is TLS enabled? + tlsEnabled bool +} + +/* +NewGRPCServer creates a new implementation of a GRPCServer given a listen address. +In order to enable TLS, serverKey and ServerCertificate are required. + +Parameters: + address: Listen address to use formatted as hostname:port + serverKey: PEM-encoded private key to be used by the server for TLS communication + serverCertificate: PEM-encoded X509 public key to be used by the server for TLS communication + serverRootCAs: (optional) Set of PEM-encoded X509 certificate authorities to optionally send as part of + the server handshake + clientRootCAs: (optional) Set of PEM-encoded X509 certificate authorities to use when verifying client + certificates +*/ +func NewGRPCServer(address string, serverKey []byte, serverCertificate []byte, serverRootCAs [][]byte, + clientRootCAs [][]byte) (GRPCServer, error) { + + if address == "" { + return nil, errors.New("Missing address parameter") + } + //create our listener + lis, err := net.Listen("tcp", address) + + if err != nil { + return nil, err + } + + return NewGRPCServerFromListener(lis, serverKey, serverCertificate, serverRootCAs, clientRootCAs) + +} + +/* +NewGRPCServerFromListener creates a new implementation of a GRPCServer given an existing Listener instance. +In order to enable TLS, serverKey and ServerCertificate are required. + +Parameters: + listener: Listener to use + serverKey: PEM-encoded private key to be used by the server for TLS communication + serverCertificate: PEM-encoded X509 public key to be used by the server for TLS communication + serverRootCAs: (optional) Set of PEM-encoded X509 certificate authorities to optionally send as part of + the server handshake + clientRootCAs: (optional) Set of PEM-encoded X509 certificate authorities to use when verifying client + certificates +*/ +func NewGRPCServerFromListener(listener net.Listener, serverKey []byte, serverCertificate []byte, + serverRootCAs [][]byte, clientRootCAs [][]byte) (GRPCServer, error) { + + grpcServer := &grpcServerImpl{ + address: listener.Addr().String(), + listener: listener, + } + + //set up our server options + var serverOpts []grpc.ServerOption + //check for TLS parameters + if serverKey != nil || serverCertificate != nil { + //both are required + if serverKey != nil && serverCertificate != nil { + grpcServer.tlsEnabled = true + //load server public and private keys + cert, err := tls.X509KeyPair(serverCertificate, serverKey) + if err != nil { + return nil, err + } + grpcServer.serverCertificate = cert + + //set up our TLS config + + //base server certificate + certificates := []tls.Certificate{grpcServer.serverCertificate} + + /** + //if we have server root CAs append them + if len(serverRootCAs) > 0 { + //certificates = append(certificates, serverRootCAs...) + } + + //if we have client root CAs, create a certPool + if len(clientRootCAs) > 0 { + grpcServer.clientRootCAs = x509.NewCertPool() + } + */ + tlsConfig := &tls.Config{ + Certificates: certificates, + } + + //create credentials + creds := credentials.NewTLS(tlsConfig) + + //add to server options + serverOpts = append(serverOpts, grpc.Creds(creds)) + + } else { + return nil, errors.New("Both serverKey and serverCertificate are required in order to enable TLS") + } + } + + grpcServer.server = grpc.NewServer(serverOpts...) + + return grpcServer, nil +} + +//Address returns the listen address for this GRPCServer instance +func (gServer *grpcServerImpl) Address() string { + return gServer.address +} + +//Listener returns the net.Listener for the GRPCServer instance +func (gServer *grpcServerImpl) Listener() net.Listener { + return gServer.listener +} + +//Server returns the grpc.Server for the GRPCServer instance +func (gServer *grpcServerImpl) Server() *grpc.Server { + return gServer.server +} + +//ServerCertificate returns the tls.Certificate used by the grpc.Server +func (gServer *grpcServerImpl) ServerCertificate() tls.Certificate { + return gServer.serverCertificate +} + +//TLSEnabled is a flag indicating whether or not TLS is enabled for the GRPCServer instance +func (gServer *grpcServerImpl) TLSEnabled() bool { + return gServer.tlsEnabled +} + +//Start starts the underlying grpc.Server +func (gServer *grpcServerImpl) Start() error { + return gServer.server.Serve(gServer.listener) +} + +//Stop stops the underlying grpc.Server +func (gServer *grpcServerImpl) Stop() { + gServer.server.Stop() +} diff --git a/core/comm/server_test.go b/core/comm/server_test.go new file mode 100644 index 00000000000..3adb0c26b25 --- /dev/null +++ b/core/comm/server_test.go @@ -0,0 +1,409 @@ +/* +Copyright IBM Corp. 2016 All Rights Reserved. + +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 comm_test + +import ( + "crypto/tls" + "crypto/x509" + "net" + "testing" + "time" + + "github.com/stretchr/testify/assert" + + "golang.org/x/net/context" + "google.golang.org/grpc" + "google.golang.org/grpc/credentials" + + "github.com/hyperledger/fabric/core/comm" + testpb "github.com/hyperledger/fabric/core/comm/testdata/grpc" +) + +//Embedded certificates for testing +//These are the prime256v1-openssl-*.pem in testdata +//The self-signed cert expires in 2026 +var selfSignedKeyPEM = `-----BEGIN EC PARAMETERS----- +BggqhkjOPQMBBw== +-----END EC PARAMETERS----- +-----BEGIN EC PRIVATE KEY----- +MHcCAQEEIM2rUTflEQ11m5g5yEm2Cer2yI+ziccl1NbSRVh3GUR0oAoGCCqGSM49 +AwEHoUQDQgAEu2FEZVSr30Afey6dwcypeg5P+BuYx5JSYdG0/KJIBjWKnzYo7FEm +gMir7GbNh4pqA8KFrJZkPuxMgnEJBZTv+w== +-----END EC PRIVATE KEY----- +` +var selfSignedCertPEM = `-----BEGIN CERTIFICATE----- +MIICRDCCAemgAwIBAgIJALwW//dz2ZBvMAoGCCqGSM49BAMCMH4xCzAJBgNVBAYT +AlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRYwFAYDVQQHDA1TYW4gRnJhbmNpc2Nv +MRgwFgYDVQQKDA9MaW51eEZvdW5kYXRpb24xFDASBgNVBAsMC0h5cGVybGVkZ2Vy +MRIwEAYDVQQDDAlsb2NhbGhvc3QwHhcNMTYxMjA0MjIzMDE4WhcNMjYxMjAyMjIz +MDE4WjB+MQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UE +BwwNU2FuIEZyYW5jaXNjbzEYMBYGA1UECgwPTGludXhGb3VuZGF0aW9uMRQwEgYD +VQQLDAtIeXBlcmxlZGdlcjESMBAGA1UEAwwJbG9jYWxob3N0MFkwEwYHKoZIzj0C +AQYIKoZIzj0DAQcDQgAEu2FEZVSr30Afey6dwcypeg5P+BuYx5JSYdG0/KJIBjWK +nzYo7FEmgMir7GbNh4pqA8KFrJZkPuxMgnEJBZTv+6NQME4wHQYDVR0OBBYEFAWO +4bfTEr2R6VYzQYrGk/2VWmtYMB8GA1UdIwQYMBaAFAWO4bfTEr2R6VYzQYrGk/2V +WmtYMAwGA1UdEwQFMAMBAf8wCgYIKoZIzj0EAwIDSQAwRgIhAIelqGdxPMHmQqRF +zA85vv7JhfMkvZYGPELC7I2K8V7ZAiEA9KcthV3HtDXKNDsA6ULT+qUkyoHRzCzr +A4QaL2VU6i4= +-----END CERTIFICATE----- +` +var timeout = time.Second * 10 + +type testServiceServer struct{} + +func (tss *testServiceServer) EmptyCall(context.Context, *testpb.Empty) (*testpb.Empty, error) { + return new(testpb.Empty), nil +} + +//invoke the EmptyCall RPC +func invokeEmptyCall(address string, dialOptions []grpc.DialOption) (*testpb.Empty, error) { + + //add DialOptions + dialOptions = append(dialOptions, grpc.WithBlock()) + dialOptions = append(dialOptions, grpc.WithTimeout(timeout)) + //create GRPC client conn + clientConn, err := grpc.Dial(address, dialOptions...) + if err != nil { + return nil, err + } + defer clientConn.Close() + + //create GRPC client + client := testpb.NewTestServiceClient(clientConn) + + ctx := context.Background() + ctx, cancel := context.WithTimeout(ctx, timeout) + defer cancel() + + //invoke service + empty, err := client.EmptyCall(ctx, new(testpb.Empty)) + if err != nil { + return nil, err + } + + return empty, nil +} + +func TestNewGRPCServerInvalidParameters(t *testing.T) { + + //missing address + _, err := comm.NewGRPCServer("", nil, nil, nil, nil) + //check for error + msg := "Missing address parameter" + assert.EqualError(t, err, msg) + if err != nil { + t.Log(err.Error()) + } + + //missing port + _, err = comm.NewGRPCServer("abcdef", nil, nil, nil, nil) + //check for error + msg = "listen tcp: missing port in address abcdef" + assert.EqualError(t, err, msg) + if err != nil { + t.Log(err.Error()) + } + + //bad port + _, err = comm.NewGRPCServer("localhost:1BBB", nil, nil, nil, nil) + //check for error + msgs := [2]string{"listen tcp: lookup tcp/1BBB: nodename nor servname provided, or not known", + "listen tcp: unknown port tcp/1BBB"} //different error on MacOS and in Docker + + if assert.Error(t, err, "%s or %s expected", msgs[0], msgs[1]) { + assert.Contains(t, msgs, err.Error()) + } + if err != nil { + t.Log(err.Error()) + } + + //bad hostname + _, err = comm.NewGRPCServer("hostdoesnotexist.localdomain:9050", nil, nil, nil, nil) + //check for error + msg = "no such host" + if assert.Error(t, err, "%s error expected", msg) { + assert.Contains(t, err.Error(), msg) //use contains here as error message inconsistent + } + + if err != nil { + t.Log(err.Error()) + } + + //address in use + _, err = comm.NewGRPCServer(":9040", nil, nil, nil, nil) + _, err = comm.NewGRPCServer(":9040", nil, nil, nil, nil) + //check for error + msg = "listen tcp :9040: bind: address already in use" + assert.EqualError(t, err, msg) + if err != nil { + t.Log(err.Error()) + } + + //missing serverCertificate + _, err = comm.NewGRPCServer(":9041", []byte{}, nil, nil, nil) + //check for error + msg = "Both serverKey and serverCertificate are required in order to enable TLS" + assert.EqualError(t, err, msg) + if err != nil { + t.Log(err.Error()) + } + + //missing serverKey + _, err = comm.NewGRPCServer(":9042", nil, []byte{}, nil, nil) + //check for error + assert.EqualError(t, err, msg) + if err != nil { + t.Log(err.Error()) + } + + //bad serverKey + _, err = comm.NewGRPCServer(":9043", []byte{}, []byte(selfSignedCertPEM), nil, nil) + //check for error + msg = "tls: failed to find any PEM data in key input" + assert.EqualError(t, err, msg) + if err != nil { + t.Log(err.Error()) + } + + //bad serverCertificate + _, err = comm.NewGRPCServer(":9044", []byte(selfSignedKeyPEM), []byte{}, nil, nil) + //check for error + msg = "tls: failed to find any PEM data in certificate input" + assert.EqualError(t, err, msg) + if err != nil { + t.Log(err.Error()) + } +} + +func TestNewGRPCServer(t *testing.T) { + + testAddress := "localhost:9053" + srv, err := comm.NewGRPCServer(testAddress, nil, nil, nil, nil) + //check for error + if err != nil { + t.Fatalf("Failed to return new GRPC server: %v", err) + } + + //make sure our properties are as expected + //resolve the address + addr, err := net.ResolveTCPAddr("tcp", testAddress) + assert.Equal(t, srv.Address(), addr.String()) + assert.Equal(t, srv.Listener().Addr().String(), addr.String()) + + //TlSEnabled should be false + assert.Equal(t, srv.TLSEnabled(), false) + + //register the GRPC test server + testpb.RegisterTestServiceServer(srv.Server(), &testServiceServer{}) + + //start the server + go srv.Start() + + defer srv.Stop() + //should not be needed + time.Sleep(10 * time.Millisecond) + + //GRPC client options + var dialOptions []grpc.DialOption + dialOptions = append(dialOptions, grpc.WithInsecure()) + + //invoke the EmptyCall service + _, err = invokeEmptyCall(testAddress, dialOptions) + + if err != nil { + t.Logf("GRPC client failed to invoke the EmptyCall service on %s: %v", + testAddress, err) + t.Fatalf(err.Error()) + } else { + t.Log("GRPC client successfully invoked the EmptyCall service: " + testAddress) + } + +} + +func TestNewGRPCServerFromListener(t *testing.T) { + + testAddress := "localhost:9054" + //create our listener + lis, err := net.Listen("tcp", testAddress) + + if err != nil { + t.Fatalf("Failed to create listener: %v", err) + } + + srv, err := comm.NewGRPCServerFromListener(lis, nil, nil, nil, nil) + //check for error + if err != nil { + t.Fatalf("Failed to return new GRPC server: %v", err) + } + + //make sure our properties are as expected + //resolve the address + addr, err := net.ResolveTCPAddr("tcp", testAddress) + assert.Equal(t, srv.Address(), addr.String()) + assert.Equal(t, srv.Listener().Addr().String(), addr.String()) + + //TlSEnabled should be false + assert.Equal(t, srv.TLSEnabled(), false) + + //register the GRPC test server + testpb.RegisterTestServiceServer(srv.Server(), &testServiceServer{}) + + //start the server + go srv.Start() + + defer srv.Stop() + //should not be needed + time.Sleep(10 * time.Millisecond) + + //GRPC client options + var dialOptions []grpc.DialOption + dialOptions = append(dialOptions, grpc.WithInsecure()) + + //invoke the EmptyCall service + _, err = invokeEmptyCall(testAddress, dialOptions) + + if err != nil { + t.Logf("GRPC client failed to invoke the EmptyCall service on %s: %v", + testAddress, err) + t.Fatalf(err.Error()) + } else { + t.Log("GRPC client successfully invoked the EmptyCall service: " + testAddress) + } +} + +func TestNewSecureGRPCServer(t *testing.T) { + + testAddress := "localhost:9055" + srv, err := comm.NewGRPCServer(testAddress, []byte(selfSignedKeyPEM), + []byte(selfSignedCertPEM), nil, nil) + //check for error + if err != nil { + t.Fatalf("Failed to return new GRPC server: %v", err) + } + + //make sure our properties are as expected + //resolve the address + addr, err := net.ResolveTCPAddr("tcp", testAddress) + assert.Equal(t, srv.Address(), addr.String()) + assert.Equal(t, srv.Listener().Addr().String(), addr.String()) + + //check the server certificate + cert, _ := tls.X509KeyPair([]byte(selfSignedCertPEM), []byte(selfSignedKeyPEM)) + assert.Equal(t, srv.ServerCertificate(), cert) + + //TlSEnabled should be true + assert.Equal(t, srv.TLSEnabled(), true) + + //register the GRPC test server + testpb.RegisterTestServiceServer(srv.Server(), &testServiceServer{}) + + //start the server + go srv.Start() + + defer srv.Stop() + //should not be needed + time.Sleep(10 * time.Millisecond) + + //create the client credentials + certPool := x509.NewCertPool() + + if !certPool.AppendCertsFromPEM([]byte(selfSignedCertPEM)) { + + t.Fatal("Failed to append certificate to client credentials") + } + + creds := credentials.NewClientTLSFromCert(certPool, "") + + //GRPC client options + var dialOptions []grpc.DialOption + dialOptions = append(dialOptions, grpc.WithTransportCredentials(creds)) + + //invoke the EmptyCall service + _, err = invokeEmptyCall(testAddress, dialOptions) + + if err != nil { + t.Logf("GRPC client failed to invoke the EmptyCall service on %s: %v", + testAddress, err) + } else { + t.Log("GRPC client successfully invoked the EmptyCall service: " + testAddress) + } +} + +func TestNewSecureGRPCServerFromListener(t *testing.T) { + + testAddress := "localhost:9056" + //create our listener + lis, err := net.Listen("tcp", testAddress) + + if err != nil { + t.Fatalf("Failed to create listener: %v", err) + } + + srv, err := comm.NewGRPCServerFromListener(lis, []byte(selfSignedKeyPEM), + []byte(selfSignedCertPEM), nil, nil) + //check for error + if err != nil { + t.Fatalf("Failed to return new GRPC server: %v", err) + } + + //make sure our properties are as expected + //resolve the address + addr, err := net.ResolveTCPAddr("tcp", testAddress) + assert.Equal(t, srv.Address(), addr.String()) + assert.Equal(t, srv.Listener().Addr().String(), addr.String()) + + //check the server certificate + cert, _ := tls.X509KeyPair([]byte(selfSignedCertPEM), []byte(selfSignedKeyPEM)) + assert.Equal(t, srv.ServerCertificate(), cert) + + //TlSEnabled should be true + assert.Equal(t, srv.TLSEnabled(), true) + + //register the GRPC test server + testpb.RegisterTestServiceServer(srv.Server(), &testServiceServer{}) + + //start the server + go srv.Start() + + defer srv.Stop() + //should not be needed + time.Sleep(10 * time.Millisecond) + + //create the client credentials + certPool := x509.NewCertPool() + + if !certPool.AppendCertsFromPEM([]byte(selfSignedCertPEM)) { + + t.Fatal("Failed to append certificate to client credentials") + } + + creds := credentials.NewClientTLSFromCert(certPool, "") + + //GRPC client options + var dialOptions []grpc.DialOption + dialOptions = append(dialOptions, grpc.WithTransportCredentials(creds)) + + //invoke the EmptyCall service + _, err = invokeEmptyCall(testAddress, dialOptions) + + if err != nil { + t.Logf("GRPC client failed to invoke the EmptyCall service on %s: %v", + testAddress, err) + } else { + t.Log("GRPC client successfully invoked the EmptyCall service: " + testAddress) + } +} diff --git a/core/comm/testdata/grpc/test.pb.go b/core/comm/testdata/grpc/test.pb.go new file mode 100644 index 00000000000..c8676919b1c --- /dev/null +++ b/core/comm/testdata/grpc/test.pb.go @@ -0,0 +1,130 @@ +// Code generated by protoc-gen-go. +// source: test.proto +// DO NOT EDIT! + +/* +Package test is a generated protocol buffer package. + +It is generated from these files: + test.proto + +It has these top-level messages: + Empty +*/ +package test + +import proto "github.com/golang/protobuf/proto" +import fmt "fmt" +import math "math" + +import ( + context "golang.org/x/net/context" + grpc "google.golang.org/grpc" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package + +type Empty struct { +} + +func (m *Empty) Reset() { *m = Empty{} } +func (m *Empty) String() string { return proto.CompactTextString(m) } +func (*Empty) ProtoMessage() {} +func (*Empty) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } + +func init() { + proto.RegisterType((*Empty)(nil), "Empty") +} + +// Reference imports to suppress errors if they are not otherwise used. +var _ context.Context +var _ grpc.ClientConn + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +const _ = grpc.SupportPackageIsVersion3 + +// Client API for TestService service + +type TestServiceClient interface { + EmptyCall(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*Empty, error) +} + +type testServiceClient struct { + cc *grpc.ClientConn +} + +func NewTestServiceClient(cc *grpc.ClientConn) TestServiceClient { + return &testServiceClient{cc} +} + +func (c *testServiceClient) EmptyCall(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*Empty, error) { + out := new(Empty) + err := grpc.Invoke(ctx, "/TestService/EmptyCall", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// Server API for TestService service + +type TestServiceServer interface { + EmptyCall(context.Context, *Empty) (*Empty, error) +} + +func RegisterTestServiceServer(s *grpc.Server, srv TestServiceServer) { + s.RegisterService(&_TestService_serviceDesc, srv) +} + +func _TestService_EmptyCall_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(Empty) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(TestServiceServer).EmptyCall(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/TestService/EmptyCall", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(TestServiceServer).EmptyCall(ctx, req.(*Empty)) + } + return interceptor(ctx, in, info, handler) +} + +var _TestService_serviceDesc = grpc.ServiceDesc{ + ServiceName: "TestService", + HandlerType: (*TestServiceServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "EmptyCall", + Handler: _TestService_EmptyCall_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: fileDescriptor0, +} + +func init() { proto.RegisterFile("test.proto", fileDescriptor0) } + +var fileDescriptor0 = []byte{ + // 81 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xe2, 0xe2, 0x2a, 0x49, 0x2d, 0x2e, + 0xd1, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x57, 0x62, 0xe7, 0x62, 0x75, 0xcd, 0x2d, 0x28, 0xa9, 0x34, + 0xd2, 0xe2, 0xe2, 0x0e, 0x01, 0x0a, 0x07, 0xa7, 0x16, 0x95, 0x65, 0x26, 0xa7, 0x0a, 0x49, 0x73, + 0x71, 0x82, 0xc5, 0x9d, 0x13, 0x73, 0x72, 0x84, 0xd8, 0xf4, 0xc0, 0x6c, 0x29, 0x28, 0x9d, 0xc4, + 0x06, 0xd6, 0x6b, 0x0c, 0x08, 0x00, 0x00, 0xff, 0xff, 0xed, 0x32, 0x6a, 0x04, 0x49, 0x00, 0x00, + 0x00, +} diff --git a/core/comm/testdata/grpc/test.proto b/core/comm/testdata/grpc/test.proto new file mode 100644 index 00000000000..1d45b0b3acf --- /dev/null +++ b/core/comm/testdata/grpc/test.proto @@ -0,0 +1,25 @@ +/* +Copyright IBM Corp. 2016 All Rights Reserved. + +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. +*/ + +syntax = "proto3"; + +message Empty {} + +service TestService { + + rpc EmptyCall(Empty) returns (Empty); + +} \ No newline at end of file diff --git a/core/comm/testdata/prime256v1-openssl-cert.pem b/core/comm/testdata/prime256v1-openssl-cert.pem new file mode 100644 index 00000000000..4c871b80a3b --- /dev/null +++ b/core/comm/testdata/prime256v1-openssl-cert.pem @@ -0,0 +1,15 @@ +-----BEGIN CERTIFICATE----- +MIICRDCCAemgAwIBAgIJALwW//dz2ZBvMAoGCCqGSM49BAMCMH4xCzAJBgNVBAYT +AlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRYwFAYDVQQHDA1TYW4gRnJhbmNpc2Nv +MRgwFgYDVQQKDA9MaW51eEZvdW5kYXRpb24xFDASBgNVBAsMC0h5cGVybGVkZ2Vy +MRIwEAYDVQQDDAlsb2NhbGhvc3QwHhcNMTYxMjA0MjIzMDE4WhcNMjYxMjAyMjIz +MDE4WjB+MQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UE +BwwNU2FuIEZyYW5jaXNjbzEYMBYGA1UECgwPTGludXhGb3VuZGF0aW9uMRQwEgYD +VQQLDAtIeXBlcmxlZGdlcjESMBAGA1UEAwwJbG9jYWxob3N0MFkwEwYHKoZIzj0C +AQYIKoZIzj0DAQcDQgAEu2FEZVSr30Afey6dwcypeg5P+BuYx5JSYdG0/KJIBjWK +nzYo7FEmgMir7GbNh4pqA8KFrJZkPuxMgnEJBZTv+6NQME4wHQYDVR0OBBYEFAWO +4bfTEr2R6VYzQYrGk/2VWmtYMB8GA1UdIwQYMBaAFAWO4bfTEr2R6VYzQYrGk/2V +WmtYMAwGA1UdEwQFMAMBAf8wCgYIKoZIzj0EAwIDSQAwRgIhAIelqGdxPMHmQqRF +zA85vv7JhfMkvZYGPELC7I2K8V7ZAiEA9KcthV3HtDXKNDsA6ULT+qUkyoHRzCzr +A4QaL2VU6i4= +-----END CERTIFICATE----- diff --git a/core/comm/testdata/prime256v1-openssl-key.pem b/core/comm/testdata/prime256v1-openssl-key.pem new file mode 100644 index 00000000000..5573e24ea17 --- /dev/null +++ b/core/comm/testdata/prime256v1-openssl-key.pem @@ -0,0 +1,8 @@ +-----BEGIN EC PARAMETERS----- +BggqhkjOPQMBBw== +-----END EC PARAMETERS----- +-----BEGIN EC PRIVATE KEY----- +MHcCAQEEIM2rUTflEQ11m5g5yEm2Cer2yI+ziccl1NbSRVh3GUR0oAoGCCqGSM49 +AwEHoUQDQgAEu2FEZVSr30Afey6dwcypeg5P+BuYx5JSYdG0/KJIBjWKnzYo7FEm +gMir7GbNh4pqA8KFrJZkPuxMgnEJBZTv+w== +-----END EC PRIVATE KEY-----