github.com/yacovm/fabric@v2.0.0-alpha.0.20191128145320-c5d4087dc723+incompatible/integration/raft/cft_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 "crypto/ecdsa" 11 "crypto/rand" 12 "crypto/x509" 13 "encoding/pem" 14 "fmt" 15 "io/ioutil" 16 "os" 17 "path" 18 "path/filepath" 19 "strconv" 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 "github.com/hyperledger/fabric/cmd/common/signer" 29 "github.com/hyperledger/fabric/common/configtx" 30 "github.com/hyperledger/fabric/common/util" 31 "github.com/hyperledger/fabric/integration/nwo" 32 "github.com/hyperledger/fabric/integration/nwo/commands" 33 "github.com/hyperledger/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 "github.com/tedsuo/ifrit/grouper" 41 ) 42 43 var _ = Describe("EndToEnd Crash Fault Tolerance", func() { 44 var ( 45 testDir string 46 client *docker.Client 47 network *nwo.Network 48 peer *nwo.Peer 49 50 ordererProc, o1Proc, o2Proc, o3Proc ifrit.Process 51 ) 52 53 BeforeEach(func() { 54 var err error 55 testDir, err = ioutil.TempDir("", "e2e") 56 Expect(err).NotTo(HaveOccurred()) 57 58 client, err = docker.NewClientFromEnv() 59 Expect(err).NotTo(HaveOccurred()) 60 }) 61 62 AfterEach(func() { 63 for _, oProc := range []ifrit.Process{o1Proc, o2Proc, o3Proc} { 64 if oProc != nil { 65 oProc.Signal(syscall.SIGTERM) 66 Eventually(oProc.Wait(), network.EventuallyTimeout).Should(Receive()) 67 } 68 } 69 70 if ordererProc != nil { 71 ordererProc.Signal(syscall.SIGTERM) 72 Eventually(ordererProc.Wait(), network.EventuallyTimeout).Should(Receive()) 73 } 74 75 if network != nil { 76 network.Cleanup() 77 } 78 os.RemoveAll(testDir) 79 }) 80 81 When("orderer stops and restarts", func() { 82 It("keeps network up and running", func() { 83 network = nwo.New(nwo.MultiNodeEtcdRaft(), testDir, client, StartPort(), components) 84 85 o1, o2, o3 := network.Orderer("orderer1"), network.Orderer("orderer2"), network.Orderer("orderer3") 86 peer = network.Peer("Org1", "peer1") 87 88 network.GenerateConfigTree() 89 network.Bootstrap() 90 91 o1Runner := network.OrdererRunner(o1) 92 orderers := grouper.Members{ 93 {Name: o2.ID(), Runner: network.OrdererRunner(o2)}, 94 {Name: o3.ID(), Runner: network.OrdererRunner(o3)}, 95 } 96 ordererGroup := grouper.NewParallel(syscall.SIGTERM, orderers) 97 98 o1Proc = ifrit.Invoke(o1Runner) 99 ordererProc = ifrit.Invoke(ordererGroup) 100 Eventually(o1Proc.Ready(), network.EventuallyTimeout).Should(BeClosed()) 101 Eventually(ordererProc.Ready(), network.EventuallyTimeout).Should(BeClosed()) 102 103 findLeader([]*ginkgomon.Runner{o1Runner}) 104 105 By("performing operation with orderer1") 106 env := CreateBroadcastEnvelope(network, o1, network.SystemChannel.Name, []byte("foo")) 107 resp, err := nwo.Broadcast(network, o1, env) 108 Expect(err).NotTo(HaveOccurred()) 109 Expect(resp.Status).To(Equal(common.Status_SUCCESS)) 110 111 block := FetchBlock(network, o1, 1, network.SystemChannel.Name) 112 Expect(block).NotTo(BeNil()) 113 114 By("killing orderer1") 115 o1Proc.Signal(syscall.SIGKILL) 116 Eventually(o1Proc.Wait(), network.EventuallyTimeout).Should(Receive(MatchError("exit status 137"))) 117 118 By("broadcasting envelope to running orderer") 119 resp, err = nwo.Broadcast(network, o2, env) 120 Expect(err).NotTo(HaveOccurred()) 121 Expect(resp.Status).To(Equal(common.Status_SUCCESS)) 122 123 block = FetchBlock(network, o2, 2, network.SystemChannel.Name) 124 Expect(block).NotTo(BeNil()) 125 126 By("restarting orderer1") 127 o1Runner = network.OrdererRunner(o1) 128 o1Proc = ifrit.Invoke(o1Runner) 129 Eventually(o1Proc.Ready(), network.EventuallyTimeout).Should(BeClosed()) 130 findLeader([]*ginkgomon.Runner{o1Runner}) 131 132 By("broadcasting envelope to restarted orderer") 133 resp, err = nwo.Broadcast(network, o1, env) 134 Expect(err).NotTo(HaveOccurred()) 135 Expect(resp.Status).To(Equal(common.Status_SUCCESS)) 136 137 blko1 := FetchBlock(network, o1, 3, network.SystemChannel.Name) 138 blko2 := FetchBlock(network, o2, 3, network.SystemChannel.Name) 139 140 Expect(blko1.Header.DataHash).To(Equal(blko2.Header.DataHash)) 141 }) 142 }) 143 144 When("an orderer is behind the latest snapshot on leader", func() { 145 It("catches up using the block stored in snapshot", func() { 146 // Steps: 147 // - start o2 & o3 148 // - send several transactions so snapshot is created 149 // - kill o2 & o3, so that entries prior to snapshot are not in memory upon restart 150 // - start o1 & o2 151 // - assert that o1 can catch up with o2 using snapshot 152 network = nwo.New(nwo.MultiNodeEtcdRaft(), testDir, client, StartPort(), components) 153 o1, o2, o3 := network.Orderer("orderer1"), network.Orderer("orderer2"), network.Orderer("orderer3") 154 peer = network.Peer("Org1", "peer1") 155 156 network.GenerateConfigTree() 157 network.Bootstrap() 158 159 orderers := grouper.Members{ 160 {Name: o2.ID(), Runner: network.OrdererRunner(o2)}, 161 {Name: o3.ID(), Runner: network.OrdererRunner(o3)}, 162 } 163 ordererGroup := grouper.NewParallel(syscall.SIGTERM, orderers) 164 165 By("Starting 2/3 of cluster") 166 ordererProc = ifrit.Invoke(ordererGroup) 167 Eventually(ordererProc.Ready(), network.EventuallyTimeout).Should(BeClosed()) 168 169 By("Creating testchannel") 170 channelID := "testchannel" 171 network.CreateChannel(channelID, o2, peer) 172 173 By("Submitting several transactions to trigger snapshot") 174 o2SnapDir := path.Join(network.RootDir, "orderers", o2.ID(), "etcdraft", "snapshot") 175 176 env := CreateBroadcastEnvelope(network, o2, channelID, make([]byte, 2000)) 177 for i := 1; i <= 4; i++ { // 4 < MaxSnapshotFiles(5), so that no snapshot is pruned 178 // Note that MaxMessageCount is 1 be default, so every tx results in a new block 179 resp, err := nwo.Broadcast(network, o2, env) 180 Expect(err).NotTo(HaveOccurred()) 181 Expect(resp.Status).To(Equal(common.Status_SUCCESS)) 182 183 // Assert that new snapshot file is created before broadcasting next tx, 184 // so that number of snapshots is deterministic. Otherwise, it is not 185 // guaranteed that every block triggers a snapshot file being created, 186 // due to the mechanism to prevent excessive snapshotting. 187 Eventually(func() int { 188 files, err := ioutil.ReadDir(path.Join(o2SnapDir, channelID)) 189 Expect(err).NotTo(HaveOccurred()) 190 return len(files) 191 }, network.EventuallyTimeout).Should(Equal(i)) // snapshot interval is 1 KB, every block triggers snapshot 192 } 193 194 By("Killing orderers so they don't have blocks prior to latest snapshot in the memory") 195 ordererProc.Signal(syscall.SIGKILL) 196 Eventually(ordererProc.Wait(), network.EventuallyTimeout).Should(Receive()) 197 198 By("Starting lagged orderer and one of up-to-date orderers") 199 orderers = grouper.Members{ 200 {Name: o1.ID(), Runner: network.OrdererRunner(o1)}, 201 {Name: o2.ID(), Runner: network.OrdererRunner(o2)}, 202 } 203 ordererGroup = grouper.NewParallel(syscall.SIGTERM, orderers) 204 ordererProc = ifrit.Invoke(ordererGroup) 205 Eventually(ordererProc.Ready(), network.EventuallyTimeout).Should(BeClosed()) 206 207 o1SnapDir := path.Join(network.RootDir, "orderers", o1.ID(), "etcdraft", "snapshot") 208 209 By("Asserting that orderer1 has snapshot dir for both system and application channel") 210 Eventually(func() int { 211 files, err := ioutil.ReadDir(o1SnapDir) 212 Expect(err).NotTo(HaveOccurred()) 213 return len(files) 214 }, network.EventuallyTimeout).Should(Equal(2)) 215 216 By("Asserting that orderer1 receives and persists snapshot") 217 Eventually(func() int { 218 files, err := ioutil.ReadDir(path.Join(o1SnapDir, channelID)) 219 Expect(err).NotTo(HaveOccurred()) 220 return len(files) 221 }, network.EventuallyTimeout).Should(Equal(1)) 222 223 By("Asserting cluster is still functional") 224 env = CreateBroadcastEnvelope(network, o1, channelID, make([]byte, 1000)) 225 resp, err := nwo.Broadcast(network, o1, env) 226 Expect(err).NotTo(HaveOccurred()) 227 Expect(resp.Status).To(Equal(common.Status_SUCCESS)) 228 229 blko1 := FetchBlock(network, o1, 5, channelID) 230 blko2 := FetchBlock(network, o2, 5, channelID) 231 232 Expect(blko1.Header.DataHash).To(Equal(blko2.Header.DataHash)) 233 }) 234 }) 235 236 When("The leader dies", func() { 237 It("Elects a new leader", func() { 238 network = nwo.New(nwo.MultiNodeEtcdRaft(), testDir, client, StartPort(), components) 239 240 o1, o2, o3 := network.Orderer("orderer1"), network.Orderer("orderer2"), network.Orderer("orderer3") 241 242 network.GenerateConfigTree() 243 network.Bootstrap() 244 245 By("Running the orderer nodes") 246 o1Runner := network.OrdererRunner(o1) 247 o2Runner := network.OrdererRunner(o2) 248 o3Runner := network.OrdererRunner(o3) 249 250 o1Proc = ifrit.Invoke(o1Runner) 251 o2Proc = ifrit.Invoke(o2Runner) 252 o3Proc = ifrit.Invoke(o3Runner) 253 254 Eventually(o1Proc.Ready(), network.EventuallyTimeout).Should(BeClosed()) 255 Eventually(o2Proc.Ready(), network.EventuallyTimeout).Should(BeClosed()) 256 Eventually(o3Proc.Ready(), network.EventuallyTimeout).Should(BeClosed()) 257 258 By("Waiting for them to elect a leader") 259 ordererProcesses := []ifrit.Process{o1Proc, o2Proc, o3Proc} 260 remainingAliveRunners := []*ginkgomon.Runner{o1Runner, o2Runner, o3Runner} 261 leader := findLeader(remainingAliveRunners) 262 263 leaderIndex := leader - 1 264 By(fmt.Sprintf("Killing the leader (%d)", leader)) 265 ordererProcesses[leaderIndex].Signal(syscall.SIGTERM) 266 By("Waiting for it to die") 267 Eventually(ordererProcesses[leaderIndex].Wait(), network.EventuallyTimeout).Should(Receive()) 268 269 // Remove the leader from the orderer runners 270 remainingAliveRunners = append(remainingAliveRunners[:leaderIndex], remainingAliveRunners[leaderIndex+1:]...) 271 272 By("Waiting for a new leader to be elected") 273 leader = findLeader(remainingAliveRunners) 274 By(fmt.Sprintf("Orderer %d took over as a leader", leader)) 275 }) 276 }) 277 278 When("Leader cannot reach quorum", func() { 279 It("Steps down", func() { 280 network = nwo.New(nwo.MultiNodeEtcdRaft(), testDir, client, StartPort(), components) 281 282 o1, o2, o3 := network.Orderer("orderer1"), network.Orderer("orderer2"), network.Orderer("orderer3") 283 orderers := []*nwo.Orderer{o1, o2, o3} 284 peer = network.Peer("Org1", "peer1") 285 network.GenerateConfigTree() 286 network.Bootstrap() 287 288 By("Running the orderer nodes") 289 o1Runner := network.OrdererRunner(o1) 290 o2Runner := network.OrdererRunner(o2) 291 o3Runner := network.OrdererRunner(o3) 292 oRunners := []*ginkgomon.Runner{o1Runner, o2Runner, o3Runner} 293 294 o1Proc = ifrit.Invoke(o1Runner) 295 o2Proc = ifrit.Invoke(o2Runner) 296 o3Proc = ifrit.Invoke(o3Runner) 297 298 Eventually(o1Proc.Ready(), network.EventuallyTimeout).Should(BeClosed()) 299 Eventually(o2Proc.Ready(), network.EventuallyTimeout).Should(BeClosed()) 300 Eventually(o3Proc.Ready(), network.EventuallyTimeout).Should(BeClosed()) 301 302 By("Waiting for them to elect a leader") 303 ordererProcesses := []ifrit.Process{o1Proc, o2Proc, o3Proc} 304 remainingAliveRunners := []*ginkgomon.Runner{o1Runner, o2Runner, o3Runner} 305 leaderID := findLeader(remainingAliveRunners) 306 leaderIndex := leaderID - 1 307 leader := orderers[leaderIndex] 308 309 followerIndices := func() []int { 310 var f []int 311 for i := range ordererProcesses { 312 if leaderIndex != i { 313 f = append(f, i) 314 } 315 } 316 317 return f 318 }() 319 320 By(fmt.Sprintf("Killing two followers (%d and %d)", followerIndices[0]+1, followerIndices[1]+1)) 321 ordererProcesses[followerIndices[0]].Signal(syscall.SIGTERM) 322 ordererProcesses[followerIndices[1]].Signal(syscall.SIGTERM) 323 324 By("Waiting for followers to die") 325 // This significantly slows test (~10s). However, reducing ElectionTimeout 326 // would introduce some flakes when disk write is exceptionally slow. 327 Eventually(ordererProcesses[followerIndices[0]].Wait(), network.EventuallyTimeout).Should(Receive()) 328 Eventually(ordererProcesses[followerIndices[1]].Wait(), network.EventuallyTimeout).Should(Receive()) 329 330 By("Waiting for leader to step down") 331 Eventually(oRunners[leaderIndex].Err(), time.Minute, time.Second).Should(gbytes.Say(fmt.Sprintf("%d stepped down to follower since quorum is not active", leaderID))) 332 333 By("Submitting tx to leader") 334 // This should fail because current leader steps down 335 // and there is no leader at this point of time 336 env := CreateBroadcastEnvelope(network, leader, network.SystemChannel.Name, []byte("foo")) 337 resp, err := nwo.Broadcast(network, leader, env) 338 Expect(err).NotTo(HaveOccurred()) 339 Expect(resp.Status).To(Equal(common.Status_SERVICE_UNAVAILABLE)) 340 }) 341 }) 342 343 When("orderer TLS certificates expire", func() { 344 It("is still possible to recover", func() { 345 network = nwo.New(nwo.MultiNodeEtcdRaft(), testDir, client, StartPort(), components) 346 347 o1, o2, o3 := network.Orderer("orderer1"), network.Orderer("orderer2"), network.Orderer("orderer3") 348 peer = network.Peer("Org1", "peer1") 349 350 network.GenerateConfigTree() 351 network.Bootstrap() 352 353 ordererDomain := network.Organization(o1.Organization).Domain 354 ordererTLSCAKeyPath := filepath.Join(network.RootDir, "crypto", "ordererOrganizations", 355 ordererDomain, "tlsca", "priv_sk") 356 357 ordererTLSCAKey, err := ioutil.ReadFile(ordererTLSCAKeyPath) 358 Expect(err).NotTo(HaveOccurred()) 359 360 ordererTLSCACertPath := filepath.Join(network.RootDir, "crypto", "ordererOrganizations", 361 ordererDomain, "tlsca", fmt.Sprintf("tlsca.%s-cert.pem", ordererDomain)) 362 ordererTLSCACert, err := ioutil.ReadFile(ordererTLSCACertPath) 363 Expect(err).NotTo(HaveOccurred()) 364 365 serverTLSCerts := make(map[string][]byte) 366 for _, orderer := range []*nwo.Orderer{o1, o2, o3} { 367 tlsCertPath := filepath.Join(network.OrdererLocalTLSDir(orderer), "server.crt") 368 serverTLSCerts[tlsCertPath], err = ioutil.ReadFile(tlsCertPath) 369 Expect(err).NotTo(HaveOccurred()) 370 } 371 372 By("Expiring orderer TLS certificates") 373 for filePath, certPEM := range serverTLSCerts { 374 expiredCert, earlyMadeCACert := expireCertificate(certPEM, ordererTLSCACert, ordererTLSCAKey) 375 err = ioutil.WriteFile(filePath, expiredCert, 600) 376 Expect(err).NotTo(HaveOccurred()) 377 378 err = ioutil.WriteFile(ordererTLSCACertPath, earlyMadeCACert, 600) 379 Expect(err).NotTo(HaveOccurred()) 380 } 381 382 By("Regenerating config") 383 sess, err := network.ConfigTxGen(commands.OutputBlock{ 384 ChannelID: network.SystemChannel.Name, 385 Profile: network.SystemChannel.Profile, 386 ConfigPath: network.RootDir, 387 OutputBlock: network.OutputBlockPath(network.SystemChannel.Name), 388 }) 389 Expect(err).NotTo(HaveOccurred()) 390 Eventually(sess, network.EventuallyTimeout).Should(gexec.Exit(0)) 391 392 By("Running the orderer nodes") 393 o1Runner := network.OrdererRunner(o1) 394 o2Runner := network.OrdererRunner(o2) 395 o3Runner := network.OrdererRunner(o3) 396 397 o1Proc = ifrit.Invoke(o1Runner) 398 o2Proc = ifrit.Invoke(o2Runner) 399 o3Proc = ifrit.Invoke(o3Runner) 400 401 Eventually(o1Proc.Ready(), network.EventuallyTimeout).Should(BeClosed()) 402 Eventually(o2Proc.Ready(), network.EventuallyTimeout).Should(BeClosed()) 403 Eventually(o3Proc.Ready(), network.EventuallyTimeout).Should(BeClosed()) 404 405 By("Waiting for TLS handshakes to fail") 406 Eventually(o1Runner.Err(), network.EventuallyTimeout).Should(gbytes.Say("tls: bad certificate")) 407 Eventually(o2Runner.Err(), network.EventuallyTimeout).Should(gbytes.Say("tls: bad certificate")) 408 Eventually(o3Runner.Err(), network.EventuallyTimeout).Should(gbytes.Say("tls: bad certificate")) 409 410 By("Killing orderers") 411 o1Proc.Signal(syscall.SIGTERM) 412 o2Proc.Signal(syscall.SIGTERM) 413 o3Proc.Signal(syscall.SIGTERM) 414 415 By("Launching orderers again") 416 o1Runner = network.OrdererRunner(o1) 417 o2Runner = network.OrdererRunner(o2) 418 o3Runner = network.OrdererRunner(o3) 419 420 for i, runner := range []*ginkgomon.Runner{o1Runner, o2Runner, o3Runner} { 421 // Switch between the general port and the cluster listener port 422 runner.Command.Env = append(runner.Command.Env, "ORDERER_GENERAL_CLUSTER_TLSHANDSHAKETIMESHIFT=90s") 423 tlsCertPath := filepath.Join(network.OrdererLocalTLSDir(network.Orderers[i]), "server.crt") 424 tlsKeyPath := filepath.Join(network.OrdererLocalTLSDir(network.Orderers[i]), "server.key") 425 runner.Command.Env = append(runner.Command.Env, fmt.Sprintf("ORDERER_GENERAL_CLUSTER_SERVERCERTIFICATE=%s", tlsCertPath)) 426 runner.Command.Env = append(runner.Command.Env, fmt.Sprintf("ORDERER_GENERAL_CLUSTER_SERVERPRIVATEKEY=%s", tlsKeyPath)) 427 runner.Command.Env = append(runner.Command.Env, fmt.Sprintf("ORDERER_GENERAL_CLUSTER_ROOTCAS=%s", ordererTLSCACertPath)) 428 } 429 430 o1Proc = ifrit.Invoke(o1Runner) 431 o2Proc = ifrit.Invoke(o2Runner) 432 o3Proc = ifrit.Invoke(o3Runner) 433 434 Eventually(o1Proc.Ready(), network.EventuallyTimeout).Should(BeClosed()) 435 Eventually(o2Proc.Ready(), network.EventuallyTimeout).Should(BeClosed()) 436 Eventually(o3Proc.Ready(), network.EventuallyTimeout).Should(BeClosed()) 437 438 By("Waiting for a leader to be elected") 439 findLeader([]*ginkgomon.Runner{o1Runner, o2Runner, o3Runner}) 440 441 }) 442 }) 443 444 When("admin certificate expires", func() { 445 It("is still possible to replace them", func() { 446 network = nwo.New(nwo.BasicEtcdRaft(), testDir, client, StartPort(), components) 447 network.GenerateConfigTree() 448 network.Bootstrap() 449 450 peer = network.Peer("Org1", "peer1") 451 orderer := network.Orderer("orderer") 452 453 ordererDomain := network.Organization(orderer.Organization).Domain 454 ordererCAKeyPath := filepath.Join(network.RootDir, "crypto", "ordererOrganizations", ordererDomain, "ca", "priv_sk") 455 456 ordererCAKey, err := ioutil.ReadFile(ordererCAKeyPath) 457 Expect(err).NotTo(HaveOccurred()) 458 459 ordererCACertPath := filepath.Join(network.RootDir, "crypto", "ordererOrganizations", ordererDomain, "ca", fmt.Sprintf("ca.%s-cert.pem", ordererDomain)) 460 ordererCACert, err := ioutil.ReadFile(ordererCACertPath) 461 Expect(err).NotTo(HaveOccurred()) 462 463 adminCertPath := fmt.Sprintf("Admin@%s-cert.pem", ordererDomain) 464 adminCertPath = filepath.Join(network.OrdererUserMSPDir(orderer, "Admin"), "signcerts", adminCertPath) 465 466 originalAdminCert, err := ioutil.ReadFile(adminCertPath) 467 Expect(err).NotTo(HaveOccurred()) 468 469 expiredAdminCert, earlyCACert := expireCertificate(originalAdminCert, ordererCACert, ordererCAKey) 470 err = ioutil.WriteFile(adminCertPath, expiredAdminCert, 600) 471 Expect(err).NotTo(HaveOccurred()) 472 473 adminPath := filepath.Join(network.RootDir, "crypto", "ordererOrganizations", 474 ordererDomain, "msp", "admincerts", fmt.Sprintf("Admin@%s-cert.pem", ordererDomain)) 475 err = ioutil.WriteFile(adminPath, expiredAdminCert, 600) 476 Expect(err).NotTo(HaveOccurred()) 477 478 err = ioutil.WriteFile(ordererCACertPath, earlyCACert, 600) 479 Expect(err).NotTo(HaveOccurred()) 480 481 ordererCACertPath = filepath.Join(network.RootDir, "crypto", "ordererOrganizations", 482 ordererDomain, "msp", "cacerts", fmt.Sprintf("ca.%s-cert.pem", ordererDomain)) 483 err = ioutil.WriteFile(ordererCACertPath, earlyCACert, 600) 484 Expect(err).NotTo(HaveOccurred()) 485 486 By("Regenerating config") 487 sess, err := network.ConfigTxGen(commands.OutputBlock{ 488 ChannelID: network.SystemChannel.Name, 489 Profile: network.SystemChannel.Profile, 490 ConfigPath: network.RootDir, 491 OutputBlock: network.OutputBlockPath(network.SystemChannel.Name), 492 }) 493 Expect(err).NotTo(HaveOccurred()) 494 Eventually(sess, network.EventuallyTimeout).Should(gexec.Exit(0)) 495 496 runner := network.OrdererRunner(orderer) 497 runner.Command.Env = append(runner.Command.Env, "FABRIC_LOGGING_SPEC=debug") 498 ordererProc = ifrit.Invoke(runner) 499 500 By("Waiting for orderer to elect a leader") 501 findLeader([]*ginkgomon.Runner{runner}) 502 503 By("Creating config update that adds another orderer admin") 504 bootBlockPath := filepath.Join(network.RootDir, fmt.Sprintf("%s_block.pb", network.SystemChannel.Name)) 505 bootBlock, err := ioutil.ReadFile(bootBlockPath) 506 Expect(err).NotTo(HaveOccurred()) 507 508 current := configFromBootstrapBlock(bootBlock) 509 updatedConfig := addAdminCertToConfig(current, originalAdminCert) 510 511 tempDir, err := ioutil.TempDir("", "adminExpirationTest") 512 Expect(err).NotTo(HaveOccurred()) 513 514 configBlockFile := filepath.Join(tempDir, "update.pb") 515 defer os.RemoveAll(tempDir) 516 nwo.ComputeUpdateOrdererConfig(configBlockFile, network, network.SystemChannel.Name, current, updatedConfig, peer) 517 518 updateTransaction, err := ioutil.ReadFile(configBlockFile) 519 Expect(err).NotTo(HaveOccurred()) 520 521 By("Creating config update") 522 channelCreateTxn := createConfigTx(updateTransaction, network.SystemChannel.Name, network, orderer, peer) 523 524 By("Updating channel config and failing") 525 p, err := nwo.Broadcast(network, orderer, channelCreateTxn) 526 Expect(err).NotTo(HaveOccurred()) 527 Expect(p.Status).To(Equal(common.Status_BAD_REQUEST)) 528 Expect(p.Info).To(ContainSubstring("identity expired")) 529 530 By("Attempting to fetch a block from orderer and failing") 531 denv := CreateDeliverEnvelope(network, orderer, 0, network.SystemChannel.Name) 532 Expect(denv).NotTo(BeNil()) 533 534 block, err := nwo.Deliver(network, orderer, denv) 535 Expect(denv).NotTo(BeNil()) 536 Expect(block).To(BeNil()) 537 Eventually(runner.Err(), time.Minute, time.Second).Should(gbytes.Say("client identity expired")) 538 539 By("Killing orderer") 540 ordererProc.Signal(syscall.SIGTERM) 541 542 By("Launching orderers again") 543 runner = network.OrdererRunner(orderer) 544 runner.Command.Env = append(runner.Command.Env, "ORDERER_GENERAL_AUTHENTICATION_NOEXPIRATIONCHECKS=true") 545 ordererProc = ifrit.Invoke(runner) 546 547 By("Waiting for orderer to launch again") 548 findLeader([]*ginkgomon.Runner{runner}) 549 550 By("Updating channel config and succeeding") 551 p, err = nwo.Broadcast(network, orderer, channelCreateTxn) 552 Expect(err).NotTo(HaveOccurred()) 553 Expect(p.Status).To(Equal(common.Status_SUCCESS)) 554 555 By("Fetching a block from the orderer and succeeding") 556 block = FetchBlock(network, orderer, 1, network.SystemChannel.Name) 557 Expect(block).NotTo(BeNil()) 558 559 By("Restore the original admin cert") 560 err = ioutil.WriteFile(adminCertPath, originalAdminCert, 600) 561 Expect(err).NotTo(HaveOccurred()) 562 563 By("Ensure we can fetch the block using our original un-expired admin cert") 564 ccb := func() uint64 { 565 return nwo.GetConfigBlock(network, peer, orderer, network.SystemChannel.Name).Header.Number 566 } 567 Eventually(ccb, network.EventuallyTimeout).Should(Equal(uint64(1))) 568 }) 569 }) 570 }) 571 572 func findLeader(ordererRunners []*ginkgomon.Runner) int { 573 var wg sync.WaitGroup 574 wg.Add(len(ordererRunners)) 575 576 findLeader := func(runner *ginkgomon.Runner) int { 577 Eventually(runner.Err(), time.Minute, time.Second).Should(gbytes.Say("Raft leader changed: [0-9] -> ")) 578 579 idBuff := make([]byte, 1) 580 runner.Err().Read(idBuff) 581 582 newLeader, err := strconv.ParseInt(string(idBuff), 10, 32) 583 Expect(err).To(BeNil()) 584 return int(newLeader) 585 } 586 587 leaders := make(chan int, len(ordererRunners)) 588 589 for _, runner := range ordererRunners { 590 go func(runner *ginkgomon.Runner) { 591 defer GinkgoRecover() 592 defer wg.Done() 593 594 for { 595 leader := findLeader(runner) 596 if leader != 0 { 597 leaders <- leader 598 break 599 } 600 } 601 }(runner) 602 } 603 604 wg.Wait() 605 606 close(leaders) 607 firstLeader := <-leaders 608 for leader := range leaders { 609 if firstLeader != leader { 610 Fail(fmt.Sprintf("First leader is %d but saw %d also as a leader", firstLeader, leader)) 611 } 612 } 613 614 return firstLeader 615 } 616 617 func expireCertificate(certPEM, caCertPEM, caKeyPEM []byte) (expiredcertPEM []byte, earlyMadeCACertPEM []byte) { 618 keyAsDER, _ := pem.Decode(caKeyPEM) 619 caKeyWithoutType, err := x509.ParsePKCS8PrivateKey(keyAsDER.Bytes) 620 Expect(err).NotTo(HaveOccurred()) 621 caKey := caKeyWithoutType.(*ecdsa.PrivateKey) 622 623 caCertAsDER, _ := pem.Decode(caCertPEM) 624 caCert, err := x509.ParseCertificate(caCertAsDER.Bytes) 625 Expect(err).NotTo(HaveOccurred()) 626 627 certAsDER, _ := pem.Decode(certPEM) 628 cert, err := x509.ParseCertificate(certAsDER.Bytes) 629 Expect(err).NotTo(HaveOccurred()) 630 631 cert.Raw = nil 632 caCert.Raw = nil 633 // The certificate was made 1 hour ago 634 cert.NotBefore = time.Now().Add((-1) * time.Hour) 635 // As well as the CA certificate 636 caCert.NotBefore = time.Now().Add((-1) * time.Hour) 637 // The certificate expires now 638 cert.NotAfter = time.Now() 639 640 // The CA signs the certificate 641 certBytes, err := x509.CreateCertificate(rand.Reader, cert, caCert, cert.PublicKey, caKey) 642 Expect(err).NotTo(HaveOccurred()) 643 644 // The CA signs its own certificate 645 caCertBytes, err := x509.CreateCertificate(rand.Reader, caCert, caCert, caCert.PublicKey, caKey) 646 Expect(err).NotTo(HaveOccurred()) 647 648 expiredcertPEM = pem.EncodeToMemory(&pem.Block{Bytes: certBytes, Type: "CERTIFICATE"}) 649 earlyMadeCACertPEM = pem.EncodeToMemory(&pem.Block{Bytes: caCertBytes, Type: "CERTIFICATE"}) 650 return 651 } 652 653 func createConfigTx(txData []byte, channelName string, network *nwo.Network, orderer *nwo.Orderer, peer *nwo.Peer) *common.Envelope { 654 ctxEnv, err := protoutil.UnmarshalEnvelope(txData) 655 Expect(err).NotTo(HaveOccurred()) 656 657 payload, err := protoutil.UnmarshalPayload(ctxEnv.Payload) 658 Expect(err).NotTo(HaveOccurred()) 659 660 configUpdateEnv, err := configtx.UnmarshalConfigUpdateEnvelope(payload.Data) 661 Expect(err).NotTo(HaveOccurred()) 662 663 conf := signer.Config{ 664 MSPID: network.Organization(orderer.Organization).MSPID, 665 IdentityPath: network.OrdererUserCert(orderer, "Admin"), 666 KeyPath: network.OrdererUserKey(orderer, "Admin"), 667 } 668 669 s, err := signer.NewSigner(conf) 670 Expect(err).NotTo(HaveOccurred()) 671 672 signConfigUpdate(conf, configUpdateEnv) 673 674 env, err := protoutil.CreateSignedEnvelope(common.HeaderType_CONFIG_UPDATE, channelName, s, configUpdateEnv, 0, 0) 675 Expect(err).NotTo(HaveOccurred()) 676 677 return env 678 } 679 680 func signConfigUpdate(conf signer.Config, configUpdateEnv *common.ConfigUpdateEnvelope) *common.ConfigUpdateEnvelope { 681 s, err := signer.NewSigner(conf) 682 Expect(err).NotTo(HaveOccurred()) 683 684 sigHeader, err := protoutil.NewSignatureHeader(s) 685 Expect(err).NotTo(HaveOccurred()) 686 687 configSig := &common.ConfigSignature{ 688 SignatureHeader: protoutil.MarshalOrPanic(sigHeader), 689 } 690 691 configSig.Signature, err = s.Sign(util.ConcatenateBytes(configSig.SignatureHeader, configUpdateEnv.ConfigUpdate)) 692 Expect(err).NotTo(HaveOccurred()) 693 694 configUpdateEnv.Signatures = append(configUpdateEnv.Signatures, configSig) 695 return configUpdateEnv 696 } 697 698 func addAdminCertToConfig(originalConfig *common.Config, additionalAdmin []byte) *common.Config { 699 updatedConfig := proto.Clone(originalConfig).(*common.Config) 700 701 rawMSPConfig := updatedConfig.ChannelGroup.Groups["Orderer"].Groups["OrdererOrg"].Values["MSP"] 702 mspConfig := &msp.MSPConfig{} 703 err := proto.Unmarshal(rawMSPConfig.Value, mspConfig) 704 Expect(err).NotTo(HaveOccurred()) 705 706 fabricConfig := &msp.FabricMSPConfig{} 707 err = proto.Unmarshal(mspConfig.Config, fabricConfig) 708 Expect(err).NotTo(HaveOccurred()) 709 710 fabricConfig.Admins = append(fabricConfig.Admins, additionalAdmin) 711 mspConfig.Config = protoutil.MarshalOrPanic(fabricConfig) 712 713 rawMSPConfig.Value = protoutil.MarshalOrPanic(mspConfig) 714 return updatedConfig 715 } 716 717 func configFromBootstrapBlock(bootstrapBlock []byte) *common.Config { 718 block := &common.Block{} 719 err := proto.Unmarshal(bootstrapBlock, block) 720 Expect(err).NotTo(HaveOccurred()) 721 722 envelope, err := protoutil.GetEnvelopeFromBlock(block.Data.Data[0]) 723 Expect(err).NotTo(HaveOccurred()) 724 725 payload, err := protoutil.UnmarshalPayload(envelope.Payload) 726 Expect(err).NotTo(HaveOccurred()) 727 728 configEnv := &common.ConfigEnvelope{} 729 err = proto.Unmarshal(payload.Data, configEnv) 730 Expect(err).NotTo(HaveOccurred()) 731 732 return configEnv.Config 733 734 }