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