github.com/silveraid/fabric-ca@v1.1.0-preview.0.20180127000700-71974f53ab08/lib/server.go (about)

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