github.com/hechain20/hechain@v0.0.0-20220316014945-b544036ba106/cmd/osnadmin/main_test.go (about) 1 /* 2 Copyright hechain. All Rights Reserved. 3 4 SPDX-License-Identifier: Apache-2.0 5 */ 6 7 package main 8 9 import ( 10 "crypto/tls" 11 "crypto/x509" 12 "encoding/json" 13 "errors" 14 "fmt" 15 "io/ioutil" 16 "math" 17 "net/http/httptest" 18 "net/url" 19 "os" 20 "path/filepath" 21 22 "github.com/golang/protobuf/proto" 23 "github.com/hechain20/hechain/bccsp" 24 "github.com/hechain20/hechain/cmd/osnadmin/mocks" 25 "github.com/hechain20/hechain/common/crypto/tlsgen" 26 "github.com/hechain20/hechain/orderer/common/channelparticipation" 27 "github.com/hechain20/hechain/orderer/common/localconfig" 28 "github.com/hechain20/hechain/orderer/common/types" 29 "github.com/hechain20/hechain/protoutil" 30 cb "github.com/hyperledger/fabric-protos-go/common" 31 . "github.com/onsi/ginkgo" 32 . "github.com/onsi/gomega" 33 ) 34 35 var _ = Describe("osnadmin", func() { 36 var ( 37 tempDir string 38 ordererCACert string 39 clientCert string 40 clientKey string 41 mockChannelManagement *mocks.ChannelManagement 42 testServer *httptest.Server 43 tlsConfig *tls.Config 44 ordererURL string 45 channelID string 46 ) 47 48 BeforeEach(func() { 49 var err error 50 tempDir, err = ioutil.TempDir("", "osnadmin") 51 Expect(err).NotTo(HaveOccurred()) 52 53 generateCertificates(tempDir) 54 55 ordererCACert = filepath.Join(tempDir, "server-ca.pem") 56 clientCert = filepath.Join(tempDir, "client-cert.pem") 57 clientKey = filepath.Join(tempDir, "client-key.pem") 58 59 channelID = "testing123" 60 61 config := localconfig.ChannelParticipation{ 62 Enabled: true, 63 MaxRequestBodySize: 1024 * 1024, 64 } 65 mockChannelManagement = &mocks.ChannelManagement{} 66 67 h := channelparticipation.NewHTTPHandler(config, mockChannelManagement) 68 Expect(h).NotTo(BeNil()) 69 testServer = httptest.NewUnstartedServer(h) 70 71 cert, err := tls.LoadX509KeyPair( 72 filepath.Join(tempDir, "server-cert.pem"), 73 filepath.Join(tempDir, "server-key.pem"), 74 ) 75 Expect(err).NotTo(HaveOccurred()) 76 77 caCertPool := x509.NewCertPool() 78 clientCAPem, err := ioutil.ReadFile(filepath.Join(tempDir, "client-ca.pem")) 79 Expect(err).NotTo(HaveOccurred()) 80 caCertPool.AppendCertsFromPEM(clientCAPem) 81 82 tlsConfig = &tls.Config{ 83 Certificates: []tls.Certificate{cert}, 84 ClientCAs: caCertPool, 85 ClientAuth: tls.RequireAndVerifyClientCert, 86 } 87 }) 88 89 JustBeforeEach(func() { 90 if tlsConfig != nil { 91 testServer.TLS = tlsConfig 92 testServer.StartTLS() 93 } else { 94 testServer.Start() 95 } 96 97 u, err := url.Parse(testServer.URL) 98 Expect(err).NotTo(HaveOccurred()) 99 ordererURL = u.Host 100 }) 101 102 AfterEach(func() { 103 os.RemoveAll(tempDir) 104 testServer.Close() 105 }) 106 107 Describe("List", func() { 108 BeforeEach(func() { 109 mockChannelManagement.ChannelListReturns(types.ChannelList{ 110 Channels: []types.ChannelInfoShort{ 111 { 112 Name: "participation-trophy", 113 }, 114 { 115 Name: "another-participation-trophy", 116 }, 117 }, 118 SystemChannel: &types.ChannelInfoShort{ 119 Name: "fight-the-system", 120 }, 121 }) 122 123 mockChannelManagement.ChannelInfoReturns(types.ChannelInfo{ 124 Name: "asparagus", 125 ConsensusRelation: "broccoli", 126 Status: "carrot", 127 Height: 987, 128 }, nil) 129 }) 130 131 It("uses the channel participation API to list all application channels and the system channel (when it exists)", func() { 132 args := []string{ 133 "channel", 134 "list", 135 "--orderer-address", ordererURL, 136 "--ca-file", ordererCACert, 137 "--client-cert", clientCert, 138 "--client-key", clientKey, 139 } 140 output, exit, err := executeForArgs(args) 141 expectedOutput := types.ChannelList{ 142 Channels: []types.ChannelInfoShort{ 143 { 144 Name: "participation-trophy", 145 URL: "/participation/v1/channels/participation-trophy", 146 }, 147 { 148 Name: "another-participation-trophy", 149 URL: "/participation/v1/channels/another-participation-trophy", 150 }, 151 }, 152 SystemChannel: &types.ChannelInfoShort{ 153 Name: "fight-the-system", 154 URL: "/participation/v1/channels/fight-the-system", 155 }, 156 } 157 checkStatusOutput(output, exit, err, 200, expectedOutput) 158 }) 159 160 It("uses the channel participation API to list the details of a single channel", func() { 161 args := []string{ 162 "channel", 163 "list", 164 "--orderer-address", ordererURL, 165 "--channelID", "tell-me-your-secrets", 166 "--ca-file", ordererCACert, 167 "--client-cert", clientCert, 168 "--client-key", clientKey, 169 } 170 output, exit, err := executeForArgs(args) 171 expectedOutput := types.ChannelInfo{ 172 Name: "asparagus", 173 URL: "/participation/v1/channels/asparagus", 174 ConsensusRelation: "broccoli", 175 Status: "carrot", 176 Height: 987, 177 } 178 checkStatusOutput(output, exit, err, 200, expectedOutput) 179 }) 180 181 Context("when the channel does not exist", func() { 182 BeforeEach(func() { 183 mockChannelManagement.ChannelInfoReturns(types.ChannelInfo{}, errors.New("eat-your-peas")) 184 }) 185 186 It("returns 404 not found", func() { 187 args := []string{ 188 "channel", 189 "list", 190 "--orderer-address", ordererURL, 191 "--channelID", "tell-me-your-secrets", 192 "--ca-file", ordererCACert, 193 "--client-cert", clientCert, 194 "--client-key", clientKey, 195 } 196 output, exit, err := executeForArgs(args) 197 expectedOutput := types.ErrorResponse{ 198 Error: "eat-your-peas", 199 } 200 checkStatusOutput(output, exit, err, 404, expectedOutput) 201 }) 202 }) 203 204 Context("when TLS is disabled", func() { 205 BeforeEach(func() { 206 tlsConfig = nil 207 }) 208 209 It("uses the channel participation API to list all channels", func() { 210 args := []string{ 211 "channel", 212 "list", 213 "--orderer-address", ordererURL, 214 } 215 output, exit, err := executeForArgs(args) 216 Expect(err).NotTo(HaveOccurred()) 217 Expect(exit).To(Equal(0)) 218 219 expectedOutput := types.ChannelList{ 220 Channels: []types.ChannelInfoShort{ 221 { 222 Name: "participation-trophy", 223 URL: "/participation/v1/channels/participation-trophy", 224 }, 225 { 226 Name: "another-participation-trophy", 227 URL: "/participation/v1/channels/another-participation-trophy", 228 }, 229 }, 230 SystemChannel: &types.ChannelInfoShort{ 231 Name: "fight-the-system", 232 URL: "/participation/v1/channels/fight-the-system", 233 }, 234 } 235 checkStatusOutput(output, exit, err, 200, expectedOutput) 236 }) 237 238 It("uses the channel participation API to list the details of a single channel", func() { 239 args := []string{ 240 "channel", 241 "list", 242 "--orderer-address", ordererURL, 243 "--channelID", "tell-me-your-secrets", 244 } 245 output, exit, err := executeForArgs(args) 246 Expect(err).NotTo(HaveOccurred()) 247 Expect(exit).To(Equal(0)) 248 249 expectedOutput := types.ChannelInfo{ 250 Name: "asparagus", 251 URL: "/participation/v1/channels/asparagus", 252 ConsensusRelation: "broccoli", 253 Status: "carrot", 254 Height: 987, 255 } 256 checkStatusOutput(output, exit, err, 200, expectedOutput) 257 }) 258 }) 259 }) 260 261 Describe("Remove", func() { 262 It("uses the channel participation API to remove a channel", func() { 263 args := []string{ 264 "channel", 265 "remove", 266 "--orderer-address", ordererURL, 267 "--channelID", channelID, 268 "--ca-file", ordererCACert, 269 "--client-cert", clientCert, 270 "--client-key", clientKey, 271 } 272 output, exit, err := executeForArgs(args) 273 Expect(err).NotTo(HaveOccurred()) 274 Expect(exit).To(Equal(0)) 275 Expect(output).To(Equal("Status: 204\n")) 276 }) 277 278 It("uses the channel participation API to remove a channel (without status)", func() { 279 args := []string{ 280 "channel", 281 "remove", 282 "--orderer-address", ordererURL, 283 "--channelID", channelID, 284 "--ca-file", ordererCACert, 285 "--client-cert", clientCert, 286 "--client-key", clientKey, 287 "--no-status", 288 } 289 output, exit, err := executeForArgs(args) 290 Expect(err).NotTo(HaveOccurred()) 291 Expect(exit).To(Equal(0)) 292 Expect(output).To(BeEmpty()) 293 }) 294 295 Context("when the channel does not exist", func() { 296 BeforeEach(func() { 297 mockChannelManagement.RemoveChannelReturns(types.ErrChannelNotExist) 298 }) 299 300 It("returns 404 not found", func() { 301 args := []string{ 302 "channel", 303 "remove", 304 "--ca-file", ordererCACert, 305 "--orderer-address", ordererURL, 306 "--channelID", channelID, 307 "--client-cert", clientCert, 308 "--client-key", clientKey, 309 } 310 output, exit, err := executeForArgs(args) 311 expectedOutput := types.ErrorResponse{ 312 Error: "cannot remove: channel does not exist", 313 } 314 checkStatusOutput(output, exit, err, 404, expectedOutput) 315 }) 316 }) 317 318 Context("when TLS is disabled", func() { 319 BeforeEach(func() { 320 tlsConfig = nil 321 }) 322 323 It("uses the channel participation API to remove a channel", func() { 324 args := []string{ 325 "channel", 326 "remove", 327 "--orderer-address", ordererURL, 328 "--channelID", channelID, 329 } 330 output, exit, err := executeForArgs(args) 331 Expect(err).NotTo(HaveOccurred()) 332 Expect(exit).To(Equal(0)) 333 Expect(output).To(Equal("Status: 204\n")) 334 }) 335 }) 336 }) 337 338 Describe("Join", func() { 339 var blockPath string 340 341 BeforeEach(func() { 342 configBlock := blockWithGroups( 343 map[string]*cb.ConfigGroup{ 344 "Application": {}, 345 }, 346 "testing123", 347 ) 348 blockPath = createBlockFile(tempDir, configBlock) 349 350 mockChannelManagement.JoinChannelReturns(types.ChannelInfo{ 351 Name: "apple", 352 ConsensusRelation: "banana", 353 Status: "orange", 354 Height: 123, 355 }, nil) 356 }) 357 358 It("uses the channel participation API to join a channel", func() { 359 args := []string{ 360 "channel", 361 "join", 362 "--orderer-address", ordererURL, 363 "--channelID", channelID, 364 "--config-block", blockPath, 365 "--ca-file", ordererCACert, 366 "--client-cert", clientCert, 367 "--client-key", clientKey, 368 } 369 output, exit, err := executeForArgs(args) 370 expectedOutput := types.ChannelInfo{ 371 Name: "apple", 372 URL: "/participation/v1/channels/apple", 373 ConsensusRelation: "banana", 374 Status: "orange", 375 Height: 123, 376 } 377 checkStatusOutput(output, exit, err, 201, expectedOutput) 378 }) 379 380 Context("when the block is empty", func() { 381 BeforeEach(func() { 382 blockPath = createBlockFile(tempDir, &cb.Block{}) 383 }) 384 385 It("returns with exit code 1 and prints the error", func() { 386 args := []string{ 387 "channel", 388 "join", 389 "--orderer-address", ordererURL, 390 "--channelID", channelID, 391 "--config-block", blockPath, 392 "--ca-file", ordererCACert, 393 "--client-cert", clientCert, 394 "--client-key", clientKey, 395 } 396 output, exit, err := executeForArgs(args) 397 398 checkFlagError(output, exit, err, "failed to retrieve channel id - block is empty") 399 }) 400 }) 401 402 Context("when the --channelID does not match the channel ID in the block", func() { 403 BeforeEach(func() { 404 channelID = "not-the-channel-youre-looking-for" 405 }) 406 407 It("returns with exit code 1 and prints the error", func() { 408 args := []string{ 409 "channel", 410 "join", 411 "--orderer-address", ordererURL, 412 "--channelID", channelID, 413 "--config-block", blockPath, 414 "--ca-file", ordererCACert, 415 "--client-cert", clientCert, 416 "--client-key", clientKey, 417 } 418 output, exit, err := executeForArgs(args) 419 420 checkFlagError(output, exit, err, "specified --channelID not-the-channel-youre-looking-for does not match channel ID testing123 in config block") 421 }) 422 }) 423 424 Context("when the block isn't a valid config block", func() { 425 BeforeEach(func() { 426 block := &cb.Block{ 427 Data: &cb.BlockData{ 428 Data: [][]byte{ 429 protoutil.MarshalOrPanic(&cb.Envelope{ 430 Payload: protoutil.MarshalOrPanic(&cb.Payload{ 431 Header: &cb.Header{ 432 ChannelHeader: protoutil.MarshalOrPanic(&cb.ChannelHeader{ 433 Type: int32(cb.HeaderType_ENDORSER_TRANSACTION), 434 ChannelId: channelID, 435 }), 436 }, 437 }), 438 }), 439 }, 440 }, 441 } 442 blockPath = createBlockFile(tempDir, block) 443 }) 444 445 It("returns 405 bad request", func() { 446 args := []string{ 447 "channel", 448 "join", 449 "--orderer-address", ordererURL, 450 "--channelID", channelID, 451 "--config-block", blockPath, 452 "--ca-file", ordererCACert, 453 "--client-cert", clientCert, 454 "--client-key", clientKey, 455 } 456 output, exit, err := executeForArgs(args) 457 Expect(err).NotTo(HaveOccurred()) 458 Expect(exit).To(Equal(0)) 459 460 expectedOutput := types.ErrorResponse{ 461 Error: "invalid join block: block is not a config block", 462 } 463 checkStatusOutput(output, exit, err, 400, expectedOutput) 464 }) 465 }) 466 467 Context("when joining the channel fails", func() { 468 BeforeEach(func() { 469 mockChannelManagement.JoinChannelReturns(types.ChannelInfo{}, types.ErrChannelAlreadyExists) 470 }) 471 472 It("returns 405 not allowed", func() { 473 args := []string{ 474 "channel", 475 "join", 476 "--orderer-address", ordererURL, 477 "--channelID", channelID, 478 "--config-block", blockPath, 479 "--ca-file", ordererCACert, 480 "--client-cert", clientCert, 481 "--client-key", clientKey, 482 } 483 output, exit, err := executeForArgs(args) 484 expectedOutput := types.ErrorResponse{ 485 Error: "cannot join: channel already exists", 486 } 487 checkStatusOutput(output, exit, err, 405, expectedOutput) 488 }) 489 490 It("returns 405 not allowed (without status)", func() { 491 args := []string{ 492 "channel", 493 "join", 494 "--orderer-address", ordererURL, 495 "--channelID", channelID, 496 "--config-block", blockPath, 497 "--ca-file", ordererCACert, 498 "--client-cert", clientCert, 499 "--client-key", clientKey, 500 "--no-status", 501 } 502 output, exit, err := executeForArgs(args) 503 expectedOutput := types.ErrorResponse{ 504 Error: "cannot join: channel already exists", 505 } 506 checkOutput(output, exit, err, expectedOutput) 507 }) 508 }) 509 510 Context("when TLS is disabled", func() { 511 BeforeEach(func() { 512 tlsConfig = nil 513 }) 514 515 It("uses the channel participation API to join a channel", func() { 516 args := []string{ 517 "channel", 518 "join", 519 "--orderer-address", ordererURL, 520 "--channelID", channelID, 521 "--config-block", blockPath, 522 } 523 output, exit, err := executeForArgs(args) 524 expectedOutput := types.ChannelInfo{ 525 Name: "apple", 526 URL: "/participation/v1/channels/apple", 527 ConsensusRelation: "banana", 528 Status: "orange", 529 Height: 123, 530 } 531 checkStatusOutput(output, exit, err, 201, expectedOutput) 532 }) 533 }) 534 }) 535 536 Describe("Flags", func() { 537 It("accepts short versions of the --orderer-address, --channelID, and --config-block flags", func() { 538 configBlock := blockWithGroups( 539 map[string]*cb.ConfigGroup{ 540 "Application": {}, 541 }, 542 "testing123", 543 ) 544 blockPath := createBlockFile(tempDir, configBlock) 545 mockChannelManagement.JoinChannelReturns(types.ChannelInfo{ 546 Name: "apple", 547 ConsensusRelation: "banana", 548 Status: "orange", 549 Height: 123, 550 }, nil) 551 552 args := []string{ 553 "channel", 554 "join", 555 "-o", ordererURL, 556 "-c", channelID, 557 "-b", blockPath, 558 "--ca-file", ordererCACert, 559 "--client-cert", clientCert, 560 "--client-key", clientKey, 561 } 562 output, exit, err := executeForArgs(args) 563 expectedOutput := types.ChannelInfo{ 564 Name: "apple", 565 URL: "/participation/v1/channels/apple", 566 ConsensusRelation: "banana", 567 Status: "orange", 568 Height: 123, 569 } 570 checkStatusOutput(output, exit, err, 201, expectedOutput) 571 }) 572 573 Context("when an unknown flag is used", func() { 574 It("returns an error for long flags", func() { 575 _, _, err := executeForArgs([]string{"channel", "list", "--bad-flag"}) 576 Expect(err).To(MatchError("unknown long flag '--bad-flag'")) 577 }) 578 579 It("returns an error for short flags", func() { 580 _, _, err := executeForArgs([]string{"channel", "list", "-z"}) 581 Expect(err).To(MatchError("unknown short flag '-z'")) 582 }) 583 }) 584 585 Context("when the ca cert cannot be read", func() { 586 BeforeEach(func() { 587 ordererCACert = "not-the-ca-cert-youre-looking-for" 588 }) 589 590 It("returns with exit code 1 and prints the error", func() { 591 args := []string{ 592 "channel", 593 "list", 594 "--orderer-address", ordererURL, 595 "--channelID", channelID, 596 "--ca-file", ordererCACert, 597 "--client-cert", clientCert, 598 "--client-key", clientKey, 599 } 600 output, exit, err := executeForArgs(args) 601 checkFlagError(output, exit, err, "reading orderer CA certificate: open not-the-ca-cert-youre-looking-for: no such file or directory") 602 }) 603 }) 604 605 Context("when the ca-file contains a private key instead of certificate(s)", func() { 606 BeforeEach(func() { 607 ordererCACert = clientKey 608 }) 609 610 It("returns with exit code 1 and prints the error", func() { 611 args := []string{ 612 "channel", 613 "remove", 614 "--orderer-address", ordererURL, 615 "--channelID", channelID, 616 "--ca-file", ordererCACert, 617 "--client-cert", clientCert, 618 "--client-key", clientKey, 619 } 620 output, exit, err := executeForArgs(args) 621 checkFlagError(output, exit, err, "failed to add ca-file PEM to cert pool") 622 }) 623 }) 624 625 Context("when the client cert/key pair fail to load", func() { 626 BeforeEach(func() { 627 clientKey = "brussel-sprouts" 628 }) 629 630 It("returns with exit code 1 and prints the error", func() { 631 args := []string{ 632 "channel", 633 "list", 634 "--orderer-address", ordererURL, 635 "--ca-file", ordererCACert, 636 "--client-cert", clientCert, 637 "--client-key", clientKey, 638 } 639 output, exit, err := executeForArgs(args) 640 checkFlagError(output, exit, err, "loading client cert/key pair: open brussel-sprouts: no such file or directory") 641 }) 642 }) 643 644 Context("when the config block cannot be read", func() { 645 var configBlockPath string 646 647 BeforeEach(func() { 648 configBlockPath = "not-the-config-block-youre-looking-for" 649 }) 650 651 It("returns with exit code 1 and prints the error", func() { 652 args := []string{ 653 "channel", 654 "join", 655 "--orderer-address", ordererURL, 656 "--channelID", channelID, 657 "--ca-file", ordererCACert, 658 "--client-cert", clientCert, 659 "--client-key", clientKey, 660 "--config-block", configBlockPath, 661 } 662 output, exit, err := executeForArgs(args) 663 checkFlagError(output, exit, err, "reading config block: open not-the-config-block-youre-looking-for: no such file or directory") 664 }) 665 }) 666 }) 667 668 Describe("Server using intermediate CA", func() { 669 BeforeEach(func() { 670 cert, err := tls.LoadX509KeyPair( 671 filepath.Join(tempDir, "server-intermediate-cert.pem"), 672 filepath.Join(tempDir, "server-intermediate-key.pem"), 673 ) 674 Expect(err).NotTo(HaveOccurred()) 675 tlsConfig.Certificates = []tls.Certificate{cert} 676 677 ordererCACert = filepath.Join(tempDir, "server-ca+intermediate-ca.pem") 678 }) 679 680 It("uses the channel participation API to list all application and and the system channel (when it exists)", func() { 681 args := []string{ 682 "channel", 683 "list", 684 "--orderer-address", ordererURL, 685 "--ca-file", ordererCACert, 686 "--client-cert", clientCert, 687 "--client-key", clientKey, 688 } 689 output, exit, err := executeForArgs(args) 690 expectedOutput := types.ChannelList{ 691 Channels: nil, 692 SystemChannel: nil, 693 } 694 checkStatusOutput(output, exit, err, 200, expectedOutput) 695 }) 696 697 Context("when the ca-file does not include the intermediate CA", func() { 698 BeforeEach(func() { 699 ordererCACert = filepath.Join(tempDir, "server-ca.pem") 700 }) 701 It("returns with exit code 1 and prints the error", func() { 702 args := []string{ 703 "channel", 704 "list", 705 "--orderer-address", ordererURL, 706 "--ca-file", ordererCACert, 707 "--client-cert", clientCert, 708 "--client-key", clientKey, 709 } 710 output, exit, err := executeForArgs(args) 711 checkCLIError(output, exit, err, fmt.Sprintf("Get \"%s/participation/v1/channels\": x509: certificate signed by unknown authority", testServer.URL)) 712 }) 713 }) 714 }) 715 }) 716 717 func checkStatusOutput(output string, exit int, err error, expectedStatus int, expectedOutput interface{}) { 718 Expect(err).NotTo(HaveOccurred()) 719 Expect(exit).To(Equal(0)) 720 json, err := json.MarshalIndent(expectedOutput, "", "\t") 721 Expect(err).NotTo(HaveOccurred()) 722 Expect(output).To(Equal(fmt.Sprintf("Status: %d\n%s\n", expectedStatus, string(json)))) 723 } 724 725 func checkOutput(output string, exit int, err error, expectedOutput interface{}) { 726 Expect(err).NotTo(HaveOccurred()) 727 Expect(exit).To(Equal(0)) 728 json, err := json.MarshalIndent(expectedOutput, "", "\t") 729 Expect(err).NotTo(HaveOccurred()) 730 Expect(output).To(Equal(string(json) + "\n")) 731 } 732 733 func checkFlagError(output string, exit int, err error, expectedError string) { 734 Expect(err).To(MatchError(ContainSubstring(expectedError))) 735 Expect(exit).To(Equal(1)) 736 Expect(output).To(BeEmpty()) 737 } 738 739 func checkCLIError(output string, exit int, err error, expectedError string) { 740 Expect(err).NotTo(HaveOccurred()) 741 Expect(exit).To(Equal(1)) 742 Expect(output).To(Equal(fmt.Sprintf("Error: %s\n", expectedError))) 743 } 744 745 func generateCertificates(tempDir string) { 746 serverCA, err := tlsgen.NewCA() 747 Expect(err).NotTo(HaveOccurred()) 748 err = ioutil.WriteFile(filepath.Join(tempDir, "server-ca.pem"), serverCA.CertBytes(), 0o640) 749 Expect(err).NotTo(HaveOccurred()) 750 serverKeyPair, err := serverCA.NewServerCertKeyPair("127.0.0.1") 751 Expect(err).NotTo(HaveOccurred()) 752 err = ioutil.WriteFile(filepath.Join(tempDir, "server-cert.pem"), serverKeyPair.Cert, 0o640) 753 Expect(err).NotTo(HaveOccurred()) 754 err = ioutil.WriteFile(filepath.Join(tempDir, "server-key.pem"), serverKeyPair.Key, 0o640) 755 Expect(err).NotTo(HaveOccurred()) 756 757 serverIntermediateCA, err := serverCA.NewIntermediateCA() 758 Expect(err).NotTo(HaveOccurred()) 759 err = ioutil.WriteFile(filepath.Join(tempDir, "server-intermediate-ca.pem"), serverIntermediateCA.CertBytes(), 0o640) 760 Expect(err).NotTo(HaveOccurred()) 761 serverIntermediateKeyPair, err := serverIntermediateCA.NewServerCertKeyPair("127.0.0.1") 762 Expect(err).NotTo(HaveOccurred()) 763 err = ioutil.WriteFile(filepath.Join(tempDir, "server-intermediate-cert.pem"), serverIntermediateKeyPair.Cert, 0o640) 764 Expect(err).NotTo(HaveOccurred()) 765 err = ioutil.WriteFile(filepath.Join(tempDir, "server-intermediate-key.pem"), serverIntermediateKeyPair.Key, 0o640) 766 Expect(err).NotTo(HaveOccurred()) 767 768 serverAndIntermediateCABytes := append(serverCA.CertBytes(), serverIntermediateCA.CertBytes()...) 769 err = ioutil.WriteFile(filepath.Join(tempDir, "server-ca+intermediate-ca.pem"), serverAndIntermediateCABytes, 0o640) 770 Expect(err).NotTo(HaveOccurred()) 771 772 clientCA, err := tlsgen.NewCA() 773 Expect(err).NotTo(HaveOccurred()) 774 err = ioutil.WriteFile(filepath.Join(tempDir, "client-ca.pem"), clientCA.CertBytes(), 0o640) 775 Expect(err).NotTo(HaveOccurred()) 776 clientKeyPair, err := clientCA.NewClientCertKeyPair() 777 Expect(err).NotTo(HaveOccurred()) 778 err = ioutil.WriteFile(filepath.Join(tempDir, "client-cert.pem"), clientKeyPair.Cert, 0o640) 779 Expect(err).NotTo(HaveOccurred()) 780 err = ioutil.WriteFile(filepath.Join(tempDir, "client-key.pem"), clientKeyPair.Key, 0o640) 781 Expect(err).NotTo(HaveOccurred()) 782 } 783 784 func blockWithGroups(groups map[string]*cb.ConfigGroup, channelID string) *cb.Block { 785 return &cb.Block{ 786 Data: &cb.BlockData{ 787 Data: [][]byte{ 788 protoutil.MarshalOrPanic(&cb.Envelope{ 789 Payload: protoutil.MarshalOrPanic(&cb.Payload{ 790 Data: protoutil.MarshalOrPanic(&cb.ConfigEnvelope{ 791 Config: &cb.Config{ 792 ChannelGroup: &cb.ConfigGroup{ 793 Groups: groups, 794 Values: map[string]*cb.ConfigValue{ 795 "HashingAlgorithm": { 796 Value: protoutil.MarshalOrPanic(&cb.HashingAlgorithm{ 797 Name: bccsp.SHA256, 798 }), 799 }, 800 "BlockDataHashingStructure": { 801 Value: protoutil.MarshalOrPanic(&cb.BlockDataHashingStructure{ 802 Width: math.MaxUint32, 803 }), 804 }, 805 "OrdererAddresses": { 806 Value: protoutil.MarshalOrPanic(&cb.OrdererAddresses{ 807 Addresses: []string{"localhost"}, 808 }), 809 }, 810 }, 811 }, 812 }, 813 }), 814 Header: &cb.Header{ 815 ChannelHeader: protoutil.MarshalOrPanic(&cb.ChannelHeader{ 816 Type: int32(cb.HeaderType_CONFIG), 817 ChannelId: channelID, 818 }), 819 }, 820 }), 821 }), 822 }, 823 }, 824 } 825 } 826 827 func createBlockFile(tempDir string, configBlock *cb.Block) string { 828 blockBytes, err := proto.Marshal(configBlock) 829 Expect(err).NotTo(HaveOccurred()) 830 blockPath := filepath.Join(tempDir, "block.pb") 831 err = ioutil.WriteFile(blockPath, blockBytes, 0o644) 832 Expect(err).NotTo(HaveOccurred()) 833 return blockPath 834 }