github.com/hyperledger-labs/bdls@v2.1.1+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", "peer0") 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", "peer0") 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", "peer0") 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", "peer0") 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 Eventually(o1Proc.Wait(), network.EventuallyTimeout).Should(Receive()) 415 Eventually(o2Proc.Wait(), network.EventuallyTimeout).Should(Receive()) 416 Eventually(o3Proc.Wait(), network.EventuallyTimeout).Should(Receive()) 417 418 By("Launching orderers again") 419 o1Runner = network.OrdererRunner(o1) 420 o2Runner = network.OrdererRunner(o2) 421 o3Runner = network.OrdererRunner(o3) 422 423 for i, runner := range []*ginkgomon.Runner{o1Runner, o2Runner, o3Runner} { 424 // Switch between the general port and the cluster listener port 425 runner.Command.Env = append(runner.Command.Env, "ORDERER_GENERAL_CLUSTER_TLSHANDSHAKETIMESHIFT=90s") 426 tlsCertPath := filepath.Join(network.OrdererLocalTLSDir(network.Orderers[i]), "server.crt") 427 tlsKeyPath := filepath.Join(network.OrdererLocalTLSDir(network.Orderers[i]), "server.key") 428 runner.Command.Env = append(runner.Command.Env, fmt.Sprintf("ORDERER_GENERAL_CLUSTER_SERVERCERTIFICATE=%s", tlsCertPath)) 429 runner.Command.Env = append(runner.Command.Env, fmt.Sprintf("ORDERER_GENERAL_CLUSTER_SERVERPRIVATEKEY=%s", tlsKeyPath)) 430 runner.Command.Env = append(runner.Command.Env, fmt.Sprintf("ORDERER_GENERAL_CLUSTER_ROOTCAS=%s", ordererTLSCACertPath)) 431 } 432 433 o1Proc = ifrit.Invoke(o1Runner) 434 o2Proc = ifrit.Invoke(o2Runner) 435 o3Proc = ifrit.Invoke(o3Runner) 436 437 Eventually(o1Proc.Ready(), network.EventuallyTimeout).Should(BeClosed()) 438 Eventually(o2Proc.Ready(), network.EventuallyTimeout).Should(BeClosed()) 439 Eventually(o3Proc.Ready(), network.EventuallyTimeout).Should(BeClosed()) 440 441 By("Waiting for a leader to be elected") 442 findLeader([]*ginkgomon.Runner{o1Runner, o2Runner, o3Runner}) 443 444 }) 445 }) 446 447 When("admin certificate expires", func() { 448 It("is still possible to replace them", func() { 449 network = nwo.New(nwo.BasicEtcdRaft(), testDir, client, StartPort(), components) 450 network.GenerateConfigTree() 451 network.Bootstrap() 452 453 peer = network.Peer("Org1", "peer0") 454 orderer := network.Orderer("orderer") 455 456 ordererDomain := network.Organization(orderer.Organization).Domain 457 ordererCAKeyPath := filepath.Join(network.RootDir, "crypto", "ordererOrganizations", ordererDomain, "ca", "priv_sk") 458 459 ordererCAKey, err := ioutil.ReadFile(ordererCAKeyPath) 460 Expect(err).NotTo(HaveOccurred()) 461 462 ordererCACertPath := filepath.Join(network.RootDir, "crypto", "ordererOrganizations", ordererDomain, "ca", fmt.Sprintf("ca.%s-cert.pem", ordererDomain)) 463 ordererCACert, err := ioutil.ReadFile(ordererCACertPath) 464 Expect(err).NotTo(HaveOccurred()) 465 466 adminCertPath := fmt.Sprintf("Admin@%s-cert.pem", ordererDomain) 467 adminCertPath = filepath.Join(network.OrdererUserMSPDir(orderer, "Admin"), "signcerts", adminCertPath) 468 469 originalAdminCert, err := ioutil.ReadFile(adminCertPath) 470 Expect(err).NotTo(HaveOccurred()) 471 472 expiredAdminCert, earlyCACert := expireCertificate(originalAdminCert, ordererCACert, ordererCAKey) 473 err = ioutil.WriteFile(adminCertPath, expiredAdminCert, 600) 474 Expect(err).NotTo(HaveOccurred()) 475 476 adminPath := filepath.Join(network.RootDir, "crypto", "ordererOrganizations", 477 ordererDomain, "msp", "admincerts", fmt.Sprintf("Admin@%s-cert.pem", ordererDomain)) 478 err = ioutil.WriteFile(adminPath, expiredAdminCert, 600) 479 Expect(err).NotTo(HaveOccurred()) 480 481 err = ioutil.WriteFile(ordererCACertPath, earlyCACert, 600) 482 Expect(err).NotTo(HaveOccurred()) 483 484 ordererCACertPath = filepath.Join(network.RootDir, "crypto", "ordererOrganizations", 485 ordererDomain, "msp", "cacerts", fmt.Sprintf("ca.%s-cert.pem", ordererDomain)) 486 err = ioutil.WriteFile(ordererCACertPath, earlyCACert, 600) 487 Expect(err).NotTo(HaveOccurred()) 488 489 By("Regenerating config") 490 sess, err := network.ConfigTxGen(commands.OutputBlock{ 491 ChannelID: network.SystemChannel.Name, 492 Profile: network.SystemChannel.Profile, 493 ConfigPath: network.RootDir, 494 OutputBlock: network.OutputBlockPath(network.SystemChannel.Name), 495 }) 496 Expect(err).NotTo(HaveOccurred()) 497 Eventually(sess, network.EventuallyTimeout).Should(gexec.Exit(0)) 498 499 runner := network.OrdererRunner(orderer) 500 runner.Command.Env = append(runner.Command.Env, "FABRIC_LOGGING_SPEC=debug") 501 ordererProc = ifrit.Invoke(runner) 502 503 By("Waiting for orderer to elect a leader") 504 findLeader([]*ginkgomon.Runner{runner}) 505 506 By("Creating config update that adds another orderer admin") 507 bootBlockPath := filepath.Join(network.RootDir, fmt.Sprintf("%s_block.pb", network.SystemChannel.Name)) 508 bootBlock, err := ioutil.ReadFile(bootBlockPath) 509 Expect(err).NotTo(HaveOccurred()) 510 511 current := configFromBootstrapBlock(bootBlock) 512 updatedConfig := addAdminCertToConfig(current, originalAdminCert) 513 514 tempDir, err := ioutil.TempDir("", "adminExpirationTest") 515 Expect(err).NotTo(HaveOccurred()) 516 517 configBlockFile := filepath.Join(tempDir, "update.pb") 518 defer os.RemoveAll(tempDir) 519 nwo.ComputeUpdateOrdererConfig(configBlockFile, network, network.SystemChannel.Name, current, updatedConfig, peer) 520 521 updateTransaction, err := ioutil.ReadFile(configBlockFile) 522 Expect(err).NotTo(HaveOccurred()) 523 524 By("Creating config update") 525 channelCreateTxn := createConfigTx(updateTransaction, network.SystemChannel.Name, network, orderer, peer) 526 527 By("Updating channel config and failing") 528 p, err := nwo.Broadcast(network, orderer, channelCreateTxn) 529 Expect(err).NotTo(HaveOccurred()) 530 Expect(p.Status).To(Equal(common.Status_BAD_REQUEST)) 531 Expect(p.Info).To(ContainSubstring("identity expired")) 532 533 By("Attempting to fetch a block from orderer and failing") 534 denv := CreateDeliverEnvelope(network, orderer, 0, network.SystemChannel.Name) 535 Expect(denv).NotTo(BeNil()) 536 537 block, err := nwo.Deliver(network, orderer, denv) 538 Expect(denv).NotTo(BeNil()) 539 Expect(block).To(BeNil()) 540 Eventually(runner.Err(), time.Minute, time.Second).Should(gbytes.Say("client identity expired")) 541 542 By("Killing orderer") 543 ordererProc.Signal(syscall.SIGTERM) 544 Eventually(ordererProc.Wait(), network.EventuallyTimeout).Should(Receive()) 545 546 By("Launching orderers again") 547 runner = network.OrdererRunner(orderer) 548 runner.Command.Env = append(runner.Command.Env, "ORDERER_GENERAL_AUTHENTICATION_NOEXPIRATIONCHECKS=true") 549 ordererProc = ifrit.Invoke(runner) 550 551 By("Waiting for orderer to launch again") 552 findLeader([]*ginkgomon.Runner{runner}) 553 554 By("Updating channel config and succeeding") 555 p, err = nwo.Broadcast(network, orderer, channelCreateTxn) 556 Expect(err).NotTo(HaveOccurred()) 557 Expect(p.Status).To(Equal(common.Status_SUCCESS)) 558 559 By("Fetching a block from the orderer and succeeding") 560 block = FetchBlock(network, orderer, 1, network.SystemChannel.Name) 561 Expect(block).NotTo(BeNil()) 562 563 By("Restore the original admin cert") 564 err = ioutil.WriteFile(adminCertPath, originalAdminCert, 600) 565 Expect(err).NotTo(HaveOccurred()) 566 567 By("Ensure we can fetch the block using our original un-expired admin cert") 568 ccb := func() uint64 { 569 return nwo.GetConfigBlock(network, peer, orderer, network.SystemChannel.Name).Header.Number 570 } 571 Eventually(ccb, network.EventuallyTimeout).Should(Equal(uint64(1))) 572 }) 573 }) 574 }) 575 576 func findLeader(ordererRunners []*ginkgomon.Runner) int { 577 var wg sync.WaitGroup 578 wg.Add(len(ordererRunners)) 579 580 findLeader := func(runner *ginkgomon.Runner) int { 581 Eventually(runner.Err(), time.Minute, time.Second).Should(gbytes.Say("Raft leader changed: [0-9] -> ")) 582 583 idBuff := make([]byte, 1) 584 runner.Err().Read(idBuff) 585 586 newLeader, err := strconv.ParseInt(string(idBuff), 10, 32) 587 Expect(err).To(BeNil()) 588 return int(newLeader) 589 } 590 591 leaders := make(chan int, len(ordererRunners)) 592 593 for _, runner := range ordererRunners { 594 go func(runner *ginkgomon.Runner) { 595 defer GinkgoRecover() 596 defer wg.Done() 597 598 for { 599 leader := findLeader(runner) 600 if leader != 0 { 601 leaders <- leader 602 break 603 } 604 } 605 }(runner) 606 } 607 608 wg.Wait() 609 610 close(leaders) 611 firstLeader := <-leaders 612 for leader := range leaders { 613 if firstLeader != leader { 614 Fail(fmt.Sprintf("First leader is %d but saw %d also as a leader", firstLeader, leader)) 615 } 616 } 617 618 return firstLeader 619 } 620 621 func expireCertificate(certPEM, caCertPEM, caKeyPEM []byte) (expiredcertPEM []byte, earlyMadeCACertPEM []byte) { 622 keyAsDER, _ := pem.Decode(caKeyPEM) 623 caKeyWithoutType, err := x509.ParsePKCS8PrivateKey(keyAsDER.Bytes) 624 Expect(err).NotTo(HaveOccurred()) 625 caKey := caKeyWithoutType.(*ecdsa.PrivateKey) 626 627 caCertAsDER, _ := pem.Decode(caCertPEM) 628 caCert, err := x509.ParseCertificate(caCertAsDER.Bytes) 629 Expect(err).NotTo(HaveOccurred()) 630 631 certAsDER, _ := pem.Decode(certPEM) 632 cert, err := x509.ParseCertificate(certAsDER.Bytes) 633 Expect(err).NotTo(HaveOccurred()) 634 635 cert.Raw = nil 636 caCert.Raw = nil 637 // The certificate was made 1 hour ago 638 cert.NotBefore = time.Now().Add((-1) * time.Hour) 639 // As well as the CA certificate 640 caCert.NotBefore = time.Now().Add((-1) * time.Hour) 641 // The certificate expires now 642 cert.NotAfter = time.Now() 643 644 // The CA signs the certificate 645 certBytes, err := x509.CreateCertificate(rand.Reader, cert, caCert, cert.PublicKey, caKey) 646 Expect(err).NotTo(HaveOccurred()) 647 648 // The CA signs its own certificate 649 caCertBytes, err := x509.CreateCertificate(rand.Reader, caCert, caCert, caCert.PublicKey, caKey) 650 Expect(err).NotTo(HaveOccurred()) 651 652 expiredcertPEM = pem.EncodeToMemory(&pem.Block{Bytes: certBytes, Type: "CERTIFICATE"}) 653 earlyMadeCACertPEM = pem.EncodeToMemory(&pem.Block{Bytes: caCertBytes, Type: "CERTIFICATE"}) 654 return 655 } 656 657 func createConfigTx(txData []byte, channelName string, network *nwo.Network, orderer *nwo.Orderer, peer *nwo.Peer) *common.Envelope { 658 ctxEnv, err := protoutil.UnmarshalEnvelope(txData) 659 Expect(err).NotTo(HaveOccurred()) 660 661 payload, err := protoutil.UnmarshalPayload(ctxEnv.Payload) 662 Expect(err).NotTo(HaveOccurred()) 663 664 configUpdateEnv, err := configtx.UnmarshalConfigUpdateEnvelope(payload.Data) 665 Expect(err).NotTo(HaveOccurred()) 666 667 conf := signer.Config{ 668 MSPID: network.Organization(orderer.Organization).MSPID, 669 IdentityPath: network.OrdererUserCert(orderer, "Admin"), 670 KeyPath: network.OrdererUserKey(orderer, "Admin"), 671 } 672 673 s, err := signer.NewSigner(conf) 674 Expect(err).NotTo(HaveOccurred()) 675 676 signConfigUpdate(conf, configUpdateEnv) 677 678 env, err := protoutil.CreateSignedEnvelope(common.HeaderType_CONFIG_UPDATE, channelName, s, configUpdateEnv, 0, 0) 679 Expect(err).NotTo(HaveOccurred()) 680 681 return env 682 } 683 684 func signConfigUpdate(conf signer.Config, configUpdateEnv *common.ConfigUpdateEnvelope) *common.ConfigUpdateEnvelope { 685 s, err := signer.NewSigner(conf) 686 Expect(err).NotTo(HaveOccurred()) 687 688 sigHeader, err := protoutil.NewSignatureHeader(s) 689 Expect(err).NotTo(HaveOccurred()) 690 691 configSig := &common.ConfigSignature{ 692 SignatureHeader: protoutil.MarshalOrPanic(sigHeader), 693 } 694 695 configSig.Signature, err = s.Sign(util.ConcatenateBytes(configSig.SignatureHeader, configUpdateEnv.ConfigUpdate)) 696 Expect(err).NotTo(HaveOccurred()) 697 698 configUpdateEnv.Signatures = append(configUpdateEnv.Signatures, configSig) 699 return configUpdateEnv 700 } 701 702 func addAdminCertToConfig(originalConfig *common.Config, additionalAdmin []byte) *common.Config { 703 updatedConfig := proto.Clone(originalConfig).(*common.Config) 704 705 rawMSPConfig := updatedConfig.ChannelGroup.Groups["Orderer"].Groups["OrdererOrg"].Values["MSP"] 706 mspConfig := &msp.MSPConfig{} 707 err := proto.Unmarshal(rawMSPConfig.Value, mspConfig) 708 Expect(err).NotTo(HaveOccurred()) 709 710 fabricConfig := &msp.FabricMSPConfig{} 711 err = proto.Unmarshal(mspConfig.Config, fabricConfig) 712 Expect(err).NotTo(HaveOccurred()) 713 714 fabricConfig.Admins = append(fabricConfig.Admins, additionalAdmin) 715 mspConfig.Config = protoutil.MarshalOrPanic(fabricConfig) 716 717 rawMSPConfig.Value = protoutil.MarshalOrPanic(mspConfig) 718 return updatedConfig 719 } 720 721 func configFromBootstrapBlock(bootstrapBlock []byte) *common.Config { 722 block := &common.Block{} 723 err := proto.Unmarshal(bootstrapBlock, block) 724 Expect(err).NotTo(HaveOccurred()) 725 726 envelope, err := protoutil.GetEnvelopeFromBlock(block.Data.Data[0]) 727 Expect(err).NotTo(HaveOccurred()) 728 729 payload, err := protoutil.UnmarshalPayload(envelope.Payload) 730 Expect(err).NotTo(HaveOccurred()) 731 732 configEnv := &common.ConfigEnvelope{} 733 err = proto.Unmarshal(payload.Data, configEnv) 734 Expect(err).NotTo(HaveOccurred()) 735 736 return configEnv.Config 737 738 }