github.com/silveraid/fabric-ca@v1.1.0-preview.0.20180127000700-71974f53ab08/cmd/fabric-ca-server/config.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 main
    18  
    19  import (
    20  	"io/ioutil"
    21  	"os"
    22  	"path/filepath"
    23  	"strings"
    24  
    25  	"github.com/pkg/errors"
    26  
    27  	"github.com/cloudflare/cfssl/log"
    28  	"github.com/hyperledger/fabric-ca/lib"
    29  	"github.com/hyperledger/fabric-ca/lib/metadata"
    30  	"github.com/hyperledger/fabric-ca/util"
    31  )
    32  
    33  const (
    34  	longName     = "Hyperledger Fabric Certificate Authority Server"
    35  	shortName    = "fabric-ca server"
    36  	cmdName      = "fabric-ca-server"
    37  	envVarPrefix = "FABRIC_CA_SERVER"
    38  	homeEnvVar   = "FABRIC_CA_SERVER_HOME"
    39  	caNameReqMsg = "ca.name property is required but is missing from the configuration file"
    40  )
    41  
    42  const (
    43  	defaultCfgTemplate = `#############################################################################
    44  #   This is a configuration file for the fabric-ca-server command.
    45  #
    46  #   COMMAND LINE ARGUMENTS AND ENVIRONMENT VARIABLES
    47  #   ------------------------------------------------
    48  #   Each configuration element can be overridden via command line
    49  #   arguments or environment variables.  The precedence for determining
    50  #   the value of each element is as follows:
    51  #   1) command line argument
    52  #      Examples:
    53  #      a) --port 443
    54  #         To set the listening port
    55  #      b) --ca-keyfile ../mykey.pem
    56  #         To set the "keyfile" element in the "ca" section below;
    57  #         note the '-' separator character.
    58  #   2) environment variable
    59  #      Examples:
    60  #      a) FABRIC_CA_SERVER_PORT=443
    61  #         To set the listening port
    62  #      b) FABRIC_CA_SERVER_CA_KEYFILE="../mykey.pem"
    63  #         To set the "keyfile" element in the "ca" section below;
    64  #         note the '_' separator character.
    65  #   3) configuration file
    66  #   4) default value (if there is one)
    67  #      All default values are shown beside each element below.
    68  #
    69  #   FILE NAME ELEMENTS
    70  #   ------------------
    71  #   The value of all fields whose name ends with "file" or "files" are
    72  #   name or names of other files.
    73  #   For example, see "tls.certfile" and "tls.clientauth.certfiles".
    74  #   The value of each of these fields can be a simple filename, a
    75  #   relative path, or an absolute path.  If the value is not an
    76  #   absolute path, it is interpretted as being relative to the location
    77  #   of this configuration file.
    78  #
    79  #############################################################################
    80  
    81  # Version of config file
    82  version: <<<VERSION>>>
    83  
    84  # Server's listening port (default: 7054)
    85  port: 7054
    86  
    87  # Enables debug logging (default: false)
    88  debug: false
    89  
    90  # Size limit of an acceptable CRL in bytes (default: 512000)
    91  crlsizelimit: 512000
    92  
    93  #############################################################################
    94  #  TLS section for the server's listening port
    95  #
    96  #  The following types are supported for client authentication: NoClientCert,
    97  #  RequestClientCert, RequireAnyClientCert, VerifyClientCertIfGiven,
    98  #  and RequireAndVerifyClientCert.
    99  #
   100  #  Certfiles is a list of root certificate authorities that the server uses
   101  #  when verifying client certificates.
   102  #############################################################################
   103  tls:
   104    # Enable TLS (default: false)
   105    enabled: false
   106    # TLS for the server's listening port
   107    certfile:
   108    keyfile:
   109    clientauth:
   110      type: noclientcert
   111      certfiles:
   112  
   113  #############################################################################
   114  #  The CA section contains information related to the Certificate Authority
   115  #  including the name of the CA, which should be unique for all members
   116  #  of a blockchain network.  It also includes the key and certificate files
   117  #  used when issuing enrollment certificates (ECerts) and transaction
   118  #  certificates (TCerts).
   119  #  The chainfile (if it exists) contains the certificate chain which
   120  #  should be trusted for this CA, where the 1st in the chain is always the
   121  #  root CA certificate.
   122  #############################################################################
   123  ca:
   124    # Name of this CA
   125    name:
   126    # Key file (is only used to import a private key into BCCSP)
   127    keyfile:
   128    # Certificate file (default: ca-cert.pem)
   129    certfile:
   130    # Chain file
   131    chainfile:
   132  
   133  #############################################################################
   134  #  The gencrl REST endpoint is used to generate a CRL that contains revoked
   135  #  certificates. This section contains configuration options that are used
   136  #  during gencrl request processing.
   137  #############################################################################
   138  crl:
   139    # Specifies expiration for the generated CRL. The number of hours
   140    # specified by this property is added to the UTC time, the resulting time
   141    # is used to set the 'Next Update' date of the CRL.
   142    expiry: 24h
   143  
   144  #############################################################################
   145  #  The registry section controls how the fabric-ca-server does two things:
   146  #  1) authenticates enrollment requests which contain a username and password
   147  #     (also known as an enrollment ID and secret).
   148  #  2) once authenticated, retrieves the identity's attribute names and
   149  #     values which the fabric-ca-server optionally puts into TCerts
   150  #     which it issues for transacting on the Hyperledger Fabric blockchain.
   151  #     These attributes are useful for making access control decisions in
   152  #     chaincode.
   153  #  There are two main configuration options:
   154  #  1) The fabric-ca-server is the registry.
   155  #     This is true if "ldap.enabled" in the ldap section below is false.
   156  #  2) An LDAP server is the registry, in which case the fabric-ca-server
   157  #     calls the LDAP server to perform these tasks.
   158  #     This is true if "ldap.enabled" in the ldap section below is true,
   159  #     which means this "registry" section is ignored.
   160  #############################################################################
   161  registry:
   162    # Maximum number of times a password/secret can be reused for enrollment
   163    # (default: -1, which means there is no limit)
   164    maxenrollments: -1
   165  
   166    # Contains identity information which is used when LDAP is disabled
   167    identities:
   168       - name: <<<ADMIN>>>
   169         pass: <<<ADMINPW>>>
   170         type: client
   171         affiliation: ""
   172         attrs:
   173            hf.Registrar.Roles: "peer,orderer,client,user"
   174            hf.Registrar.DelegateRoles: "peer,orderer,client,user"
   175            hf.Revoker: true
   176            hf.IntermediateCA: true
   177            hf.GenCRL: true
   178            hf.Registrar.Attributes: "*"
   179            hf.AffiliationMgr: true
   180  
   181  #############################################################################
   182  #  Database section
   183  #  Supported types are: "sqlite3", "postgres", and "mysql".
   184  #  The datasource value depends on the type.
   185  #  If the type is "sqlite3", the datasource value is a file name to use
   186  #  as the database store.  Since "sqlite3" is an embedded database, it
   187  #  may not be used if you want to run the fabric-ca-server in a cluster.
   188  #  To run the fabric-ca-server in a cluster, you must choose "postgres"
   189  #  or "mysql".
   190  #############################################################################
   191  db:
   192    type: sqlite3
   193    datasource: fabric-ca-server.db
   194    tls:
   195        enabled: false
   196        certfiles:
   197        client:
   198          certfile:
   199          keyfile:
   200  
   201  #############################################################################
   202  #  LDAP section
   203  #  If LDAP is enabled, the fabric-ca-server calls LDAP to:
   204  #  1) authenticate enrollment ID and secret (i.e. username and password)
   205  #     for enrollment requests;
   206  #  2) To retrieve identity attributes
   207  #############################################################################
   208  ldap:
   209     # Enables or disables the LDAP client (default: false)
   210     # If this is set to true, the "registry" section is ignored.
   211     enabled: false
   212     # The URL of the LDAP server
   213     url: ldap://<adminDN>:<adminPassword>@<host>:<port>/<base>
   214     # TLS configuration for the client connection to the LDAP server
   215     tls:
   216        certfiles:
   217        client:
   218           certfile:
   219           keyfile:
   220     # Attribute related configuration for mapping from LDAP entries to Fabric CA attributes
   221     attribute:
   222        # 'names' is an array of strings containing the LDAP attribute names which are
   223        # requested from the LDAP server for an LDAP identity's entry
   224        names: ['uid','member']
   225        # The 'converters' section is used to convert an LDAP entry to the value of
   226        # a fabric CA attribute.
   227        # For example, the following converts an LDAP 'uid' attribute
   228        # whose value begins with 'revoker' to a fabric CA attribute
   229        # named "hf.Revoker" with a value of "true" (because the boolean expression
   230        # evaluates to true).
   231        #    converters:
   232        #       - name: hf.Revoker
   233        #         value: attr("uid") =~ "revoker*"
   234        converters:
   235           - name:
   236             value:
   237        # The 'maps' section contains named maps which may be referenced by the 'map'
   238        # function in the 'converters' section to map LDAP responses to arbitrary values.
   239        # For example, assume a user has an LDAP attribute named 'member' which has multiple
   240        # values which are each a distinguished name (i.e. a DN). For simplicity, assume the
   241        # values of the 'member' attribute are 'dn1', 'dn2', and 'dn3'.
   242        # Further assume the following configuration.
   243        #    converters:
   244        #       - name: hf.Registrar.Roles
   245        #         value: map(attr("member"),"groups")
   246        #    maps:
   247        #       groups:
   248        #          - name: dn1
   249        #            value: peer
   250        #          - name: dn2
   251        #            value: client
   252        # The value of the user's 'hf.Registrar.Roles' attribute is then computed to be
   253        # "peer,client,dn3".  This is because the value of 'attr("member")' is
   254        # "dn1,dn2,dn3", and the call to 'map' with a 2nd argument of
   255        # "group" replaces "dn1" with "peer" and "dn2" with "client".
   256        maps:
   257           groups:
   258              - name:
   259                value:
   260  
   261  #############################################################################
   262  #  Affiliation section
   263  #############################################################################
   264  affiliations:
   265     org1:
   266        - department1
   267        - department2
   268     org2:
   269        - department1
   270  
   271  #############################################################################
   272  #  Signing section
   273  #
   274  #  The "default" subsection is used to sign enrollment certificates;
   275  #  the default expiration ("expiry" field) is "8760h", which is 1 year in hours.
   276  #
   277  #  The "ca" profile subsection is used to sign intermediate CA certificates;
   278  #  the default expiration ("expiry" field) is "43800h" which is 5 years in hours.
   279  #  Note that "isca" is true, meaning that it issues a CA certificate.
   280  #  A maxpathlen of 0 means that the intermediate CA cannot issue other
   281  #  intermediate CA certificates, though it can still issue end entity certificates.
   282  #  (See RFC 5280, section 4.2.1.9)
   283  #
   284  #  The "tls" profile subsection is used to sign TLS certificate requests;
   285  #  the default expiration ("expiry" field) is "8760h", which is 1 year in hours.
   286  #############################################################################
   287  signing:
   288      default:
   289        usage:
   290          - digital signature
   291        expiry: 8760h
   292      profiles:
   293        ca:
   294           usage:
   295             - cert sign
   296             - crl sign
   297           expiry: 43800h
   298           caconstraint:
   299             isca: true
   300             maxpathlen: 0
   301        tls:
   302           usage:
   303              - signing
   304              - key encipherment
   305              - server auth
   306              - client auth
   307              - key agreement
   308           expiry: 8760h
   309  
   310  ###########################################################################
   311  #  Certificate Signing Request (CSR) section.
   312  #  This controls the creation of the root CA certificate.
   313  #  The expiration for the root CA certificate is configured with the
   314  #  "ca.expiry" field below, whose default value is "131400h" which is
   315  #  15 years in hours.
   316  #  The pathlength field is used to limit CA certificate hierarchy as described
   317  #  in section 4.2.1.9 of RFC 5280.
   318  #  Examples:
   319  #  1) No pathlength value means no limit is requested.
   320  #  2) pathlength == 1 means a limit of 1 is requested which is the default for
   321  #     a root CA.  This means the root CA can issue intermediate CA certificates,
   322  #     but these intermediate CAs may not in turn issue other CA certificates
   323  #     though they can still issue end entity certificates.
   324  #  3) pathlength == 0 means a limit of 0 is requested;
   325  #     this is the default for an intermediate CA, which means it can not issue
   326  #     CA certificates though it can still issue end entity certificates.
   327  ###########################################################################
   328  csr:
   329     cn: <<<COMMONNAME>>>
   330     names:
   331        - C: US
   332          ST: "North Carolina"
   333          L:
   334          O: Hyperledger
   335          OU: Fabric
   336     hosts:
   337       - <<<MYHOST>>>
   338       - localhost
   339     ca:
   340        expiry: 131400h
   341        pathlength: <<<PATHLENGTH>>>
   342  
   343  #############################################################################
   344  # BCCSP (BlockChain Crypto Service Provider) section is used to select which
   345  # crypto library implementation to use
   346  #############################################################################
   347  bccsp:
   348      default: SW
   349      sw:
   350          hash: SHA2
   351          security: 256
   352          filekeystore:
   353              # The directory used for the software file-based keystore
   354              keystore: msp/keystore
   355  
   356  #############################################################################
   357  # Multi CA section
   358  #
   359  # Each Fabric CA server contains one CA by default.  This section is used
   360  # to configure multiple CAs in a single server.
   361  #
   362  # 1) --cacount <number-of-CAs>
   363  # Automatically generate <number-of-CAs> non-default CAs.  The names of these
   364  # additional CAs are "ca1", "ca2", ... "caN", where "N" is <number-of-CAs>
   365  # This is particularly useful in a development environment to quickly set up
   366  # multiple CAs.
   367  #
   368  # 2) --cafiles <CA-config-files>
   369  # For each CA config file in the list, generate a separate signing CA.  Each CA
   370  # config file in this list MAY contain all of the same elements as are found in
   371  # the server config file except port, debug, and tls sections.
   372  #
   373  # Examples:
   374  # fabric-ca-server start -b admin:adminpw --cacount 2
   375  #
   376  # fabric-ca-server start -b admin:adminpw --cafiles ca/ca1/fabric-ca-server-config.yaml
   377  # --cafiles ca/ca2/fabric-ca-server-config.yaml
   378  #
   379  #############################################################################
   380  
   381  cacount:
   382  
   383  cafiles:
   384  
   385  #############################################################################
   386  # Intermediate CA section
   387  #
   388  # The relationship between servers and CAs is as follows:
   389  #   1) A single server process may contain or function as one or more CAs.
   390  #      This is configured by the "Multi CA section" above.
   391  #   2) Each CA is either a root CA or an intermediate CA.
   392  #   3) Each intermediate CA has a parent CA which is either a root CA or another intermediate CA.
   393  #
   394  # This section pertains to configuration of #2 and #3.
   395  # If the "intermediate.parentserver.url" property is set,
   396  # then this is an intermediate CA with the specified parent
   397  # CA.
   398  #
   399  # parentserver section
   400  #    url - The URL of the parent server
   401  #    caname - Name of the CA to enroll within the server
   402  #
   403  # enrollment section used to enroll intermediate CA with parent CA
   404  #    profile - Name of the signing profile to use in issuing the certificate
   405  #    label - Label to use in HSM operations
   406  #
   407  # tls section for secure socket connection
   408  #   certfiles - PEM-encoded list of trusted root certificate files
   409  #   client:
   410  #     certfile - PEM-encoded certificate file for when client authentication
   411  #     is enabled on server
   412  #     keyfile - PEM-encoded key file for when client authentication
   413  #     is enabled on server
   414  #############################################################################
   415  intermediate:
   416    parentserver:
   417      url:
   418      caname:
   419  
   420    enrollment:
   421      hosts:
   422      profile:
   423      label:
   424  
   425    tls:
   426      certfiles:
   427      client:
   428        certfile:
   429        keyfile:
   430  `
   431  )
   432  
   433  var (
   434  	extraArgsError = "Unrecognized arguments found: %v\n\n%s"
   435  )
   436  
   437  // Initialize config
   438  func (s *ServerCmd) configInit() (err error) {
   439  	if !s.configRequired() {
   440  		return nil
   441  	}
   442  
   443  	s.cfgFileName, s.homeDirectory, err = util.ValidateAndReturnAbsConf(s.cfgFileName, s.homeDirectory, cmdName)
   444  	if err != nil {
   445  		return err
   446  	}
   447  
   448  	log.Debugf("Home directory: %s", s.homeDirectory)
   449  
   450  	// If the config file doesn't exist, create a default one
   451  	if !util.FileExists(s.cfgFileName) {
   452  		err = s.createDefaultConfigFile()
   453  		if err != nil {
   454  			return errors.WithMessage(err, "Failed to create default configuration file")
   455  		}
   456  		log.Infof("Created default configuration file at %s", s.cfgFileName)
   457  	} else {
   458  		log.Infof("Configuration file location: %s", s.cfgFileName)
   459  	}
   460  
   461  	// Read the config
   462  	s.myViper.AutomaticEnv() // read in environment variables that match
   463  	err = lib.UnmarshalConfig(s.cfg, s.myViper, s.cfgFileName, true)
   464  	if err != nil {
   465  		return err
   466  	}
   467  
   468  	// The pathlength field controls how deep the CA hierarchy when requesting
   469  	// certificates. If it is explicitly set to 0, set the PathLenZero field to
   470  	// true as CFSSL expects.
   471  	pl := "csr.ca.pathlength"
   472  	if s.myViper.IsSet(pl) && s.myViper.GetInt(pl) == 0 {
   473  		s.cfg.CAcfg.CSR.CA.PathLenZero = true
   474  	}
   475  	// The maxpathlen field controls how deep the CA hierarchy when issuing
   476  	// a CA certificate. If it is explicitly set to 0, set the PathLenZero
   477  	// field to true as CFSSL expects.
   478  	pl = "signing.profiles.ca.caconstraint.maxpathlen"
   479  	if s.myViper.IsSet(pl) && s.myViper.GetInt(pl) == 0 {
   480  		s.cfg.CAcfg.Signing.Profiles["ca"].CAConstraint.MaxPathLenZero = true
   481  	}
   482  
   483  	return nil
   484  }
   485  
   486  func (s *ServerCmd) createDefaultConfigFile() error {
   487  	var user, pass string
   488  	// If LDAP is enabled, authentication of enrollment requests are performed
   489  	// by using LDAP authentication; therefore, no bootstrap username and password
   490  	// are required.
   491  	ldapEnabled := s.myViper.GetBool("ldap.enabled")
   492  	if !ldapEnabled {
   493  		// When LDAP is disabled, the fabric-ca-server functions as its own
   494  		// identity registry; therefore, we require that the default configuration
   495  		// file have a bootstrap username and password that is used to enroll a
   496  		// bootstrap administrator.  Other identities can be dynamically registered.
   497  		// Create the default config, but only if they provided this bootstrap
   498  		// username and password.
   499  		up := s.myViper.GetString("boot")
   500  		if up == "" {
   501  			return errors.New("The '-b user:pass' option is required")
   502  		}
   503  		ups := strings.Split(up, ":")
   504  		if len(ups) < 2 {
   505  			return errors.Errorf("The value '%s' on the command line is missing a colon separator", up)
   506  		}
   507  		if len(ups) > 2 {
   508  			ups = []string{ups[0], strings.Join(ups[1:], ":")}
   509  		}
   510  		user = ups[0]
   511  		pass = ups[1]
   512  		if len(user) >= 1024 {
   513  			return errors.Errorf("The identity name must be less than 1024 characters: '%s'", user)
   514  		}
   515  		if len(pass) == 0 {
   516  			return errors.New("An empty password in the '-b user:pass' option is not permitted")
   517  		}
   518  	}
   519  
   520  	var myhost string
   521  	var err error
   522  	myhost, err = os.Hostname()
   523  	if err != nil {
   524  		return err
   525  	}
   526  
   527  	// Do string subtitution to get the default config
   528  	cfg := strings.Replace(defaultCfgTemplate, "<<<VERSION>>>", metadata.Version, 1)
   529  	cfg = strings.Replace(cfg, "<<<ADMIN>>>", user, 1)
   530  	cfg = strings.Replace(cfg, "<<<ADMINPW>>>", pass, 1)
   531  	cfg = strings.Replace(cfg, "<<<MYHOST>>>", myhost, 1)
   532  	purl := s.myViper.GetString("intermediate.parentserver.url")
   533  	log.Debugf("parent server URL: '%s'", purl)
   534  	if purl == "" {
   535  		// This is a root CA
   536  		cfg = strings.Replace(cfg, "<<<COMMONNAME>>>", "fabric-ca-server", 1)
   537  		cfg = strings.Replace(cfg, "<<<PATHLENGTH>>>", "1", 1)
   538  	} else {
   539  		// This is an intermediate CA
   540  		cfg = strings.Replace(cfg, "<<<COMMONNAME>>>", "", 1)
   541  		cfg = strings.Replace(cfg, "<<<PATHLENGTH>>>", "0", 1)
   542  	}
   543  
   544  	// Now write the file
   545  	cfgDir := filepath.Dir(s.cfgFileName)
   546  	err = os.MkdirAll(cfgDir, 0755)
   547  	if err != nil {
   548  		return err
   549  	}
   550  
   551  	// Now write the file
   552  	return ioutil.WriteFile(s.cfgFileName, []byte(cfg), 0644)
   553  }