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 }