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