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  }