github.com/kaituanwang/hyperledger@v2.0.1+incompatible/integration/raft/config_test.go (about) 1 /* 2 Copyright IBM Corp All Rights Reserved. 3 4 SPDX-License-Identifier: Apache-2.0 5 */ 6 7 package raft 8 9 import ( 10 "bytes" 11 "crypto/ecdsa" 12 "crypto/rand" 13 "crypto/x509" 14 "encoding/pem" 15 "fmt" 16 "io/ioutil" 17 "os" 18 "path/filepath" 19 "strings" 20 "sync" 21 "syscall" 22 "time" 23 24 docker "github.com/fsouza/go-dockerclient" 25 "github.com/golang/protobuf/proto" 26 "github.com/hyperledger/fabric-protos-go/common" 27 "github.com/hyperledger/fabric-protos-go/msp" 28 protosorderer "github.com/hyperledger/fabric-protos-go/orderer" 29 "github.com/hyperledger/fabric-protos-go/orderer/etcdraft" 30 "github.com/hyperledger/fabric/integration/nwo" 31 "github.com/hyperledger/fabric/integration/nwo/commands" 32 "github.com/hyperledger/fabric/internal/configtxgen/encoder" 33 "github.com/hyperledger/fabric/internal/configtxgen/genesisconfig" 34 "github.com/hyperledger/fabric/protoutil" 35 . "github.com/onsi/ginkgo" 36 . "github.com/onsi/gomega" 37 "github.com/onsi/gomega/gbytes" 38 "github.com/onsi/gomega/gexec" 39 "github.com/tedsuo/ifrit" 40 "github.com/tedsuo/ifrit/ginkgomon" 41 ) 42 43 var _ = Describe("EndToEnd reconfiguration and onboarding", func() { 44 var ( 45 testDir string 46 client *docker.Client 47 network *nwo.Network 48 peer *nwo.Peer 49 50 networkProcess ifrit.Process 51 ordererProcesses []ifrit.Process 52 ordererRunners []*ginkgomon.Runner 53 ) 54 55 BeforeEach(func() { 56 ordererRunners = nil 57 ordererProcesses = nil 58 59 var err error 60 testDir, err = ioutil.TempDir("", "e2e-etcfraft_reconfig") 61 Expect(err).NotTo(HaveOccurred()) 62 63 client, err = docker.NewClientFromEnv() 64 Expect(err).NotTo(HaveOccurred()) 65 }) 66 67 AfterEach(func() { 68 if networkProcess != nil { 69 networkProcess.Signal(syscall.SIGTERM) 70 Eventually(networkProcess.Wait(), network.EventuallyTimeout).Should(Receive()) 71 } 72 if network != nil { 73 network.Cleanup() 74 } 75 for _, ordererInstance := range ordererProcesses { 76 ordererInstance.Signal(syscall.SIGTERM) 77 Eventually(ordererInstance.Wait(), network.EventuallyTimeout).Should(Receive()) 78 } 79 os.RemoveAll(testDir) 80 }) 81 82 Describe("three node etcdraft network with 2 orgs", func() { 83 BeforeEach(func() { 84 network = nwo.New(nwo.MultiNodeEtcdRaft(), testDir, client, StartPort(), components) 85 network.GenerateConfigTree() 86 network.Bootstrap() 87 88 networkRunner := network.NetworkGroupRunner() 89 networkProcess = ifrit.Invoke(networkRunner) 90 Eventually(networkProcess.Ready(), network.EventuallyTimeout).Should(BeClosed()) 91 }) 92 93 // This tests: 94 // 95 // 1. channel creation with raft orderer, 96 // 2. all the nodes on three-node raft cluster are in sync wrt blocks, 97 // 3. raft orderer processes type A config updates and delivers the 98 // config blocks to the peers. 99 It("executes an etcdraft network with 2 orgs and three orderer nodes", func() { 100 orderer1 := network.Orderer("orderer1") 101 orderer2 := network.Orderer("orderer2") 102 orderer3 := network.Orderer("orderer3") 103 peer := network.Peer("Org1", "peer0") 104 blockFile1 := filepath.Join(testDir, "newest_orderer1_block.pb") 105 blockFile2 := filepath.Join(testDir, "newest_orderer2_block.pb") 106 blockFile3 := filepath.Join(testDir, "newest_orderer3_block.pb") 107 108 By("Ordering service system channel is ready") 109 assertBlockReception(map[string]int{ 110 "systemchannel": 0, 111 }, []*nwo.Orderer{orderer1, orderer2, orderer3}, peer, network) 112 113 fetchLatestBlock := func(targetOrderer *nwo.Orderer, blockFile string) { 114 c := commands.ChannelFetch{ 115 ChannelID: "testchannel", 116 Block: "newest", 117 OutputFile: blockFile, 118 } 119 if targetOrderer != nil { 120 c.Orderer = network.OrdererAddress(targetOrderer, nwo.ListenPort) 121 } 122 sess, err := network.PeerAdminSession(peer, c) 123 Expect(err).NotTo(HaveOccurred()) 124 Eventually(sess, network.EventuallyTimeout).Should(gexec.Exit(0)) 125 } 126 127 By("Creating a new channel") 128 network.CreateChannel("testchannel", orderer1, peer) 129 130 // the above can work even if the orderer nodes are not in the same Raft 131 // cluster; we need to verify all the three orderer nodes are in sync wrt 132 // blocks. 133 By("Fetching the latest blocks from all the orderer nodes and testing them for equality") 134 fetchLatestBlock(orderer1, blockFile1) 135 fetchLatestBlock(orderer2, blockFile2) 136 fetchLatestBlock(orderer3, blockFile3) 137 b1 := nwo.UnmarshalBlockFromFile(blockFile1) 138 b2 := nwo.UnmarshalBlockFromFile(blockFile2) 139 b3 := nwo.UnmarshalBlockFromFile(blockFile3) 140 Expect(protoutil.BlockHeaderBytes(b1.Header)).To(Equal(protoutil.BlockHeaderBytes(b2.Header))) 141 Expect(protoutil.BlockHeaderBytes(b2.Header)).To(Equal(protoutil.BlockHeaderBytes(b3.Header))) 142 }) 143 }) 144 145 Describe("Invalid Raft config metadata", func() { 146 It("refuses to start orderer or rejects config update", func() { 147 By("Creating malformed genesis block") 148 network = nwo.New(nwo.BasicEtcdRaft(), testDir, client, StartPort(), components) 149 network.GenerateConfigTree() 150 network.Bootstrap() 151 152 sysProfile := genesisconfig.Load(network.SystemChannel.Profile, network.RootDir) 153 Expect(sysProfile.Orderer).NotTo(BeNil()) 154 sysProfile.Orderer.EtcdRaft.Options.ElectionTick = sysProfile.Orderer.EtcdRaft.Options.HeartbeatTick 155 pgen := encoder.New(sysProfile) 156 genesisBlock := pgen.GenesisBlockForChannel(network.SystemChannel.Name) 157 data, err := proto.Marshal(genesisBlock) 158 Expect(err).NotTo(HaveOccurred()) 159 ioutil.WriteFile(network.OutputBlockPath(network.SystemChannel.Name), data, 0644) 160 161 By("Starting orderer with malformed genesis block") 162 ordererRunner := network.OrdererGroupRunner() 163 process := ifrit.Invoke(ordererRunner) 164 Eventually(process.Wait, network.EventuallyTimeout).Should(Receive()) // orderer process should exit 165 os.RemoveAll(testDir) 166 167 By("Starting orderer with correct genesis block") 168 testDir, err = ioutil.TempDir("", "e2e") 169 Expect(err).NotTo(HaveOccurred()) 170 network = nwo.New(nwo.BasicEtcdRaft(), testDir, client, StartPort(), components) 171 network.GenerateConfigTree() 172 network.Bootstrap() 173 174 orderer := network.Orderer("orderer") 175 runner := network.OrdererRunner(orderer) 176 process = ifrit.Invoke(runner) 177 Eventually(process.Ready, network.EventuallyTimeout).Should(BeClosed()) 178 defer func() { 179 process.Signal(syscall.SIGTERM) 180 Eventually(process.Wait(), network.EventuallyTimeout).Should(Receive()) 181 }() 182 183 By("Waiting for system channel to be ready") 184 findLeader([]*ginkgomon.Runner{runner}) 185 186 By("Creating malformed channel creation config tx") 187 channel := "testchannel" 188 sysProfile = genesisconfig.Load(network.SystemChannel.Profile, network.RootDir) 189 Expect(sysProfile.Orderer).NotTo(BeNil()) 190 appProfile := genesisconfig.Load(network.ProfileForChannel(channel), network.RootDir) 191 Expect(appProfile).NotTo(BeNil()) 192 o := *sysProfile.Orderer 193 appProfile.Orderer = &o 194 appProfile.Orderer.EtcdRaft = proto.Clone(sysProfile.Orderer.EtcdRaft).(*etcdraft.ConfigMetadata) 195 appProfile.Orderer.EtcdRaft.Options.HeartbeatTick = appProfile.Orderer.EtcdRaft.Options.ElectionTick 196 configtx, err := encoder.MakeChannelCreationTransactionWithSystemChannelContext(channel, nil, appProfile, sysProfile) 197 Expect(err).NotTo(HaveOccurred()) 198 data, err = proto.Marshal(configtx) 199 Expect(err).NotTo(HaveOccurred()) 200 ioutil.WriteFile(network.CreateChannelTxPath(channel), data, 0644) 201 202 By("Submitting malformed channel creation config tx to orderer") 203 org1Peer0 := network.Peer("Org1", "peer0") 204 org2Peer0 := network.Peer("Org2", "peer0") 205 206 exitCode := network.CreateChannelExitCode(channel, orderer, org1Peer0, org1Peer0, org2Peer0, orderer) 207 Expect(exitCode).NotTo(Equal(0)) 208 Consistently(process.Wait).ShouldNot(Receive()) // malformed tx should not crash orderer 209 Expect(runner.Err()).To(gbytes.Say(`invalid new config metdadata: ElectionTick \(10\) must be greater than HeartbeatTick \(10\)`)) 210 211 By("Submitting channel config update with illegal value") 212 channel = network.SystemChannel.Name 213 config := nwo.GetConfig(network, org1Peer0, orderer, channel) 214 updatedConfig := proto.Clone(config).(*common.Config) 215 216 consensusTypeConfigValue := updatedConfig.ChannelGroup.Groups["Orderer"].Values["ConsensusType"] 217 consensusTypeValue := &protosorderer.ConsensusType{} 218 Expect(proto.Unmarshal(consensusTypeConfigValue.Value, consensusTypeValue)).To(Succeed()) 219 220 metadata := &etcdraft.ConfigMetadata{} 221 Expect(proto.Unmarshal(consensusTypeValue.Metadata, metadata)).To(Succeed()) 222 223 metadata.Options.HeartbeatTick = 10 224 metadata.Options.ElectionTick = 10 225 226 newMetadata, err := proto.Marshal(metadata) 227 Expect(err).NotTo(HaveOccurred()) 228 consensusTypeValue.Metadata = newMetadata 229 230 updatedConfig.ChannelGroup.Groups["Orderer"].Values["ConsensusType"] = &common.ConfigValue{ 231 ModPolicy: "Admins", 232 Value: protoutil.MarshalOrPanic(consensusTypeValue), 233 } 234 235 sess := nwo.UpdateOrdererConfigSession(network, orderer, channel, config, updatedConfig, org1Peer0, orderer) 236 Eventually(sess, network.EventuallyTimeout).Should(gexec.Exit(1)) 237 Expect(sess.Err).To(gbytes.Say(`invalid new config metdadata: ElectionTick \(10\) must be greater than HeartbeatTick \(10\)`)) 238 }) 239 }) 240 241 When("a single node cluster is expanded", func() { 242 It("is still possible to onboard the new cluster member and then another one with a different TLS root CA", func() { 243 launch := func(o *nwo.Orderer) { 244 runner := network.OrdererRunner(o) 245 ordererRunners = append(ordererRunners, runner) 246 247 process := ifrit.Invoke(runner) 248 Eventually(process.Ready(), network.EventuallyTimeout).Should(BeClosed()) 249 ordererProcesses = append(ordererProcesses, process) 250 } 251 252 network = nwo.New(nwo.BasicEtcdRaft(), testDir, client, StartPort(), components) 253 network.GenerateConfigTree() 254 network.Bootstrap() 255 256 orderer := network.Orderer("orderer") 257 peer = network.Peer("Org1", "peer0") 258 259 By("Launching the orderer") 260 launch(orderer) 261 262 By("Checking that it elected itself as a leader") 263 findLeader(ordererRunners) 264 265 By("Extending the network configuration to add a new orderer") 266 orderer2 := &nwo.Orderer{ 267 Name: "orderer2", 268 Organization: "OrdererOrg", 269 } 270 ports := nwo.Ports{} 271 for _, portName := range nwo.OrdererPortNames() { 272 ports[portName] = network.ReservePort() 273 } 274 network.PortsByOrdererID[orderer2.ID()] = ports 275 network.Orderers = append(network.Orderers, orderer2) 276 network.GenerateOrdererConfig(orderer2) 277 extendNetwork(network) 278 279 secondOrdererCertificatePath := filepath.Join(network.OrdererLocalTLSDir(orderer2), "server.crt") 280 secondOrdererCertificate, err := ioutil.ReadFile(secondOrdererCertificatePath) 281 Expect(err).NotTo(HaveOccurred()) 282 283 By("Adding the second orderer") 284 addConsenter(network, peer, orderer, "systemchannel", etcdraft.Consenter{ 285 ServerTlsCert: secondOrdererCertificate, 286 ClientTlsCert: secondOrdererCertificate, 287 Host: "127.0.0.1", 288 Port: uint32(network.OrdererPort(orderer2, nwo.ClusterPort)), 289 }) 290 291 By("Obtaining the last config block from the orderer") 292 // Get the last config block of the system channel 293 configBlock := nwo.GetConfigBlock(network, peer, orderer, "systemchannel") 294 // Plant it in the file system of orderer2, the new node to be onboarded. 295 err = ioutil.WriteFile(filepath.Join(testDir, "systemchannel_block.pb"), protoutil.MarshalOrPanic(configBlock), 0644) 296 Expect(err).NotTo(HaveOccurred()) 297 298 By("Waiting for the existing orderer to relinquish its leadership") 299 Eventually(ordererRunners[0].Err(), network.EventuallyTimeout).Should(gbytes.Say("1 stepped down to follower since quorum is not active")) 300 Eventually(ordererRunners[0].Err(), network.EventuallyTimeout).Should(gbytes.Say("No leader is present, cluster size is 2")) 301 By("Launching the second orderer") 302 launch(orderer2) 303 By("Waiting for a leader to be re-elected") 304 findLeader(ordererRunners) 305 306 // In the next part of the test we're going to bring up a third node with a different TLS root CA 307 // and we're going to add the TLS root CA *after* we add it to the channel, to ensure 308 // that we can dynamically update TLS root CAs in Raft while membership stays the same. 309 310 By("Creating configuration for a third orderer with a different TLS root CA") 311 orderer3 := &nwo.Orderer{ 312 Name: "orderer3", 313 Organization: "OrdererOrg", 314 } 315 ports = nwo.Ports{} 316 for _, portName := range nwo.OrdererPortNames() { 317 ports[portName] = network.ReservePort() 318 } 319 network.PortsByOrdererID[orderer3.ID()] = ports 320 network.Orderers = append(network.Orderers, orderer3) 321 network.GenerateOrdererConfig(orderer3) 322 323 tmpDir, err := ioutil.TempDir("", "e2e-etcfraft_reconfig") 324 Expect(err).NotTo(HaveOccurred()) 325 defer os.RemoveAll(tmpDir) 326 327 sess, err := network.Cryptogen(commands.Generate{ 328 Config: network.CryptoConfigPath(), 329 Output: tmpDir, 330 }) 331 Expect(err).NotTo(HaveOccurred()) 332 Eventually(sess, network.EventuallyTimeout).Should(gexec.Exit(0)) 333 334 name := network.Orderers[0].Name 335 domain := network.Organization(network.Orderers[0].Organization).Domain 336 nameDomain := fmt.Sprintf("%s.%s", name, domain) 337 ordererTLSPath := filepath.Join(tmpDir, "ordererOrganizations", domain, "orderers", nameDomain, "tls") 338 339 caKeyPath := filepath.Join(tmpDir, "ordererOrganizations", domain, "tlsca", "priv_sk") 340 caCertPath := filepath.Join(tmpDir, "ordererOrganizations", domain, "tlsca", fmt.Sprintf("tlsca.%s-cert.pem", domain)) 341 342 caKey, err := ioutil.ReadFile(caKeyPath) 343 Expect(err).NotTo(HaveOccurred()) 344 345 caCert, err := ioutil.ReadFile(caCertPath) 346 Expect(err).NotTo(HaveOccurred()) 347 348 thirdOrdererCertificatePath := filepath.Join(ordererTLSPath, "server.crt") 349 thirdOrdererCertificate, err := ioutil.ReadFile(thirdOrdererCertificatePath) 350 Expect(err).NotTo(HaveOccurred()) 351 352 By("Changing its subject name") 353 caCert, thirdOrdererCertificate = changeSubjectName(caCert, caKey, thirdOrdererCertificate, "tlsca2") 354 355 By("Updating it on the file system") 356 err = ioutil.WriteFile(caCertPath, caCert, 0644) 357 Expect(err).NotTo(HaveOccurred()) 358 err = ioutil.WriteFile(thirdOrdererCertificatePath, thirdOrdererCertificate, 0644) 359 Expect(err).NotTo(HaveOccurred()) 360 361 By("Overwriting the TLS directory of the new orderer") 362 for _, fileName := range []string{"server.crt", "server.key", "ca.crt"} { 363 dst := filepath.Join(network.OrdererLocalTLSDir(orderer3), fileName) 364 365 data, err := ioutil.ReadFile(filepath.Join(ordererTLSPath, fileName)) 366 Expect(err).NotTo(HaveOccurred()) 367 368 err = ioutil.WriteFile(dst, data, 0644) 369 Expect(err).NotTo(HaveOccurred()) 370 } 371 372 By("Adding the third orderer to the channel") 373 addConsenter(network, peer, orderer, "systemchannel", etcdraft.Consenter{ 374 ServerTlsCert: thirdOrdererCertificate, 375 ClientTlsCert: thirdOrdererCertificate, 376 Host: "127.0.0.1", 377 Port: uint32(network.OrdererPort(orderer3, nwo.ClusterPort)), 378 }) 379 380 By("Obtaining the last config block from the orderer once more to update the bootstrap file") 381 configBlock = nwo.GetConfigBlock(network, peer, orderer, "systemchannel") 382 err = ioutil.WriteFile(filepath.Join(testDir, "systemchannel_block.pb"), protoutil.MarshalOrPanic(configBlock), 0644) 383 Expect(err).NotTo(HaveOccurred()) 384 385 By("Launching the third orderer") 386 launch(orderer3) 387 388 By("Expanding the TLS root CA certificates") 389 nwo.UpdateOrdererMSP(network, peer, orderer, "systemchannel", "OrdererOrg", func(config msp.FabricMSPConfig) msp.FabricMSPConfig { 390 config.TlsRootCerts = append(config.TlsRootCerts, caCert) 391 return config 392 }) 393 394 By("Waiting for orderer3 to see the leader") 395 leader := findLeader([]*ginkgomon.Runner{ordererRunners[2]}) 396 leaderIndex := leader - 1 397 398 fmt.Fprint(GinkgoWriter, "Killing the leader", leader) 399 ordererProcesses[leaderIndex].Signal(syscall.SIGTERM) 400 Eventually(ordererProcesses[leaderIndex].Wait(), network.EventuallyTimeout).Should(Receive()) 401 402 By("Ensuring orderer3 detects leader loss") 403 leaderLoss := fmt.Sprintf("Raft leader changed: %d -> 0", leader) 404 Eventually(ordererRunners[2].Err(), network.EventuallyTimeout, time.Second).Should(gbytes.Say(leaderLoss)) 405 406 By("Waiting for the leader to be re-elected") 407 findLeader([]*ginkgomon.Runner{ordererRunners[2]}) 408 }) 409 }) 410 411 When("the orderer certificates are all rotated", func() { 412 It("is possible to rotate certificate by adding & removing cert in single config", func() { 413 layout := nwo.MultiNodeEtcdRaft() 414 network = nwo.New(layout, testDir, client, StartPort(), components) 415 network.GenerateConfigTree() 416 network.Bootstrap() 417 418 o1, o2, o3 := network.Orderer("orderer1"), network.Orderer("orderer2"), network.Orderer("orderer3") 419 orderers := []*nwo.Orderer{o1, o2, o3} 420 peer = network.Peer("Org1", "peer0") 421 422 By("Launching the orderers") 423 for _, o := range orderers { 424 runner := network.OrdererRunner(o) 425 ordererRunners = append(ordererRunners, runner) 426 process := ifrit.Invoke(runner) 427 ordererProcesses = append(ordererProcesses, process) 428 } 429 430 for _, ordererProc := range ordererProcesses { 431 Eventually(ordererProc.Ready(), network.EventuallyTimeout).Should(BeClosed()) 432 } 433 434 By("Finding leader") 435 leader := findLeader(ordererRunners) 436 leaderIndex := leader - 1 437 blockSeq := 0 438 439 By("Checking that all orderers are online") 440 assertBlockReception(map[string]int{ 441 "systemchannel": blockSeq, 442 }, orderers, peer, network) 443 444 By("Preparing new certificates for the orderer nodes") 445 extendNetwork(network) 446 certificateRotations := refreshOrdererPEMs(network) 447 448 swap := func(o *nwo.Orderer, certificate []byte, c etcdraft.Consenter) { 449 updateEtcdRaftMetadata(network, peer, o, network.SystemChannel.Name, func(metadata *etcdraft.ConfigMetadata) { 450 var newConsenters []*etcdraft.Consenter 451 for _, consenter := range metadata.Consenters { 452 if bytes.Equal(consenter.ClientTlsCert, certificate) || bytes.Equal(consenter.ServerTlsCert, certificate) { 453 continue 454 } 455 newConsenters = append(newConsenters, consenter) 456 } 457 newConsenters = append(newConsenters, &c) 458 459 metadata.Consenters = newConsenters 460 }) 461 blockSeq++ 462 } 463 464 rotate := func(target int) { 465 // submit a config tx to rotate the cert of an orderer. 466 // The orderer being rotated is going to be unavailable 467 // eventually, therefore submitter of tx is different 468 // from the target, so the configuration can be reliably 469 // checked. 470 submitter := (target + 1) % 3 471 rotation := certificateRotations[target] 472 targetOrderer := network.Orderers[target] 473 remainder := func() []*nwo.Orderer { 474 var ret []*nwo.Orderer 475 for i, o := range network.Orderers { 476 if i == target { 477 continue 478 } 479 ret = append(ret, o) 480 } 481 return ret 482 }() 483 submitterOrderer := network.Orderers[submitter] 484 port := network.OrdererPort(targetOrderer, nwo.ClusterPort) 485 486 fmt.Fprintf(GinkgoWriter, "Rotating certificate of orderer node %d\n", target+1) 487 swap(submitterOrderer, rotation.oldCert, etcdraft.Consenter{ 488 ServerTlsCert: rotation.newCert, 489 ClientTlsCert: rotation.newCert, 490 Host: "127.0.0.1", 491 Port: uint32(port), 492 }) 493 494 By("Waiting for all orderers to sync") 495 assertBlockReception(map[string]int{ 496 "systemchannel": blockSeq, 497 }, remainder, peer, network) 498 499 By("Waiting for rotated node to be unavailable") 500 c := commands.ChannelFetch{ 501 ChannelID: network.SystemChannel.Name, 502 Block: "newest", 503 OutputFile: "/dev/null", 504 Orderer: network.OrdererAddress(targetOrderer, nwo.ClusterPort), 505 } 506 Eventually(func() string { 507 sess, err := network.OrdererAdminSession(targetOrderer, peer, c) 508 Expect(err).NotTo(HaveOccurred()) 509 Eventually(sess, network.EventuallyTimeout).Should(gexec.Exit()) 510 if sess.ExitCode() != 0 { 511 return fmt.Sprintf("exit code is %d: %s", sess.ExitCode(), string(sess.Err.Contents())) 512 } 513 sessErr := string(sess.Err.Contents()) 514 expected := fmt.Sprintf("Received block: %d", blockSeq) 515 if strings.Contains(sessErr, expected) { 516 return "" 517 } 518 return sessErr 519 }, network.EventuallyTimeout, time.Second).ShouldNot(BeEmpty()) 520 521 By("Killing the orderer") 522 ordererProcesses[target].Signal(syscall.SIGTERM) 523 Eventually(ordererProcesses[target].Wait(), network.EventuallyTimeout).Should(Receive()) 524 525 By("Starting the orderer again") 526 ordererRunner := network.OrdererRunner(targetOrderer) 527 ordererRunners = append(ordererRunners, ordererRunner) 528 ordererProcesses[target] = ifrit.Invoke(ordererRunner) 529 Eventually(ordererProcesses[target].Ready(), network.EventuallyTimeout).Should(BeClosed()) 530 531 By("And waiting for it to stabilize") 532 assertBlockReception(map[string]int{ 533 "systemchannel": blockSeq, 534 }, orderers, peer, network) 535 } 536 537 By(fmt.Sprintf("Rotating cert on leader %d", leader)) 538 rotate(leaderIndex) 539 540 By("Rotating certificates of other orderer nodes") 541 for i := range certificateRotations { 542 if i != leaderIndex { 543 rotate(i) 544 } 545 } 546 }) 547 548 It("is still possible to onboard new orderers", func() { 549 // In this test, we have 3 OSNs and we rotate their TLS certificates one by one, 550 // by adding the future certificate to the channel, killing the OSN to make it 551 // grab the new certificate, and then removing the old certificate from the channel. 552 553 // After we completely rotate all the certificates, we put the last config block 554 // of the system channel into the file system of orderer4, and then launch it, 555 // and ensure it onboards and pulls channels testchannel only, and not testchannel2 556 // which it is not part of. 557 558 // Consenter i after its certificate is rotated is denoted as consenter i' 559 // The blocks of channels contain the following updates: 560 // | system channel height | testchannel height | update description 561 // ------------------------------------------------------------------------ 562 // 0 | 2 | 1 | adding consenter 1' 563 // 1 | 3 | 2 | removing consenter 1 564 // 2 | 4 | 3 | adding consenter 2' 565 // 3 | 5 | 4 | removing consenter 2 566 // 4 | 6 | 5 | adding consenter 3' 567 // 5 | 7 | 6 | removing consenter 3 568 // 6 | 8 | 6 | creating channel testchannel2 569 // 7 | 9 | 6 | creating channel testchannel3 570 // 8 | 10 | 7 | adding consenter 4 571 572 layout := nwo.MultiNodeEtcdRaft() 573 layout.Channels = append(layout.Channels, &nwo.Channel{ 574 Name: "testchannel2", 575 Profile: "TwoOrgsChannel", 576 }, &nwo.Channel{ 577 Name: "testchannel3", 578 Profile: "TwoOrgsChannel", 579 }) 580 581 network = nwo.New(layout, testDir, client, StartPort(), components) 582 network.GenerateConfigTree() 583 network.Bootstrap() 584 585 o1, o2, o3 := network.Orderer("orderer1"), network.Orderer("orderer2"), network.Orderer("orderer3") 586 orderers := []*nwo.Orderer{o1, o2, o3} 587 peer = network.Peer("Org1", "peer0") 588 589 By("Launching the orderers") 590 for _, o := range orderers { 591 runner := network.OrdererRunner(o) 592 ordererRunners = append(ordererRunners, runner) 593 process := ifrit.Invoke(runner) 594 ordererProcesses = append(ordererProcesses, process) 595 } 596 597 for _, ordererProc := range ordererProcesses { 598 Eventually(ordererProc.Ready(), network.EventuallyTimeout).Should(BeClosed()) 599 } 600 601 By("Checking that all orderers are online") 602 assertBlockReception(map[string]int{ 603 "systemchannel": 0, 604 }, orderers, peer, network) 605 606 By("Creating a channel and checking that all orderers got the channel creation") 607 network.CreateChannel("testchannel", network.Orderers[0], peer) 608 assertBlockReception(map[string]int{ 609 "systemchannel": 1, 610 "testchannel": 0, 611 }, orderers, peer, network) 612 613 By("Preparing new certificates for the orderer nodes") 614 extendNetwork(network) 615 certificateRotations := refreshOrdererPEMs(network) 616 617 expectedBlockHeightsPerChannel := []map[string]int{ 618 {"systemchannel": 2, "testchannel": 1}, 619 {"systemchannel": 3, "testchannel": 2}, 620 {"systemchannel": 4, "testchannel": 3}, 621 {"systemchannel": 5, "testchannel": 4}, 622 {"systemchannel": 6, "testchannel": 5}, 623 {"systemchannel": 7, "testchannel": 6}, 624 } 625 626 for i, rotation := range certificateRotations { 627 o := network.Orderers[i] 628 port := network.OrdererPort(o, nwo.ClusterPort) 629 630 By(fmt.Sprintf("Adding the future certificate of orderer node %d", i)) 631 for _, channelName := range []string{"systemchannel", "testchannel"} { 632 addConsenter(network, peer, o, channelName, etcdraft.Consenter{ 633 ServerTlsCert: rotation.newCert, 634 ClientTlsCert: rotation.newCert, 635 Host: "127.0.0.1", 636 Port: uint32(port), 637 }) 638 } 639 640 By("Waiting for all orderers to sync") 641 assertBlockReception(expectedBlockHeightsPerChannel[i*2], orderers, peer, network) 642 643 By("Killing the orderer") 644 ordererProcesses[i].Signal(syscall.SIGTERM) 645 Eventually(ordererProcesses[i].Wait(), network.EventuallyTimeout).Should(Receive()) 646 647 By("Starting the orderer again") 648 ordererRunner := network.OrdererRunner(orderers[i]) 649 ordererRunners = append(ordererRunners, ordererRunner) 650 ordererProcesses[i] = ifrit.Invoke(ordererRunner) 651 Eventually(ordererProcesses[i].Ready(), network.EventuallyTimeout).Should(BeClosed()) 652 653 By("And waiting for it to stabilize") 654 assertBlockReception(expectedBlockHeightsPerChannel[i*2], orderers, peer, network) 655 656 By("Removing the previous certificate of the old orderer") 657 for _, channelName := range []string{"systemchannel", "testchannel"} { 658 removeConsenter(network, peer, network.Orderers[(i+1)%len(network.Orderers)], channelName, rotation.oldCert) 659 } 660 661 By("Waiting for all orderers to sync") 662 assertBlockReception(expectedBlockHeightsPerChannel[i*2+1], orderers, peer, network) 663 } 664 665 By("Creating testchannel2") 666 network.CreateChannel("testchannel2", network.Orderers[0], peer) 667 assertBlockReception(map[string]int{ 668 "systemchannel": 8, 669 }, orderers, peer, network) 670 671 By("Creating testchannel3") 672 network.CreateChannel("testchannel3", network.Orderers[0], peer) 673 assertBlockReception(map[string]int{ 674 "systemchannel": 9, 675 }, orderers, peer, network) 676 677 o4 := &nwo.Orderer{ 678 Name: "orderer4", 679 Organization: "OrdererOrg", 680 } 681 682 By("Configuring orderer4 in the network") 683 ports := nwo.Ports{} 684 for _, portName := range nwo.OrdererPortNames() { 685 ports[portName] = network.ReservePort() 686 } 687 network.PortsByOrdererID[o4.ID()] = ports 688 689 network.Orderers = append(network.Orderers, o4) 690 network.GenerateOrdererConfig(network.Orderer("orderer4")) 691 692 By("Adding orderer4 to the channels") 693 orderer4CertificatePath := filepath.Join(network.OrdererLocalTLSDir(o4), "server.crt") 694 orderer4Certificate, err := ioutil.ReadFile(orderer4CertificatePath) 695 Expect(err).NotTo(HaveOccurred()) 696 for _, channel := range []string{"systemchannel", "testchannel"} { 697 addConsenter(network, peer, o1, channel, etcdraft.Consenter{ 698 ServerTlsCert: orderer4Certificate, 699 ClientTlsCert: orderer4Certificate, 700 Host: "127.0.0.1", 701 Port: uint32(network.OrdererPort(o4, nwo.ClusterPort)), 702 }) 703 } 704 705 By("Ensuring all orderers know about orderer4's addition") 706 assertBlockReception(map[string]int{ 707 "systemchannel": 10, 708 "testchannel": 7, 709 }, orderers, peer, network) 710 711 By("Broadcasting envelope to testchannel") 712 env := CreateBroadcastEnvelope(network, peer, "testchannel", []byte("hello")) 713 resp, err := nwo.Broadcast(network, o1, env) 714 Expect(err).NotTo(HaveOccurred()) 715 Expect(resp.Status).To(Equal(common.Status_SUCCESS)) 716 717 assertBlockReception(map[string]int{ 718 "testchannel": 8, 719 }, orderers, peer, network) 720 721 By("Corrupting the readers policy of testchannel3") 722 revokeReaderAccess(network, "testchannel3", o3, peer) 723 724 // Get the last config block of the system channel 725 configBlock := nwo.GetConfigBlock(network, peer, o1, "systemchannel") 726 // Plant it in the file system of orderer4, the new node to be onboarded. 727 err = ioutil.WriteFile(filepath.Join(testDir, "systemchannel_block.pb"), protoutil.MarshalOrPanic(configBlock), 0644) 728 Expect(err).NotTo(HaveOccurred()) 729 730 By("Launching orderer4") 731 orderers = append(orderers, o4) 732 orderer4Runner := network.OrdererRunner(o4) 733 ordererRunners = append(ordererRunners, orderer4Runner) 734 // Spawn orderer4's process 735 o4process := ifrit.Invoke(orderer4Runner) 736 Eventually(o4process.Ready(), network.EventuallyTimeout).Should(BeClosed()) 737 ordererProcesses = append(ordererProcesses, o4process) 738 739 By("And waiting for it to sync with the rest of the orderers") 740 assertBlockReception(map[string]int{ 741 "systemchannel": 10, 742 "testchannel": 8, 743 }, orderers, peer, network) 744 745 By("Ensuring orderer4 doesn't serve testchannel2 and testchannel3") 746 env = CreateBroadcastEnvelope(network, peer, "testchannel2", []byte("hello")) 747 resp, err = nwo.Broadcast(network, o4, env) 748 Expect(err).NotTo(HaveOccurred()) 749 Expect(resp.Status).To(Equal(common.Status_SERVICE_UNAVAILABLE)) 750 751 env = CreateBroadcastEnvelope(network, peer, "testchannel3", []byte("hello")) 752 resp, err = nwo.Broadcast(network, o4, env) 753 Expect(err).NotTo(HaveOccurred()) 754 Expect(resp.Status).To(Equal(common.Status_SERVICE_UNAVAILABLE)) 755 756 belongRegex := `\QI do not belong to channel testchannel2 or am forbidden pulling it (not in the channel), skipping chain retrieval\E` 757 forbiddenRegex := `\QI do not belong to channel testchannel3 or am forbidden pulling it (forbidden pulling the channel), skipping chain retrieval\E` 758 759 Expect(orderer4Runner.Err()).To(gbytes.Say(belongRegex + "|" + forbiddenRegex)) 760 Expect(orderer4Runner.Err()).To(gbytes.Say(belongRegex + "|" + forbiddenRegex)) 761 762 By("Adding orderer4 to testchannel2") 763 addConsenter(network, peer, o1, "testchannel2", etcdraft.Consenter{ 764 ServerTlsCert: orderer4Certificate, 765 ClientTlsCert: orderer4Certificate, 766 Host: "127.0.0.1", 767 Port: uint32(network.OrdererPort(o4, nwo.ClusterPort)), 768 }) 769 770 By("Waiting for orderer4 and to replicate testchannel2") 771 assertBlockReception(map[string]int{ 772 "testchannel2": 1, 773 }, []*nwo.Orderer{o4}, peer, network) 774 775 By("Ensuring orderer4 doesn't have any errors in the logs") 776 Consistently(orderer4Runner.Err()).ShouldNot(gbytes.Say("ERRO")) 777 778 By("Submitting a transaction through orderer4") 779 env = CreateBroadcastEnvelope(network, peer, "testchannel2", []byte("hello")) 780 resp, err = nwo.Broadcast(network, o4, env) 781 Expect(err).NotTo(HaveOccurred()) 782 Expect(resp.Status).To(Equal(common.Status_SUCCESS)) 783 784 By("And ensuring it is propagated amongst all orderers") 785 assertBlockReception(map[string]int{ 786 "testchannel2": 2, 787 }, orderers, peer, network) 788 }) 789 }) 790 791 When("an orderer channel is created with a subset of nodes", func() { 792 It("is still possible to onboard a new orderer to the channel", func() { 793 network = nwo.New(nwo.MultiNodeEtcdRaft(), testDir, client, StartPort(), components) 794 network.Profiles = append(network.Profiles, &nwo.Profile{ 795 Name: "myprofile", 796 Consortium: "SampleConsortium", 797 Orderers: []string{"orderer1"}, 798 Organizations: []string{"Org1"}, 799 }) 800 network.Channels = append(network.Channels, &nwo.Channel{ 801 Name: "mychannel", 802 Profile: "myprofile", 803 BaseProfile: "SampleDevModeEtcdRaft", 804 }) 805 806 network.GenerateConfigTree() 807 network.Bootstrap() 808 809 o1, o2, o3 := network.Orderer("orderer1"), network.Orderer("orderer2"), network.Orderer("orderer3") 810 orderers := []*nwo.Orderer{o1, o2, o3} 811 peer = network.Peer("Org1", "peer0") 812 813 By("Launching the orderers") 814 for _, o := range orderers { 815 runner := network.OrdererRunner(o) 816 ordererRunners = append(ordererRunners, runner) 817 process := ifrit.Invoke(runner) 818 ordererProcesses = append(ordererProcesses, process) 819 } 820 821 for _, ordererProc := range ordererProcesses { 822 Eventually(ordererProc.Ready(), network.EventuallyTimeout).Should(BeClosed()) 823 } 824 825 By("Waiting for the system channel to be available") 826 assertBlockReception(map[string]int{ 827 "systemchannel": 0, 828 }, orderers, peer, network) 829 830 By("Creating a channel with a subset of orderers") 831 network.CreateChannel("mychannel", o1, peer, peer, o1) 832 833 By("Waiting for the channel to be available") 834 assertBlockReception(map[string]int{ 835 "mychannel": 0, 836 }, []*nwo.Orderer{o1}, peer, network) 837 838 By("Ensuring only orderer1 services the channel") 839 ensureEvicted(o2, peer, network, "mychannel") 840 ensureEvicted(o3, peer, network, "mychannel") 841 842 By("Adding orderer2 to the channel") 843 ordererCertificatePath := filepath.Join(network.OrdererLocalTLSDir(o2), "server.crt") 844 ordererCertificate, err := ioutil.ReadFile(ordererCertificatePath) 845 Expect(err).NotTo(HaveOccurred()) 846 847 addConsenter(network, peer, o1, "mychannel", etcdraft.Consenter{ 848 ServerTlsCert: ordererCertificate, 849 ClientTlsCert: ordererCertificate, 850 Host: "127.0.0.1", 851 Port: uint32(network.OrdererPort(o2, nwo.ClusterPort)), 852 }) 853 854 By("Waiting for orderer2 to join the channel") 855 assertBlockReception(map[string]int{ 856 "mychannel": 1, 857 }, []*nwo.Orderer{o1, o2}, peer, network) 858 859 By("Adding orderer3 to the channel") 860 ordererCertificatePath = filepath.Join(network.OrdererLocalTLSDir(o3), "server.crt") 861 ordererCertificate, err = ioutil.ReadFile(ordererCertificatePath) 862 Expect(err).NotTo(HaveOccurred()) 863 addConsenter(network, peer, o1, "mychannel", etcdraft.Consenter{ 864 ServerTlsCert: ordererCertificate, 865 ClientTlsCert: ordererCertificate, 866 Host: "127.0.0.1", 867 Port: uint32(network.OrdererPort(o3, nwo.ClusterPort)), 868 }) 869 870 By("Waiting for orderer3 to join the channel") 871 assertBlockReception(map[string]int{ 872 "mychannel": 2, 873 }, orderers, peer, network) 874 }) 875 }) 876 877 When("orderer cluster is not healthy", func() { 878 var ( 879 o1, o2 *nwo.Orderer 880 ) 881 882 BeforeEach(func() { 883 network = nwo.New(nwo.MultiNodeEtcdRaft(), testDir, client, StartPort(), components) 884 network.GenerateConfigTree() 885 network.Bootstrap() 886 887 o1, o2 = network.Orderer("orderer1"), network.Orderer("orderer2") 888 orderers := []*nwo.Orderer{o1, o2} 889 By("Launching the orderers") 890 for _, o := range orderers { 891 runner := network.OrdererRunner(o) 892 ordererRunners = append(ordererRunners, runner) 893 process := ifrit.Invoke(runner) 894 ordererProcesses = append(ordererProcesses, process) 895 } 896 897 for _, ordererProc := range ordererProcesses { 898 Eventually(ordererProc.Ready(), network.EventuallyTimeout).Should(BeClosed()) 899 } 900 }) 901 902 AfterEach(func() { 903 for _, ordererInstance := range ordererProcesses { 904 ordererInstance.Signal(syscall.SIGTERM) 905 Eventually(ordererInstance.Wait(), network.EventuallyTimeout).Should(Receive()) 906 } 907 }) 908 909 It("refuses to reconfig if it results in quorum loss", func() { 910 By("Waiting for them to elect a leader") 911 findLeader(ordererRunners) 912 913 extendNetwork(network) 914 certificatesOfOrderers := refreshOrdererPEMs(network) 915 916 By("Removing alive node from 2/3 cluster") 917 peer := network.Peer("Org1", "peer0") 918 current, updated := consenterRemover(network, peer, o2, network.SystemChannel.Name, certificatesOfOrderers[1].oldCert) 919 Eventually(func() []byte { 920 sess := nwo.UpdateOrdererConfigSession(network, o2, network.SystemChannel.Name, current, updated, peer, o2) 921 Eventually(sess, network.EventuallyTimeout).Should(gexec.Exit(1)) 922 return sess.Err.Contents() 923 }, network.EventuallyTimeout).Should(ContainSubstring("2 out of 3 nodes are alive, configuration will result in quorum loss")) 924 925 By("Adding node to 2/3 cluster") 926 current, updated = consenterAdder( 927 network, 928 peer, 929 o2, 930 network.SystemChannel.Name, 931 etcdraft.Consenter{ 932 ServerTlsCert: certificatesOfOrderers[0].newCert, 933 ClientTlsCert: certificatesOfOrderers[0].newCert, 934 Host: "127.0.0.1", 935 Port: uint32(network.OrdererPort(o1, nwo.ListenPort)), 936 }, 937 ) 938 sess := nwo.UpdateOrdererConfigSession(network, o2, network.SystemChannel.Name, current, updated, peer, o2) 939 Eventually(sess, network.EventuallyTimeout).Should(gexec.Exit(1)) 940 Expect(string(sess.Err.Contents())).To(ContainSubstring("2 out of 3 nodes are alive, configuration will result in quorum loss")) 941 }) 942 }) 943 944 When("an orderer node is evicted", func() { 945 BeforeEach(func() { 946 ordererRunners = nil 947 ordererProcesses = nil 948 949 network = nwo.New(nwo.MultiNodeEtcdRaft(), testDir, client, StartPort(), components) 950 network.GenerateConfigTree() 951 network.Bootstrap() 952 953 o1, o2, o3 := network.Orderer("orderer1"), network.Orderer("orderer2"), network.Orderer("orderer3") 954 orderers := []*nwo.Orderer{o1, o2, o3} 955 peer = network.Peer("Org1", "peer0") 956 957 By("Launching the orderers") 958 for _, o := range orderers { 959 runner := network.OrdererRunner(o) 960 ordererRunners = append(ordererRunners, runner) 961 process := ifrit.Invoke(runner) 962 ordererProcesses = append(ordererProcesses, process) 963 } 964 965 for _, ordererProc := range ordererProcesses { 966 Eventually(ordererProc.Ready(), network.EventuallyTimeout).Should(BeClosed()) 967 } 968 }) 969 970 AfterEach(func() { 971 for _, ordererInstance := range ordererProcesses { 972 ordererInstance.Signal(syscall.SIGTERM) 973 Eventually(ordererInstance.Wait(), network.EventuallyTimeout).Should(Receive()) 974 } 975 }) 976 977 It("doesn't complain and does it obediently", func() { 978 o1, o2, o3 := network.Orderer("orderer1"), network.Orderer("orderer2"), network.Orderer("orderer3") 979 orderers := []*nwo.Orderer{o1, o2, o3} 980 981 By("Waiting for them to elect a leader") 982 firstEvictedNode := findLeader(ordererRunners) - 1 983 984 By("Removing the leader from 3-node channel") 985 server1CertBytes, err := ioutil.ReadFile(filepath.Join(network.OrdererLocalTLSDir(orderers[firstEvictedNode]), "server.crt")) 986 Expect(err).To(Not(HaveOccurred())) 987 988 removeConsenter(network, peer, network.Orderers[(firstEvictedNode+1)%3], "systemchannel", server1CertBytes) 989 990 var survivedOrdererRunners []*ginkgomon.Runner 991 for i := range orderers { 992 if i == firstEvictedNode { 993 continue 994 } 995 996 survivedOrdererRunners = append(survivedOrdererRunners, ordererRunners[i]) 997 } 998 999 secondEvictedNode := findLeader(survivedOrdererRunners) - 1 1000 1001 var surviver int 1002 for i := range orderers { 1003 if i != firstEvictedNode && i != secondEvictedNode { 1004 surviver = i 1005 break 1006 } 1007 } 1008 1009 const stopMsg = "Raft node stopped channel=systemchannel" 1010 fmt.Fprintln(GinkgoWriter, "Ensuring the evicted orderer stops rafting on channel systemchannel") 1011 Eventually(ordererRunners[firstEvictedNode].Err(), network.EventuallyTimeout, time.Second).Should(gbytes.Say(stopMsg)) 1012 1013 By("Ensuring the evicted orderer now doesn't serve clients") 1014 ensureEvicted(orderers[firstEvictedNode], peer, network, "systemchannel") 1015 1016 By("Removing the leader from 2-node channel") 1017 server2CertBytes, err := ioutil.ReadFile(filepath.Join(network.OrdererLocalTLSDir(orderers[secondEvictedNode]), "server.crt")) 1018 Expect(err).To(Not(HaveOccurred())) 1019 1020 removeConsenter(network, peer, orderers[surviver], "systemchannel", server2CertBytes) 1021 findLeader([]*ginkgomon.Runner{ordererRunners[surviver]}) 1022 1023 fmt.Fprintln(GinkgoWriter, "Ensuring the other orderer detect the eviction of the node on channel systemchannel") 1024 Eventually(ordererRunners[secondEvictedNode].Err(), network.EventuallyTimeout, time.Second).Should(gbytes.Say(stopMsg)) 1025 1026 By("Ensuring the evicted orderer now doesn't serve clients") 1027 ensureEvicted(orderers[secondEvictedNode], peer, network, "systemchannel") 1028 1029 By("Re-adding first evicted orderer") 1030 addConsenter(network, peer, network.Orderers[surviver], "systemchannel", etcdraft.Consenter{ 1031 Host: "127.0.0.1", 1032 Port: uint32(network.OrdererPort(orderers[firstEvictedNode], nwo.ClusterPort)), 1033 ClientTlsCert: server1CertBytes, 1034 ServerTlsCert: server1CertBytes, 1035 }) 1036 1037 By("Ensuring re-added orderer starts serving system channel") 1038 assertBlockReception(map[string]int{ 1039 "systemchannel": 3, 1040 }, []*nwo.Orderer{orderers[firstEvictedNode]}, peer, network) 1041 1042 env := CreateBroadcastEnvelope(network, orderers[secondEvictedNode], network.SystemChannel.Name, []byte("foo")) 1043 resp, err := nwo.Broadcast(network, orderers[surviver], env) 1044 Expect(err).NotTo(HaveOccurred()) 1045 Expect(resp.Status).To(Equal(common.Status_SUCCESS)) 1046 }) 1047 1048 It("notices it even if it is down at the time of its eviction", func() { 1049 o1 := network.Orderer("orderer1") 1050 o2 := network.Orderer("orderer2") 1051 o3 := network.Orderer("orderer3") 1052 1053 orderers := []*nwo.Orderer{o1, o2, o3} 1054 1055 By("Waiting for them to elect a leader") 1056 findLeader(ordererRunners) 1057 1058 By("Creating a channel") 1059 network.CreateChannel("testchannel", o1, peer) 1060 1061 assertBlockReception(map[string]int{ 1062 "testchannel": 0, 1063 "systemchannel": 1, 1064 }, []*nwo.Orderer{o1, o2, o3}, peer, network) 1065 1066 By("Killing the orderer") 1067 ordererProcesses[0].Signal(syscall.SIGTERM) 1068 Eventually(ordererProcesses[0].Wait(), network.EventuallyTimeout).Should(Receive()) 1069 1070 // We need to wait for stabilization, as we might have killed the leader OSN. 1071 By("Waiting for the channel to stabilize after killing the orderer") 1072 assertBlockReception(map[string]int{ 1073 "testchannel": 0, 1074 "systemchannel": 1, 1075 }, []*nwo.Orderer{o2, o3}, peer, network) 1076 1077 By("Removing the first orderer from an application channel") 1078 extendNetwork(network) 1079 certificatesOfOrderers := refreshOrdererPEMs(network) 1080 removeConsenter(network, peer, o2, "testchannel", certificatesOfOrderers[0].oldCert) 1081 1082 certPath := certificatesOfOrderers[0].dstFile 1083 keyFile := strings.Replace(certPath, "server.crt", "server.key", -1) 1084 err := ioutil.WriteFile(certPath, certificatesOfOrderers[0].oldCert, 0644) 1085 Expect(err).To(Not(HaveOccurred())) 1086 err = ioutil.WriteFile(keyFile, certificatesOfOrderers[0].oldKey, 0644) 1087 Expect(err).To(Not(HaveOccurred())) 1088 1089 By("Starting the orderer again") 1090 ordererRunner := network.OrdererRunner(orderers[0]) 1091 ordererRunners[0] = ordererRunner 1092 ordererProcesses[0] = ifrit.Invoke(ordererRunner) 1093 Eventually(ordererProcesses[0].Ready(), network.EventuallyTimeout).Should(BeClosed()) 1094 1095 By("Ensuring the remaining OSNs reject authentication") 1096 Eventually(ordererRunners[1].Err(), time.Minute, time.Second).Should(gbytes.Say("certificate extracted from TLS connection isn't authorized")) 1097 Eventually(ordererRunners[2].Err(), time.Minute, time.Second).Should(gbytes.Say("certificate extracted from TLS connection isn't authorized")) 1098 1099 By("Ensuring it detects its eviction") 1100 evictionDetection := gbytes.Say(`Detected our own eviction from the channel in block \[1\] channel=testchannel`) 1101 Eventually(ordererRunner.Err(), time.Minute, time.Second).Should(evictionDetection) 1102 1103 By("Ensuring all blocks are pulled up to the block that evicts the OSN") 1104 Eventually(ordererRunner.Err(), time.Minute, time.Second).Should(gbytes.Say("Periodic check is stopping. channel=testchannel")) 1105 Eventually(ordererRunner.Err(), time.Minute, time.Second).Should(gbytes.Say("Pulled all blocks up to eviction block. channel=testchannel")) 1106 1107 By("Killing the evicted orderer") 1108 ordererProcesses[0].Signal(syscall.SIGTERM) 1109 Eventually(ordererProcesses[0].Wait(), network.EventuallyTimeout).Should(Receive()) 1110 1111 By("Starting the evicted orderer again") 1112 ordererRunner = network.OrdererRunner(orderers[0]) 1113 ordererRunners[0] = ordererRunner 1114 ordererProcesses[0] = ifrit.Invoke(ordererRunner) 1115 Eventually(ordererProcesses[0].Ready(), network.EventuallyTimeout).Should(BeClosed()) 1116 1117 By("Ensuring the evicted orderer starts up marked the channel is inactive") 1118 Eventually(ordererRunner.Err(), time.Minute, time.Second).Should(gbytes.Say("Found 1 inactive chains")) 1119 1120 iDoNotBelong := "I do not belong to channel testchannel or am forbidden pulling it" 1121 Eventually(ordererRunner.Err(), time.Minute, time.Second).Should(gbytes.Say(iDoNotBelong)) 1122 1123 By("Adding the evicted orderer back to the application channel") 1124 addConsenter(network, peer, o2, "testchannel", etcdraft.Consenter{ 1125 ServerTlsCert: certificatesOfOrderers[0].oldCert, 1126 ClientTlsCert: certificatesOfOrderers[0].oldCert, 1127 Host: "127.0.0.1", 1128 Port: uint32(network.OrdererPort(orderers[0], nwo.ClusterPort)), 1129 }) 1130 1131 By("Ensuring the re-added orderer joins the Raft cluster") 1132 findLeader([]*ginkgomon.Runner{ordererRunner}) 1133 }) 1134 }) 1135 1136 When("an orderer node is joined", func() { 1137 It("isn't influenced by outdated orderers", func() { 1138 // This test checks that if a lagged is not aware of newly added nodes, 1139 // among which leader is present, it eventually pulls config block from 1140 // the orderer it knows, gets the certificates from it and participate 1141 // in consensus again. 1142 // 1143 // Steps: 1144 // Initial nodes in cluster: <1, 2, 3, 4> 1145 // - start <1, 2, 3> 1146 // - add <5, 6, 7>, start <5, 6, 7> 1147 // - kill <1> 1148 // - submit a tx, so that Raft index on <1> is behind <5, 6, 7> and <2, 3> 1149 // - kill <2, 3> 1150 // - start <1> and <4>. Since <1> is behind <5, 6, 7>, leader is certainly 1151 // going to be elected from <5, 6, 7> 1152 // - assert that even <4> is not aware of leader, it can pull config block 1153 // from <1>, and start participating in consensus. 1154 1155 orderers := make([]*nwo.Orderer, 7) 1156 ordererRunners = make([]*ginkgomon.Runner, 7) 1157 ordererProcesses = make([]ifrit.Process, 7) 1158 1159 for i := range orderers { 1160 orderers[i] = &nwo.Orderer{ 1161 Name: fmt.Sprintf("orderer%d", i+1), 1162 Organization: "OrdererOrg", 1163 } 1164 } 1165 1166 layout := nwo.MultiNodeEtcdRaft() 1167 layout.Orderers = orderers[:4] 1168 layout.Profiles[0].Orderers = []string{"orderer1", "orderer2", "orderer3", "orderer4"} 1169 1170 network = nwo.New(layout, testDir, client, StartPort(), components) 1171 network.GenerateConfigTree() 1172 network.Bootstrap() 1173 1174 peer = network.Peer("Org1", "peer0") 1175 1176 launch := func(i int) { 1177 runner := network.OrdererRunner(orderers[i]) 1178 ordererRunners[i] = runner 1179 process := ifrit.Invoke(runner) 1180 Eventually(process.Ready(), network.EventuallyTimeout).Should(BeClosed()) 1181 ordererProcesses[i] = process 1182 } 1183 1184 By("Launching 3 out of 4 orderers") 1185 for i := range orderers[:3] { 1186 launch(i) 1187 } 1188 1189 leader := findLeader(ordererRunners[:3]) 1190 1191 By("Checking that all orderers are online") 1192 assertBlockReception(map[string]int{ 1193 "systemchannel": 0, 1194 }, orderers[:3], peer, network) 1195 1196 By("Configuring orderer[5, 6, 7] in the network") 1197 extendNetwork(network) 1198 1199 for _, o := range orderers[4:7] { 1200 ports := nwo.Ports{} 1201 for _, portName := range nwo.OrdererPortNames() { 1202 ports[portName] = network.ReservePort() 1203 } 1204 network.PortsByOrdererID[o.ID()] = ports 1205 1206 network.Orderers = append(network.Orderers, o) 1207 network.GenerateOrdererConfig(o) 1208 } 1209 1210 // Backup previous system channel block 1211 genesisBootBlock, err := ioutil.ReadFile(filepath.Join(testDir, "systemchannel_block.pb")) 1212 Expect(err).NotTo(HaveOccurred()) 1213 restoreBootBlock := func() { 1214 err = ioutil.WriteFile(filepath.Join(testDir, "systemchannel_block.pb"), genesisBootBlock, 0644) 1215 Expect(err).NotTo(HaveOccurred()) 1216 } 1217 1218 blockSeq := 0 // there's only one block in channel - genesis 1219 for _, i := range []int{4, 5, 6} { 1220 By(fmt.Sprintf("Adding orderer%d", i+1)) 1221 ordererCertificatePath := filepath.Join(network.OrdererLocalTLSDir(orderers[i]), "server.crt") 1222 ordererCertificate, err := ioutil.ReadFile(ordererCertificatePath) 1223 Expect(err).NotTo(HaveOccurred()) 1224 1225 addConsenter(network, peer, orderers[0], "systemchannel", etcdraft.Consenter{ 1226 ServerTlsCert: ordererCertificate, 1227 ClientTlsCert: ordererCertificate, 1228 Host: "127.0.0.1", 1229 Port: uint32(network.OrdererPort(orderers[i], nwo.ClusterPort)), 1230 }) 1231 blockSeq++ 1232 1233 // Get the last config block of the system channel 1234 configBlock := nwo.GetConfigBlock(network, peer, orderers[0], "systemchannel") 1235 // Plant it in the file system of orderer, the new node to be onboarded. 1236 err = ioutil.WriteFile(filepath.Join(testDir, "systemchannel_block.pb"), protoutil.MarshalOrPanic(configBlock), 0644) 1237 Expect(err).NotTo(HaveOccurred()) 1238 1239 By(fmt.Sprintf("Launching orderer%d", i+1)) 1240 launch(i) 1241 1242 By(fmt.Sprintf("Checking that orderer%d has onboarded the network", i+1)) 1243 assertBlockReception(map[string]int{ 1244 "systemchannel": blockSeq, 1245 }, []*nwo.Orderer{orderers[i]}, peer, network) 1246 } 1247 1248 Expect(findLeader(ordererRunners[4:])).To(Equal(leader)) 1249 1250 // Later on, when we start [1, 4, 5, 6, 7], we want to make sure that leader 1251 // is elected from [5, 6, 7], who are unknown to [4]. So we can assert that 1252 // [4] suspects its own eviction, pulls block from [1], and join the cluster. 1253 // Otherwise, if [1] is elected, and all other nodes already knew it, [4] may 1254 // simply replicate missing blocks with Raft, instead of pulling from others 1255 // triggered by eviction suspector. 1256 1257 By("Killing orderer1") 1258 ordererProcesses[0].Signal(syscall.SIGTERM) 1259 Eventually(ordererProcesses[0].Wait(), network.EventuallyTimeout).Should(Receive()) 1260 1261 By("Submitting another tx to increment Raft index on alive orderers") 1262 if leader == 1 { 1263 // if orderer1 was leader, we should expect a new leader being elected before going forward 1264 findLeader([]*ginkgomon.Runner{ordererRunners[4]}) 1265 } 1266 1267 env := CreateBroadcastEnvelope(network, orderers[4], network.SystemChannel.Name, []byte("hello")) 1268 resp, err := nwo.Broadcast(network, orderers[4], env) 1269 Expect(err).NotTo(HaveOccurred()) 1270 Expect(resp.Status).To(Equal(common.Status_SUCCESS)) 1271 blockSeq++ 1272 1273 assertBlockReception(map[string]int{ 1274 "systemchannel": blockSeq, 1275 }, []*nwo.Orderer{orderers[1], orderers[2], orderers[4], orderers[5], orderers[6]}, peer, network) // alive orderers: 2, 3, 5, 6, 7 1276 1277 By("Killing orderer[2,3]") 1278 for _, i := range []int{1, 2} { 1279 ordererProcesses[i].Signal(syscall.SIGTERM) 1280 Eventually(ordererProcesses[i].Wait(), network.EventuallyTimeout).Should(Receive()) 1281 } 1282 1283 By("Launching the orderer that was never started") 1284 restoreBootBlock() 1285 launch(3) 1286 1287 By("Launching orderer1") 1288 launch(0) 1289 1290 By("Waiting until it suspects its eviction from the channel") 1291 Eventually(ordererRunners[3].Err(), time.Minute, time.Second).Should(gbytes.Say("Suspecting our own eviction from the channel")) 1292 1293 By("Making sure 4/7 orderers form quorum and serve request") 1294 assertBlockReception(map[string]int{ 1295 "systemchannel": blockSeq, 1296 }, []*nwo.Orderer{orderers[3], orderers[4], orderers[5], orderers[6]}, peer, network) // alive orderers: 4, 5, 6, 7 1297 }) 1298 }) 1299 1300 It("can create a channel that contains a subset of orderers in system channel", func() { 1301 config := nwo.BasicEtcdRaft() 1302 config.Orderers = []*nwo.Orderer{ 1303 {Name: "orderer1", Organization: "OrdererOrg"}, 1304 {Name: "orderer2", Organization: "OrdererOrg"}, 1305 {Name: "orderer3", Organization: "OrdererOrg"}, 1306 } 1307 config.Profiles = []*nwo.Profile{{ 1308 Name: "SampleDevModeEtcdRaft", 1309 Orderers: []string{"orderer1", "orderer2", "orderer3"}, 1310 }, { 1311 Name: "ThreeOrdererChannel", 1312 Consortium: "SampleConsortium", 1313 Organizations: []string{"Org1", "Org2"}, 1314 Orderers: []string{"orderer1", "orderer2", "orderer3"}, 1315 }, { 1316 Name: "SingleOrdererChannel", 1317 Consortium: "SampleConsortium", 1318 Organizations: []string{"Org1", "Org2"}, 1319 Orderers: []string{"orderer1"}, 1320 }} 1321 config.Channels = []*nwo.Channel{ 1322 {Name: "single-orderer-channel", Profile: "SingleOrdererChannel", BaseProfile: "SampleDevModeEtcdRaft"}, 1323 {Name: "three-orderer-channel", Profile: "ThreeOrdererChannel"}, 1324 } 1325 1326 network = nwo.New(config, testDir, client, StartPort(), components) 1327 o1, o2, o3 := network.Orderer("orderer1"), network.Orderer("orderer2"), network.Orderer("orderer3") 1328 orderers := []*nwo.Orderer{o1, o2, o3} 1329 peer = network.Peer("Org1", "peer0") 1330 1331 network.GenerateConfigTree() 1332 network.Bootstrap() 1333 1334 By("Launching the orderers") 1335 for _, o := range orderers { 1336 runner := network.OrdererRunner(o) 1337 ordererRunners = append(ordererRunners, runner) 1338 process := ifrit.Invoke(runner) 1339 ordererProcesses = append(ordererProcesses, process) 1340 } 1341 1342 for _, ordererProc := range ordererProcesses { 1343 Eventually(ordererProc.Ready(), network.EventuallyTimeout).Should(BeClosed()) 1344 } 1345 1346 By("Creating an application channel with a subset of orderers in system channel") 1347 additionalPeer := network.Peer("Org2", "peer0") 1348 network.CreateChannel("single-orderer-channel", network.Orderers[0], peer, additionalPeer, network.Orderers[0]) 1349 1350 By("Creating another channel via the orderer that is in system channel but not app channel") 1351 network.CreateChannel("three-orderer-channel", network.Orderers[2], peer) 1352 }) 1353 1354 It("can add a new orderer organization", func() { 1355 network = nwo.New(nwo.MultiNodeEtcdRaft(), testDir, client, StartPort(), components) 1356 o1, o2, o3 := network.Orderer("orderer1"), network.Orderer("orderer2"), network.Orderer("orderer3") 1357 orderers := []*nwo.Orderer{o1, o2, o3} 1358 1359 network.GenerateConfigTree() 1360 network.Bootstrap() 1361 1362 By("Launching the orderers") 1363 for _, o := range orderers { 1364 runner := network.OrdererRunner(o) 1365 ordererRunners = append(ordererRunners, runner) 1366 process := ifrit.Invoke(runner) 1367 ordererProcesses = append(ordererProcesses, process) 1368 } 1369 1370 for _, ordererProc := range ordererProcesses { 1371 Eventually(ordererProc.Ready(), network.EventuallyTimeout).Should(BeClosed()) 1372 } 1373 1374 By("Waiting for system channel to be ready") 1375 findLeader(ordererRunners) 1376 1377 peer := network.Peer("Org1", "peer0") 1378 channel := "systemchannel" 1379 1380 config := nwo.GetConfig(network, peer, o1, channel) 1381 updatedConfig := proto.Clone(config).(*common.Config) 1382 1383 ordererOrg := updatedConfig.ChannelGroup.Groups["Orderer"].Groups["OrdererOrg"] 1384 mspConfig := &msp.MSPConfig{} 1385 proto.Unmarshal(ordererOrg.Values["MSP"].Value, mspConfig) 1386 1387 fabMSPConfig := &msp.FabricMSPConfig{} 1388 proto.Unmarshal(mspConfig.Config, fabMSPConfig) 1389 1390 fabMSPConfig.Name = "OrdererMSP2" 1391 1392 mspConfig.Config, _ = proto.Marshal(fabMSPConfig) 1393 updatedConfig.ChannelGroup.Groups["Orderer"].Groups["OrdererMSP2"] = &common.ConfigGroup{ 1394 Values: map[string]*common.ConfigValue{ 1395 "MSP": { 1396 Value: protoutil.MarshalOrPanic(mspConfig), 1397 ModPolicy: "Admins", 1398 }, 1399 }, 1400 ModPolicy: "Admins", 1401 } 1402 1403 nwo.UpdateOrdererConfig(network, o1, channel, config, updatedConfig, peer, o1) 1404 }) 1405 }) 1406 1407 func ensureEvicted(evictedOrderer *nwo.Orderer, submitter *nwo.Peer, network *nwo.Network, channel string) { 1408 c := commands.ChannelFetch{ 1409 ChannelID: channel, 1410 Block: "newest", 1411 OutputFile: "/dev/null", 1412 Orderer: network.OrdererAddress(evictedOrderer, nwo.ListenPort), 1413 } 1414 1415 sess, err := network.OrdererAdminSession(evictedOrderer, submitter, c) 1416 Expect(err).NotTo(HaveOccurred()) 1417 1418 Eventually(sess, network.EventuallyTimeout).Should(gexec.Exit()) 1419 Expect(sess.Err).To(gbytes.Say("SERVICE_UNAVAILABLE")) 1420 } 1421 1422 var extendedCryptoConfig = `--- 1423 OrdererOrgs: 1424 - Name: OrdererOrg 1425 Domain: example.com 1426 EnableNodeOUs: false 1427 CA: 1428 Hostname: ca 1429 Specs: 1430 - Hostname: orderer1 1431 SANS: 1432 - localhost 1433 - 127.0.0.1 1434 - ::1 1435 - Hostname: orderer1new 1436 SANS: 1437 - localhost 1438 - 127.0.0.1 1439 - ::1 1440 - Hostname: orderer2 1441 SANS: 1442 - localhost 1443 - 127.0.0.1 1444 - ::1 1445 - Hostname: orderer2new 1446 SANS: 1447 - localhost 1448 - 127.0.0.1 1449 - ::1 1450 - Hostname: orderer3 1451 SANS: 1452 - localhost 1453 - 127.0.0.1 1454 - ::1 1455 - Hostname: orderer3new 1456 SANS: 1457 - localhost 1458 - 127.0.0.1 1459 - ::1 1460 - Hostname: orderer4 1461 SANS: 1462 - localhost 1463 - 127.0.0.1 1464 - ::1 1465 - Hostname: orderer5 1466 SANS: 1467 - localhost 1468 - 127.0.0.1 1469 - ::1 1470 - Hostname: orderer6 1471 SANS: 1472 - localhost 1473 - 127.0.0.1 1474 - ::1 1475 - Hostname: orderer7 1476 SANS: 1477 - localhost 1478 - 127.0.0.1 1479 - ::1 1480 ` 1481 1482 type certificateChange struct { 1483 srcFile string 1484 dstFile string 1485 oldCert []byte 1486 oldKey []byte 1487 newCert []byte 1488 } 1489 1490 // extendNetwork rotates adds an additional orderer 1491 func extendNetwork(n *nwo.Network) { 1492 // Overwrite the current crypto-config with additional orderers 1493 cryptoConfigYAML, err := ioutil.TempFile("", "crypto-config.yaml") 1494 Expect(err).NotTo(HaveOccurred()) 1495 defer os.Remove(cryptoConfigYAML.Name()) 1496 1497 err = ioutil.WriteFile(cryptoConfigYAML.Name(), []byte(extendedCryptoConfig), 0644) 1498 Expect(err).NotTo(HaveOccurred()) 1499 1500 // Invoke cryptogen extend to add new orderers 1501 sess, err := n.Cryptogen(commands.Extend{ 1502 Config: cryptoConfigYAML.Name(), 1503 Input: n.CryptoPath(), 1504 }) 1505 Expect(err).NotTo(HaveOccurred()) 1506 Eventually(sess, n.EventuallyTimeout).Should(gexec.Exit(0)) 1507 } 1508 1509 // refreshOrdererPEMs rotates all TLS certificates of all nodes, 1510 // and returns the deltas 1511 func refreshOrdererPEMs(n *nwo.Network) []*certificateChange { 1512 var fileChanges []*certificateChange 1513 // Populate source to destination files 1514 err := filepath.Walk(n.CryptoPath(), func(path string, info os.FileInfo, err error) error { 1515 if !strings.Contains(path, "/tls/") { 1516 return nil 1517 } 1518 if strings.Contains(path, "new") { 1519 fileChanges = append(fileChanges, &certificateChange{ 1520 srcFile: path, 1521 dstFile: strings.Replace(path, "new", "", -1), 1522 }) 1523 } 1524 return nil 1525 }) 1526 Expect(err).NotTo(HaveOccurred()) 1527 1528 var serverCertChanges []*certificateChange 1529 1530 // Overwrite the destination files with the contents of the source files. 1531 for _, certChange := range fileChanges { 1532 previousCertBytes, err := ioutil.ReadFile(certChange.dstFile) 1533 Expect(err).NotTo(HaveOccurred()) 1534 1535 newCertBytes, err := ioutil.ReadFile(certChange.srcFile) 1536 Expect(err).NotTo(HaveOccurred()) 1537 1538 err = ioutil.WriteFile(certChange.dstFile, newCertBytes, 0644) 1539 Expect(err).NotTo(HaveOccurred()) 1540 1541 if !strings.Contains(certChange.dstFile, "server.crt") { 1542 continue 1543 } 1544 1545 // Read the previous key file 1546 previousKeyBytes, err := ioutil.ReadFile(strings.Replace(certChange.dstFile, "server.crt", "server.key", -1)) 1547 Expect(err).NotTo(HaveOccurred()) 1548 1549 serverCertChanges = append(serverCertChanges, certChange) 1550 certChange.newCert = newCertBytes 1551 certChange.oldCert = previousCertBytes 1552 certChange.oldKey = previousKeyBytes 1553 } 1554 return serverCertChanges 1555 } 1556 1557 // assertBlockReception asserts that the given orderers have expected heights for the given channel--> height mapping 1558 func assertBlockReception(expectedHeightsPerChannel map[string]int, orderers []*nwo.Orderer, p *nwo.Peer, n *nwo.Network) { 1559 assertReception := func(channelName string, blockSeq int) { 1560 var wg sync.WaitGroup 1561 wg.Add(len(orderers)) 1562 for _, orderer := range orderers { 1563 go func(orderer *nwo.Orderer) { 1564 defer GinkgoRecover() 1565 defer wg.Done() 1566 waitForBlockReception(orderer, p, n, channelName, blockSeq) 1567 }(orderer) 1568 } 1569 wg.Wait() 1570 } 1571 1572 var wg sync.WaitGroup 1573 wg.Add(len(expectedHeightsPerChannel)) 1574 1575 for channelName, blockSeq := range expectedHeightsPerChannel { 1576 go func(channelName string, blockSeq int) { 1577 defer GinkgoRecover() 1578 defer wg.Done() 1579 assertReception(channelName, blockSeq) 1580 }(channelName, blockSeq) 1581 } 1582 wg.Wait() 1583 } 1584 1585 func waitForBlockReception(o *nwo.Orderer, submitter *nwo.Peer, network *nwo.Network, channelName string, blockSeq int) { 1586 c := commands.ChannelFetch{ 1587 ChannelID: channelName, 1588 Block: "newest", 1589 OutputFile: "/dev/null", 1590 Orderer: network.OrdererAddress(o, nwo.ListenPort), 1591 } 1592 Eventually(func() string { 1593 sess, err := network.OrdererAdminSession(o, submitter, c) 1594 Expect(err).NotTo(HaveOccurred()) 1595 Eventually(sess, network.EventuallyTimeout).Should(gexec.Exit()) 1596 if sess.ExitCode() != 0 { 1597 return fmt.Sprintf("exit code is %d: %s", sess.ExitCode(), string(sess.Err.Contents())) 1598 } 1599 sessErr := string(sess.Err.Contents()) 1600 expected := fmt.Sprintf("Received block: %d", blockSeq) 1601 if strings.Contains(sessErr, expected) { 1602 return "" 1603 } 1604 return sessErr 1605 }, network.EventuallyTimeout, time.Second).Should(BeEmpty()) 1606 } 1607 1608 func revokeReaderAccess(network *nwo.Network, channel string, orderer *nwo.Orderer, peer *nwo.Peer) { 1609 config := nwo.GetConfig(network, peer, orderer, channel) 1610 updatedConfig := proto.Clone(config).(*common.Config) 1611 1612 // set the policy 1613 adminPolicy := protoutil.MarshalOrPanic(&common.ImplicitMetaPolicy{ 1614 SubPolicy: "Admins", 1615 Rule: common.ImplicitMetaPolicy_MAJORITY, 1616 }) 1617 updatedConfig.ChannelGroup.Groups["Orderer"].Policies["Readers"].Policy.Value = adminPolicy 1618 nwo.UpdateOrdererConfig(network, orderer, channel, config, updatedConfig, peer, orderer) 1619 } 1620 1621 // consenterAdder constructs configs that can be used by `UpdateOrdererConfig` 1622 // to add a consenter. 1623 func consenterAdder(n *nwo.Network, peer *nwo.Peer, orderer *nwo.Orderer, channel string, consenter etcdraft.Consenter) (current, updated *common.Config) { 1624 config := nwo.GetConfig(n, peer, orderer, channel) 1625 updatedConfig := proto.Clone(config).(*common.Config) 1626 1627 consensusTypeConfigValue := updatedConfig.ChannelGroup.Groups["Orderer"].Values["ConsensusType"] 1628 consensusTypeValue := &protosorderer.ConsensusType{} 1629 err := proto.Unmarshal(consensusTypeConfigValue.Value, consensusTypeValue) 1630 Expect(err).NotTo(HaveOccurred()) 1631 1632 metadata := &etcdraft.ConfigMetadata{} 1633 err = proto.Unmarshal(consensusTypeValue.Metadata, metadata) 1634 Expect(err).NotTo(HaveOccurred()) 1635 1636 metadata.Consenters = append(metadata.Consenters, &consenter) 1637 1638 consensusTypeValue.Metadata, err = proto.Marshal(metadata) 1639 Expect(err).NotTo(HaveOccurred()) 1640 1641 updatedConfig.ChannelGroup.Groups["Orderer"].Values["ConsensusType"] = &common.ConfigValue{ 1642 ModPolicy: "Admins", 1643 Value: protoutil.MarshalOrPanic(consensusTypeValue), 1644 } 1645 1646 return config, updatedConfig 1647 } 1648 1649 // consenterRemover constructs configs that can be used by 1650 // `UpdateOrdererConfig` to remove a consenter. 1651 func consenterRemover(n *nwo.Network, peer *nwo.Peer, orderer *nwo.Orderer, channel string, certificate []byte) (current, updated *common.Config) { 1652 config := nwo.GetConfig(n, peer, orderer, channel) 1653 updatedConfig := proto.Clone(config).(*common.Config) 1654 1655 consensusTypeConfigValue := updatedConfig.ChannelGroup.Groups["Orderer"].Values["ConsensusType"] 1656 consensusTypeValue := &protosorderer.ConsensusType{} 1657 err := proto.Unmarshal(consensusTypeConfigValue.Value, consensusTypeValue) 1658 Expect(err).NotTo(HaveOccurred()) 1659 1660 metadata := &etcdraft.ConfigMetadata{} 1661 err = proto.Unmarshal(consensusTypeValue.Metadata, metadata) 1662 Expect(err).NotTo(HaveOccurred()) 1663 1664 var newConsenters []*etcdraft.Consenter 1665 for _, consenter := range metadata.Consenters { 1666 if bytes.Equal(consenter.ClientTlsCert, certificate) || bytes.Equal(consenter.ServerTlsCert, certificate) { 1667 continue 1668 } 1669 newConsenters = append(newConsenters, consenter) 1670 } 1671 1672 metadata.Consenters = newConsenters 1673 consensusTypeValue.Metadata, err = proto.Marshal(metadata) 1674 Expect(err).NotTo(HaveOccurred()) 1675 1676 updatedConfig.ChannelGroup.Groups["Orderer"].Values["ConsensusType"] = &common.ConfigValue{ 1677 ModPolicy: "Admins", 1678 Value: protoutil.MarshalOrPanic(consensusTypeValue), 1679 } 1680 1681 return config, updatedConfig 1682 } 1683 1684 // addConsenter adds a new consenter to the given channel. 1685 func addConsenter(n *nwo.Network, peer *nwo.Peer, orderer *nwo.Orderer, channel string, consenter etcdraft.Consenter) { 1686 updateEtcdRaftMetadata(n, peer, orderer, channel, func(metadata *etcdraft.ConfigMetadata) { 1687 metadata.Consenters = append(metadata.Consenters, &consenter) 1688 }) 1689 } 1690 1691 // removeConsenter removes a consenter with the given certificate in PEM format 1692 // from the given channel. 1693 func removeConsenter(n *nwo.Network, peer *nwo.Peer, orderer *nwo.Orderer, channel string, certificate []byte) { 1694 updateEtcdRaftMetadata(n, peer, orderer, channel, func(metadata *etcdraft.ConfigMetadata) { 1695 var newConsenters []*etcdraft.Consenter 1696 for _, consenter := range metadata.Consenters { 1697 if bytes.Equal(consenter.ClientTlsCert, certificate) || bytes.Equal(consenter.ServerTlsCert, certificate) { 1698 continue 1699 } 1700 newConsenters = append(newConsenters, consenter) 1701 } 1702 1703 metadata.Consenters = newConsenters 1704 }) 1705 } 1706 1707 // updateEtcdRaftMetadata executes a config update that updates the etcdraft 1708 // metadata according to the given function f. 1709 func updateEtcdRaftMetadata(network *nwo.Network, peer *nwo.Peer, orderer *nwo.Orderer, channel string, f func(md *etcdraft.ConfigMetadata)) { 1710 nwo.UpdateConsensusMetadata(network, peer, orderer, channel, func(originalMetadata []byte) []byte { 1711 metadata := &etcdraft.ConfigMetadata{} 1712 err := proto.Unmarshal(originalMetadata, metadata) 1713 Expect(err).NotTo(HaveOccurred()) 1714 1715 f(metadata) 1716 1717 newMetadata, err := proto.Marshal(metadata) 1718 Expect(err).NotTo(HaveOccurred()) 1719 return newMetadata 1720 }) 1721 } 1722 1723 func changeSubjectName(caCertPEM, caKeyPEM, leafPEM []byte, newSubjectName string) (newCA, newLeaf []byte) { 1724 keyAsDER, _ := pem.Decode(caKeyPEM) 1725 caKeyWithoutType, err := x509.ParsePKCS8PrivateKey(keyAsDER.Bytes) 1726 Expect(err).NotTo(HaveOccurred()) 1727 caKey := caKeyWithoutType.(*ecdsa.PrivateKey) 1728 1729 caCertAsDER, _ := pem.Decode(caCertPEM) 1730 caCert, err := x509.ParseCertificate(caCertAsDER.Bytes) 1731 Expect(err).NotTo(HaveOccurred()) 1732 1733 // Change its subject name 1734 caCert.Subject.CommonName = newSubjectName 1735 caCert.Issuer.CommonName = newSubjectName 1736 caCert.RawTBSCertificate = nil 1737 caCert.RawSubjectPublicKeyInfo = nil 1738 caCert.Raw = nil 1739 caCert.RawSubject = nil 1740 caCert.RawIssuer = nil 1741 1742 // The CA signs its own certificate 1743 caCertBytes, err := x509.CreateCertificate(rand.Reader, caCert, caCert, caCert.PublicKey, caKey) 1744 Expect(err).NotTo(HaveOccurred()) 1745 1746 // Now it's the turn of the leaf certificate 1747 leafAsDER, _ := pem.Decode(leafPEM) 1748 leafCert, err := x509.ParseCertificate(leafAsDER.Bytes) 1749 Expect(err).NotTo(HaveOccurred()) 1750 1751 leafCert.Raw = nil 1752 leafCert.RawIssuer = nil 1753 leafCert.RawTBSCertificate = nil 1754 1755 // The CA signs the leaf cert 1756 leafCertBytes, err := x509.CreateCertificate(rand.Reader, leafCert, caCert, leafCert.PublicKey, caKey) 1757 Expect(err).NotTo(HaveOccurred()) 1758 1759 newCA = pem.EncodeToMemory(&pem.Block{Bytes: caCertBytes, Type: "CERTIFICATE"}) 1760 newLeaf = pem.EncodeToMemory(&pem.Block{Bytes: leafCertBytes, Type: "CERTIFICATE"}) 1761 return 1762 }