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