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