github.com/leonlxy/hyperledger@v1.0.0-alpha.0.20170427033203-34922035d248/core/comm/server.go (about) 1 /* 2 Copyright IBM Corp. 2016 All Rights Reserved. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package comm 18 19 import ( 20 "crypto/tls" 21 "crypto/x509" 22 "encoding/pem" 23 "errors" 24 "fmt" 25 "net" 26 "sync" 27 28 "google.golang.org/grpc" 29 "google.golang.org/grpc/credentials" 30 ) 31 32 //A SecureServerConfig structure is used to configure security (e.g. TLS) for a 33 //GRPCServer instance 34 type SecureServerConfig struct { 35 //Whether or not to use TLS for communication 36 UseTLS bool 37 //PEM-encoded X509 public key to be used by the server for TLS communication 38 ServerCertificate []byte 39 //PEM-encoded private key to be used by the server for TLS communication 40 ServerKey []byte 41 //Set of PEM-encoded X509 certificate authorities to optionally send 42 //as part of the server handshake 43 ServerRootCAs [][]byte 44 //Whether or not TLS client must present certificates for authentication 45 RequireClientCert bool 46 //Set of PEM-encoded X509 certificate authorities to use when verifying 47 //client certificates 48 ClientRootCAs [][]byte 49 } 50 51 //GRPCServer defines an interface representing a GRPC-based server 52 type GRPCServer interface { 53 //Address returns the listen address for the GRPCServer 54 Address() string 55 //Start starts the underlying grpc.Server 56 Start() error 57 //Stop stops the underlying grpc.Server 58 Stop() 59 //Server returns the grpc.Server instance for the GRPCServer 60 Server() *grpc.Server 61 //Listener returns the net.Listener instance for the GRPCServer 62 Listener() net.Listener 63 //ServerCertificate returns the tls.Certificate used by the grpc.Server 64 ServerCertificate() tls.Certificate 65 //TLSEnabled is a flag indicating whether or not TLS is enabled for this 66 //GRPCServer instance 67 TLSEnabled() bool 68 //AppendClientRootCAs appends PEM-encoded X509 certificate authorities to 69 //the list of authorities used to verify client certificates 70 AppendClientRootCAs(clientRoots [][]byte) error 71 //RemoveClientRootCAs removes PEM-encoded X509 certificate authorities from 72 //the list of authorities used to verify client certificates 73 RemoveClientRootCAs(clientRoots [][]byte) error 74 //SetClientRootCAs sets the list of authorities used to verify client 75 //certificates based on a list of PEM-encoded X509 certificate authorities 76 SetClientRootCAs(clientRoots [][]byte) error 77 } 78 79 type grpcServerImpl struct { 80 //Listen address for the server specified as hostname:port 81 address string 82 //Listener for handling network requests 83 listener net.Listener 84 //GRPC server 85 server *grpc.Server 86 //Certificate presented by the server for TLS communication 87 serverCertificate tls.Certificate 88 //Key used by the server for TLS communication 89 serverKeyPEM []byte 90 //List of certificate authorities to optionally pass to the client during 91 //the TLS handshake 92 serverRootCAs []tls.Certificate 93 //lock to protect concurrent access to append / remove 94 lock *sync.Mutex 95 //Set of PEM-encoded X509 certificate authorities used to populate 96 //the tlsConfig.ClientCAs indexed by subject 97 clientRootCAs map[string]*x509.Certificate 98 //TLS configuration used by the grpc server 99 tlsConfig *tls.Config 100 //Is TLS enabled? 101 tlsEnabled bool 102 } 103 104 //NewGRPCServer creates a new implementation of a GRPCServer given a 105 //listen address. 106 func NewGRPCServer(address string, secureConfig SecureServerConfig) (GRPCServer, error) { 107 108 if address == "" { 109 return nil, errors.New("Missing address parameter") 110 } 111 //create our listener 112 lis, err := net.Listen("tcp", address) 113 114 if err != nil { 115 return nil, err 116 } 117 118 return NewGRPCServerFromListener(lis, secureConfig) 119 120 } 121 122 //NewGRPCServerFromListener creates a new implementation of a GRPCServer given 123 //an existing net.Listener instance. 124 func NewGRPCServerFromListener(listener net.Listener, secureConfig SecureServerConfig) (GRPCServer, error) { 125 126 grpcServer := &grpcServerImpl{ 127 address: listener.Addr().String(), 128 listener: listener, 129 lock: &sync.Mutex{}, 130 } 131 132 //set up our server options 133 var serverOpts []grpc.ServerOption 134 //check secureConfig 135 if secureConfig.UseTLS { 136 //both key and cert are required 137 if secureConfig.ServerKey != nil && secureConfig.ServerCertificate != nil { 138 grpcServer.tlsEnabled = true 139 //load server public and private keys 140 cert, err := tls.X509KeyPair(secureConfig.ServerCertificate, secureConfig.ServerKey) 141 if err != nil { 142 return nil, err 143 } 144 grpcServer.serverCertificate = cert 145 146 //set up our TLS config 147 148 //base server certificate 149 certificates := []tls.Certificate{grpcServer.serverCertificate} 150 grpcServer.tlsConfig = &tls.Config{ 151 Certificates: certificates, 152 SessionTicketsDisabled: true, 153 } 154 //checkif client authentication is required 155 if secureConfig.RequireClientCert { 156 //require TLS client auth 157 grpcServer.tlsConfig.ClientAuth = tls.RequireAndVerifyClientCert 158 //if we have client root CAs, create a certPool 159 if len(secureConfig.ClientRootCAs) > 0 { 160 grpcServer.clientRootCAs = make(map[string]*x509.Certificate) 161 grpcServer.tlsConfig.ClientCAs = x509.NewCertPool() 162 for _, clientRootCA := range secureConfig.ClientRootCAs { 163 err = grpcServer.appendClientRootCA(clientRootCA) 164 if err != nil { 165 return nil, err 166 } 167 } 168 } 169 } 170 171 //create credentials 172 creds := credentials.NewTLS(grpcServer.tlsConfig) 173 174 //add to server options 175 serverOpts = append(serverOpts, grpc.Creds(creds)) 176 177 } else { 178 return nil, errors.New("secureConfig must contain both ServerKey and " + 179 "ServerCertificate when UseTLS is true") 180 } 181 } 182 grpcServer.server = grpc.NewServer(serverOpts...) 183 184 return grpcServer, nil 185 } 186 187 //Address returns the listen address for this GRPCServer instance 188 func (gServer *grpcServerImpl) Address() string { 189 return gServer.address 190 } 191 192 //Listener returns the net.Listener for the GRPCServer instance 193 func (gServer *grpcServerImpl) Listener() net.Listener { 194 return gServer.listener 195 } 196 197 //Server returns the grpc.Server for the GRPCServer instance 198 func (gServer *grpcServerImpl) Server() *grpc.Server { 199 return gServer.server 200 } 201 202 //ServerCertificate returns the tls.Certificate used by the grpc.Server 203 func (gServer *grpcServerImpl) ServerCertificate() tls.Certificate { 204 return gServer.serverCertificate 205 } 206 207 //TLSEnabled is a flag indicating whether or not TLS is enabled for the 208 //GRPCServer instance 209 func (gServer *grpcServerImpl) TLSEnabled() bool { 210 return gServer.tlsEnabled 211 } 212 213 //Start starts the underlying grpc.Server 214 func (gServer *grpcServerImpl) Start() error { 215 return gServer.server.Serve(gServer.listener) 216 } 217 218 //Stop stops the underlying grpc.Server 219 func (gServer *grpcServerImpl) Stop() { 220 gServer.server.Stop() 221 } 222 223 //AppendClientRootCAs appends PEM-encoded X509 certificate authorities to 224 //the list of authorities used to verify client certificates 225 func (gServer *grpcServerImpl) AppendClientRootCAs(clientRoots [][]byte) error { 226 gServer.lock.Lock() 227 defer gServer.lock.Unlock() 228 for _, clientRoot := range clientRoots { 229 err := gServer.appendClientRootCA(clientRoot) 230 if err != nil { 231 return err 232 } 233 } 234 return nil 235 } 236 237 //internal function to add a PEM-encoded clientRootCA 238 func (gServer *grpcServerImpl) appendClientRootCA(clientRoot []byte) error { 239 240 errMsg := "Failed to append client root certificate(s): %s" 241 //convert to x509 242 certs, subjects, err := pemToX509Certs(clientRoot) 243 if err != nil { 244 return fmt.Errorf(errMsg, err.Error()) 245 } 246 247 if len(certs) < 1 { 248 return fmt.Errorf(errMsg, "No client root certificates found") 249 } 250 251 for i, cert := range certs { 252 //first add to the ClientCAs 253 gServer.tlsConfig.ClientCAs.AddCert(cert) 254 //add it to our clientRootCAs map using subject as key 255 gServer.clientRootCAs[subjects[i]] = cert 256 } 257 return nil 258 } 259 260 //RemoveClientRootCAs removes PEM-encoded X509 certificate authorities from 261 //the list of authorities used to verify client certificates 262 func (gServer *grpcServerImpl) RemoveClientRootCAs(clientRoots [][]byte) error { 263 gServer.lock.Lock() 264 defer gServer.lock.Unlock() 265 //remove from internal map 266 for _, clientRoot := range clientRoots { 267 err := gServer.removeClientRootCA(clientRoot) 268 if err != nil { 269 return err 270 } 271 } 272 273 //create a new CertPool and populate with current clientRootCAs 274 certPool := x509.NewCertPool() 275 for _, clientRoot := range gServer.clientRootCAs { 276 certPool.AddCert(clientRoot) 277 } 278 279 //replace the current ClientCAs pool 280 gServer.tlsConfig.ClientCAs = certPool 281 return nil 282 } 283 284 //internal function to remove a PEM-encoded clientRootCA 285 func (gServer *grpcServerImpl) removeClientRootCA(clientRoot []byte) error { 286 287 errMsg := "Failed to remove client root certificate(s): %s" 288 //convert to x509 289 certs, subjects, err := pemToX509Certs(clientRoot) 290 if err != nil { 291 return fmt.Errorf(errMsg, err.Error()) 292 } 293 294 if len(certs) < 1 { 295 return fmt.Errorf(errMsg, "No client root certificates found") 296 } 297 298 for i, subject := range subjects { 299 //remove it from our clientRootCAs map using subject as key 300 //check to see if we have match 301 if certs[i].Equal(gServer.clientRootCAs[subject]) { 302 delete(gServer.clientRootCAs, subject) 303 } 304 } 305 return nil 306 } 307 308 //SetClientRootCAs sets the list of authorities used to verify client 309 //certificates based on a list of PEM-encoded X509 certificate authorities 310 func (gServer *grpcServerImpl) SetClientRootCAs(clientRoots [][]byte) error { 311 gServer.lock.Lock() 312 defer gServer.lock.Unlock() 313 314 errMsg := "Failed to set client root certificate(s): %s" 315 316 //create a new map and CertPool 317 clientRootCAs := make(map[string]*x509.Certificate) 318 for _, clientRoot := range clientRoots { 319 certs, subjects, err := pemToX509Certs(clientRoot) 320 if err != nil { 321 return fmt.Errorf(errMsg, err.Error()) 322 } 323 if len(certs) >= 1 { 324 for i, cert := range certs { 325 //add it to our clientRootCAs map using subject as key 326 clientRootCAs[subjects[i]] = cert 327 } 328 } 329 } 330 331 //create a new CertPool and populate with the new clientRootCAs 332 certPool := x509.NewCertPool() 333 for _, clientRoot := range clientRootCAs { 334 certPool.AddCert(clientRoot) 335 } 336 //replace the internal map 337 gServer.clientRootCAs = clientRootCAs 338 //replace the current ClientCAs pool 339 gServer.tlsConfig.ClientCAs = certPool 340 return nil 341 } 342 343 //utility function to parse PEM-encoded certs 344 func pemToX509Certs(pemCerts []byte) ([]*x509.Certificate, []string, error) { 345 346 //it's possible that multiple certs are encoded 347 certs := []*x509.Certificate{} 348 subjects := []string{} 349 for len(pemCerts) > 0 { 350 var block *pem.Block 351 block, pemCerts = pem.Decode(pemCerts) 352 if block == nil { 353 break 354 } 355 /** TODO: check why msp does not add type to PEM header 356 if block.Type != "CERTIFICATE" || len(block.Headers) != 0 { 357 continue 358 } 359 */ 360 361 cert, err := x509.ParseCertificate(block.Bytes) 362 if err != nil { 363 return nil, subjects, err 364 } else { 365 certs = append(certs, cert) 366 //extract and append the subject 367 subjects = append(subjects, string(cert.RawSubject)) 368 } 369 } 370 return certs, subjects, nil 371 }