github.com/lzy4123/fabric@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  }