gitee.com/hyperledger/fabric-ca@v2.0.0-alpha+incompatible/lib/server.go (about)

     1  /*
     2  Copyright IBM Corp. All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package lib
     8  
     9  import (
    10  	"context"
    11  	"crypto/tls"
    12  	"crypto/x509"
    13  	"fmt"
    14  	"io"
    15  	"io/ioutil"
    16  	"net"
    17  	"net/http"
    18  	_ "net/http/pprof" // import to support profiling
    19  	"os"
    20  	"path/filepath"
    21  	"strconv"
    22  	"strings"
    23  	"sync"
    24  	"time"
    25  
    26  	"github.com/cloudflare/cfssl/log"
    27  	"github.com/cloudflare/cfssl/revoke"
    28  	"github.com/cloudflare/cfssl/signer"
    29  	"github.com/felixge/httpsnoop"
    30  	ghandlers "github.com/gorilla/handlers"
    31  	gmux "github.com/gorilla/mux"
    32  	"github.com/hyperledger/fabric-ca/lib/attr"
    33  	"github.com/hyperledger/fabric-ca/lib/caerrors"
    34  	calog "github.com/hyperledger/fabric-ca/lib/common/log"
    35  	"github.com/hyperledger/fabric-ca/lib/metadata"
    36  	dbutil "github.com/hyperledger/fabric-ca/lib/server/db/util"
    37  	cametrics "github.com/hyperledger/fabric-ca/lib/server/metrics"
    38  	"github.com/hyperledger/fabric-ca/lib/server/operations"
    39  	stls "github.com/hyperledger/fabric-ca/lib/tls"
    40  	"github.com/hyperledger/fabric-ca/util"
    41  	"github.com/hyperledger/fabric-lib-go/healthz"
    42  	"github.com/hyperledger/fabric/common/metrics"
    43  	"github.com/pkg/errors"
    44  	"github.com/spf13/viper"
    45  )
    46  
    47  const (
    48  	defaultClientAuth         = "noclientcert"
    49  	fabricCAServerProfilePort = "FABRIC_CA_SERVER_PROFILE_PORT"
    50  	allRoles                  = "peer,orderer,client,user"
    51  	apiPathPrefix             = "/api/v1/"
    52  )
    53  
    54  //go:generate counterfeiter -o mocks/operations_server.go -fake-name OperationsServer . operationsServer
    55  
    56  // operationsServer defines the contract required for an operations server
    57  type operationsServer interface {
    58  	metrics.Provider
    59  	Start() error
    60  	Stop() error
    61  	Addr() string
    62  	RegisterChecker(component string, checker healthz.HealthChecker) error
    63  }
    64  
    65  // Server is the fabric-ca server
    66  type Server struct {
    67  	// The home directory for the server
    68  	HomeDir string
    69  	// BlockingStart if true makes the Start function blocking;
    70  	// It is non-blocking by default.
    71  	BlockingStart bool
    72  	// The server's configuration
    73  	Config *ServerConfig
    74  	// Metrics are the metrics that the server tracks
    75  	Metrics cametrics.Metrics
    76  	// Operations is responsible for the server's operation information
    77  	Operations operationsServer
    78  	// The server mux
    79  	mux *gmux.Router
    80  	// The current listener for this server
    81  	listener net.Listener
    82  	// An error which occurs when serving
    83  	serveError error
    84  	// Server's default CA
    85  	CA
    86  	// A map of CAs stored by CA name as key
    87  	caMap map[string]*CA
    88  	// A map of CA configs stored by CA file as key
    89  	caConfigMap map[string]*CAConfig
    90  	// channel for communication between http.serve and main threads.
    91  	wait chan bool
    92  	// Server mutex
    93  	mutex sync.Mutex
    94  	// The server's current levels
    95  	levels *dbutil.Levels
    96  }
    97  
    98  // Init initializes a fabric-ca server
    99  func (s *Server) Init(renew bool) (err error) {
   100  	err = s.init(renew)
   101  	err2 := s.closeDB()
   102  	if err2 != nil {
   103  		log.Errorf("Close DB failed: %s", err2)
   104  	}
   105  	return err
   106  }
   107  
   108  // init initializses the server leaving the DB open
   109  func (s *Server) init(renew bool) (err error) {
   110  	s.Config.Operations.Metrics = s.Config.Metrics
   111  	s.Operations = operations.NewSystem(s.Config.Operations)
   112  
   113  	serverVersion := metadata.GetVersion()
   114  	err = calog.SetLogLevel(s.Config.LogLevel, s.Config.Debug)
   115  	if err != nil {
   116  		return err
   117  	}
   118  	log.Infof("Server Version: %s", serverVersion)
   119  	s.levels, err = metadata.GetLevels(serverVersion)
   120  	if err != nil {
   121  		return err
   122  	}
   123  	log.Infof("Server Levels: %+v", s.levels)
   124  
   125  	s.mux = gmux.NewRouter()
   126  	// Initialize the config
   127  	err = s.initConfig()
   128  	if err != nil {
   129  		return err
   130  	}
   131  	// Initialize the default CA last
   132  	err = s.initDefaultCA(renew)
   133  	if err != nil {
   134  		return err
   135  	}
   136  	// Successful initialization
   137  	return nil
   138  }
   139  
   140  func (s *Server) initMetrics() {
   141  	metricsProvider := s.Operations
   142  	s.Metrics.APICounter = metricsProvider.NewCounter(cametrics.APICounterOpts)
   143  	s.Metrics.APIDuration = metricsProvider.NewHistogram(cametrics.APIDurationOpts)
   144  }
   145  
   146  func (s *Server) startOperationsServer() error {
   147  	err := s.Operations.Start()
   148  	if err != nil {
   149  		return err
   150  	}
   151  
   152  	return nil
   153  }
   154  
   155  // Start the fabric-ca server
   156  func (s *Server) Start() (err error) {
   157  	log.Infof("Starting server in home directory: %s", s.HomeDir)
   158  
   159  	s.serveError = nil
   160  
   161  	if s.listener != nil {
   162  		return errors.New("server is already started")
   163  	}
   164  
   165  	// Initialize the server
   166  	err = s.init(false)
   167  	if err != nil {
   168  		err2 := s.closeDB()
   169  		if err2 != nil {
   170  			log.Errorf("Close DB failed: %s", err2)
   171  		}
   172  		return err
   173  	}
   174  
   175  	// Register http handlers
   176  	s.registerHandlers()
   177  
   178  	log.Debugf("%d CA instance(s) running on server", len(s.caMap))
   179  
   180  	// Start operations server
   181  	err = s.startOperationsServer()
   182  	if err != nil {
   183  		return err
   184  	}
   185  
   186  	err = s.Operations.RegisterChecker("server", s)
   187  	if err != nil {
   188  		return nil
   189  	}
   190  	s.initMetrics()
   191  
   192  	// Start listening and serving
   193  	err = s.listenAndServe()
   194  	if err != nil {
   195  		err2 := s.closeDB()
   196  		if err2 != nil {
   197  			log.Errorf("Close DB failed: %s", err2)
   198  		}
   199  		return err
   200  	}
   201  
   202  	return nil
   203  }
   204  
   205  // Stop the server
   206  // WARNING: This forcefully closes the listening socket and may cause
   207  // requests in transit to fail, and so is only used for testing.
   208  // A graceful shutdown will be supported with golang 1.8.
   209  func (s *Server) Stop() error {
   210  	// Stop operations server
   211  	err := s.Operations.Stop()
   212  	if err != nil {
   213  		return err
   214  	}
   215  
   216  	if s.listener == nil {
   217  		return nil
   218  	}
   219  
   220  	_, port, err := net.SplitHostPort(s.listener.Addr().String())
   221  	if err != nil {
   222  		return err
   223  	}
   224  
   225  	err = s.closeListener()
   226  	if err != nil {
   227  		return err
   228  	}
   229  	if s.wait == nil {
   230  		return nil
   231  	}
   232  
   233  	for i := 0; i < 10; i++ {
   234  		select {
   235  		case <-s.wait:
   236  			log.Debugf("Stop: successful stop on port %s", port)
   237  			close(s.wait)
   238  			s.wait = nil
   239  			return nil
   240  		default:
   241  			log.Debugf("Stop: waiting for listener on port %s to stop", port)
   242  			time.Sleep(time.Second)
   243  		}
   244  	}
   245  	log.Debugf("Stop: timed out waiting for stop notification for port %s", port)
   246  	// make sure DB is closed
   247  	err = s.closeDB()
   248  	if err != nil {
   249  		log.Errorf("Close DB failed: %s", err)
   250  	}
   251  
   252  	return nil
   253  }
   254  
   255  // RegisterBootstrapUser registers the bootstrap user with appropriate privileges
   256  func (s *Server) RegisterBootstrapUser(user, pass, affiliation string) error {
   257  	// Initialize the config, setting defaults, etc
   258  	log.Debugf("Register bootstrap user: name=%s, affiliation=%s", user, affiliation)
   259  
   260  	if user == "" || pass == "" {
   261  		return errors.New("Empty identity name and/or pass not allowed")
   262  	}
   263  
   264  	id := CAConfigIdentity{
   265  		Name:           user,
   266  		Pass:           pass,
   267  		Type:           "client",
   268  		Affiliation:    affiliation,
   269  		MaxEnrollments: 0, // 0 means to use the server's max enrollment setting
   270  		Attrs: map[string]string{
   271  			attr.Roles:          "*",
   272  			attr.DelegateRoles:  "*",
   273  			attr.Revoker:        "true",
   274  			attr.IntermediateCA: "true",
   275  			attr.GenCRL:         "true",
   276  			attr.RegistrarAttr:  "*",
   277  			attr.AffiliationMgr: "true",
   278  		},
   279  	}
   280  
   281  	registry := &s.CA.Config.Registry
   282  	registry.Identities = append(registry.Identities, id)
   283  
   284  	log.Debugf("Registered bootstrap identity: %+v", id)
   285  	return nil
   286  }
   287  
   288  // initConfig initializes the configuration for the server
   289  func (s *Server) initConfig() (err error) {
   290  	// Home directory is current working directory by default
   291  	if s.HomeDir == "" {
   292  		s.HomeDir, err = os.Getwd()
   293  		if err != nil {
   294  			return errors.Wrap(err, "Failed to get server's home directory")
   295  		}
   296  	}
   297  	// Make home directory absolute, if not already
   298  	absoluteHomeDir, err := filepath.Abs(s.HomeDir)
   299  	if err != nil {
   300  		return fmt.Errorf("Failed to make server's home directory path absolute: %s", err)
   301  	}
   302  	s.HomeDir = absoluteHomeDir
   303  	// Create config if not set
   304  	if s.Config == nil {
   305  		s.Config = new(ServerConfig)
   306  	}
   307  	s.CA.server = s
   308  	s.CA.HomeDir = s.HomeDir
   309  	err = s.initMultiCAConfig()
   310  	if err != nil {
   311  		return err
   312  	}
   313  	revoke.SetCRLFetcher(s.fetchCRL)
   314  	// Make file names absolute
   315  	s.makeFileNamesAbsolute()
   316  
   317  	compModeStr := os.Getenv("FABRIC_CA_SERVER_COMPATIBILITY_MODE_V1_3")
   318  	if compModeStr == "" {
   319  		compModeStr = "true" // TODO: Change default to false once all clients have been updated to use the new authorization header
   320  	}
   321  
   322  	s.Config.CompMode1_3, err = strconv.ParseBool(compModeStr)
   323  	if err != nil {
   324  		return errors.WithMessage(err, "Invalid value for boolean environment variable 'FABRIC_CA_SERVER_COMPATIBILITY_MODE_V1_3'")
   325  	}
   326  
   327  	return nil
   328  }
   329  
   330  // Initialize config related to multiple CAs
   331  func (s *Server) initMultiCAConfig() (err error) {
   332  	cfg := s.Config
   333  	if cfg.CAcount != 0 && len(cfg.CAfiles) > 0 {
   334  		return errors.New("The --cacount and --cafiles options are mutually exclusive")
   335  	}
   336  	if cfg.CAcfg.Intermediate.ParentServer.URL != "" && cfg.CAcount > 0 {
   337  		return errors.New("The --cacount option is not permissible for an intermediate server; use the --cafiles option instead")
   338  	}
   339  	cfg.CAfiles, err = util.NormalizeFileList(cfg.CAfiles, s.HomeDir)
   340  	if err != nil {
   341  		return err
   342  	}
   343  	// Multi-CA related configuration initialization
   344  	s.caMap = make(map[string]*CA)
   345  	if cfg.CAcount >= 1 {
   346  		s.createDefaultCAConfigs(cfg.CAcount)
   347  	}
   348  	if len(cfg.CAfiles) != 0 {
   349  		log.Debugf("Default CA configuration, if necessary, will be used to replace missing values for additional CAs: %+v", s.Config.CAcfg)
   350  		log.Debugf("Additional CAs to be started: %s", cfg.CAfiles)
   351  		var caFiles []string
   352  		caFiles = util.NormalizeStringSlice(cfg.CAfiles)
   353  		for _, caFile := range caFiles {
   354  			err = s.loadCA(caFile, false)
   355  			if err != nil {
   356  				return err
   357  			}
   358  		}
   359  	}
   360  	return nil
   361  }
   362  
   363  func (s *Server) initDefaultCA(renew bool) error {
   364  	log.Debugf("Initializing default CA in directory %s", s.HomeDir)
   365  	ca := &s.CA
   366  	err := initCA(ca, s.HomeDir, s.CA.Config, s, renew)
   367  	if err != nil {
   368  		return err
   369  	}
   370  	err = s.addCA(ca)
   371  	if err != nil {
   372  		return err
   373  	}
   374  	log.Infof("Home directory for default CA: %s", ca.HomeDir)
   375  	return nil
   376  }
   377  
   378  // loadCAConfig loads up a CA's configuration from the specified
   379  // CA configuration file
   380  func (s *Server) loadCA(caFile string, renew bool) error {
   381  	log.Infof("Loading CA from %s", caFile)
   382  	var err error
   383  
   384  	if !util.FileExists(caFile) {
   385  		return errors.Errorf("%s file does not exist", caFile)
   386  	}
   387  
   388  	// Creating new Viper instance, to prevent any server level environment variables or
   389  	// flags from overridding the configuration options specified in the
   390  	// CA config file
   391  	cfg := &CAConfig{}
   392  	caViper := viper.New()
   393  	err = UnmarshalConfig(cfg, caViper, caFile, false)
   394  	if err != nil {
   395  		return err
   396  	}
   397  
   398  	// Need to error if no CA name provided in config file, we cannot revert to using
   399  	// the name of default CA cause CA names must be unique
   400  	caName := cfg.CA.Name
   401  	if caName == "" {
   402  		return errors.Errorf("No CA name provided in CA configuration file. CA name is required in %s", caFile)
   403  	}
   404  
   405  	// Replace missing values in CA configuration values with values from the
   406  	// defaut CA configuration
   407  	util.CopyMissingValues(s.CA.Config, cfg)
   408  
   409  	// Integers and boolean values are handled outside the util.CopyMissingValues
   410  	// because there is no way through reflect to detect if a value was explicitly
   411  	// set to 0 or false, or it is using the default value for its type. Viper is
   412  	// employed here to help detect.
   413  	if !caViper.IsSet("registry.maxenrollments") {
   414  		cfg.Registry.MaxEnrollments = s.CA.Config.Registry.MaxEnrollments
   415  	}
   416  
   417  	if !caViper.IsSet("db.tls.enabled") {
   418  		cfg.DB.TLS.Enabled = s.CA.Config.DB.TLS.Enabled
   419  	}
   420  
   421  	log.Debugf("CA configuration after checking for missing values: %+v", cfg)
   422  
   423  	ca, err := newCA(caFile, cfg, s, renew)
   424  	if err != nil {
   425  		return err
   426  	}
   427  	err = s.addCA(ca)
   428  	if err != nil {
   429  		err2 := ca.closeDB()
   430  		if err2 != nil {
   431  			log.Errorf("Close DB failed: %s", err2)
   432  		}
   433  	}
   434  	return err
   435  }
   436  
   437  // DN is the distinguished name inside a certificate
   438  type DN struct {
   439  	issuer  string
   440  	subject string
   441  }
   442  
   443  // addCA adds a CA to the server if there are no conflicts
   444  func (s *Server) addCA(ca *CA) error {
   445  	// check for conflicts
   446  	caName := ca.Config.CA.Name
   447  	for _, c := range s.caMap {
   448  		if c.Config.CA.Name == caName {
   449  			return errors.Errorf("CA name '%s' is used in '%s' and '%s'",
   450  				caName, ca.ConfigFilePath, c.ConfigFilePath)
   451  		}
   452  		err := s.compareDN(c.Config.CA.Certfile, ca.Config.CA.Certfile)
   453  		if err != nil {
   454  			return err
   455  		}
   456  	}
   457  	// no conflicts, so add it
   458  	s.caMap[caName] = ca
   459  
   460  	return nil
   461  }
   462  
   463  // closeDB closes all CA dabatases
   464  func (s *Server) closeDB() error {
   465  	log.Debugf("Closing server DBs")
   466  	// close default CA DB
   467  	err := s.CA.closeDB()
   468  	if err != nil {
   469  		return err
   470  	}
   471  	// close other CAs DB
   472  	for _, c := range s.caMap {
   473  		err = c.closeDB()
   474  		if err != nil {
   475  			return err
   476  		}
   477  	}
   478  	return nil
   479  }
   480  
   481  // createDefaultCAConfigs creates specified number of default CA configuration files
   482  func (s *Server) createDefaultCAConfigs(cacount int) error {
   483  	log.Debugf("Creating %d default CA configuration files", cacount)
   484  
   485  	cashome, err := util.MakeFileAbs("ca", s.HomeDir)
   486  	if err != nil {
   487  		return err
   488  	}
   489  
   490  	os.Mkdir(cashome, 0755)
   491  
   492  	for i := 1; i <= cacount; i++ {
   493  		cahome := fmt.Sprintf(cashome+"/ca%d", i)
   494  		cfgFileName := filepath.Join(cahome, "fabric-ca-config.yaml")
   495  
   496  		caName := fmt.Sprintf("ca%d", i)
   497  		cfg := strings.Replace(defaultCACfgTemplate, "<<<CANAME>>>", caName, 1)
   498  
   499  		cn := fmt.Sprintf("fabric-ca-server-ca%d", i)
   500  		cfg = strings.Replace(cfg, "<<<COMMONNAME>>>", cn, 1)
   501  
   502  		datasource := dbutil.GetCADataSource(s.CA.Config.DB.Type, s.CA.Config.DB.Datasource, i)
   503  		cfg = strings.Replace(cfg, "<<<DATASOURCE>>>", datasource, 1)
   504  
   505  		s.Config.CAfiles = append(s.Config.CAfiles, cfgFileName)
   506  
   507  		// Now write the file
   508  		err := os.MkdirAll(filepath.Dir(cfgFileName), 0755)
   509  		if err != nil {
   510  			return err
   511  		}
   512  
   513  		err = ioutil.WriteFile(cfgFileName, []byte(cfg), 0644)
   514  		if err != nil {
   515  			return err
   516  		}
   517  
   518  	}
   519  	return nil
   520  }
   521  
   522  // GetCA returns the CA given its name
   523  func (s *Server) GetCA(name string) (*CA, error) {
   524  	// Lookup the CA from the server
   525  	ca := s.caMap[name]
   526  	if ca == nil {
   527  		return nil, caerrors.NewHTTPErr(404, caerrors.ErrCANotFound, "CA '%s' does not exist", name)
   528  	}
   529  	return ca, nil
   530  }
   531  
   532  // Register all endpoint handlers
   533  func (s *Server) registerHandlers() {
   534  	s.mux.Use(s.cors, s.middleware)
   535  	s.registerHandler(newCAInfoEndpoint(s))
   536  	s.registerHandler(newRegisterEndpoint(s))
   537  	s.registerHandler(newEnrollEndpoint(s))
   538  	s.registerHandler(newIdemixEnrollEndpoint(s))
   539  	s.registerHandler(newIdemixCRIEndpoint(s))
   540  	s.registerHandler(newReenrollEndpoint(s))
   541  	s.registerHandler(newRevokeEndpoint(s))
   542  	s.registerHandler(newTCertEndpoint(s))
   543  	s.registerHandler(newGenCRLEndpoint(s))
   544  	s.registerHandler(newIdentitiesStreamingEndpoint(s))
   545  	s.registerHandler(newIdentitiesEndpoint(s))
   546  	s.registerHandler(newAffiliationsStreamingEndpoint(s))
   547  	s.registerHandler(newAffiliationsEndpoint(s))
   548  	s.registerHandler(newCertificateEndpoint(s))
   549  }
   550  
   551  // Register a handler
   552  func (s *Server) registerHandler(se *serverEndpoint) {
   553  	s.mux.Handle("/"+se.Path, se).Name(se.Path)
   554  	s.mux.Handle(apiPathPrefix+se.Path, se).Name(se.Path)
   555  }
   556  
   557  func (s *Server) middleware(next http.Handler) http.Handler {
   558  	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   559  		metrics := httpsnoop.CaptureMetrics(next, w, r)
   560  		apiName := s.getAPIName(r)
   561  		caName := s.getCAName()
   562  		s.recordMetrics(metrics.Duration, caName, apiName, strconv.Itoa(metrics.Code))
   563  	})
   564  }
   565  
   566  func (s *Server) cors(next http.Handler) http.Handler {
   567  	if s.Config.CORS.Enabled {
   568  		return ghandlers.CORS(ghandlers.AllowedOrigins(s.Config.CORS.Origins))(next)
   569  	}
   570  	return next
   571  }
   572  
   573  func (s *Server) getAPIName(r *http.Request) string {
   574  	var apiName string
   575  	var match gmux.RouteMatch
   576  	if s.mux.Match(r, &match) {
   577  		apiName = match.Route.GetName()
   578  	}
   579  	return apiName
   580  }
   581  
   582  func (s *Server) getCAName() string {
   583  	return s.CA.Config.CA.Name
   584  }
   585  
   586  func (s *Server) recordMetrics(duration time.Duration, caName, apiName, statusCode string) {
   587  	s.Metrics.APICounter.With("ca_name", caName, "api_name", apiName, "status_code", statusCode).Add(1)
   588  	s.Metrics.APIDuration.With("ca_name", caName, "api_name", apiName, "status_code", statusCode).Observe(duration.Seconds())
   589  }
   590  
   591  // Starting listening and serving
   592  func (s *Server) listenAndServe() (err error) {
   593  
   594  	var listener net.Listener
   595  	var clientAuth tls.ClientAuthType
   596  	var ok bool
   597  
   598  	c := s.Config
   599  
   600  	// Set default listening address and port
   601  	if c.Address == "" {
   602  		c.Address = DefaultServerAddr
   603  	}
   604  	if c.Port == 0 {
   605  		c.Port = DefaultServerPort
   606  	}
   607  	addr := net.JoinHostPort(c.Address, strconv.Itoa(c.Port))
   608  	var addrStr string
   609  
   610  	if c.TLS.Enabled {
   611  		log.Debug("TLS is enabled")
   612  		addrStr = fmt.Sprintf("https://%s", addr)
   613  
   614  		// If key file is specified and it does not exist or its corresponding certificate file does not exist
   615  		// then need to return error and not start the server. The TLS key file is specified when the user
   616  		// wants the server to use custom tls key and cert and don't want server to auto generate its own. So,
   617  		// when the key file is specified, it must exist on the file system
   618  		if c.TLS.KeyFile != "" {
   619  			if !util.FileExists(c.TLS.KeyFile) {
   620  				return fmt.Errorf("File specified by 'tls.keyfile' does not exist: %s", c.TLS.KeyFile)
   621  			}
   622  			if !util.FileExists(c.TLS.CertFile) {
   623  				return fmt.Errorf("File specified by 'tls.certfile' does not exist: %s", c.TLS.CertFile)
   624  			}
   625  			log.Debugf("TLS Certificate: %s, TLS Key: %s", c.TLS.CertFile, c.TLS.KeyFile)
   626  		} else if !util.FileExists(c.TLS.CertFile) {
   627  			// TLS key file is not specified, generate TLS key and cert if they are not already generated
   628  			err = s.autoGenerateTLSCertificateKey()
   629  			if err != nil {
   630  				return fmt.Errorf("Failed to automatically generate TLS certificate and key: %s", err)
   631  			}
   632  		}
   633  
   634  		cer, err := util.LoadX509KeyPair(c.TLS.CertFile, c.TLS.KeyFile, s.csp)
   635  		if err != nil {
   636  			return err
   637  		}
   638  
   639  		if c.TLS.ClientAuth.Type == "" {
   640  			c.TLS.ClientAuth.Type = defaultClientAuth
   641  		}
   642  
   643  		log.Debugf("Client authentication type requested: %s", c.TLS.ClientAuth.Type)
   644  
   645  		authType := strings.ToLower(c.TLS.ClientAuth.Type)
   646  		if clientAuth, ok = clientAuthTypes[authType]; !ok {
   647  			return errors.New("Invalid client auth type provided")
   648  		}
   649  
   650  		var certPool *x509.CertPool
   651  		if authType != defaultClientAuth {
   652  			certPool, err = LoadPEMCertPool(c.TLS.ClientAuth.CertFiles)
   653  			if err != nil {
   654  				return err
   655  			}
   656  		}
   657  
   658  		config := &tls.Config{
   659  			Certificates: []tls.Certificate{*cer},
   660  			ClientAuth:   clientAuth,
   661  			ClientCAs:    certPool,
   662  			MinVersion:   tls.VersionTLS12,
   663  			MaxVersion:   tls.VersionTLS12,
   664  			CipherSuites: stls.DefaultCipherSuites,
   665  		}
   666  
   667  		listener, err = tls.Listen("tcp", addr, config)
   668  		if err != nil {
   669  			return errors.Wrapf(err, "TLS listen failed for %s", addrStr)
   670  		}
   671  	} else {
   672  		addrStr = fmt.Sprintf("http://%s", addr)
   673  		listener, err = net.Listen("tcp", addr)
   674  		if err != nil {
   675  			return errors.Wrapf(err, "TCP listen failed for %s", addrStr)
   676  		}
   677  	}
   678  	s.listener = listener
   679  	log.Infof("Listening on %s", addrStr)
   680  
   681  	err = s.checkAndEnableProfiling()
   682  	if err != nil {
   683  		s.closeListener()
   684  		return errors.WithMessage(err, "TCP listen for profiling failed")
   685  	}
   686  
   687  	// Start serving requests, either blocking or non-blocking
   688  	if s.BlockingStart {
   689  		return s.serve()
   690  	}
   691  	s.wait = make(chan bool)
   692  	go s.serve()
   693  
   694  	return nil
   695  }
   696  
   697  func (s *Server) serve() error {
   698  	listener := s.listener
   699  	if listener == nil {
   700  		// This can happen as follows:
   701  		// 1) listenAndServe above is called with s.BlockingStart set to false
   702  		//    and returns to the caller
   703  		// 2) the caller immediately calls s.Stop, which sets s.listener to nil
   704  		// 3) the go routine runs and calls this function
   705  		// So this prevents the panic which was reported in
   706  		// in https://jira.hyperledger.org/browse/FAB-3100.
   707  		return nil
   708  	}
   709  
   710  	s.serveError = http.Serve(listener, s.mux)
   711  
   712  	log.Errorf("Server has stopped serving: %s", s.serveError)
   713  	s.closeListener()
   714  	err := s.closeDB()
   715  	if err != nil {
   716  		log.Errorf("Close DB failed: %s", err)
   717  	}
   718  	if s.wait != nil {
   719  		s.wait <- true
   720  	}
   721  	return s.serveError
   722  }
   723  
   724  // HealthCheck pings the database to determine if it is reachable
   725  func (s *Server) HealthCheck(ctx context.Context) error {
   726  	return s.db.PingContext(ctx)
   727  }
   728  
   729  // checkAndEnableProfiling checks for FABRIC_CA_SERVER_PROFILE_PORT env variable
   730  // if it is set, starts listening for profiling requests at the port specified
   731  // by the environment variable
   732  func (s *Server) checkAndEnableProfiling() error {
   733  	// Start listening for profile requests
   734  	pport := os.Getenv(fabricCAServerProfilePort)
   735  	if pport != "" {
   736  		iport, err := strconv.Atoi(pport)
   737  		if err != nil || iport < 0 {
   738  			log.Warningf("Profile port specified by the %s environment variable is not a valid port, not enabling profiling",
   739  				fabricCAServerProfilePort)
   740  		} else {
   741  			addr := net.JoinHostPort(s.Config.Address, pport)
   742  			listener, err1 := net.Listen("tcp", addr)
   743  			log.Infof("Profiling enabled; listening for profile requests on port %s", pport)
   744  			if err1 != nil {
   745  				return err1
   746  			}
   747  			go func() {
   748  				log.Debugf("Profiling enabled; waiting for profile requests on port %s", pport)
   749  				err := http.Serve(listener, nil)
   750  				log.Errorf("Stopped serving for profiling requests on port %s: %s", pport, err)
   751  			}()
   752  		}
   753  	}
   754  	return nil
   755  }
   756  
   757  // Make all file names in the config absolute
   758  func (s *Server) makeFileNamesAbsolute() error {
   759  	log.Debug("Making server filenames absolute")
   760  	err := stls.AbsTLSServer(&s.Config.TLS, s.HomeDir)
   761  	if err != nil {
   762  		return err
   763  	}
   764  	return nil
   765  }
   766  
   767  // closeListener closes the listening endpoint
   768  func (s *Server) closeListener() error {
   769  	s.mutex.Lock()
   770  	defer s.mutex.Unlock()
   771  
   772  	if s.listener == nil {
   773  		msg := fmt.Sprintf("Stop: listener was already closed")
   774  		log.Debugf(msg)
   775  		return errors.New(msg)
   776  	}
   777  
   778  	_, port, err := net.SplitHostPort(s.listener.Addr().String())
   779  	if err != nil {
   780  		return err
   781  	}
   782  
   783  	err = s.listener.Close()
   784  	if err != nil {
   785  		log.Debugf("Stop: failed to close listener on port %s: %s", port, err)
   786  		return err
   787  	}
   788  
   789  	log.Debugf("Stop: successfully closed listener on port %s", port)
   790  	s.listener = nil
   791  
   792  	return nil
   793  }
   794  
   795  func (s *Server) compareDN(existingCACertFile, newCACertFile string) error {
   796  	log.Debugf("Comparing DNs from certificates: %s and %s", existingCACertFile, newCACertFile)
   797  	existingDN, err := s.loadDNFromCertFile(existingCACertFile)
   798  	if err != nil {
   799  		return err
   800  	}
   801  
   802  	newDN, err := s.loadDNFromCertFile(newCACertFile)
   803  	if err != nil {
   804  		return err
   805  	}
   806  
   807  	err = existingDN.equal(newDN)
   808  	if err != nil {
   809  		return errors.Wrapf(err, "a CA already exists with the following subject distinguished name: %s", newDN.subject)
   810  	}
   811  	return nil
   812  }
   813  
   814  // Read the CRL from body of http response
   815  func (s *Server) fetchCRL(r io.Reader) ([]byte, error) {
   816  	crlSizeLimit := s.Config.CRLSizeLimit
   817  	log.Debugf("CRL size limit is %d bytes", crlSizeLimit)
   818  
   819  	crl := make([]byte, crlSizeLimit)
   820  
   821  	crl, err := util.Read(r, crl)
   822  	if err != nil {
   823  		return nil, errors.WithMessage(err, fmt.Sprintf("Error reading CRL with max buffer size of %d", crlSizeLimit))
   824  	}
   825  
   826  	return crl, nil
   827  }
   828  
   829  func (s *Server) loadDNFromCertFile(certFile string) (*DN, error) {
   830  	log.Debugf("Loading DNs from certificate %s", certFile)
   831  	cert, err := util.GetX509CertificateFromPEMFile(certFile)
   832  	if err != nil {
   833  		return nil, err
   834  	}
   835  	distinguishedName := &DN{
   836  		issuer:  cert.Issuer.String(),
   837  		subject: cert.Subject.String(),
   838  	}
   839  	return distinguishedName, nil
   840  }
   841  
   842  func (s *Server) autoGenerateTLSCertificateKey() error {
   843  	log.Debug("TLS enabled but either certificate or key file does not exist, automatically generating TLS credentials")
   844  
   845  	clientCfg := &ClientConfig{
   846  		CSP: s.CA.Config.CSP,
   847  	}
   848  	client := Client{
   849  		HomeDir: s.HomeDir,
   850  		Config:  clientCfg,
   851  	}
   852  
   853  	// Generate CSR that will be used to create the TLS certificate
   854  	csrReq := s.Config.CAcfg.CSR
   855  	csrReq.CA = nil // Not requesting a CA certificate
   856  	hostname := util.Hostname()
   857  	log.Debugf("TLS CSR: %+v\n", csrReq)
   858  
   859  	// Can't use the same CN as the signing certificate CN (default: fabric-ca-server) otherwise no AKI is generated
   860  	csr, _, err := client.GenCSR(&csrReq, hostname)
   861  	if err != nil {
   862  		return fmt.Errorf("Failed to generate CSR: %s", err)
   863  	}
   864  
   865  	// Use the 'tls' profile that will return a certificate with the appropriate extensions
   866  	req := signer.SignRequest{
   867  		Profile: "tls",
   868  		Request: string(csr),
   869  	}
   870  
   871  	// Use default CA to get back signed TLS certificate
   872  	cert, err := s.CA.enrollSigner.Sign(req)
   873  	if err != nil {
   874  		return fmt.Errorf("Failed to generate TLS certificate: %s", err)
   875  	}
   876  
   877  	// Write the TLS certificate to the file system
   878  	err = ioutil.WriteFile(s.Config.TLS.CertFile, cert, 0644)
   879  	if err != nil {
   880  		return fmt.Errorf("Failed to write TLS certificate: %s", err)
   881  	}
   882  
   883  	// If c.TLS.Keyfile is specified then print out the key file path. If key file is not provided, then key generation is
   884  	// handled by BCCSP then only print out cert file path
   885  	c := s.Config
   886  	log.Debugf("Generated TLS Certificate: %s", c.TLS.CertFile)
   887  
   888  	return nil
   889  }
   890  
   891  // Log is a function required to meet the interface required by statsd
   892  func (s *Server) Log(keyvals ...interface{}) error {
   893  	log.Warning(keyvals...)
   894  	return nil
   895  }
   896  
   897  func (dn *DN) equal(checkDN *DN) error {
   898  	log.Debugf("Check to see if two DNs are equal - %+v and %+v", dn, checkDN)
   899  	if dn.issuer == checkDN.issuer {
   900  		log.Debug("Issuer distinguished name already in use, checking for unique subject distinguished name")
   901  		if dn.subject == checkDN.subject {
   902  			return errors.New("Both issuer and subject distinguished name are already in use")
   903  		}
   904  	}
   905  	return nil
   906  }