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 = ¤t.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, ¤t.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 := ¤t.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 ¤t.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 := ¤t.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 ¤t.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 := ¤t.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, ¤t.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 := ¤t.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 ¤t.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 := ¤t.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 ¤t.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 := ¤t.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, ¤t.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 := ¤t.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 }