github.com/IBM-Blockchain/fabric-operator@v1.0.4/integration/actions/orderer/orderer_test.go (about)

     1  /*
     2   * Copyright contributors to the Hyperledger Fabric Operator project
     3   *
     4   * SPDX-License-Identifier: Apache-2.0
     5   *
     6   * Licensed under the Apache License, Version 2.0 (the "License");
     7   * you may not use this file except in compliance with the License.
     8   * You may obtain a copy of the License at:
     9   *
    10   * 	  http://www.apache.org/licenses/LICENSE-2.0
    11   *
    12   * Unless required by applicable law or agreed to in writing, software
    13   * distributed under the License is distributed on an "AS IS" BASIS,
    14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    15   * See the License for the specific language governing permissions and
    16   * limitations under the License.
    17   */
    18  
    19  package orderer_test
    20  
    21  import (
    22  	"bytes"
    23  	"context"
    24  	"encoding/base64"
    25  	"encoding/json"
    26  	"fmt"
    27  	"time"
    28  
    29  	. "github.com/onsi/ginkgo/v2"
    30  	. "github.com/onsi/gomega"
    31  	"sigs.k8s.io/controller-runtime/pkg/client"
    32  
    33  	current "github.com/IBM-Blockchain/fabric-operator/api/v1beta1"
    34  	"github.com/IBM-Blockchain/fabric-operator/integration"
    35  	"github.com/IBM-Blockchain/fabric-operator/integration/helper"
    36  	"github.com/IBM-Blockchain/fabric-operator/pkg/offering/common"
    37  
    38  	k8serrors "k8s.io/apimachinery/pkg/api/errors"
    39  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    40  )
    41  
    42  var _ = Describe("trigger orderer actions", func() {
    43  	AfterEach(func() {
    44  		// Set flag if a test falls
    45  		if CurrentGinkgoTestDescription().Failed {
    46  			testFailed = true
    47  		}
    48  	})
    49  
    50  	var (
    51  		node1 helper.Orderer
    52  		node2 helper.Orderer
    53  		node3 helper.Orderer
    54  
    55  		podNameNode1 string
    56  		podNameNode2 string
    57  		podNameNode3 string
    58  
    59  		ibpordererNode1 *current.IBPOrderer
    60  	)
    61  
    62  	BeforeEach(func() {
    63  		node1 = orderer.Nodes[0]
    64  		node2 = orderer.Nodes[1]
    65  		node3 = orderer.Nodes[2]
    66  
    67  		Eventually(node1.PodIsRunning, time.Second*60, time.Second*2).Should((Equal(true)))
    68  
    69  		// NOTE: Need to keep same operator config for duration of test to ensure that the correct
    70  		// reason string is passed into operator-restart-config CM.
    71  		// integration.ClearOperatorConfig(kclient, namespace)
    72  
    73  		Eventually(func() int { return len(node1.GetPods()) }).Should(Equal(1))
    74  		Eventually(func() int { return len(node2.GetPods()) }).Should(Equal(1))
    75  		Eventually(func() int { return len(node3.GetPods()) }).Should(Equal(1))
    76  
    77  		podNameNode1 = node1.GetPods()[0].Name
    78  		podNameNode2 = node2.GetPods()[0].Name
    79  		podNameNode3 = node3.GetPods()[0].Name
    80  
    81  		result := ibpCRClient.Get().Namespace(namespace).
    82  			Resource(IBPORDERERS).
    83  			Name(node1.Name).
    84  			Do(context.TODO())
    85  		Expect(result.Error()).NotTo(HaveOccurred())
    86  
    87  		ibpordererNode1 = &current.IBPOrderer{}
    88  		result.Into(ibpordererNode1)
    89  	})
    90  
    91  	Context("spec has restart flag set to true", func() {
    92  		It("performs restart action", func() {
    93  			patch := func(o client.Object) {
    94  				ibporderer := o.(*current.IBPOrderer)
    95  				ibporderer.Spec.Action.Restart = true
    96  			}
    97  
    98  			err := integration.ResilientPatch(ibpCRClient, node1.Name, namespace, IBPORDERERS, 3, &current.IBPOrderer{}, patch)
    99  			Expect(err).NotTo(HaveOccurred())
   100  
   101  			Eventually(node1.PodIsRunning).Should((Equal(true)))
   102  
   103  			By("restarting orderer pods", func() {
   104  				Eventually(func() bool {
   105  					pods := node1.GetRunningPods()
   106  					if len(pods) == 0 {
   107  						return false
   108  					}
   109  
   110  					newPodName := pods[0].Name
   111  					if newPodName != podNameNode1 {
   112  						return true
   113  					}
   114  
   115  					return false
   116  				}).Should(Equal(true))
   117  			})
   118  
   119  			By("setting restart flag back to false after restart", func() {
   120  				Eventually(func() bool {
   121  					result := ibpCRClient.Get().Namespace(namespace).Resource(IBPORDERERS).Name(node1.Name).Do(context.TODO())
   122  					ibporderer := &current.IBPOrderer{}
   123  					result.Into(ibporderer)
   124  
   125  					return ibporderer.Spec.Action.Restart
   126  				}).Should(Equal(false))
   127  			})
   128  		})
   129  	})
   130  
   131  	Context("spec has ecert reenroll flag set to true", func() {
   132  		var (
   133  			ecert, ekey []byte
   134  
   135  			commonAssertions = func() {
   136  				By("restarting orderer pods", func() {
   137  					Eventually(func() bool {
   138  						pods := node1.GetRunningPods()
   139  						if len(pods) != 1 {
   140  							return false
   141  						}
   142  
   143  						newPodName := pods[0].Name
   144  						if newPodName != podNameNode1 {
   145  							return true
   146  						}
   147  
   148  						return false
   149  					}).Should(Equal(true))
   150  				})
   151  
   152  				By("backing up old signcert", func() {
   153  					backup := GetBackup("ecert", node1.Name)
   154  					Expect(len(backup.List)).NotTo(Equal(0))
   155  					Expect(backup.List[len(backup.List)-1].SignCerts).To(Equal(base64.StdEncoding.EncodeToString(ecert)))
   156  				})
   157  
   158  				By("updating ecert signcert secret", func() {
   159  					updatedEcertSecret, err := kclient.CoreV1().Secrets(namespace).
   160  						Get(context.TODO(), fmt.Sprintf("ecert-%s-signcert", node1.Name), metav1.GetOptions{})
   161  					Expect(err).NotTo(HaveOccurred())
   162  					Expect(bytes.Equal(ecert, updatedEcertSecret.Data["cert.pem"])).To(Equal(false))
   163  				})
   164  			}
   165  		)
   166  
   167  		BeforeEach(func() {
   168  			ecertSecret, err := kclient.CoreV1().Secrets(namespace).
   169  				Get(context.TODO(), fmt.Sprintf("ecert-%s-signcert", node1.Name), metav1.GetOptions{})
   170  			Expect(err).NotTo(HaveOccurred())
   171  			ecert = ecertSecret.Data["cert.pem"]
   172  
   173  			ecertSecret, err = kclient.CoreV1().Secrets(namespace).
   174  				Get(context.TODO(), fmt.Sprintf("ecert-%s-keystore", node1.Name), metav1.GetOptions{})
   175  			Expect(err).NotTo(HaveOccurred())
   176  			ekey = ecertSecret.Data["key.pem"]
   177  		})
   178  
   179  		When("requesting a new key", func() {
   180  			It("gets a new key and certificate", func() {
   181  				patch := func(o client.Object) {
   182  					ibporderer := o.(*current.IBPOrderer)
   183  					ibporderer.Spec.Action.Reenroll.EcertNewKey = true
   184  				}
   185  
   186  				err := integration.ResilientPatch(ibpCRClient,
   187  					node1.Name,
   188  					namespace,
   189  					IBPORDERERS,
   190  					3,
   191  					&current.IBPOrderer{},
   192  					patch)
   193  				Expect(err).NotTo(HaveOccurred())
   194  
   195  				commonAssertions()
   196  
   197  				By("generating a new key", func() {
   198  					updatedEcertKey, err := kclient.CoreV1().Secrets(namespace).
   199  						Get(context.TODO(), fmt.Sprintf("ecert-%s-keystore", node1.Name), metav1.GetOptions{})
   200  					Expect(err).NotTo(HaveOccurred())
   201  					Expect(bytes.Equal(ekey, updatedEcertKey.Data["key.pem"])).To(Equal(false))
   202  				})
   203  
   204  				By("setting reenroll flag back to false after restart", func() {
   205  					ibporderer := &current.IBPOrderer{}
   206  					Eventually(func() bool {
   207  						result := ibpCRClient.Get().Namespace(namespace).Resource(IBPORDERERS).
   208  							Name(node1.Name).Do(context.TODO())
   209  						result.Into(ibporderer)
   210  
   211  						return ibporderer.Spec.Action.Reenroll.EcertNewKey
   212  					}).Should(Equal(false))
   213  				})
   214  			})
   215  		})
   216  
   217  		When("reusing existing key", func() {
   218  			It("gets a new certificate", func() {
   219  				patch := func(o client.Object) {
   220  					ibporderer := o.(*current.IBPOrderer)
   221  					ibporderer.Spec.Action.Reenroll.Ecert = true
   222  				}
   223  
   224  				err := integration.ResilientPatch(ibpCRClient,
   225  					node1.Name,
   226  					namespace,
   227  					IBPORDERERS,
   228  					3,
   229  					&current.IBPOrderer{},
   230  					patch)
   231  				Expect(err).NotTo(HaveOccurred())
   232  
   233  				commonAssertions()
   234  
   235  				By("not generating a new key", func() {
   236  					updatedEcertKey, err := kclient.CoreV1().Secrets(namespace).
   237  						Get(context.TODO(), fmt.Sprintf("ecert-%s-keystore", node1.Name), metav1.GetOptions{})
   238  					Expect(err).NotTo(HaveOccurred())
   239  					Expect(bytes.Equal(ekey, updatedEcertKey.Data["key.pem"])).To(Equal(true))
   240  				})
   241  
   242  				By("setting reenroll flag back to false after restart", func() {
   243  					ibporderer := &current.IBPOrderer{}
   244  					Eventually(func() bool {
   245  						result := ibpCRClient.Get().Namespace(namespace).Resource(IBPORDERERS).
   246  							Name(node1.Name).Do(context.TODO())
   247  						result.Into(ibporderer)
   248  
   249  						return ibporderer.Spec.Action.Reenroll.Ecert
   250  					}).Should(Equal(false))
   251  				})
   252  			})
   253  		})
   254  	})
   255  
   256  	Context("spec has ecert enroll flag set to true", func() {
   257  		var (
   258  			ecert    []byte
   259  			ecertKey []byte
   260  		)
   261  
   262  		BeforeEach(func() {
   263  			ecertSecret, err := kclient.CoreV1().
   264  				Secrets(namespace).
   265  				Get(context.TODO(), fmt.Sprintf("ecert-%s-signcert", node1.Name), metav1.GetOptions{})
   266  			Expect(err).NotTo(HaveOccurred())
   267  
   268  			ecertKeySecret, err := kclient.CoreV1().
   269  				Secrets(namespace).
   270  				Get(context.TODO(), fmt.Sprintf("ecert-%s-keystore", node1.Name), metav1.GetOptions{})
   271  			Expect(err).NotTo(HaveOccurred())
   272  
   273  			ecert = ecertSecret.Data["cert.pem"]
   274  			ecertKey = ecertKeySecret.Data["key.pem"]
   275  		})
   276  
   277  		It("generates new crypto", func() {
   278  			patch := func(o client.Object) {
   279  				ibporderer := o.(*current.IBPOrderer)
   280  				ibporderer.Spec.Action.Enroll.Ecert = true
   281  			}
   282  
   283  			err := integration.ResilientPatch(ibpCRClient, node1.Name, namespace, IBPORDERERS, 3, &current.IBPOrderer{}, patch)
   284  			Expect(err).NotTo(HaveOccurred())
   285  
   286  			By("backing up old crypto", func() {
   287  				Eventually(func() bool {
   288  					backup := GetBackup("ecert", node1.Name)
   289  					Expect(len(backup.List)).NotTo(Equal(0))
   290  					return backup.List[len(backup.List)-1].SignCerts == base64.StdEncoding.EncodeToString(ecert) &&
   291  						backup.List[len(backup.List)-1].KeyStore == base64.StdEncoding.EncodeToString(ecertKey)
   292  				}).Should(Equal(true))
   293  			})
   294  
   295  			By("updating ecert signcert secret", func() {
   296  				Eventually(func() bool {
   297  					updatedEcertSecret, err := kclient.CoreV1().
   298  						Secrets(namespace).
   299  						Get(context.TODO(), fmt.Sprintf("ecert-%s-signcert", node1.Name), metav1.GetOptions{})
   300  					Expect(err).NotTo(HaveOccurred())
   301  
   302  					return bytes.Equal(ecert, updatedEcertSecret.Data["cert.pem"])
   303  				}).Should(Equal(false))
   304  			})
   305  
   306  			By("updating ecert key secret", func() {
   307  				Eventually(func() bool {
   308  					updatedEcertSecret, err := kclient.CoreV1().
   309  						Secrets(namespace).
   310  						Get(context.TODO(), fmt.Sprintf("ecert-%s-keystore", node1.Name), metav1.GetOptions{})
   311  					Expect(err).NotTo(HaveOccurred())
   312  
   313  					return bytes.Equal(ecertKey, updatedEcertSecret.Data["key.pem"])
   314  				}).Should(Equal(false))
   315  			})
   316  
   317  			By("setting enroll flag back to false after restart", func() {
   318  				Eventually(func() bool {
   319  					result := ibpCRClient.Get().Namespace(namespace).Resource(IBPORDERERS).Name(node1.Name).Do(context.TODO())
   320  					ibporderer := &current.IBPOrderer{}
   321  					result.Into(ibporderer)
   322  
   323  					return ibporderer.Spec.Action.Enroll.Ecert
   324  				}).Should(Equal(false))
   325  			})
   326  		})
   327  	})
   328  
   329  	Context("spec has tlscert reenroll flag set to true", func() {
   330  		var (
   331  			tlsCert, tlsKey []byte
   332  
   333  			commonAssertions = func() {
   334  				By("restarting orderer pods", func() {
   335  					Eventually(func() bool {
   336  						pods := node2.GetRunningPods()
   337  						if len(pods) != 1 {
   338  							return false
   339  						}
   340  
   341  						newPodName := pods[0].Name
   342  						if newPodName != podNameNode2 {
   343  							return true
   344  						}
   345  
   346  						return false
   347  					}).Should(Equal(true))
   348  				})
   349  
   350  				By("updating tls signcert secret", func() {
   351  					updatedTLSSecret, err := kclient.CoreV1().Secrets(namespace).
   352  						Get(context.TODO(), fmt.Sprintf("tls-%s-signcert", node2.Name), metav1.GetOptions{})
   353  					Expect(err).NotTo(HaveOccurred())
   354  					Expect(bytes.Equal(tlsCert, updatedTLSSecret.Data["cert.pem"])).To(Equal(false))
   355  				})
   356  			}
   357  		)
   358  
   359  		BeforeEach(func() {
   360  			tlsSecret, err := kclient.CoreV1().Secrets(namespace).
   361  				Get(context.TODO(), fmt.Sprintf("tls-%s-signcert", node2.Name), metav1.GetOptions{})
   362  			Expect(err).NotTo(HaveOccurred())
   363  			tlsCert = tlsSecret.Data["cert.pem"]
   364  
   365  			tlsSecret, err = kclient.CoreV1().Secrets(namespace).
   366  				Get(context.TODO(), fmt.Sprintf("tls-%s-keystore", node2.Name), metav1.GetOptions{})
   367  			Expect(err).NotTo(HaveOccurred())
   368  			tlsKey = tlsSecret.Data["key.pem"]
   369  		})
   370  
   371  		When("requesting a new key", func() {
   372  			It("gets a new key and certificate", func() {
   373  				patch := func(o client.Object) {
   374  					ibporderer := o.(*current.IBPOrderer)
   375  					ibporderer.Spec.Action.Reenroll.TLSCertNewKey = true
   376  				}
   377  
   378  				err := integration.ResilientPatch(
   379  					ibpCRClient,
   380  					node2.Name,
   381  					namespace,
   382  					IBPORDERERS,
   383  					3,
   384  					&current.IBPOrderer{},
   385  					patch)
   386  				Expect(err).NotTo(HaveOccurred())
   387  
   388  				commonAssertions()
   389  
   390  				By("generating a new key", func() {
   391  					updatedEcertKey, err := kclient.CoreV1().Secrets(namespace).
   392  						Get(context.TODO(), fmt.Sprintf("tls-%s-keystore", node2.Name), metav1.GetOptions{})
   393  					Expect(err).NotTo(HaveOccurred())
   394  					Expect(bytes.Equal(tlsKey, updatedEcertKey.Data["key.pem"])).To(Equal(false))
   395  				})
   396  
   397  				By("setting reenroll flag back to false after restart", func() {
   398  					ibporderer := &current.IBPOrderer{}
   399  					Eventually(func() bool {
   400  						result := ibpCRClient.Get().Namespace(namespace).Resource(IBPORDERERS).
   401  							Name(node2.Name).Do(context.TODO())
   402  						result.Into(ibporderer)
   403  
   404  						return ibporderer.Spec.Action.Reenroll.TLSCertNewKey
   405  					}).Should(Equal(false))
   406  				})
   407  			})
   408  		})
   409  
   410  		When("reusing existing key", func() {
   411  			It("gets a new certificate", func() {
   412  				patch := func(o client.Object) {
   413  					ibporderer := o.(*current.IBPOrderer)
   414  					ibporderer.Spec.Action.Reenroll.TLSCert = true
   415  				}
   416  
   417  				err := integration.ResilientPatch(
   418  					ibpCRClient,
   419  					node2.Name,
   420  					namespace,
   421  					IBPORDERERS,
   422  					3,
   423  					&current.IBPOrderer{},
   424  					patch)
   425  				Expect(err).NotTo(HaveOccurred())
   426  
   427  				commonAssertions()
   428  
   429  				By("not generating a new key", func() {
   430  					updatedEcertKey, err := kclient.CoreV1().Secrets(namespace).
   431  						Get(context.TODO(), fmt.Sprintf("tls-%s-keystore", node2.Name), metav1.GetOptions{})
   432  					Expect(err).NotTo(HaveOccurred())
   433  					Expect(bytes.Equal(tlsKey, updatedEcertKey.Data["key.pem"])).To(Equal(true))
   434  				})
   435  
   436  				By("setting reenroll flag back to false after restart", func() {
   437  					ibporderer := &current.IBPOrderer{}
   438  					Eventually(func() bool {
   439  						result := ibpCRClient.Get().Namespace(namespace).Resource(IBPORDERERS).
   440  							Name(node2.Name).Do(context.TODO())
   441  						result.Into(ibporderer)
   442  
   443  						return ibporderer.Spec.Action.Reenroll.TLSCert
   444  					}).Should(Equal(false))
   445  				})
   446  			})
   447  		})
   448  	})
   449  
   450  	Context("spec has tlscert enroll flag set to true", func() {
   451  		var (
   452  			tls []byte
   453  		)
   454  
   455  		BeforeEach(func() {
   456  			tlsSecret, err := kclient.CoreV1().Secrets(namespace).Get(context.TODO(), fmt.Sprintf("tls-%s-signcert", node3.Name), metav1.GetOptions{})
   457  			Expect(err).NotTo(HaveOccurred())
   458  
   459  			tls = tlsSecret.Data["cert.pem"]
   460  		})
   461  
   462  		It("gets a new certificate", func() {
   463  			patch := func(o client.Object) {
   464  				ibporderer := o.(*current.IBPOrderer)
   465  				ibporderer.Spec.Action.Enroll.TLSCert = true
   466  			}
   467  
   468  			err := integration.ResilientPatch(ibpCRClient, node3.Name, namespace, IBPORDERERS, 3, &current.IBPOrderer{}, patch)
   469  			Expect(err).NotTo(HaveOccurred())
   470  
   471  			By("restarting orderer pods", func() {
   472  				Eventually(func() bool {
   473  					pods := node3.GetPods()
   474  					if len(pods) != 1 {
   475  						return false
   476  					}
   477  
   478  					newPodName := pods[0].Name
   479  					if newPodName != podNameNode3 {
   480  						return true
   481  					}
   482  
   483  					return false
   484  				}).Should(Equal(true))
   485  			})
   486  
   487  			By("backing up old signcert", func() {
   488  				backup := GetBackup("tls", node3.Name)
   489  				Expect(len(backup.List)).NotTo(Equal(0))
   490  				Expect(backup.List[len(backup.List)-1].SignCerts).To(Equal(base64.StdEncoding.EncodeToString(tls)))
   491  			})
   492  
   493  			By("updating tls signcert secret", func() {
   494  				updatedTLSSecret, err := kclient.CoreV1().Secrets(namespace).Get(context.TODO(), fmt.Sprintf("tls-%s-signcert", node3.Name), metav1.GetOptions{})
   495  				Expect(err).NotTo(HaveOccurred())
   496  
   497  				Expect(bytes.Equal(tls, updatedTLSSecret.Data["cert.pem"])).To(Equal(false))
   498  			})
   499  
   500  			By("setting reenroll flag back to false after restart", func() {
   501  				Eventually(func() bool {
   502  					result := ibpCRClient.Get().Namespace(namespace).Resource(IBPORDERERS).Name(node3.Name).Do(context.TODO())
   503  					ibporderer := &current.IBPOrderer{}
   504  					result.Into(ibporderer)
   505  
   506  					return ibporderer.Spec.Action.Enroll.TLSCert
   507  				}).Should(Equal(false))
   508  			})
   509  		})
   510  	})
   511  
   512  })
   513  
   514  func GetBackup(certType, name string) *common.Backup {
   515  	backupSecret, err := kclient.CoreV1().Secrets(namespace).Get(context.TODO(), fmt.Sprintf("%s-crypto-backup", name), metav1.GetOptions{})
   516  	if err != nil {
   517  		Expect(k8serrors.IsNotFound(err)).To(Equal(true))
   518  		return &common.Backup{}
   519  	}
   520  
   521  	backup := &common.Backup{}
   522  	key := fmt.Sprintf("%s-backup.json", certType)
   523  	err = json.Unmarshal(backupSecret.Data[key], backup)
   524  	Expect(err).NotTo(HaveOccurred())
   525  
   526  	return backup
   527  }