github.com/lzy4123/fabric@v2.1.1+incompatible/internal/pkg/comm/server.go (about) 1 /* 2 Copyright IBM Corp. All Rights Reserved. 3 4 SPDX-License-Identifier: Apache-2.0 5 */ 6 7 package comm 8 9 import ( 10 "crypto/tls" 11 "crypto/x509" 12 "net" 13 "sync" 14 "sync/atomic" 15 "time" 16 17 grpc_middleware "github.com/grpc-ecosystem/go-grpc-middleware" 18 "github.com/pkg/errors" 19 "google.golang.org/grpc" 20 "google.golang.org/grpc/health" 21 healthpb "google.golang.org/grpc/health/grpc_health_v1" 22 ) 23 24 type GRPCServer struct { 25 // Listen address for the server specified as hostname:port 26 address string 27 // Listener for handling network requests 28 listener net.Listener 29 // GRPC server 30 server *grpc.Server 31 // Certificate presented by the server for TLS communication 32 // stored as an atomic reference 33 serverCertificate atomic.Value 34 // lock to protect concurrent access to append / remove 35 lock *sync.Mutex 36 // Set of PEM-encoded X509 certificate authorities used to populate 37 // the tlsConfig.ClientCAs indexed by subject 38 clientRootCAs map[string]*x509.Certificate 39 // TLS configuration used by the grpc server 40 tls *TLSConfig 41 // Server for gRPC Health Check Protocol. 42 healthServer *health.Server 43 } 44 45 // NewGRPCServer creates a new implementation of a GRPCServer given a 46 // listen address 47 func NewGRPCServer(address string, serverConfig ServerConfig) (*GRPCServer, error) { 48 if address == "" { 49 return nil, errors.New("missing address parameter") 50 } 51 //create our listener 52 lis, err := net.Listen("tcp", address) 53 54 if err != nil { 55 return nil, err 56 } 57 return NewGRPCServerFromListener(lis, serverConfig) 58 } 59 60 // NewGRPCServerFromListener creates a new implementation of a GRPCServer given 61 // an existing net.Listener instance using default keepalive 62 func NewGRPCServerFromListener(listener net.Listener, serverConfig ServerConfig) (*GRPCServer, error) { 63 grpcServer := &GRPCServer{ 64 address: listener.Addr().String(), 65 listener: listener, 66 lock: &sync.Mutex{}, 67 } 68 69 //set up our server options 70 var serverOpts []grpc.ServerOption 71 72 secureConfig := serverConfig.SecOpts 73 if secureConfig.UseTLS { 74 //both key and cert are required 75 if secureConfig.Key != nil && secureConfig.Certificate != nil { 76 //load server public and private keys 77 cert, err := tls.X509KeyPair(secureConfig.Certificate, secureConfig.Key) 78 if err != nil { 79 return nil, err 80 } 81 82 grpcServer.serverCertificate.Store(cert) 83 84 //set up our TLS config 85 if len(secureConfig.CipherSuites) == 0 { 86 secureConfig.CipherSuites = DefaultTLSCipherSuites 87 } 88 getCert := func(_ *tls.ClientHelloInfo) (*tls.Certificate, error) { 89 cert := grpcServer.serverCertificate.Load().(tls.Certificate) 90 return &cert, nil 91 } 92 93 grpcServer.tls = NewTLSConfig(&tls.Config{ 94 VerifyPeerCertificate: secureConfig.VerifyCertificate, 95 GetCertificate: getCert, 96 SessionTicketsDisabled: true, 97 CipherSuites: secureConfig.CipherSuites, 98 }) 99 100 if serverConfig.SecOpts.TimeShift > 0 { 101 timeShift := serverConfig.SecOpts.TimeShift 102 grpcServer.tls.config.Time = func() time.Time { 103 return time.Now().Add((-1) * timeShift) 104 } 105 } 106 grpcServer.tls.config.ClientAuth = tls.RequestClientCert 107 //check if client authentication is required 108 if secureConfig.RequireClientCert { 109 //require TLS client auth 110 grpcServer.tls.config.ClientAuth = tls.RequireAndVerifyClientCert 111 //if we have client root CAs, create a certPool 112 if len(secureConfig.ClientRootCAs) > 0 { 113 grpcServer.clientRootCAs = make(map[string]*x509.Certificate) 114 115 grpcServer.tls.config.ClientCAs = x509.NewCertPool() 116 for _, clientRootCA := range secureConfig.ClientRootCAs { 117 err = grpcServer.appendClientRootCA(clientRootCA) 118 if err != nil { 119 return nil, err 120 } 121 } 122 } 123 } 124 125 // create credentials and add to server options 126 creds := NewServerTransportCredentials(grpcServer.tls, serverConfig.Logger) 127 serverOpts = append(serverOpts, grpc.Creds(creds)) 128 } else { 129 return nil, errors.New("serverConfig.SecOpts must contain both Key and Certificate when UseTLS is true") 130 } 131 } 132 // set max send and recv msg sizes 133 serverOpts = append(serverOpts, grpc.MaxSendMsgSize(MaxSendMsgSize)) 134 serverOpts = append(serverOpts, grpc.MaxRecvMsgSize(MaxRecvMsgSize)) 135 // set the keepalive options 136 serverOpts = append(serverOpts, ServerKeepaliveOptions(serverConfig.KaOpts)...) 137 // set connection timeout 138 if serverConfig.ConnectionTimeout <= 0 { 139 serverConfig.ConnectionTimeout = DefaultConnectionTimeout 140 } 141 serverOpts = append( 142 serverOpts, 143 grpc.ConnectionTimeout(serverConfig.ConnectionTimeout)) 144 // set the interceptors 145 if len(serverConfig.StreamInterceptors) > 0 { 146 serverOpts = append( 147 serverOpts, 148 grpc.StreamInterceptor(grpc_middleware.ChainStreamServer(serverConfig.StreamInterceptors...)), 149 ) 150 } 151 152 if len(serverConfig.UnaryInterceptors) > 0 { 153 serverOpts = append( 154 serverOpts, 155 grpc.UnaryInterceptor(grpc_middleware.ChainUnaryServer(serverConfig.UnaryInterceptors...)), 156 ) 157 } 158 159 if serverConfig.ServerStatsHandler != nil { 160 serverOpts = append(serverOpts, grpc.StatsHandler(serverConfig.ServerStatsHandler)) 161 } 162 163 grpcServer.server = grpc.NewServer(serverOpts...) 164 165 if serverConfig.HealthCheckEnabled { 166 grpcServer.healthServer = health.NewServer() 167 healthpb.RegisterHealthServer(grpcServer.server, grpcServer.healthServer) 168 } 169 170 return grpcServer, nil 171 } 172 173 // SetServerCertificate assigns the current TLS certificate to be the peer's server certificate 174 func (gServer *GRPCServer) SetServerCertificate(cert tls.Certificate) { 175 gServer.serverCertificate.Store(cert) 176 } 177 178 // Address returns the listen address for this GRPCServer instance 179 func (gServer *GRPCServer) Address() string { 180 return gServer.address 181 } 182 183 // Listener returns the net.Listener for the GRPCServer instance 184 func (gServer *GRPCServer) Listener() net.Listener { 185 return gServer.listener 186 } 187 188 // Server returns the grpc.Server for the GRPCServer instance 189 func (gServer *GRPCServer) Server() *grpc.Server { 190 return gServer.server 191 } 192 193 // ServerCertificate returns the tls.Certificate used by the grpc.Server 194 func (gServer *GRPCServer) ServerCertificate() tls.Certificate { 195 return gServer.serverCertificate.Load().(tls.Certificate) 196 } 197 198 // TLSEnabled is a flag indicating whether or not TLS is enabled for the 199 // GRPCServer instance 200 func (gServer *GRPCServer) TLSEnabled() bool { 201 return gServer.tls != nil 202 } 203 204 // MutualTLSRequired is a flag indicating whether or not client certificates 205 // are required for this GRPCServer instance 206 func (gServer *GRPCServer) MutualTLSRequired() bool { 207 return gServer.TLSEnabled() && 208 gServer.tls.Config().ClientAuth == tls.RequireAndVerifyClientCert 209 } 210 211 // Start starts the underlying grpc.Server 212 func (gServer *GRPCServer) Start() error { 213 // if health check is enabled, set the health status for all registered services 214 if gServer.healthServer != nil { 215 for name := range gServer.server.GetServiceInfo() { 216 gServer.healthServer.SetServingStatus( 217 name, 218 healthpb.HealthCheckResponse_SERVING, 219 ) 220 } 221 222 gServer.healthServer.SetServingStatus( 223 "", 224 healthpb.HealthCheckResponse_SERVING, 225 ) 226 } 227 return gServer.server.Serve(gServer.listener) 228 } 229 230 // Stop stops the underlying grpc.Server 231 func (gServer *GRPCServer) Stop() { 232 gServer.server.Stop() 233 } 234 235 // internal function to add a PEM-encoded clientRootCA 236 func (gServer *GRPCServer) appendClientRootCA(clientRoot []byte) error { 237 certs, subjects, err := pemToX509Certs(clientRoot) 238 if err != nil { 239 return errors.WithMessage(err, "failed to append client root certificate(s)") 240 } 241 242 if len(certs) < 1 { 243 return errors.New("no client root certificates found") 244 } 245 246 for i, cert := range certs { 247 //first add to the ClientCAs 248 gServer.tls.AddClientRootCA(cert) 249 //add it to our clientRootCAs map using subject as key 250 gServer.clientRootCAs[subjects[i]] = cert 251 } 252 253 return nil 254 } 255 256 // SetClientRootCAs sets the list of authorities used to verify client 257 // certificates based on a list of PEM-encoded X509 certificate authorities 258 func (gServer *GRPCServer) SetClientRootCAs(clientRoots [][]byte) error { 259 gServer.lock.Lock() 260 defer gServer.lock.Unlock() 261 262 //create a new map and CertPool 263 clientRootCAs := make(map[string]*x509.Certificate) 264 for _, clientRoot := range clientRoots { 265 certs, subjects, err := pemToX509Certs(clientRoot) 266 if err != nil { 267 return errors.WithMessage(err, "failed to set client root certificate(s)") 268 } 269 270 for i, cert := range certs { 271 clientRootCAs[subjects[i]] = cert 272 } 273 } 274 275 //create a new CertPool and populate with the new clientRootCAs 276 certPool := x509.NewCertPool() 277 for _, clientRoot := range clientRootCAs { 278 certPool.AddCert(clientRoot) 279 } 280 281 gServer.clientRootCAs = clientRootCAs 282 gServer.tls.SetClientCAs(certPool) 283 return nil 284 }