gitee.com/zhaochuninhefei/fabric-ca-gm@v0.0.2/cmd/fabric-ca-server/config.go (about)

     1  /*
     2  Copyright IBM Corp. All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package main
     8  
     9  import (
    10  	"io/ioutil"
    11  	"os"
    12  	"path/filepath"
    13  	"strings"
    14  
    15  	calog "gitee.com/zhaochuninhefei/fabric-ca-gm/internal/pkg/log"
    16  	"gitee.com/zhaochuninhefei/fabric-ca-gm/internal/pkg/util"
    17  	"gitee.com/zhaochuninhefei/fabric-ca-gm/lib"
    18  	"gitee.com/zhaochuninhefei/fabric-ca-gm/lib/metadata"
    19  	"gitee.com/zhaochuninhefei/zcgolog/zclog"
    20  	"github.com/pkg/errors"
    21  )
    22  
    23  const (
    24  	longName     = "Hyperledger Fabric Certificate Authority Server"
    25  	shortName    = "fabric-ca server"
    26  	cmdName      = "fabric-ca-server"
    27  	envVarPrefix = "FABRIC_CA_SERVER"
    28  	homeEnvVar   = "FABRIC_CA_SERVER_HOME"
    29  )
    30  
    31  const (
    32  	defaultCfgTemplate = `#############################################################################
    33  #   This is a configuration file for the fabric-ca-server command.
    34  #
    35  #   COMMAND LINE ARGUMENTS AND ENVIRONMENT VARIABLES
    36  #   ------------------------------------------------
    37  #   Each configuration element can be overridden via command line
    38  #   arguments or environment variables.  The precedence for determining
    39  #   the value of each element is as follows:
    40  #   1) command line argument
    41  #      Examples:
    42  #      a) --port 443
    43  #         To set the listening port
    44  #      b) --ca.keyfile ../mykey.pem
    45  #         To set the "keyfile" element in the "ca" section below;
    46  #         note the '.' separator character.
    47  #   2) environment variable
    48  #      Examples:
    49  #      a) FABRIC_CA_SERVER_PORT=443
    50  #         To set the listening port
    51  #      b) FABRIC_CA_SERVER_CA_KEYFILE="../mykey.pem"
    52  #         To set the "keyfile" element in the "ca" section below;
    53  #         note the '_' separator character.
    54  #   3) configuration file
    55  #   4) default value (if there is one)
    56  #      All default values are shown beside each element below.
    57  #
    58  #   FILE NAME ELEMENTS
    59  #   ------------------
    60  #   The value of all fields whose name ends with "file" or "files" are
    61  #   name or names of other files.
    62  #   For example, see "tls.certfile" and "tls.clientauth.certfiles".
    63  #   The value of each of these fields can be a simple filename, a
    64  #   relative path, or an absolute path.  If the value is not an
    65  #   absolute path, it is interpreted as being relative to the location
    66  #   of this configuration file.
    67  #
    68  #############################################################################
    69  
    70  # Version of config file
    71  version: <<<VERSION>>>
    72  
    73  # Server's listening port (default: 7054)
    74  port: 7054
    75  
    76  # Cross-Origin Resource Sharing (CORS)
    77  cors:
    78      enabled: false
    79      origins:
    80        - "*"
    81  
    82  # Enables debug logging (default: false)
    83  debug: false
    84  
    85  # Size limit of an acceptable CRL in bytes (default: 512000)
    86  crlsizelimit: 512000
    87  
    88  #############################################################################
    89  #  TLS section for the server's listening port
    90  #
    91  #  The following types are supported for client authentication: NoClientCert,
    92  #  RequestClientCert, RequireAnyClientCert, VerifyClientCertIfGiven,
    93  #  and RequireAndVerifyClientCert.
    94  #
    95  #  Certfiles is a list of root certificate authorities that the server uses
    96  #  when verifying client certificates.
    97  #############################################################################
    98  tls:
    99    # Enable TLS (default: false)
   100    enabled: false
   101    # TLS for the server's listening port
   102    certfile:
   103    keyfile:
   104    clientauth:
   105      type: noclientcert
   106      certfiles:
   107  
   108  #############################################################################
   109  #  The CA section contains information related to the Certificate Authority
   110  #  including the name of the CA, which should be unique for all members
   111  #  of a blockchain network.  It also includes the key and certificate files
   112  #  used when issuing enrollment certificates (ECerts).
   113  #  The chainfile (if it exists) contains the certificate chain which
   114  #  should be trusted for this CA, where the 1st in the chain is always the
   115  #  root CA certificate.
   116  #############################################################################
   117  ca:
   118    # Name of this CA
   119    name:
   120    # Key file (is only used to import a private key into BCCSP)
   121    keyfile:
   122    # Certificate file (default: ca-cert.pem)
   123    certfile:
   124    # Chain file
   125    chainfile:
   126    # Ignore Certificate Expiration in the case of re-enroll
   127    reenrollIgnoreCertExpiry: false
   128  
   129  #############################################################################
   130  #  The gencrl REST endpoint is used to generate a CRL that contains revoked
   131  #  certificates. This section contains configuration options that are used
   132  #  during gencrl request processing.
   133  #############################################################################
   134  crl:
   135    # Specifies expiration for the generated CRL. The number of hours
   136    # specified by this property is added to the UTC time, the resulting time
   137    # is used to set the 'Next Update' date of the CRL.
   138    expiry: 24h
   139  
   140  #############################################################################
   141  #  The registry section controls how the fabric-ca-server does two things:
   142  #  1) authenticates enrollment requests which contain a username and password
   143  #     (also known as an enrollment ID and secret).
   144  #  2) once authenticated, retrieves the identity's attribute names and values.
   145  #     These attributes are useful for making access control decisions in
   146  #     chaincode.
   147  #  There are two main configuration options:
   148  #  1) The fabric-ca-server is the registry.
   149  #     This is true if "ldap.enabled" in the ldap section below is false.
   150  #  2) An LDAP server is the registry, in which case the fabric-ca-server
   151  #     calls the LDAP server to perform these tasks.
   152  #     This is true if "ldap.enabled" in the ldap section below is true,
   153  #     which means this "registry" section is ignored.
   154  #############################################################################
   155  registry:
   156    # Maximum number of times a password/secret can be reused for enrollment
   157    # (default: -1, which means there is no limit)
   158    maxenrollments: -1
   159  
   160    # Contains identity information which is used when LDAP is disabled
   161    identities:
   162       - name: <<<ADMIN>>>
   163         pass: <<<ADMINPW>>>
   164         type: client
   165         affiliation: ""
   166         attrs:
   167            hf.Registrar.Roles: "*"
   168            hf.Registrar.DelegateRoles: "*"
   169            hf.Revoker: true
   170            hf.IntermediateCA: true
   171            hf.GenCRL: true
   172            hf.Registrar.Attributes: "*"
   173            hf.AffiliationMgr: true
   174  
   175  #############################################################################
   176  #  Database section
   177  #  Supported types are: "sqlite3", "postgres", and "mysql".
   178  #  The datasource value depends on the type.
   179  #  If the type is "sqlite3", the datasource value is a file name to use
   180  #  as the database store.  Since "sqlite3" is an embedded database, it
   181  #  may not be used if you want to run the fabric-ca-server in a cluster.
   182  #  To run the fabric-ca-server in a cluster, you must choose "postgres"
   183  #  or "mysql".
   184  #############################################################################
   185  db:
   186    type: sqlite3
   187    datasource: fabric-ca-server.db
   188    tls:
   189        enabled: false
   190        certfiles:
   191        client:
   192          certfile:
   193          keyfile:
   194  
   195  #############################################################################
   196  #  LDAP section
   197  #  If LDAP is enabled, the fabric-ca-server calls LDAP to:
   198  #  1) authenticate enrollment ID and secret (i.e. username and password)
   199  #     for enrollment requests;
   200  #  2) To retrieve identity attributes
   201  #############################################################################
   202  ldap:
   203     # Enables or disables the LDAP client (default: false)
   204     # If this is set to true, the "registry" section is ignored.
   205     enabled: false
   206     # The URL of the LDAP server
   207     url: ldap://<adminDN>:<adminPassword>@<host>:<port>/<base>
   208     # TLS configuration for the client connection to the LDAP server
   209     tls:
   210        certfiles:
   211        client:
   212           certfile:
   213           keyfile:
   214     # Attribute related configuration for mapping from LDAP entries to Fabric CA attributes
   215     attribute:
   216        # 'names' is an array of strings containing the LDAP attribute names which are
   217        # requested from the LDAP server for an LDAP identity's entry
   218        names: ['uid','member']
   219        # The 'converters' section is used to convert an LDAP entry to the value of
   220        # a fabric CA attribute.
   221        # For example, the following converts an LDAP 'uid' attribute
   222        # whose value begins with 'revoker' to a fabric CA attribute
   223        # named "hf.Revoker" with a value of "true" (because the boolean expression
   224        # evaluates to true).
   225        #    converters:
   226        #       - name: hf.Revoker
   227        #         value: attr("uid") =~ "revoker*"
   228        converters:
   229           - name:
   230             value:
   231        # The 'maps' section contains named maps which may be referenced by the 'map'
   232        # function in the 'converters' section to map LDAP responses to arbitrary values.
   233        # For example, assume a user has an LDAP attribute named 'member' which has multiple
   234        # values which are each a distinguished name (i.e. a DN). For simplicity, assume the
   235        # values of the 'member' attribute are 'dn1', 'dn2', and 'dn3'.
   236        # Further assume the following configuration.
   237        #    converters:
   238        #       - name: hf.Registrar.Roles
   239        #         value: map(attr("member"),"groups")
   240        #    maps:
   241        #       groups:
   242        #          - name: dn1
   243        #            value: peer
   244        #          - name: dn2
   245        #            value: client
   246        # The value of the user's 'hf.Registrar.Roles' attribute is then computed to be
   247        # "peer,client,dn3".  This is because the value of 'attr("member")' is
   248        # "dn1,dn2,dn3", and the call to 'map' with a 2nd argument of
   249        # "group" replaces "dn1" with "peer" and "dn2" with "client".
   250        maps:
   251           groups:
   252              - name:
   253                value:
   254  
   255  #############################################################################
   256  # Affiliations section. Fabric CA server can be bootstrapped with the
   257  # affiliations specified in this section. Affiliations are specified as maps.
   258  # For example:
   259  #   businessunit1:
   260  #     department1:
   261  #       - team1
   262  #   businessunit2:
   263  #     - department2
   264  #     - department3
   265  #
   266  # Affiliations are hierarchical in nature. In the above example,
   267  # department1 (used as businessunit1.department1) is the child of businessunit1.
   268  # team1 (used as businessunit1.department1.team1) is the child of department1.
   269  # department2 (used as businessunit2.department2) and department3 (businessunit2.department3)
   270  # are children of businessunit2.
   271  # Note: Affiliations are case sensitive except for the non-leaf affiliations
   272  # (like businessunit1, department1, businessunit2) that are specified in the configuration file,
   273  # which are always stored in lower case.
   274  #############################################################################
   275  affiliations:
   276     org1:
   277        - department1
   278        - department2
   279     org2:
   280        - department1
   281  
   282  #############################################################################
   283  #  Signing section
   284  #
   285  #  The "default" subsection is used to sign enrollment certificates;
   286  #  the default expiration ("expiry" field) is "8760h", which is 1 year in hours.
   287  #
   288  #  The "ca" profile subsection is used to sign intermediate CA certificates;
   289  #  the default expiration ("expiry" field) is "43800h" which is 5 years in hours.
   290  #  Note that "isca" is true, meaning that it issues a CA certificate.
   291  #  A maxpathlen of 0 means that the intermediate CA cannot issue other
   292  #  intermediate CA certificates, though it can still issue end entity certificates.
   293  #  (See RFC 5280, section 4.2.1.9)
   294  #
   295  #  The "tls" profile subsection is used to sign TLS certificate requests;
   296  #  the default expiration ("expiry" field) is "8760h", which is 1 year in hours.
   297  #############################################################################
   298  signing:
   299      default:
   300        usage:
   301          - digital signature
   302        expiry: 438000h
   303      profiles:
   304        ca:
   305           usage:
   306             - cert sign
   307             - crl sign
   308           expiry: 700800h
   309           caconstraint:
   310             isca: true
   311             maxpathlen: 0
   312        tls:
   313           usage:
   314              - signing
   315              - key encipherment
   316              - server auth
   317              - client auth
   318              - key agreement
   319           expiry: 438000h
   320  
   321  ###########################################################################
   322  #  Certificate Signing Request (CSR) section.
   323  #  This controls the creation of the root CA certificate.
   324  #  The expiration for the root CA certificate is configured with the
   325  #  "ca.expiry" field below, whose default value is "131400h" which is
   326  #  15 years in hours.
   327  #  The pathlength field is used to limit CA certificate hierarchy as described
   328  #  in section 4.2.1.9 of RFC 5280.
   329  #  Examples:
   330  #  1) No pathlength value means no limit is requested.
   331  #  2) pathlength == 1 means a limit of 1 is requested which is the default for
   332  #     a root CA.  This means the root CA can issue intermediate CA certificates,
   333  #     but these intermediate CAs may not in turn issue other CA certificates
   334  #     though they can still issue end entity certificates.
   335  #  3) pathlength == 0 means a limit of 0 is requested;
   336  #     this is the default for an intermediate CA, which means it can not issue
   337  #     CA certificates though it can still issue end entity certificates.
   338  ###########################################################################
   339  csr:
   340     cn: <<<COMMONNAME>>>
   341     keyrequest:
   342       algo: SM2
   343       size: 256
   344     names:
   345        - C: CN
   346          ST: "Anhui"
   347          L: "Hefei"
   348          O: gcsoft
   349          OU: gcbaas
   350     hosts:
   351       - <<<MYHOST>>>
   352       - localhost
   353     ca:
   354        expiry: 876000h
   355        pathlength: <<<PATHLENGTH>>>
   356  
   357  ###########################################################################
   358  # Each CA can issue both X509 enrollment certificate as well as Idemix
   359  # Credential. This section specifies configuration for the issuer component
   360  # that is responsible for issuing Idemix credentials.
   361  ###########################################################################
   362  idemix:
   363    # Specifies pool size for revocation handles. A revocation handle is an unique identifier of an
   364    # Idemix credential. The issuer will create a pool revocation handles of this specified size. When
   365    # a credential is requested, issuer will get handle from the pool and assign it to the credential.
   366    # Issuer will repopulate the pool with new handles when the last handle in the pool is used.
   367    # A revocation handle and credential revocation information (CRI) are used to create non revocation proof
   368    # by the prover to prove to the verifier that her credential is not revoked.
   369    rhpoolsize: 1000
   370  
   371    # The Idemix credential issuance is a two step process. First step is to  get a nonce from the issuer
   372    # and second step is send credential request that is constructed using the nonce to the isuser to
   373    # request a credential. This configuration property specifies expiration for the nonces. By default is
   374    # nonces expire after 15 seconds. The value is expressed in the time.Duration format (see https://golang.org/pkg/time/#ParseDuration).
   375    nonceexpiration: 15s
   376  
   377    # Specifies interval at which expired nonces are removed from datastore. Default value is 15 minutes.
   378    #  The value is expressed in the time.Duration format (see https://golang.org/pkg/time/#ParseDuration)
   379    noncesweepinterval: 15m
   380  
   381  #############################################################################
   382  # BCCSP (BlockChain Crypto Service Provider) section is used to select which
   383  # crypto library implementation to use
   384  #############################################################################
   385  bccsp:
   386      default: SW
   387      sw:
   388          hash: SM3
   389          security: 256
   390          filekeystore:
   391              # The directory used for the software file-based keystore
   392              keystore: msp/keystore
   393  
   394  #############################################################################
   395  # Multi CA section
   396  #
   397  # Each Fabric CA server contains one CA by default.  This section is used
   398  # to configure multiple CAs in a single server.
   399  #
   400  # 1) --cacount <number-of-CAs>
   401  # Automatically generate <number-of-CAs> non-default CAs.  The names of these
   402  # additional CAs are "ca1", "ca2", ... "caN", where "N" is <number-of-CAs>
   403  # This is particularly useful in a development environment to quickly set up
   404  # multiple CAs. Note that, this config option is not applicable to intermediate CA server
   405  # i.e., Fabric CA server that is started with intermediate.parentserver.url config
   406  # option (-u command line option)
   407  #
   408  # 2) --cafiles <CA-config-files>
   409  # For each CA config file in the list, generate a separate signing CA.  Each CA
   410  # config file in this list MAY contain all of the same elements as are found in
   411  # the server config file except port, debug, and tls sections.
   412  #
   413  # Examples:
   414  # fabric-ca-server start -b admin:adminpw --cacount 2
   415  #
   416  # fabric-ca-server start -b admin:adminpw --cafiles ca/ca1/fabric-ca-server-config.yaml
   417  # --cafiles ca/ca2/fabric-ca-server-config.yaml
   418  #
   419  #############################################################################
   420  
   421  cacount:
   422  
   423  cafiles:
   424  
   425  #############################################################################
   426  # Intermediate CA section
   427  #
   428  # The relationship between servers and CAs is as follows:
   429  #   1) A single server process may contain or function as one or more CAs.
   430  #      This is configured by the "Multi CA section" above.
   431  #   2) Each CA is either a root CA or an intermediate CA.
   432  #   3) Each intermediate CA has a parent CA which is either a root CA or another intermediate CA.
   433  #
   434  # This section pertains to configuration of #2 and #3.
   435  # If the "intermediate.parentserver.url" property is set,
   436  # then this is an intermediate CA with the specified parent
   437  # CA.
   438  #
   439  # parentserver section
   440  #    url - The URL of the parent server
   441  #    caname - Name of the CA to enroll within the server
   442  #
   443  # enrollment section used to enroll intermediate CA with parent CA
   444  #    profile - Name of the signing profile to use in issuing the certificate
   445  #    label - Label to use in HSM operations
   446  #
   447  # tls section for secure socket connection
   448  #   certfiles - PEM-encoded list of trusted root certificate files
   449  #   client:
   450  #     certfile - PEM-encoded certificate file for when client authentication
   451  #     is enabled on server
   452  #     keyfile - PEM-encoded key file for when client authentication
   453  #     is enabled on server
   454  #############################################################################
   455  intermediate:
   456    parentserver:
   457      url:
   458      caname:
   459  
   460    enrollment:
   461      hosts:
   462      profile:
   463      label:
   464  
   465    tls:
   466      certfiles:
   467      client:
   468        certfile:
   469        keyfile:
   470  
   471  #############################################################################
   472  # CA configuration section
   473  #
   474  # Configure the number of incorrect password attempts are allowed for
   475  # identities. By default, the value of 'passwordattempts' is 10, which
   476  # means that 10 incorrect password attempts can be made before an identity get
   477  # locked out.
   478  #############################################################################
   479  cfg:
   480    identities:
   481      passwordattempts: 10
   482  
   483  ###############################################################################
   484  #
   485  #    Operations section
   486  #
   487  ###############################################################################
   488  operations:
   489      # host and port for the operations server
   490      listenAddress: 127.0.0.1:9443
   491  
   492      # TLS configuration for the operations endpoint
   493      tls:
   494          # TLS enabled
   495          enabled: false
   496  
   497          # path to PEM encoded server certificate for the operations server
   498          cert:
   499              file:
   500  
   501          # path to PEM encoded server key for the operations server
   502          key:
   503              file:
   504  
   505          # require client certificate authentication to access all resources
   506          clientAuthRequired: false
   507  
   508          # paths to PEM encoded ca certificates to trust for client authentication
   509          clientRootCAs:
   510              files: []
   511  
   512  ###############################################################################
   513  #
   514  #    Metrics section
   515  #
   516  ###############################################################################
   517  metrics:
   518      # statsd, prometheus, or disabled
   519      provider: disabled
   520  
   521      # statsd configuration
   522      statsd:
   523          # network type: tcp or udp
   524          network: udp
   525  
   526          # statsd server address
   527          address: 127.0.0.1:8125
   528  
   529          # the interval at which locally cached counters and gauges are pushed
   530          # to statsd; timings are pushed immediately
   531          writeInterval: 10s
   532  
   533          # prefix is prepended to all emitted statsd metrics
   534          prefix: server
   535  `
   536  )
   537  
   538  // Initialize config
   539  func (s *ServerCmd) configInit() (err error) {
   540  	if !s.configRequired() {
   541  		return nil
   542  	}
   543  
   544  	s.cfgFileName, s.homeDirectory, err = util.ValidateAndReturnAbsConf(s.cfgFileName, s.homeDirectory, cmdName)
   545  	if err != nil {
   546  		return err
   547  	}
   548  
   549  	s.myViper.AutomaticEnv() // read in environment variables that match
   550  	logLevel := s.myViper.GetString("loglevel")
   551  	debug := s.myViper.GetBool("debug")
   552  	calog.SetLogLevel(logLevel, debug)
   553  
   554  	zclog.Debugf("===== Home directory: %s", s.homeDirectory)
   555  
   556  	// If the config file doesn't exist, create a default one
   557  	if !util.FileExists(s.cfgFileName) {
   558  		err = s.createDefaultConfigFile()
   559  		if err != nil {
   560  			return errors.WithMessage(err, "Failed to create default configuration file")
   561  		}
   562  		zclog.Infof("===== Created default configuration file at %s", s.cfgFileName)
   563  	} else {
   564  		zclog.Infof("===== Configuration file location: %s", s.cfgFileName)
   565  	}
   566  
   567  	// Read the config
   568  	err = lib.UnmarshalConfig(s.cfg, s.myViper, s.cfgFileName, true)
   569  	if err != nil {
   570  		return err
   571  	}
   572  
   573  	// Read operations tls files
   574  	if s.myViper.GetBool("operations.tls.enabled") {
   575  		cf := s.myViper.GetString("operations.tls.cert.file")
   576  		if cf == "" {
   577  			cf = s.cfg.Operations.TLS.CertFile
   578  		}
   579  		if !filepath.IsAbs(cf) {
   580  			cf = filepath.Join(s.homeDirectory, cf)
   581  		}
   582  		if !util.FileExists(cf) {
   583  			return errors.Errorf("failed to read certificate file: %s", cf)
   584  		}
   585  		s.cfg.Operations.TLS.CertFile = cf
   586  
   587  		kf := s.myViper.GetString("operations.tls.key.file")
   588  		if kf == "" {
   589  			kf = s.cfg.Operations.TLS.KeyFile
   590  		}
   591  		if !filepath.IsAbs(kf) {
   592  			kf = filepath.Join(s.homeDirectory, kf)
   593  		}
   594  		if !util.FileExists(kf) {
   595  			return errors.Errorf("failed to read key file: %s", kf)
   596  		}
   597  		s.cfg.Operations.TLS.KeyFile = kf
   598  	}
   599  
   600  	// The pathlength field controls how deep the CA hierarchy when requesting
   601  	// certificates. If it is explicitly set to 0, set the PathLenZero field to
   602  	// true as CFSSL expects.
   603  	pl := "csr.ca.pathlength"
   604  	if s.myViper.IsSet(pl) && s.myViper.GetInt(pl) == 0 {
   605  		s.cfg.CAcfg.CSR.CA.PathLenZero = true
   606  	}
   607  	// The maxpathlen field controls how deep the CA hierarchy when issuing
   608  	// a CA certificate. If it is explicitly set to 0, set the PathLenZero
   609  	// field to true as CFSSL expects.
   610  	pl = "signing.profiles.ca.caconstraint.maxpathlen"
   611  	if s.myViper.IsSet(pl) && s.myViper.GetInt(pl) == 0 {
   612  		s.cfg.CAcfg.Signing.Profiles["ca"].CAConstraint.MaxPathLenZero = true
   613  	}
   614  
   615  	return nil
   616  }
   617  
   618  func (s *ServerCmd) createDefaultConfigFile() error {
   619  	var user, pass string
   620  	// If LDAP is enabled, authentication of enrollment requests are performed
   621  	// by using LDAP authentication; therefore, no bootstrap username and password
   622  	// are required.
   623  	ldapEnabled := s.myViper.GetBool("ldap.enabled")
   624  	if !ldapEnabled {
   625  		// When LDAP is disabled, the fabric-ca-server functions as its own
   626  		// identity registry; therefore, we require that the default configuration
   627  		// file have a bootstrap username and password that is used to enroll a
   628  		// bootstrap administrator.  Other identities can be dynamically registered.
   629  		// Create the default config, but only if they provided this bootstrap
   630  		// username and password.
   631  		up := s.myViper.GetString("boot")
   632  		zclog.Infof("===== up: %s", up)
   633  		if up == "" {
   634  			return errors.New("The '-b user:pass' option is required")
   635  		}
   636  		ups := strings.Split(up, ":")
   637  		zclog.Infof("===== ups: %s", ups)
   638  		if len(ups) < 2 {
   639  			return errors.Errorf("The value '%s' on the command line is missing a colon separator", up)
   640  		}
   641  		if len(ups) > 2 {
   642  			ups = []string{ups[0], strings.Join(ups[1:], ":")}
   643  		}
   644  		user = ups[0]
   645  		pass = ups[1]
   646  		if len(user) >= 1024 {
   647  			return errors.Errorf("The identity name must be less than 1024 characters: '%s'", user)
   648  		}
   649  		if len(pass) == 0 {
   650  			return errors.New("An empty password in the '-b user:pass' option is not permitted")
   651  		}
   652  	}
   653  
   654  	var myhost string
   655  	var err error
   656  	myhost, err = os.Hostname()
   657  	if err != nil {
   658  		return err
   659  	}
   660  
   661  	// Do string substitution to get the default config
   662  	cfg := strings.Replace(defaultCfgTemplate, "<<<VERSION>>>", metadata.Version, 1)
   663  	cfg = strings.Replace(cfg, "<<<ADMIN>>>", user, 1)
   664  	cfg = strings.Replace(cfg, "<<<ADMINPW>>>", pass, 1)
   665  	cfg = strings.Replace(cfg, "<<<MYHOST>>>", myhost, 1)
   666  	purl := s.myViper.GetString("intermediate.parentserver.url")
   667  	zclog.Debugf("===== parent server URL: '%s'", util.GetMaskedURL(purl))
   668  	if purl == "" {
   669  		// This is a root CA
   670  		cfg = strings.Replace(cfg, "<<<COMMONNAME>>>", "fabric-ca-server", 1)
   671  		cfg = strings.Replace(cfg, "<<<PATHLENGTH>>>", "1", 1)
   672  	} else {
   673  		// This is an intermediate CA
   674  		cfg = strings.Replace(cfg, "<<<COMMONNAME>>>", "", 1)
   675  		cfg = strings.Replace(cfg, "<<<PATHLENGTH>>>", "0", 1)
   676  	}
   677  
   678  	// Now write the file
   679  	cfgDir := filepath.Dir(s.cfgFileName)
   680  	err = os.MkdirAll(cfgDir, 0755)
   681  	if err != nil {
   682  		return err
   683  	}
   684  
   685  	// Now write the file
   686  	return ioutil.WriteFile(s.cfgFileName, []byte(cfg), 0644)
   687  }