github.com/hechain20/hechain@v0.0.0-20220316014945-b544036ba106/cmd/cryptogen/main.go (about)

     1  /*
     2  Copyright hechain. All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  package main
     7  
     8  import (
     9  	"bytes"
    10  	"fmt"
    11  	"io"
    12  	"io/ioutil"
    13  	"os"
    14  	"path/filepath"
    15  	"text/template"
    16  
    17  	"github.com/hechain20/hechain/internal/cryptogen/ca"
    18  	"github.com/hechain20/hechain/internal/cryptogen/csp"
    19  	"github.com/hechain20/hechain/internal/cryptogen/metadata"
    20  	"github.com/hechain20/hechain/internal/cryptogen/msp"
    21  
    22  	kingpin "gopkg.in/alecthomas/kingpin.v2"
    23  	yaml "gopkg.in/yaml.v2"
    24  )
    25  
    26  const (
    27  	userBaseName            = "User"
    28  	adminBaseName           = "Admin"
    29  	defaultHostnameTemplate = "{{.Prefix}}{{.Index}}"
    30  	defaultCNTemplate       = "{{.Hostname}}.{{.Domain}}"
    31  )
    32  
    33  type HostnameData struct {
    34  	Prefix string
    35  	Index  int
    36  	Domain string
    37  }
    38  
    39  type SpecData struct {
    40  	Hostname   string
    41  	Domain     string
    42  	CommonName string
    43  }
    44  
    45  type NodeTemplate struct {
    46  	Count    int      `yaml:"Count"`
    47  	Start    int      `yaml:"Start"`
    48  	Hostname string   `yaml:"Hostname"`
    49  	SANS     []string `yaml:"SANS"`
    50  }
    51  
    52  type NodeSpec struct {
    53  	isAdmin            bool
    54  	Hostname           string   `yaml:"Hostname"`
    55  	CommonName         string   `yaml:"CommonName"`
    56  	Country            string   `yaml:"Country"`
    57  	Province           string   `yaml:"Province"`
    58  	Locality           string   `yaml:"Locality"`
    59  	OrganizationalUnit string   `yaml:"OrganizationalUnit"`
    60  	StreetAddress      string   `yaml:"StreetAddress"`
    61  	PostalCode         string   `yaml:"PostalCode"`
    62  	SANS               []string `yaml:"SANS"`
    63  }
    64  
    65  type UsersSpec struct {
    66  	Count int `yaml:"Count"`
    67  }
    68  
    69  type OrgSpec struct {
    70  	Name          string       `yaml:"Name"`
    71  	Domain        string       `yaml:"Domain"`
    72  	EnableNodeOUs bool         `yaml:"EnableNodeOUs"`
    73  	CA            NodeSpec     `yaml:"CA"`
    74  	Template      NodeTemplate `yaml:"Template"`
    75  	Specs         []NodeSpec   `yaml:"Specs"`
    76  	Users         UsersSpec    `yaml:"Users"`
    77  }
    78  
    79  type Config struct {
    80  	OrdererOrgs []OrgSpec `yaml:"OrdererOrgs"`
    81  	PeerOrgs    []OrgSpec `yaml:"PeerOrgs"`
    82  }
    83  
    84  var defaultConfig = `
    85  # ---------------------------------------------------------------------------
    86  # "OrdererOrgs" - Definition of organizations managing orderer nodes
    87  # ---------------------------------------------------------------------------
    88  OrdererOrgs:
    89    # ---------------------------------------------------------------------------
    90    # Orderer
    91    # ---------------------------------------------------------------------------
    92    - Name: Orderer
    93      Domain: example.com
    94      EnableNodeOUs: false
    95  
    96      # ---------------------------------------------------------------------------
    97      # "Specs" - See PeerOrgs below for complete description
    98      # ---------------------------------------------------------------------------
    99      Specs:
   100        - Hostname: orderer
   101  
   102  # ---------------------------------------------------------------------------
   103  # "PeerOrgs" - Definition of organizations managing peer nodes
   104  # ---------------------------------------------------------------------------
   105  PeerOrgs:
   106    # ---------------------------------------------------------------------------
   107    # Org1
   108    # ---------------------------------------------------------------------------
   109    - Name: Org1
   110      Domain: org1.example.com
   111      EnableNodeOUs: false
   112  
   113      # ---------------------------------------------------------------------------
   114      # "CA"
   115      # ---------------------------------------------------------------------------
   116      # Uncomment this section to enable the explicit definition of the CA for this
   117      # organization.  This entry is a Spec.  See "Specs" section below for details.
   118      # ---------------------------------------------------------------------------
   119      # CA:
   120      #    Hostname: ca # implicitly ca.org1.example.com
   121      #    Country: US
   122      #    Province: California
   123      #    Locality: San Francisco
   124      #    OrganizationalUnit: Hechain
   125      #    StreetAddress: address for org # default nil
   126      #    PostalCode: postalCode for org # default nil
   127  
   128      # ---------------------------------------------------------------------------
   129      # "Specs"
   130      # ---------------------------------------------------------------------------
   131      # Uncomment this section to enable the explicit definition of hosts in your
   132      # configuration.  Most users will want to use Template, below
   133      #
   134      # Specs is an array of Spec entries.  Each Spec entry consists of two fields:
   135      #   - Hostname:   (Required) The desired hostname, sans the domain.
   136      #   - CommonName: (Optional) Specifies the template or explicit override for
   137      #                 the CN.  By default, this is the template:
   138      #
   139      #                              "{{.Hostname}}.{{.Domain}}"
   140      #
   141      #                 which obtains its values from the Spec.Hostname and
   142      #                 Org.Domain, respectively.
   143      #   - SANS:       (Optional) Specifies one or more Subject Alternative Names
   144      #                 to be set in the resulting x509. Accepts template
   145      #                 variables {{.Hostname}}, {{.Domain}}, {{.CommonName}}. IP
   146      #                 addresses provided here will be properly recognized. Other
   147      #                 values will be taken as DNS names.
   148      #                 NOTE: Two implicit entries are created for you:
   149      #                     - {{ .CommonName }}
   150      #                     - {{ .Hostname }}
   151      # ---------------------------------------------------------------------------
   152      # Specs:
   153      #   - Hostname: foo # implicitly "foo.org1.example.com"
   154      #     CommonName: foo27.org5.example.com # overrides Hostname-based FQDN set above
   155      #     SANS:
   156      #       - "bar.{{.Domain}}"
   157      #       - "altfoo.{{.Domain}}"
   158      #       - "{{.Hostname}}.org6.net"
   159      #       - 172.16.10.31
   160      #   - Hostname: bar
   161      #   - Hostname: baz
   162  
   163      # ---------------------------------------------------------------------------
   164      # "Template"
   165      # ---------------------------------------------------------------------------
   166      # Allows for the definition of 1 or more hosts that are created sequentially
   167      # from a template. By default, this looks like "peer%d" from 0 to Count-1.
   168      # You may override the number of nodes (Count), the starting index (Start)
   169      # or the template used to construct the name (Hostname).
   170      #
   171      # Note: Template and Specs are not mutually exclusive.  You may define both
   172      # sections and the aggregate nodes will be created for you.  Take care with
   173      # name collisions
   174      # ---------------------------------------------------------------------------
   175      Template:
   176        Count: 1
   177        # Start: 5
   178        # Hostname: {{.Prefix}}{{.Index}} # default
   179        # SANS:
   180        #   - "{{.Hostname}}.alt.{{.Domain}}"
   181  
   182      # ---------------------------------------------------------------------------
   183      # "Users"
   184      # ---------------------------------------------------------------------------
   185      # Count: The number of user accounts _in addition_ to Admin
   186      # ---------------------------------------------------------------------------
   187      Users:
   188        Count: 1
   189  
   190    # ---------------------------------------------------------------------------
   191    # Org2: See "Org1" for full specification
   192    # ---------------------------------------------------------------------------
   193    - Name: Org2
   194      Domain: org2.example.com
   195      EnableNodeOUs: false
   196      Template:
   197        Count: 1
   198      Users:
   199        Count: 1
   200  `
   201  
   202  // command line flags
   203  var (
   204  	app = kingpin.New("cryptogen", "Utility for generating Hechain key material")
   205  
   206  	gen           = app.Command("generate", "Generate key material")
   207  	outputDir     = gen.Flag("output", "The output directory in which to place artifacts").Default("crypto-config").String()
   208  	genConfigFile = gen.Flag("config", "The configuration template to use").File()
   209  
   210  	showtemplate = app.Command("showtemplate", "Show the default configuration template")
   211  
   212  	version       = app.Command("version", "Show version information")
   213  	ext           = app.Command("extend", "Extend existing network")
   214  	inputDir      = ext.Flag("input", "The input directory in which existing network place").Default("crypto-config").String()
   215  	extConfigFile = ext.Flag("config", "The configuration template to use").File()
   216  )
   217  
   218  func main() {
   219  	kingpin.Version("0.0.1")
   220  	switch kingpin.MustParse(app.Parse(os.Args[1:])) {
   221  
   222  	// "generate" command
   223  	case gen.FullCommand():
   224  		generate()
   225  
   226  	case ext.FullCommand():
   227  		extend()
   228  
   229  		// "showtemplate" command
   230  	case showtemplate.FullCommand():
   231  		fmt.Print(defaultConfig)
   232  		os.Exit(0)
   233  
   234  		// "version" command
   235  	case version.FullCommand():
   236  		printVersion()
   237  	}
   238  }
   239  
   240  func getConfig() (*Config, error) {
   241  	var configData string
   242  
   243  	if *genConfigFile != nil {
   244  		data, err := ioutil.ReadAll(*genConfigFile)
   245  		if err != nil {
   246  			return nil, fmt.Errorf("Error reading configuration: %s", err)
   247  		}
   248  
   249  		configData = string(data)
   250  	} else if *extConfigFile != nil {
   251  		data, err := ioutil.ReadAll(*extConfigFile)
   252  		if err != nil {
   253  			return nil, fmt.Errorf("Error reading configuration: %s", err)
   254  		}
   255  
   256  		configData = string(data)
   257  	} else {
   258  		configData = defaultConfig
   259  	}
   260  
   261  	config := &Config{}
   262  	err := yaml.Unmarshal([]byte(configData), &config)
   263  	if err != nil {
   264  		return nil, fmt.Errorf("Error Unmarshalling YAML: %s", err)
   265  	}
   266  
   267  	return config, nil
   268  }
   269  
   270  func extend() {
   271  	config, err := getConfig()
   272  	if err != nil {
   273  		fmt.Printf("Error reading config: %s", err)
   274  		os.Exit(-1)
   275  	}
   276  
   277  	for _, orgSpec := range config.PeerOrgs {
   278  		err = renderOrgSpec(&orgSpec, "peer")
   279  		if err != nil {
   280  			fmt.Printf("Error processing peer configuration: %s", err)
   281  			os.Exit(-1)
   282  		}
   283  		extendPeerOrg(orgSpec)
   284  	}
   285  
   286  	for _, orgSpec := range config.OrdererOrgs {
   287  		err = renderOrgSpec(&orgSpec, "orderer")
   288  		if err != nil {
   289  			fmt.Printf("Error processing orderer configuration: %s", err)
   290  			os.Exit(-1)
   291  		}
   292  		extendOrdererOrg(orgSpec)
   293  	}
   294  }
   295  
   296  func extendPeerOrg(orgSpec OrgSpec) {
   297  	orgName := orgSpec.Domain
   298  	orgDir := filepath.Join(*inputDir, "peerOrganizations", orgName)
   299  	if _, err := os.Stat(orgDir); os.IsNotExist(err) {
   300  		generatePeerOrg(*inputDir, orgSpec)
   301  		return
   302  	}
   303  
   304  	peersDir := filepath.Join(orgDir, "peers")
   305  	usersDir := filepath.Join(orgDir, "users")
   306  	caDir := filepath.Join(orgDir, "ca")
   307  	tlscaDir := filepath.Join(orgDir, "tlsca")
   308  
   309  	signCA := getCA(caDir, orgSpec, orgSpec.CA.CommonName)
   310  	tlsCA := getCA(tlscaDir, orgSpec, "tls"+orgSpec.CA.CommonName)
   311  
   312  	generateNodes(peersDir, orgSpec.Specs, signCA, tlsCA, msp.PEER, orgSpec.EnableNodeOUs)
   313  
   314  	adminUser := NodeSpec{
   315  		isAdmin:    true,
   316  		CommonName: fmt.Sprintf("%s@%s", adminBaseName, orgName),
   317  	}
   318  	// copy the admin cert to each of the org's peer's MSP admincerts
   319  	for _, spec := range orgSpec.Specs {
   320  		if orgSpec.EnableNodeOUs {
   321  			continue
   322  		}
   323  		err := copyAdminCert(usersDir,
   324  			filepath.Join(peersDir, spec.CommonName, "msp", "admincerts"), adminUser.CommonName)
   325  		if err != nil {
   326  			fmt.Printf("Error copying admin cert for org %s peer %s:\n%v\n",
   327  				orgName, spec.CommonName, err)
   328  			os.Exit(1)
   329  		}
   330  	}
   331  
   332  	// TODO: add ability to specify usernames
   333  	users := []NodeSpec{}
   334  	for j := 1; j <= orgSpec.Users.Count; j++ {
   335  		user := NodeSpec{
   336  			CommonName: fmt.Sprintf("%s%d@%s", userBaseName, j, orgName),
   337  		}
   338  
   339  		users = append(users, user)
   340  	}
   341  
   342  	generateNodes(usersDir, users, signCA, tlsCA, msp.CLIENT, orgSpec.EnableNodeOUs)
   343  }
   344  
   345  func extendOrdererOrg(orgSpec OrgSpec) {
   346  	orgName := orgSpec.Domain
   347  
   348  	orgDir := filepath.Join(*inputDir, "ordererOrganizations", orgName)
   349  	caDir := filepath.Join(orgDir, "ca")
   350  	usersDir := filepath.Join(orgDir, "users")
   351  	tlscaDir := filepath.Join(orgDir, "tlsca")
   352  	orderersDir := filepath.Join(orgDir, "orderers")
   353  	if _, err := os.Stat(orgDir); os.IsNotExist(err) {
   354  		generateOrdererOrg(*inputDir, orgSpec)
   355  		return
   356  	}
   357  
   358  	signCA := getCA(caDir, orgSpec, orgSpec.CA.CommonName)
   359  	tlsCA := getCA(tlscaDir, orgSpec, "tls"+orgSpec.CA.CommonName)
   360  
   361  	generateNodes(orderersDir, orgSpec.Specs, signCA, tlsCA, msp.ORDERER, orgSpec.EnableNodeOUs)
   362  
   363  	adminUser := NodeSpec{
   364  		isAdmin:    true,
   365  		CommonName: fmt.Sprintf("%s@%s", adminBaseName, orgName),
   366  	}
   367  
   368  	for _, spec := range orgSpec.Specs {
   369  		if orgSpec.EnableNodeOUs {
   370  			continue
   371  		}
   372  		err := copyAdminCert(usersDir,
   373  			filepath.Join(orderersDir, spec.CommonName, "msp", "admincerts"), adminUser.CommonName)
   374  		if err != nil {
   375  			fmt.Printf("Error copying admin cert for org %s orderer %s:\n%v\n",
   376  				orgName, spec.CommonName, err)
   377  			os.Exit(1)
   378  		}
   379  	}
   380  }
   381  
   382  func generate() {
   383  	config, err := getConfig()
   384  	if err != nil {
   385  		fmt.Printf("Error reading config: %s", err)
   386  		os.Exit(-1)
   387  	}
   388  
   389  	for _, orgSpec := range config.PeerOrgs {
   390  		err = renderOrgSpec(&orgSpec, "peer")
   391  		if err != nil {
   392  			fmt.Printf("Error processing peer configuration: %s", err)
   393  			os.Exit(-1)
   394  		}
   395  		generatePeerOrg(*outputDir, orgSpec)
   396  	}
   397  
   398  	for _, orgSpec := range config.OrdererOrgs {
   399  		err = renderOrgSpec(&orgSpec, "orderer")
   400  		if err != nil {
   401  			fmt.Printf("Error processing orderer configuration: %s", err)
   402  			os.Exit(-1)
   403  		}
   404  		generateOrdererOrg(*outputDir, orgSpec)
   405  	}
   406  }
   407  
   408  func parseTemplate(input string, data interface{}) (string, error) {
   409  	t, err := template.New("parse").Parse(input)
   410  	if err != nil {
   411  		return "", fmt.Errorf("Error parsing template: %s", err)
   412  	}
   413  
   414  	output := new(bytes.Buffer)
   415  	err = t.Execute(output, data)
   416  	if err != nil {
   417  		return "", fmt.Errorf("Error executing template: %s", err)
   418  	}
   419  
   420  	return output.String(), nil
   421  }
   422  
   423  func parseTemplateWithDefault(input, defaultInput string, data interface{}) (string, error) {
   424  	// Use the default if the input is an empty string
   425  	if len(input) == 0 {
   426  		input = defaultInput
   427  	}
   428  
   429  	return parseTemplate(input, data)
   430  }
   431  
   432  func renderNodeSpec(domain string, spec *NodeSpec) error {
   433  	data := SpecData{
   434  		Hostname: spec.Hostname,
   435  		Domain:   domain,
   436  	}
   437  
   438  	// Process our CommonName
   439  	cn, err := parseTemplateWithDefault(spec.CommonName, defaultCNTemplate, data)
   440  	if err != nil {
   441  		return err
   442  	}
   443  
   444  	spec.CommonName = cn
   445  	data.CommonName = cn
   446  
   447  	// Save off our original, unprocessed SANS entries
   448  	origSANS := spec.SANS
   449  
   450  	// Set our implicit SANS entries for CN/Hostname
   451  	spec.SANS = []string{cn, spec.Hostname}
   452  
   453  	// Finally, process any remaining SANS entries
   454  	for _, _san := range origSANS {
   455  		san, err := parseTemplate(_san, data)
   456  		if err != nil {
   457  			return err
   458  		}
   459  
   460  		spec.SANS = append(spec.SANS, san)
   461  	}
   462  
   463  	return nil
   464  }
   465  
   466  func renderOrgSpec(orgSpec *OrgSpec, prefix string) error {
   467  	// First process all of our templated nodes
   468  	for i := 0; i < orgSpec.Template.Count; i++ {
   469  		data := HostnameData{
   470  			Prefix: prefix,
   471  			Index:  i + orgSpec.Template.Start,
   472  			Domain: orgSpec.Domain,
   473  		}
   474  
   475  		hostname, err := parseTemplateWithDefault(orgSpec.Template.Hostname, defaultHostnameTemplate, data)
   476  		if err != nil {
   477  			return err
   478  		}
   479  
   480  		spec := NodeSpec{
   481  			Hostname: hostname,
   482  			SANS:     orgSpec.Template.SANS,
   483  		}
   484  		orgSpec.Specs = append(orgSpec.Specs, spec)
   485  	}
   486  
   487  	// Touch up all general node-specs to add the domain
   488  	for idx, spec := range orgSpec.Specs {
   489  		err := renderNodeSpec(orgSpec.Domain, &spec)
   490  		if err != nil {
   491  			return err
   492  		}
   493  
   494  		orgSpec.Specs[idx] = spec
   495  	}
   496  
   497  	// Process the CA node-spec in the same manner
   498  	if len(orgSpec.CA.Hostname) == 0 {
   499  		orgSpec.CA.Hostname = "ca"
   500  	}
   501  	err := renderNodeSpec(orgSpec.Domain, &orgSpec.CA)
   502  	if err != nil {
   503  		return err
   504  	}
   505  
   506  	return nil
   507  }
   508  
   509  func generatePeerOrg(baseDir string, orgSpec OrgSpec) {
   510  	orgName := orgSpec.Domain
   511  
   512  	fmt.Println(orgName)
   513  	// generate CAs
   514  	orgDir := filepath.Join(baseDir, "peerOrganizations", orgName)
   515  	caDir := filepath.Join(orgDir, "ca")
   516  	tlsCADir := filepath.Join(orgDir, "tlsca")
   517  	mspDir := filepath.Join(orgDir, "msp")
   518  	peersDir := filepath.Join(orgDir, "peers")
   519  	usersDir := filepath.Join(orgDir, "users")
   520  	adminCertsDir := filepath.Join(mspDir, "admincerts")
   521  	// generate signing CA
   522  	signCA, err := ca.NewCA(caDir, orgName, orgSpec.CA.CommonName, orgSpec.CA.Country, orgSpec.CA.Province, orgSpec.CA.Locality, orgSpec.CA.OrganizationalUnit, orgSpec.CA.StreetAddress, orgSpec.CA.PostalCode)
   523  	if err != nil {
   524  		fmt.Printf("Error generating signCA for org %s:\n%v\n", orgName, err)
   525  		os.Exit(1)
   526  	}
   527  	// generate TLS CA
   528  	tlsCA, err := ca.NewCA(tlsCADir, orgName, "tls"+orgSpec.CA.CommonName, orgSpec.CA.Country, orgSpec.CA.Province, orgSpec.CA.Locality, orgSpec.CA.OrganizationalUnit, orgSpec.CA.StreetAddress, orgSpec.CA.PostalCode)
   529  	if err != nil {
   530  		fmt.Printf("Error generating tlsCA for org %s:\n%v\n", orgName, err)
   531  		os.Exit(1)
   532  	}
   533  
   534  	err = msp.GenerateVerifyingMSP(mspDir, signCA, tlsCA, orgSpec.EnableNodeOUs)
   535  	if err != nil {
   536  		fmt.Printf("Error generating MSP for org %s:\n%v\n", orgName, err)
   537  		os.Exit(1)
   538  	}
   539  
   540  	generateNodes(peersDir, orgSpec.Specs, signCA, tlsCA, msp.PEER, orgSpec.EnableNodeOUs)
   541  
   542  	// TODO: add ability to specify usernames
   543  	users := []NodeSpec{}
   544  	for j := 1; j <= orgSpec.Users.Count; j++ {
   545  		user := NodeSpec{
   546  			CommonName: fmt.Sprintf("%s%d@%s", userBaseName, j, orgName),
   547  		}
   548  
   549  		users = append(users, user)
   550  	}
   551  	// add an admin user
   552  	adminUser := NodeSpec{
   553  		isAdmin:    true,
   554  		CommonName: fmt.Sprintf("%s@%s", adminBaseName, orgName),
   555  	}
   556  
   557  	users = append(users, adminUser)
   558  	generateNodes(usersDir, users, signCA, tlsCA, msp.CLIENT, orgSpec.EnableNodeOUs)
   559  
   560  	// copy the admin cert to the org's MSP admincerts
   561  	if !orgSpec.EnableNodeOUs {
   562  		err = copyAdminCert(usersDir, adminCertsDir, adminUser.CommonName)
   563  		if err != nil {
   564  			fmt.Printf("Error copying admin cert for org %s:\n%v\n",
   565  				orgName, err)
   566  			os.Exit(1)
   567  		}
   568  	}
   569  
   570  	// copy the admin cert to each of the org's peer's MSP admincerts
   571  	for _, spec := range orgSpec.Specs {
   572  		if orgSpec.EnableNodeOUs {
   573  			continue
   574  		}
   575  		err = copyAdminCert(usersDir,
   576  			filepath.Join(peersDir, spec.CommonName, "msp", "admincerts"), adminUser.CommonName)
   577  		if err != nil {
   578  			fmt.Printf("Error copying admin cert for org %s peer %s:\n%v\n",
   579  				orgName, spec.CommonName, err)
   580  			os.Exit(1)
   581  		}
   582  	}
   583  }
   584  
   585  func copyAdminCert(usersDir, adminCertsDir, adminUserName string) error {
   586  	if _, err := os.Stat(filepath.Join(adminCertsDir,
   587  		adminUserName+"-cert.pem")); err == nil {
   588  		return nil
   589  	}
   590  	// delete the contents of admincerts
   591  	err := os.RemoveAll(adminCertsDir)
   592  	if err != nil {
   593  		return err
   594  	}
   595  	// recreate the admincerts directory
   596  	err = os.MkdirAll(adminCertsDir, 0o755)
   597  	if err != nil {
   598  		return err
   599  	}
   600  	err = copyFile(filepath.Join(usersDir, adminUserName, "msp", "signcerts",
   601  		adminUserName+"-cert.pem"), filepath.Join(adminCertsDir,
   602  		adminUserName+"-cert.pem"))
   603  	if err != nil {
   604  		return err
   605  	}
   606  	return nil
   607  }
   608  
   609  func generateNodes(baseDir string, nodes []NodeSpec, signCA *ca.CA, tlsCA *ca.CA, nodeType int, nodeOUs bool) {
   610  	for _, node := range nodes {
   611  		nodeDir := filepath.Join(baseDir, node.CommonName)
   612  		if _, err := os.Stat(nodeDir); os.IsNotExist(err) {
   613  			currentNodeType := nodeType
   614  			if node.isAdmin && nodeOUs {
   615  				currentNodeType = msp.ADMIN
   616  			}
   617  			err := msp.GenerateLocalMSP(nodeDir, node.CommonName, node.SANS, signCA, tlsCA, currentNodeType, nodeOUs)
   618  			if err != nil {
   619  				fmt.Printf("Error generating local MSP for %v:\n%v\n", node, err)
   620  				os.Exit(1)
   621  			}
   622  		}
   623  	}
   624  }
   625  
   626  func generateOrdererOrg(baseDir string, orgSpec OrgSpec) {
   627  	orgName := orgSpec.Domain
   628  
   629  	// generate CAs
   630  	orgDir := filepath.Join(baseDir, "ordererOrganizations", orgName)
   631  	caDir := filepath.Join(orgDir, "ca")
   632  	tlsCADir := filepath.Join(orgDir, "tlsca")
   633  	mspDir := filepath.Join(orgDir, "msp")
   634  	orderersDir := filepath.Join(orgDir, "orderers")
   635  	usersDir := filepath.Join(orgDir, "users")
   636  	adminCertsDir := filepath.Join(mspDir, "admincerts")
   637  	// generate signing CA
   638  	signCA, err := ca.NewCA(caDir, orgName, orgSpec.CA.CommonName, orgSpec.CA.Country, orgSpec.CA.Province, orgSpec.CA.Locality, orgSpec.CA.OrganizationalUnit, orgSpec.CA.StreetAddress, orgSpec.CA.PostalCode)
   639  	if err != nil {
   640  		fmt.Printf("Error generating signCA for org %s:\n%v\n", orgName, err)
   641  		os.Exit(1)
   642  	}
   643  	// generate TLS CA
   644  	tlsCA, err := ca.NewCA(tlsCADir, orgName, "tls"+orgSpec.CA.CommonName, orgSpec.CA.Country, orgSpec.CA.Province, orgSpec.CA.Locality, orgSpec.CA.OrganizationalUnit, orgSpec.CA.StreetAddress, orgSpec.CA.PostalCode)
   645  	if err != nil {
   646  		fmt.Printf("Error generating tlsCA for org %s:\n%v\n", orgName, err)
   647  		os.Exit(1)
   648  	}
   649  
   650  	err = msp.GenerateVerifyingMSP(mspDir, signCA, tlsCA, orgSpec.EnableNodeOUs)
   651  	if err != nil {
   652  		fmt.Printf("Error generating MSP for org %s:\n%v\n", orgName, err)
   653  		os.Exit(1)
   654  	}
   655  
   656  	generateNodes(orderersDir, orgSpec.Specs, signCA, tlsCA, msp.ORDERER, orgSpec.EnableNodeOUs)
   657  
   658  	adminUser := NodeSpec{
   659  		isAdmin:    true,
   660  		CommonName: fmt.Sprintf("%s@%s", adminBaseName, orgName),
   661  	}
   662  
   663  	// generate an admin for the orderer org
   664  	users := []NodeSpec{}
   665  	// add an admin user
   666  	users = append(users, adminUser)
   667  	generateNodes(usersDir, users, signCA, tlsCA, msp.CLIENT, orgSpec.EnableNodeOUs)
   668  
   669  	// copy the admin cert to the org's MSP admincerts
   670  	if !orgSpec.EnableNodeOUs {
   671  		err = copyAdminCert(usersDir, adminCertsDir, adminUser.CommonName)
   672  		if err != nil {
   673  			fmt.Printf("Error copying admin cert for org %s:\n%v\n",
   674  				orgName, err)
   675  			os.Exit(1)
   676  		}
   677  	}
   678  
   679  	// copy the admin cert to each of the org's orderers's MSP admincerts
   680  	for _, spec := range orgSpec.Specs {
   681  		if orgSpec.EnableNodeOUs {
   682  			continue
   683  		}
   684  		err = copyAdminCert(usersDir,
   685  			filepath.Join(orderersDir, spec.CommonName, "msp", "admincerts"), adminUser.CommonName)
   686  		if err != nil {
   687  			fmt.Printf("Error copying admin cert for org %s orderer %s:\n%v\n",
   688  				orgName, spec.CommonName, err)
   689  			os.Exit(1)
   690  		}
   691  	}
   692  }
   693  
   694  func copyFile(src, dst string) error {
   695  	in, err := os.Open(src)
   696  	if err != nil {
   697  		return err
   698  	}
   699  	defer in.Close()
   700  	out, err := os.Create(dst)
   701  	if err != nil {
   702  		return err
   703  	}
   704  	defer out.Close()
   705  	_, err = io.Copy(out, in)
   706  	cerr := out.Close()
   707  	if err != nil {
   708  		return err
   709  	}
   710  	return cerr
   711  }
   712  
   713  func printVersion() {
   714  	fmt.Println(metadata.GetVersionInfo())
   715  }
   716  
   717  func getCA(caDir string, spec OrgSpec, name string) *ca.CA {
   718  	priv, _ := csp.LoadPrivateKey(caDir)
   719  	cert, _ := ca.LoadCertificateECDSA(caDir)
   720  
   721  	return &ca.CA{
   722  		Name:               name,
   723  		Signer:             priv,
   724  		SignCert:           cert,
   725  		Country:            spec.CA.Country,
   726  		Province:           spec.CA.Province,
   727  		Locality:           spec.CA.Locality,
   728  		OrganizationalUnit: spec.CA.OrganizationalUnit,
   729  		StreetAddress:      spec.CA.StreetAddress,
   730  		PostalCode:         spec.CA.PostalCode,
   731  	}
   732  }