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