github.com/IBM-Blockchain/fabric-operator@v1.0.4/pkg/offering/base/orderer/node.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 baseorderer 20 21 import ( 22 "context" 23 "encoding/json" 24 "fmt" 25 "os" 26 "path/filepath" 27 "strings" 28 "time" 29 30 current "github.com/IBM-Blockchain/fabric-operator/api/v1beta1" 31 config "github.com/IBM-Blockchain/fabric-operator/operatorconfig" 32 "github.com/IBM-Blockchain/fabric-operator/pkg/action" 33 commonapi "github.com/IBM-Blockchain/fabric-operator/pkg/apis/common" 34 "github.com/IBM-Blockchain/fabric-operator/pkg/certificate" 35 commoninit "github.com/IBM-Blockchain/fabric-operator/pkg/initializer/common" 36 commonconfig "github.com/IBM-Blockchain/fabric-operator/pkg/initializer/common/config" 37 initializer "github.com/IBM-Blockchain/fabric-operator/pkg/initializer/orderer" 38 ordererconfig "github.com/IBM-Blockchain/fabric-operator/pkg/initializer/orderer/config/v1" 39 v2ordererconfig "github.com/IBM-Blockchain/fabric-operator/pkg/initializer/orderer/config/v2" 40 v24ordererconfig "github.com/IBM-Blockchain/fabric-operator/pkg/initializer/orderer/config/v24" 41 "github.com/IBM-Blockchain/fabric-operator/pkg/initializer/validator" 42 controllerclient "github.com/IBM-Blockchain/fabric-operator/pkg/k8s/controllerclient" 43 "github.com/IBM-Blockchain/fabric-operator/pkg/manager/resources" 44 resourcemanager "github.com/IBM-Blockchain/fabric-operator/pkg/manager/resources/manager" 45 "github.com/IBM-Blockchain/fabric-operator/pkg/offering/base/orderer/override" 46 "github.com/IBM-Blockchain/fabric-operator/pkg/offering/common" 47 "github.com/IBM-Blockchain/fabric-operator/pkg/offering/common/reconcilechecks" 48 "github.com/IBM-Blockchain/fabric-operator/pkg/operatorerrors" 49 "github.com/IBM-Blockchain/fabric-operator/pkg/restart" 50 "github.com/IBM-Blockchain/fabric-operator/pkg/util" 51 "github.com/IBM-Blockchain/fabric-operator/version" 52 "github.com/pkg/errors" 53 appsv1 "k8s.io/api/apps/v1" 54 corev1 "k8s.io/api/core/v1" 55 k8serrors "k8s.io/apimachinery/pkg/api/errors" 56 v1 "k8s.io/apimachinery/pkg/apis/meta/v1" 57 "k8s.io/apimachinery/pkg/labels" 58 "k8s.io/apimachinery/pkg/runtime" 59 "k8s.io/apimachinery/pkg/types" 60 "sigs.k8s.io/controller-runtime/pkg/client" 61 k8sclient "sigs.k8s.io/controller-runtime/pkg/client" 62 "sigs.k8s.io/controller-runtime/pkg/reconcile" 63 "sigs.k8s.io/yaml" 64 ) 65 66 const ( 67 NODE = "node" 68 ) 69 70 type Override interface { 71 Deployment(v1.Object, *appsv1.Deployment, resources.Action) error 72 Service(v1.Object, *corev1.Service, resources.Action) error 73 PVC(v1.Object, *corev1.PersistentVolumeClaim, resources.Action) error 74 EnvCM(v1.Object, *corev1.ConfigMap, resources.Action, map[string]interface{}) error 75 OrdererNode(v1.Object, *current.IBPOrderer, resources.Action) error 76 } 77 78 //go:generate counterfeiter -o mocks/deployment_manager.go -fake-name DeploymentManager . DeploymentManager 79 80 type DeploymentManager interface { 81 resources.Manager 82 CheckForSecretChange(v1.Object, string, func(string, *appsv1.Deployment) bool) error 83 } 84 85 //go:generate counterfeiter -o mocks/initializeibporderer.go -fake-name InitializeIBPOrderer . InitializeIBPOrderer 86 87 type InitializeIBPOrderer interface { 88 GenerateSecrets(commoninit.SecretType, *current.IBPOrderer, *commonconfig.Response) error 89 Create(initializer.OrdererConfig, initializer.IBPOrderer, string) (*initializer.Response, error) 90 Update(initializer.OrdererConfig, initializer.IBPOrderer) (*initializer.Response, error) 91 CreateOrUpdateConfigMap(*current.IBPOrderer, initializer.OrdererConfig) error 92 GetConfigFromConfigMap(instance *current.IBPOrderer) (*corev1.ConfigMap, error) 93 MissingCrypto(*current.IBPOrderer) bool 94 Delete(*current.IBPOrderer) error 95 CheckIfAdminCertsUpdated(*current.IBPOrderer) (bool, error) 96 UpdateAdminSecret(*current.IBPOrderer) error 97 GetInitOrderer(instance *current.IBPOrderer, storagePath string) (*initializer.Orderer, error) 98 GetUpdatedOrderer(instance *current.IBPOrderer) (*initializer.Orderer, error) 99 UpdateSecrets(prefix commoninit.SecretType, instance *current.IBPOrderer, crypto *commonconfig.Response) error 100 GenerateSecretsFromResponse(instance *current.IBPOrderer, cryptoResponse *commonconfig.CryptoResponse) error 101 UpdateSecretsFromResponse(instance *current.IBPOrderer, cryptoResponse *commonconfig.CryptoResponse) error 102 GetCrypto(instance *current.IBPOrderer) (*commonconfig.CryptoResponse, error) 103 GetCoreConfigFromFile(instance *current.IBPOrderer, file string) (initializer.OrdererConfig, error) 104 GetCoreConfigFromBytes(instance *current.IBPOrderer, bytes []byte) (initializer.OrdererConfig, error) 105 } 106 107 //go:generate counterfeiter -o mocks/update.go -fake-name Update . Update 108 109 type Update interface { 110 SpecUpdated() bool 111 ConfigOverridesUpdated() bool 112 TLSCertUpdated() bool 113 EcertUpdated() bool 114 OrdererTagUpdated() bool 115 CertificateUpdated() bool 116 RestartNeeded() bool 117 EcertReenrollNeeded() bool 118 TLScertReenrollNeeded() bool 119 EcertNewKeyReenroll() bool 120 TLScertNewKeyReenroll() bool 121 DeploymentUpdated() bool 122 MSPUpdated() bool 123 EcertEnroll() bool 124 TLScertEnroll() bool 125 CertificateCreated() bool 126 GetCreatedCertType() commoninit.SecretType 127 CryptoBackupNeeded() bool 128 MigrateToV2() bool 129 MigrateToV24() bool 130 NodeOUUpdated() bool 131 ImagesUpdated() bool 132 FabricVersionUpdated() bool 133 } 134 135 type IBPOrderer interface { 136 Initialize(instance *current.IBPOrderer, update Update) error 137 PreReconcileChecks(instance *current.IBPOrderer, update Update) (bool, error) 138 ReconcileManagers(instance *current.IBPOrderer, update Update, genesisBlock []byte) error 139 Reconcile(instance *current.IBPOrderer, update Update) (common.Result, error) 140 } 141 142 //go:generate counterfeiter -o mocks/certificate_manager.go -fake-name CertificateManager . CertificateManager 143 144 type CertificateManager interface { 145 CheckCertificatesForExpire(instance v1.Object, numSecondsBeforeExpire int64) (current.IBPCRStatusType, string, error) 146 GetSignCert(string, string) ([]byte, error) 147 GetDurationToNextRenewal(commoninit.SecretType, v1.Object, int64) (time.Duration, error) 148 RenewCert(commoninit.SecretType, certificate.Instance, *current.EnrollmentSpec, *commonapi.BCCSP, string, bool, bool) error 149 } 150 151 //go:generate counterfeiter -o mocks/restart_manager.go -fake-name RestartManager . RestartManager 152 153 type RestartManager interface { 154 ForAdminCertUpdate(instance v1.Object) error 155 ForCertUpdate(certType commoninit.SecretType, instance v1.Object) error 156 ForConfigOverride(instance v1.Object) error 157 ForNodeOU(instance v1.Object) error 158 TriggerIfNeeded(instance restart.Instance) error 159 ForRestartAction(instance v1.Object) error 160 } 161 162 type OrdererConfig interface { 163 MergeWith(interface{}, bool) error 164 ToBytes() ([]byte, error) 165 UsingPKCS11() bool 166 SetPKCS11Defaults(bool) 167 GetBCCSPSection() *commonapi.BCCSP 168 SetDefaultKeyStore() 169 SetBCCSPLibrary(string) 170 } 171 172 type Manager struct { 173 Client controllerclient.Client 174 Scheme *runtime.Scheme 175 Config *config.Config 176 } 177 178 func (m *Manager) GetNode(nodeNumber int, renewCertTimers map[string]*time.Timer, restartManager RestartManager) *Node { 179 return NewNode(m.Client, m.Scheme, m.Config, fmt.Sprintf("%s%d", NODE, nodeNumber), renewCertTimers, restartManager) 180 } 181 182 var _ IBPOrderer = &Node{} 183 184 type Node struct { 185 Client controllerclient.Client 186 Scheme *runtime.Scheme 187 Config *config.Config 188 189 DeploymentManager DeploymentManager 190 ServiceManager resources.Manager 191 PVCManager resources.Manager 192 EnvConfigMapManager resources.Manager 193 RoleManager resources.Manager 194 RoleBindingManager resources.Manager 195 ServiceAccountManager resources.Manager 196 197 Override Override 198 Initializer InitializeIBPOrderer 199 Name string 200 201 CertificateManager CertificateManager 202 RenewCertTimers map[string]*time.Timer 203 204 Restart RestartManager 205 } 206 207 func NewNode(client controllerclient.Client, scheme *runtime.Scheme, config *config.Config, name string, renewCertTimers map[string]*time.Timer, restartManager RestartManager) *Node { 208 n := &Node{ 209 Client: client, 210 Scheme: scheme, 211 Config: config, 212 Override: &override.Override{ 213 Name: name, 214 Client: client, 215 Config: config, 216 }, 217 Name: name, 218 RenewCertTimers: renewCertTimers, 219 Restart: restartManager, 220 } 221 n.CreateManagers() 222 223 validator := &validator.Validator{ 224 Client: client, 225 } 226 227 n.Initializer = initializer.New(client, scheme, config.OrdererInitConfig, name, validator) 228 n.CertificateManager = certificate.New(client, scheme) 229 230 return n 231 } 232 233 func NewNodeWithOverrides(client controllerclient.Client, scheme *runtime.Scheme, config *config.Config, name string, o Override, renewCertTimers map[string]*time.Timer, restartManager RestartManager) *Node { 234 n := &Node{ 235 Client: client, 236 Scheme: scheme, 237 Config: config, 238 Override: o, 239 Name: name, 240 RenewCertTimers: renewCertTimers, 241 Restart: restartManager, 242 } 243 n.CreateManagers() 244 245 validator := &validator.Validator{ 246 Client: client, 247 } 248 249 n.Initializer = initializer.New(client, scheme, config.OrdererInitConfig, name, validator) 250 n.CertificateManager = certificate.New(client, scheme) 251 252 return n 253 } 254 255 func (n *Node) CreateManagers() { 256 override := n.Override 257 resourceManager := resourcemanager.New(n.Client, n.Scheme) 258 n.DeploymentManager = resourceManager.CreateDeploymentManager("", override.Deployment, n.GetLabels, n.Config.OrdererInitConfig.DeploymentFile) 259 n.ServiceManager = resourceManager.CreateServiceManager("", override.Service, n.GetLabels, n.Config.OrdererInitConfig.ServiceFile) 260 n.PVCManager = resourceManager.CreatePVCManager("", override.PVC, n.GetLabels, n.Config.OrdererInitConfig.PVCFile) 261 n.EnvConfigMapManager = resourceManager.CreateConfigMapManager("env", override.EnvCM, n.GetLabels, n.Config.OrdererInitConfig.CMFile, nil) 262 n.RoleManager = resourceManager.CreateRoleManager("", nil, n.GetLabels, n.Config.OrdererInitConfig.RoleFile) 263 n.RoleBindingManager = resourceManager.CreateRoleBindingManager("", nil, n.GetLabels, n.Config.OrdererInitConfig.RoleBindingFile) 264 n.ServiceAccountManager = resourceManager.CreateServiceAccountManager("", nil, n.GetLabels, n.Config.OrdererInitConfig.ServiceAccountFile) 265 } 266 267 func (n *Node) Reconcile(instance *current.IBPOrderer, update Update) (common.Result, error) { 268 log.Info(fmt.Sprintf("Reconciling node instance '%s' ... update: %+v", instance.Name, update)) 269 var err error 270 var status *current.CRStatus 271 272 versionSet, err := n.SetVersion(instance) 273 if err != nil { 274 return common.Result{}, errors.Wrap(err, fmt.Sprintf("failed updating CR '%s' to version '%s'", instance.Name, version.Operator)) 275 } 276 if versionSet { 277 log.Info("Instance version updated, requeuing request...") 278 return common.Result{ 279 Result: reconcile.Result{ 280 Requeue: true, 281 }, 282 }, nil 283 } 284 285 instanceUpdated, err := n.PreReconcileChecks(instance, update) 286 if err != nil { 287 return common.Result{}, errors.Wrap(err, "failed pre reconcile checks") 288 } 289 externalEndpointUpdated := n.UpdateExternalEndpoint(instance) 290 291 if instanceUpdated || externalEndpointUpdated { 292 log.Info(fmt.Sprintf("Updating instance after pre reconcile checks: %t, updating external endpoint: %t", 293 instanceUpdated, externalEndpointUpdated)) 294 295 err = n.Client.Patch(context.TODO(), instance, nil, controllerclient.PatchOption{ 296 Resilient: &controllerclient.ResilientPatch{ 297 Retry: 3, 298 Into: ¤t.IBPOrderer{}, 299 Strategy: k8sclient.MergeFrom, 300 }, 301 }) 302 if err != nil { 303 return common.Result{}, errors.Wrap(err, "failed to update instance") 304 } 305 306 log.Info("Instance updated, requeuing request...") 307 return common.Result{ 308 Result: reconcile.Result{ 309 Requeue: true, 310 }, 311 Status: ¤t.CRStatus{ 312 Type: current.Initializing, 313 Reason: "Setting default values for either zone, region, and/or external endpoint", 314 Message: "Operator has updated spec with defaults as part of initialization", 315 }, 316 }, nil 317 } 318 319 err = n.Initialize(instance, update) 320 if err != nil { 321 return common.Result{}, operatorerrors.Wrap(err, operatorerrors.OrdererInitilizationFailed, "failed to initialize orderer node") 322 } 323 324 err = n.ReconcileManagers(instance, update, nil) 325 if err != nil { 326 return common.Result{}, errors.Wrap(err, "failed to reconcile managers") 327 } 328 329 err = n.UpdateConnectionProfile(instance) 330 if err != nil { 331 return common.Result{}, errors.Wrap(err, "failed to create connection profile") 332 } 333 334 err = n.CheckStates(instance) 335 if err != nil { 336 return common.Result{}, errors.Wrap(err, "failed to check and restore state") 337 } 338 339 // custom product logic can be implemented here 340 // No-Op atm 341 status, result, err := n.CustomLogic(instance, update) 342 343 if err != nil { 344 return common.Result{}, errors.Wrap(err, "failed to run custom offering logic") 345 } 346 347 if result != nil { 348 return *result, nil 349 } 350 351 if update.MSPUpdated() { 352 err = n.UpdateMSPCertificates(instance) 353 if err != nil { 354 if err != nil { 355 return common.Result{}, errors.Wrap(err, "failed to update certificates passed in MSP spec") 356 } 357 } 358 } 359 360 if update.EcertUpdated() { 361 log.Info("Ecert was updated") 362 // Request deployment restart for tls cert update 363 err = n.Restart.ForCertUpdate(commoninit.ECERT, instance) 364 if err != nil { 365 return common.Result{}, errors.Wrap(err, "failed to update restart config") 366 } 367 } 368 369 if update.TLSCertUpdated() { 370 log.Info("TLS cert was updated") 371 // Request deployment restart for ecert update 372 err = n.Restart.ForCertUpdate(commoninit.TLS, instance) 373 if err != nil { 374 return common.Result{}, errors.Wrap(err, "failed to update restart config") 375 } 376 } 377 378 if err := n.HandleActions(instance, update); err != nil { 379 return common.Result{}, errors.Wrap(err, "failed to handle actions") 380 } 381 382 if err := n.HandleRestart(instance, update); err != nil { 383 return common.Result{}, err 384 } 385 386 return common.Result{ 387 Status: status, 388 }, nil 389 } 390 391 // PreReconcileChecks validate CR request before starting reconcile flow 392 func (n *Node) PreReconcileChecks(instance *current.IBPOrderer, update Update) (bool, error) { 393 var err error 394 395 imagesUpdated, err := reconcilechecks.FabricVersionHelper(instance, n.Config.Operator.Versions, update) 396 if err != nil { 397 return false, errors.Wrap(err, "failed during version and image checks") 398 } 399 400 if instance.Spec.HSMSet() { 401 err = util.ValidateHSMProxyURL(instance.Spec.HSM.PKCS11Endpoint) 402 if err != nil { 403 return false, errors.Wrapf(err, "invalid HSM endpoint for orderer instance '%s'", instance.GetName()) 404 } 405 } 406 407 if !instance.Spec.DomainSet() { 408 return false, fmt.Errorf("domain not set for orderer instance '%s'", instance.GetName()) 409 } 410 411 if instance.Spec.Action.Enroll.Ecert && instance.Spec.Action.Reenroll.Ecert { 412 return false, errors.New("both enroll and renenroll action requested for ecert, must only select one") 413 } 414 415 if instance.Spec.Action.Enroll.TLSCert && instance.Spec.Action.Reenroll.TLSCert { 416 return false, errors.New("both enroll and renenroll action requested for TLS cert, must only select one") 417 } 418 419 if instance.Spec.Action.Enroll.Ecert && instance.Spec.Action.Reenroll.EcertNewKey { 420 return false, errors.New("both enroll and renenroll with new key action requested for ecert, must only select one") 421 } 422 423 if instance.Spec.Action.Enroll.TLSCert && instance.Spec.Action.Reenroll.TLSCertNewKey { 424 return false, errors.New("both enroll and renenroll with new key action requested for TLS cert, must only select one") 425 } 426 427 if instance.Spec.Action.Reenroll.Ecert && instance.Spec.Action.Reenroll.EcertNewKey { 428 return false, errors.New("both reenroll and renenroll with new key action requested for ecert, must only select one") 429 } 430 431 if instance.Spec.Action.Reenroll.TLSCert && instance.Spec.Action.Reenroll.TLSCertNewKey { 432 return false, errors.New("both reenroll and renenroll with new key action requested for TLS cert, must only select one") 433 } 434 435 zoneUpdated, err := n.SelectZone(instance) 436 if err != nil { 437 return false, err 438 } 439 440 regionUpdated, err := n.SelectRegion(instance) 441 if err != nil { 442 return false, err 443 } 444 445 hsmImageUpdated := n.ReconcileHSMImages(instance) 446 447 var replicasUpdated bool 448 if instance.Spec.Replicas == nil { 449 replicas := int32(1) 450 instance.Spec.Replicas = &replicas 451 replicasUpdated = true 452 } 453 454 updated := zoneUpdated || regionUpdated || hsmImageUpdated || replicasUpdated || imagesUpdated 455 456 if updated { 457 log.Info(fmt.Sprintf("zoneUpdated %t, regionUpdated %t, hsmImageUpdated %t, replicasUpdated %t, imagesUpdated %t", 458 zoneUpdated, regionUpdated, hsmImageUpdated, replicasUpdated, imagesUpdated)) 459 } 460 461 return updated, nil 462 } 463 464 func (n *Node) Initialize(instance *current.IBPOrderer, update Update) error { 465 var err error 466 467 log.Info(fmt.Sprintf("Checking if initialization needed for node: %s", instance.GetName())) 468 469 // TODO: Add checks to determine if initialization is neeeded. Split this method into 470 // two, one should handle initialization during the create event of a CR and the other 471 // should update events 472 473 // Service account is required by HSM init job 474 err = n.ReconcileRBAC(instance) 475 if err != nil { 476 return errors.Wrap(err, "failed RBAC reconciliation") 477 } 478 479 if instance.IsHSMEnabled() { 480 // If HSM config not found, HSM proxy is being used 481 if instance.UsingHSMProxy() { 482 err = os.Setenv("PKCS11_PROXY_SOCKET", instance.Spec.HSM.PKCS11Endpoint) 483 if err != nil { 484 return err 485 } 486 } else { 487 488 hsmConfig, err := commonconfig.ReadHSMConfig(n.Client, instance) 489 if err != nil { 490 return errors.New("using non-proxy HSM, but no HSM config defined as config map 'ibp-hsm-config'") 491 } 492 493 if hsmConfig.Daemon != nil { 494 log.Info("Using daemon based HSM, creating pvc...") 495 n.PVCManager.SetCustomName(instance.Spec.CustomNames.PVC.Orderer) 496 err = n.PVCManager.Reconcile(instance, update.SpecUpdated()) 497 if err != nil { 498 return errors.Wrap(err, "failed PVC reconciliation") 499 } 500 } 501 } 502 } 503 504 initOrderer, err := n.Initializer.GetInitOrderer(instance, n.GetInitStoragePath(instance)) 505 if err != nil { 506 return err 507 } 508 initOrderer.UsingHSMProxy = instance.UsingHSMProxy() 509 510 ordererConfig := n.Config.OrdererInitConfig.OrdererFile 511 if version.GetMajorReleaseVersion(instance.Spec.FabricVersion) == version.V2 { 512 currentVer := version.String(instance.Spec.FabricVersion) 513 if currentVer.EqualWithoutTag(version.V2_4_1) || currentVer.GreaterThan(version.V2_4_1) { 514 ordererConfig = n.Config.OrdererInitConfig.OrdererV24File 515 } else if currentVer.LessThan(version.V2_4_1) { 516 ordererConfig = n.Config.OrdererInitConfig.OrdererV2File 517 } 518 } 519 520 initOrderer.Config, err = n.Initializer.GetCoreConfigFromFile(instance, ordererConfig) 521 if err != nil { 522 return err 523 } 524 525 updated := update.ConfigOverridesUpdated() || update.NodeOUUpdated() 526 if update.ConfigOverridesUpdated() { 527 err = n.InitializeUpdateConfigOverride(instance, initOrderer) 528 if err != nil { 529 return err 530 } 531 // Request deployment restart for config override update 532 if err := n.Restart.ForConfigOverride(instance); err != nil { 533 return err 534 } 535 } 536 if update.NodeOUUpdated() { 537 err = n.InitializeUpdateNodeOU(instance) 538 if err != nil { 539 return err 540 } 541 // Request deloyment restart for node OU update 542 if err = n.Restart.ForNodeOU(instance); err != nil { 543 return err 544 } 545 } 546 if !updated { 547 err = n.InitializeCreate(instance, initOrderer) 548 if err != nil { 549 return err 550 } 551 } 552 553 updateNeeded, err := n.Initializer.CheckIfAdminCertsUpdated(instance) 554 if err != nil { 555 return err 556 } 557 558 if updateNeeded { 559 err = n.Initializer.UpdateAdminSecret(instance) 560 if err != nil { 561 return err 562 } 563 // Request deployment restart for admin cert updates 564 if err = n.Restart.ForAdminCertUpdate(instance); err != nil { 565 return err 566 } 567 } 568 569 return nil 570 } 571 572 func (n *Node) InitializeCreate(instance *current.IBPOrderer, initOrderer *initializer.Orderer) error { 573 // TODO: Should also check for secrets not just config map 574 if n.ConfigExists(instance) { 575 log.Info(fmt.Sprintf("Config '%s-config' exists, not reinitializing node", instance.GetName())) 576 return nil 577 } 578 579 log.Info(fmt.Sprintf("Running initialization for create event on node '%s', since config '%s-config' does not exists", instance.GetName(), instance.GetName())) 580 configOverride, err := instance.GetConfigOverride() 581 if err != nil { 582 return err 583 } 584 resp, err := n.Initializer.Create(configOverride.(OrdererConfig), initOrderer, n.GetInitStoragePath(instance)) 585 if err != nil { 586 return err 587 } 588 589 if resp != nil { 590 if resp.Crypto != nil { 591 if !instance.Spec.NodeOUDisabled() { 592 if err := resp.Crypto.VerifyCertOU("orderer"); err != nil { 593 return err 594 } 595 } 596 597 err = n.Initializer.GenerateSecretsFromResponse(instance, resp.Crypto) 598 if err != nil { 599 return err 600 } 601 } 602 603 if resp.Config != nil { 604 log.Info(fmt.Sprintf("Create config map for '%s'...", instance.GetName())) 605 if instance.IsHSMEnabled() && !instance.UsingHSMProxy() { 606 hsmConfig, err := commonconfig.ReadHSMConfig(n.Client, instance) 607 if err != nil { 608 return err 609 } 610 resp.Config.SetBCCSPLibrary(filepath.Join("/hsm/lib", filepath.Base(hsmConfig.Library.FilePath))) 611 } 612 613 err = n.Initializer.CreateOrUpdateConfigMap(instance, resp.Config) 614 if err != nil { 615 return err 616 } 617 } 618 } 619 620 return nil 621 } 622 623 func (n *Node) ConfigExists(instance *current.IBPOrderer) bool { 624 name := fmt.Sprintf("%s-config", instance.GetName()) 625 namespacedName := types.NamespacedName{ 626 Name: name, 627 Namespace: instance.Namespace, 628 } 629 630 cm := &corev1.ConfigMap{} 631 err := n.Client.Get(context.TODO(), namespacedName, cm) 632 if err != nil { 633 return false 634 } 635 636 return true 637 } 638 639 func (n *Node) InitializeUpdateConfigOverride(instance *current.IBPOrderer, initOrderer *initializer.Orderer) error { 640 log.Info(fmt.Sprintf("Running initialization update config override for node: %s", instance.GetName())) 641 642 if n.Initializer.MissingCrypto(instance) { 643 log.Info("Missing crypto for node") 644 // If crypto is missing, we should run the create logic 645 err := n.InitializeCreate(instance, initOrderer) 646 if err != nil { 647 return err 648 } 649 650 return nil 651 } 652 653 cm, err := n.Initializer.GetConfigFromConfigMap(instance) 654 if err != nil { 655 return err 656 } 657 658 initOrderer.Config, err = n.Initializer.GetCoreConfigFromBytes(instance, cm.BinaryData["orderer.yaml"]) 659 if err != nil { 660 return err 661 } 662 663 configOverride, err := instance.GetConfigOverride() 664 if err != nil { 665 return err 666 } 667 668 resp, err := n.Initializer.Update(configOverride.(OrdererConfig), initOrderer) 669 if err != nil { 670 return err 671 } 672 673 if resp != nil && resp.Config != nil { 674 log.Info(fmt.Sprintf("Update config map for '%s'...", instance.GetName())) 675 err = n.Initializer.CreateOrUpdateConfigMap(instance, resp.Config) 676 if err != nil { 677 return err 678 } 679 } 680 681 return nil 682 } 683 684 func (n *Node) InitializeUpdateNodeOU(instance *current.IBPOrderer) error { 685 log.Info(fmt.Sprintf("Running initialize update node OU enabled: %t for orderer '%s", !instance.Spec.NodeOUDisabled(), instance.GetName())) 686 687 crypto, err := n.Initializer.GetCrypto(instance) 688 if err != nil { 689 return err 690 } 691 692 if !instance.Spec.NodeOUDisabled() { 693 if err := crypto.VerifyCertOU("orderer"); err != nil { 694 return err 695 696 } 697 } else { 698 // If nodeOUDisabled, admin certs are required 699 if crypto.Enrollment.AdminCerts == nil { 700 return errors.New("node OU disabled, admin certs are required but missing") 701 } 702 } 703 704 // Update config.yaml in config map 705 err = n.Initializer.CreateOrUpdateConfigMap(instance, nil) 706 if err != nil { 707 return err 708 } 709 710 return nil 711 } 712 713 func (n *Node) ReconcileManagers(instance *current.IBPOrderer, updated Update, genesisBlock []byte) error { 714 var err error 715 716 update := updated.SpecUpdated() 717 718 n.PVCManager.SetCustomName(instance.Spec.CustomNames.PVC.Orderer) 719 err = n.PVCManager.Reconcile(instance, update) 720 if err != nil { 721 return errors.Wrapf(err, "failed PVC reconciliation") 722 } 723 724 err = n.ServiceManager.Reconcile(instance, update) 725 if err != nil { 726 return errors.Wrap(err, "failed Service reconciliation") 727 } 728 729 err = n.ReconcileRBAC(instance) 730 if err != nil { 731 return errors.Wrap(err, "failed RBAC reconciliation") 732 } 733 734 err = n.EnvConfigMapManager.Reconcile(instance, update) 735 if err != nil { 736 return errors.Wrap(err, "failed Env ConfigMap reconciliation") 737 } 738 739 if instance.Spec.IsUsingChannelLess() { 740 log.Info("Node is in channel less mode - ending reconcile") 741 } else if !instance.Spec.IsPrecreateOrderer() { 742 log.Info("Node is not precreate - reconciling genesis secret") 743 err = n.ReconcileGenesisSecret(instance) 744 if err != nil { 745 return errors.Wrap(err, "failed Genesis Secret reconciliation") 746 } 747 } 748 749 err = n.DeploymentManager.Reconcile(instance, updated.DeploymentUpdated()) 750 if err != nil { 751 return errors.Wrap(err, "failed Deployment reconciliation") 752 } 753 754 return nil 755 } 756 757 func (n *Node) CheckStates(instance *current.IBPOrderer) error { 758 // Don't need to check state if the state is being updated via CR. State needs 759 // to be checked if operator detects changes to a resources that was not triggered 760 // via CR. 761 if n.DeploymentManager.Exists(instance) { 762 err := n.DeploymentManager.CheckState(instance) 763 if err != nil { 764 log.Error(err, "unexpected state") 765 err = n.DeploymentManager.RestoreState(instance) 766 if err != nil { 767 return err 768 } 769 } 770 } 771 772 return nil 773 } 774 775 func (n *Node) SetVersion(instance *current.IBPOrderer) (bool, error) { 776 if instance.Status.Version == "" || !version.String(instance.Status.Version).Equal(version.Operator) { 777 log.Info("Version of Operator: ", "version", version.Operator) 778 log.Info(fmt.Sprintf("Version of CR '%s': %s", instance.GetName(), instance.Status.Version)) 779 log.Info(fmt.Sprintf("Setting '%s' to version '%s'", instance.Name, version.Operator)) 780 781 instance.Status.Version = version.Operator 782 err := n.Client.PatchStatus(context.TODO(), instance, nil, controllerclient.PatchOption{ 783 Resilient: &controllerclient.ResilientPatch{ 784 Retry: 3, 785 Into: ¤t.IBPOrderer{}, 786 Strategy: k8sclient.MergeFrom, 787 }, 788 }) 789 if err != nil { 790 return false, err 791 } 792 return true, nil 793 } 794 return false, nil 795 } 796 797 func (n *Node) GetLabels(instance v1.Object) map[string]string { 798 parts := strings.Split(instance.GetName(), "node") 799 label := os.Getenv("OPERATOR_LABEL_PREFIX") 800 if label == "" { 801 label = "fabric" 802 } 803 804 if len(parts) > 1 { 805 ordererclustername := strings.Join(parts[:len(parts)-1], "node") 806 orderingnode := "node" + parts[len(parts)-1] 807 return map[string]string{ 808 "app": instance.GetName(), 809 "creator": label, 810 "orderingservice": ordererclustername, 811 "orderingnode": orderingnode, 812 "parent": ordererclustername, 813 "app.kubernetes.io/name": label, 814 "app.kubernetes.io/instance": label + "orderer", 815 "app.kubernetes.io/managed-by": label + "-operator", 816 } 817 } 818 819 return map[string]string{ 820 "app": instance.GetName(), 821 "creator": label, 822 "orderingservice": fmt.Sprintf("%s", instance.GetName()), 823 "app.kubernetes.io/name": label, 824 "app.kubernetes.io/instance": label + "orderer", 825 "app.kubernetes.io/managed-by": label + "-operator", 826 } 827 } 828 829 func (n *Node) Delete(instance *current.IBPOrderer) error { 830 log.Info(fmt.Sprintf("Deleting node '%s'", n.Name)) 831 err := n.ServiceManager.Delete(instance) 832 if err != nil { 833 return errors.Wrapf(err, "failed to delete service '%s'", n.ServiceManager.GetName(instance)) 834 } 835 836 err = n.PVCManager.Delete(instance) 837 if err != nil { 838 return errors.Wrapf(err, "failed to delete pvc '%s'", n.ServiceManager.GetName(instance)) 839 } 840 841 err = n.EnvConfigMapManager.Delete(instance) 842 if err != nil { 843 return errors.Wrapf(err, "failed to delete config map '%s'", n.ServiceManager.GetName(instance)) 844 } 845 846 err = n.Initializer.Delete(instance) 847 if err != nil { 848 return errors.Wrapf(err, "failed to delete secrets") 849 } 850 851 // Important: This must always be the last resource to be deleted 852 err = n.DeploymentManager.Delete(instance) 853 if err != nil { 854 return errors.Wrapf(err, "failed to delete deployment '%s'", n.DeploymentManager.GetName(instance)) 855 } 856 857 return nil 858 } 859 860 func (n *Node) ReconcileGenesisSecret(instance *current.IBPOrderer) error { 861 namespacedName := types.NamespacedName{ 862 Name: instance.Name + "-genesis", 863 Namespace: instance.Namespace, 864 } 865 866 secret := &corev1.Secret{} 867 err := n.Client.Get(context.TODO(), namespacedName, secret) 868 if err != nil { 869 if k8serrors.IsNotFound(err) { 870 // Request object not found, could have been deleted after reconcile request. 871 // Owned objects are automatically garbage collected. For additional cleanup logic use finalizers. 872 // Return and don't requeue 873 return n.CreateGenesisSecret(instance) 874 } 875 // Error reading the object - requeue the request. 876 return err 877 } 878 return nil 879 } 880 881 func (n *Node) CreateGenesisSecret(instance *current.IBPOrderer) error { 882 data := map[string][]byte{} 883 884 genesisBlock, err := util.Base64ToBytes(instance.Spec.GenesisBlock) 885 if err != nil { 886 return errors.Wrap(err, "failed to decode genesis block") 887 } 888 889 data["orderer.block"] = genesisBlock 890 s := &corev1.Secret{ 891 Data: data, 892 } 893 s.Name = instance.Name + "-genesis" 894 s.Namespace = instance.Namespace 895 s.Labels = n.GetLabels(instance) 896 897 err = n.Client.CreateOrUpdate(context.TODO(), s, controllerclient.CreateOrUpdateOption{ 898 Owner: instance, 899 Scheme: n.Scheme, 900 }) 901 if err != nil { 902 return errors.Wrap(err, "failed to create genesis secret") 903 } 904 905 return nil 906 } 907 908 func (n *Node) ReconcileRBAC(instance *current.IBPOrderer) error { 909 var err error 910 911 err = n.RoleManager.Reconcile(instance, false) 912 if err != nil { 913 return err 914 } 915 916 err = n.RoleBindingManager.Reconcile(instance, false) 917 if err != nil { 918 return err 919 } 920 921 err = n.ServiceAccountManager.Reconcile(instance, false) 922 if err != nil { 923 return err 924 } 925 926 return nil 927 } 928 929 func (n *Node) SelectZone(instance *current.IBPOrderer) (bool, error) { 930 if instance.Spec.Zone == "select" { 931 log.Info("Selecting zone...") 932 zone := util.GetZone(n.Client) 933 log.Info(fmt.Sprintf("Zone set to: '%s'", zone)) 934 instance.Spec.Zone = zone 935 return true, nil 936 } 937 if instance.Spec.Zone != "" { 938 err := util.ValidateZone(n.Client, instance.Spec.Zone) 939 if err != nil { 940 return false, err 941 } 942 } 943 return false, nil 944 } 945 946 func (n *Node) SelectRegion(instance *current.IBPOrderer) (bool, error) { 947 if instance.Spec.Region == "select" { 948 log.Info("Selecting region...") 949 region := util.GetRegion(n.Client) 950 log.Info(fmt.Sprintf("Region set to: '%s'", region)) 951 instance.Spec.Region = region 952 return true, nil 953 } 954 if instance.Spec.Region != "" { 955 err := util.ValidateRegion(n.Client, instance.Spec.Region) 956 if err != nil { 957 return false, err 958 } 959 } 960 return false, nil 961 } 962 963 func (n *Node) UpdateExternalEndpoint(instance *current.IBPOrderer) bool { 964 if instance.Spec.ExternalAddress == "" { 965 instance.Spec.ExternalAddress = instance.Namespace + "-" + instance.Name + "-orderer" + "." + instance.Spec.Domain + ":443" 966 return true 967 } 968 return false 969 } 970 971 func (n *Node) UpdateConnectionProfile(instance *current.IBPOrderer) error { 972 var err error 973 974 endpoints := n.GetEndpoints(instance) 975 976 tlscert, err := common.GetTLSSignCertEncoded(n.Client, instance) 977 if err != nil { 978 return err 979 } 980 981 tlscacerts, err := common.GetTLSCACertEncoded(n.Client, instance) 982 if err != nil { 983 return err 984 } 985 986 tlsintercerts, err := common.GetTLSIntercertEncoded(n.Client, instance) 987 if err != nil { 988 return err 989 } 990 991 ecert, err := common.GetEcertSignCertEncoded(n.Client, instance) 992 if err != nil { 993 return err 994 } 995 996 cacert, err := common.GetEcertCACertEncoded(n.Client, instance) 997 if err != nil { 998 return err 999 } 1000 1001 admincerts, err := common.GetEcertAdmincertEncoded(n.Client, instance) 1002 if err != nil { 1003 return err 1004 } 1005 1006 if len(tlsintercerts) > 0 { 1007 tlscacerts = tlsintercerts 1008 } 1009 1010 err = n.UpdateConnectionProfileConfigmap(instance, *endpoints, tlscert, tlscacerts, ecert, cacert, admincerts) 1011 if err != nil { 1012 return err 1013 } 1014 1015 return nil 1016 } 1017 1018 func (n *Node) UpdateConnectionProfileConfigmap(instance *current.IBPOrderer, endpoints current.OrdererEndpoints, tlscert string, tlscacerts []string, ecert string, cacert []string, admincerts []string) error { 1019 1020 // TODO add ecert.intermediatecerts and ecert.admincerts 1021 // TODO add tls.cacerts 1022 // TODO get the whole PeerConnectionProfile object from caller?? 1023 name := instance.Name + "-connection-profile" 1024 connectionProfile := ¤t.OrdererConnectionProfile{ 1025 Endpoints: endpoints, 1026 TLS: ¤t.MSP{ 1027 SignCerts: tlscert, 1028 CACerts: tlscacerts, 1029 }, 1030 Component: ¤t.MSP{ 1031 SignCerts: ecert, 1032 CACerts: cacert, 1033 AdminCerts: admincerts, 1034 }, 1035 } 1036 1037 bytes, err := json.Marshal(connectionProfile) 1038 if err != nil { 1039 return errors.Wrap(err, "failed to marshal connection profile") 1040 } 1041 cm := &corev1.ConfigMap{ 1042 BinaryData: map[string][]byte{"profile.json": bytes}, 1043 } 1044 cm.Name = name 1045 cm.Namespace = instance.Namespace 1046 cm.Labels = n.GetLabels(instance) 1047 1048 nn := types.NamespacedName{ 1049 Name: name, 1050 Namespace: instance.GetNamespace(), 1051 } 1052 1053 err = n.Client.Get(context.TODO(), nn, &corev1.ConfigMap{}) 1054 if err == nil { 1055 log.Info(fmt.Sprintf("Update connection profile configmap '%s' for %s", nn.Name, instance.Name)) 1056 err = n.Client.Update(context.TODO(), cm, controllerclient.UpdateOption{Owner: instance, Scheme: n.Scheme}) 1057 if err != nil { 1058 return errors.Wrap(err, "failed to update connection profile configmap") 1059 } 1060 } else { 1061 log.Info(fmt.Sprintf("Create connection profile configmap '%s' for %s", nn.Name, instance.Name)) 1062 err = n.Client.Create(context.TODO(), cm, controllerclient.CreateOption{Owner: instance, Scheme: n.Scheme}) 1063 if err != nil { 1064 return errors.Wrap(err, "failed to create connection profile configmap") 1065 } 1066 } 1067 1068 return nil 1069 } 1070 1071 func (n *Node) GetEndpoints(instance *current.IBPOrderer) *current.OrdererEndpoints { 1072 endpoints := ¤t.OrdererEndpoints{ 1073 API: "grpcs://" + instance.Namespace + "-" + instance.Name + "-orderer." + instance.Spec.Domain + ":443", 1074 Operations: "https://" + instance.Namespace + "-" + instance.Name + "-operations." + instance.Spec.Domain + ":443", 1075 Grpcweb: "https://" + instance.Namespace + "-" + instance.Name + "-grpcweb." + instance.Spec.Domain + ":443", 1076 } 1077 currentVer := version.String(instance.Spec.FabricVersion) 1078 if currentVer.EqualWithoutTag(version.V2_4_1) || currentVer.GreaterThan(version.V2_4_1) { 1079 endpoints.Admin = "https://" + instance.Namespace + "-" + instance.Name + "-admin." + instance.Spec.Domain + ":443" 1080 } 1081 return endpoints 1082 } 1083 1084 func (n *Node) UpdateParentStatus(instance *current.IBPOrderer) error { 1085 parentName := instance.Labels["parent"] 1086 1087 nn := types.NamespacedName{ 1088 Name: parentName, 1089 Namespace: instance.GetNamespace(), 1090 } 1091 1092 log.Info(fmt.Sprintf("Node '%s' is setting parent '%s' status", instance.GetName(), parentName)) 1093 1094 parentInstance := ¤t.IBPOrderer{} 1095 err := n.Client.Get(context.TODO(), nn, parentInstance) 1096 if err != nil { 1097 if k8serrors.IsNotFound(err) { 1098 log.Info(fmt.Sprintf("Parent '%s' for node '%s' not found, skipping setting parent status", parentName, instance.GetName())) 1099 return nil 1100 } 1101 return err 1102 } 1103 1104 // If parent is deployed and child was not updated to warning state, no longer update the parent 1105 if parentInstance.Status.Type == current.Deployed && instance.Status.Type != current.Warning { 1106 log.Info(fmt.Sprintf("Parent '%s' is in 'Deployed' state, can't update status", parentName)) 1107 return nil 1108 } 1109 1110 labelSelector, err := labels.Parse(fmt.Sprintf("parent=%s", parentName)) 1111 if err != nil { 1112 return errors.Wrap(err, "failed to parse selector for parent name") 1113 } 1114 1115 listOptions := &client.ListOptions{ 1116 LabelSelector: labelSelector, 1117 Namespace: instance.GetNamespace(), 1118 } 1119 1120 ordererList := ¤t.IBPOrdererList{} 1121 err = n.Client.List(context.TODO(), ordererList, listOptions) 1122 if err != nil { 1123 return err 1124 } 1125 1126 clustersize := parentInstance.Spec.ClusterSize 1127 1128 var returnStatus current.IBPCRStatusType 1129 reason := "No reason" 1130 1131 log.Info(fmt.Sprintf("Found %d nodes, original cluster size %d", len(ordererList.Items), clustersize)) 1132 1133 updateStatus := false 1134 errorstateNodes := []string{} 1135 deployingstateNodes := []string{} 1136 precreatedNodes := []string{} 1137 deployedNodes := []string{} 1138 warningNodes := []string{} 1139 1140 for _, node := range ordererList.Items { 1141 if node.Status.Type == current.Error { 1142 log.Info(fmt.Sprintf("Node %s is in Error state", node.GetName())) 1143 errorstateNodes = append(errorstateNodes, node.GetName()) 1144 } else if node.Status.Type == current.Deploying { 1145 log.Info(fmt.Sprintf("Node %s is in Deploying state", node.GetName())) 1146 deployingstateNodes = append(deployingstateNodes, node.GetName()) 1147 } else if node.Status.Type == current.Precreated { 1148 log.Info(fmt.Sprintf("Node %s is in Precreating state", node.GetName())) 1149 precreatedNodes = append(precreatedNodes, node.GetName()) 1150 } else if node.Status.Type == current.Warning { 1151 log.Info(fmt.Sprintf("Node %s is in Warning state", node.GetName())) 1152 warningNodes = append(warningNodes, node.GetName()) 1153 } else if node.Status.Type == current.Deployed { 1154 log.Info(fmt.Sprintf("Node %s is in Deployed state", node.GetName())) 1155 deployedNodes = append(deployedNodes, node.GetName()) 1156 } 1157 } 1158 1159 if len(deployingstateNodes) != 0 { 1160 log.Info("Nodes are in deploying state currently, not updating parent status") 1161 updateStatus = false 1162 } else if len(errorstateNodes) != 0 { 1163 updateStatus = true 1164 reason = "The orderer nodes " + strings.Join(errorstateNodes[:], ",") + " are in Error state" 1165 returnStatus = current.Error 1166 } else if len(precreatedNodes) != 0 { 1167 updateStatus = true 1168 reason = "The orderer nodes " + strings.Join(precreatedNodes[:], ",") + " are in Precreated state" 1169 returnStatus = current.Precreated 1170 } else if len(warningNodes) != 0 { 1171 updateStatus = true 1172 reason = "The orderer nodes " + strings.Join(warningNodes[:], ",") + " are in Warning state" 1173 returnStatus = current.Warning 1174 } else if len(deployedNodes) != 0 { 1175 updateStatus = true 1176 returnStatus = current.Deployed 1177 reason = "All nodes are deployed" 1178 } 1179 1180 if updateStatus { 1181 parentInstance.Status.Type = returnStatus 1182 parentInstance.Status.Status = current.True 1183 parentInstance.Status.Reason = reason 1184 parentInstance.Status.LastHeartbeatTime = time.Now().String() 1185 1186 log.Info(fmt.Sprintf("Setting parent status to: %+v", parentInstance.Status)) 1187 err = n.Client.UpdateStatus(context.TODO(), parentInstance) 1188 if err != nil { 1189 return err 1190 } 1191 } 1192 1193 return nil 1194 } 1195 1196 func (n *Node) GetInitStoragePath(instance *current.IBPOrderer) string { 1197 if n.Config != nil && n.Config.OrdererInitConfig != nil && n.Config.OrdererInitConfig.StoragePath != "" { 1198 return filepath.Join(n.Config.OrdererInitConfig.StoragePath, instance.GetName()) 1199 } 1200 1201 return filepath.Join("/", "ordererinit", instance.GetName()) 1202 } 1203 1204 func (n *Node) GetBCCSPSectionForInstance(instance *current.IBPOrderer) (*commonapi.BCCSP, error) { 1205 var bccsp *commonapi.BCCSP 1206 if instance.IsHSMEnabled() { 1207 co, err := instance.GetConfigOverride() 1208 if err != nil { 1209 return nil, errors.Wrap(err, "failed to get configoverride") 1210 } 1211 1212 configOverride := co.(OrdererConfig) 1213 configOverride.SetPKCS11Defaults(instance.UsingHSMProxy()) 1214 bccsp = configOverride.GetBCCSPSection() 1215 } 1216 1217 return bccsp, nil 1218 } 1219 1220 func (n *Node) ReconcileFabricOrdererMigration(instance *current.IBPOrderer) error { 1221 ordererConfig, err := n.FabricOrdererMigration(instance) 1222 if err != nil { 1223 return errors.Wrap(err, "failed to migrate orderer between fabric versions") 1224 } 1225 1226 if ordererConfig != nil { 1227 log.Info("Orderer config updated during fabric orderer migration, updating config map...") 1228 if err := n.Initializer.CreateOrUpdateConfigMap(instance, ordererConfig); err != nil { 1229 return errors.Wrapf(err, "failed to create/update '%s' orderer's config map", instance.GetName()) 1230 } 1231 } 1232 1233 return nil 1234 } 1235 1236 // Moving to fabric version above 1.4.6 require that the `msp/keystore` value be removed 1237 // from BCCSP section if configured to use PKCS11 (HSM). NOTE: This does not support 1238 // migration across major release, will not cover migration orderer from 1.4.x to 2.x 1239 func (n *Node) FabricOrdererMigration(instance *current.IBPOrderer) (*ordererconfig.Orderer, error) { 1240 if !instance.IsHSMEnabled() { 1241 return nil, nil 1242 } 1243 1244 ordererTag := instance.Spec.Images.OrdererTag 1245 if !strings.Contains(ordererTag, "sha") { 1246 tag := strings.Split(ordererTag, "-")[0] 1247 1248 ordererVersion := version.String(tag) 1249 if !ordererVersion.GreaterThan(version.V1_4_6) { 1250 return nil, nil 1251 } 1252 1253 log.Info(fmt.Sprintf("Orderer moving to fabric version %s", ordererVersion)) 1254 } else { 1255 if instance.Spec.FabricVersion == version.V2 { 1256 return nil, nil 1257 } 1258 log.Info(fmt.Sprintf("Orderer moving to digest %s", ordererTag)) 1259 } 1260 1261 // Read orderer config map and remove keystore value from BCCSP section 1262 cm, err := n.Initializer.GetConfigFromConfigMap(instance) 1263 if err != nil { 1264 return nil, errors.Wrapf(err, "failed to get '%s' orderer's config map", instance.GetName()) 1265 } 1266 1267 ordererConfig := &ordererconfig.Orderer{} 1268 if err := yaml.Unmarshal(cm.BinaryData["orderer.yaml"], ordererConfig); err != nil { 1269 return nil, errors.Wrap(err, "invalid orderer config") 1270 } 1271 1272 // If already nil, don't need to proceed further as config updates are not required 1273 if ordererConfig.General.BCCSP.PKCS11.FileKeyStore == nil { 1274 return nil, nil 1275 } 1276 1277 ordererConfig.General.BCCSP.PKCS11.FileKeyStore = nil 1278 1279 return ordererConfig, nil 1280 } 1281 1282 func (n *Node) UpdateMSPCertificates(instance *current.IBPOrderer) error { 1283 log.Info("Updating certificates passed in MSP spec") 1284 updatedOrderer, err := n.Initializer.GetUpdatedOrderer(instance) 1285 if err != nil { 1286 return err 1287 } 1288 1289 crypto, err := updatedOrderer.GenerateCrypto() 1290 if err != nil { 1291 return err 1292 } 1293 1294 if crypto != nil { 1295 err = n.Initializer.UpdateSecrets("ecert", instance, crypto.Enrollment) 1296 if err != nil { 1297 return errors.Wrap(err, "failed to update ecert secrets") 1298 } 1299 1300 err = n.Initializer.UpdateSecrets("tls", instance, crypto.TLS) 1301 if err != nil { 1302 return errors.Wrap(err, "failed to update tls secrets") 1303 } 1304 1305 err = n.Initializer.UpdateSecrets("clientauth", instance, crypto.ClientAuth) 1306 if err != nil { 1307 return errors.Wrap(err, "failed to update client auth secrets") 1308 } 1309 } 1310 1311 return nil 1312 } 1313 1314 func (n *Node) RenewCert(certType commoninit.SecretType, obj runtime.Object, newKey bool) error { 1315 instance := obj.(*current.IBPOrderer) 1316 if instance.Spec.Secret == nil { 1317 return errors.New(fmt.Sprintf("missing secret spec for instance '%s'", instance.GetName())) 1318 } 1319 1320 if instance.Spec.Secret.Enrollment != nil { 1321 log.Info(fmt.Sprintf("Renewing %s certificate for instance '%s'", string(certType), instance.Name)) 1322 1323 hsmEnabled := instance.IsHSMEnabled() 1324 spec := instance.Spec.Secret.Enrollment 1325 storagePath := n.GetInitStoragePath(instance) 1326 bccsp, err := n.GetBCCSPSectionForInstance(instance) 1327 if err != nil { 1328 return err 1329 } 1330 1331 err = n.CertificateManager.RenewCert(certType, instance, spec, bccsp, storagePath, hsmEnabled, newKey) 1332 if err != nil { 1333 return err 1334 } 1335 } else { 1336 return errors.New("cannot auto-renew certificate created by MSP, force renewal required") 1337 } 1338 1339 return nil 1340 } 1341 1342 func (n *Node) EnrollForEcert(instance *current.IBPOrderer) error { 1343 log.Info(fmt.Sprintf("Ecert enroll triggered via action parameter for '%s'", instance.GetName())) 1344 1345 secret := instance.Spec.Secret 1346 if secret == nil || secret.Enrollment == nil || secret.Enrollment.Component == nil { 1347 return errors.New("unable to enroll, no ecert enrollment information provided") 1348 } 1349 ecertSpec := secret.Enrollment.Component 1350 1351 storagePath := filepath.Join(n.GetInitStoragePath(instance), "ecert") 1352 crypto, err := action.Enroll(instance, ecertSpec, storagePath, n.Client, n.Scheme, true, n.Config.Operator.Orderer.Timeouts.EnrollJob) 1353 if err != nil { 1354 return errors.Wrap(err, "failed to enroll for ecert") 1355 } 1356 1357 err = n.Initializer.GenerateSecrets("ecert", instance, crypto) 1358 if err != nil { 1359 return errors.Wrap(err, "failed to generate ecert secrets") 1360 } 1361 1362 return nil 1363 } 1364 1365 func (n *Node) EnrollForTLSCert(instance *current.IBPOrderer) error { 1366 log.Info(fmt.Sprintf("TLS cert enroll triggered via action parameter for '%s'", instance.GetName())) 1367 1368 secret := instance.Spec.Secret 1369 if secret == nil || secret.Enrollment == nil || secret.Enrollment.TLS == nil { 1370 return errors.New("unable to enroll, no TLS enrollment information provided") 1371 } 1372 tlscertSpec := secret.Enrollment.TLS 1373 1374 storagePath := filepath.Join(n.GetInitStoragePath(instance), "tls") 1375 crypto, err := action.Enroll(instance, tlscertSpec, storagePath, n.Client, n.Scheme, false, n.Config.Operator.Orderer.Timeouts.EnrollJob) 1376 if err != nil { 1377 return errors.Wrap(err, "failed to enroll for TLS cert") 1378 } 1379 1380 err = n.Initializer.GenerateSecrets("tls", instance, crypto) 1381 if err != nil { 1382 return errors.Wrap(err, "failed to generate ecert secrets") 1383 } 1384 1385 return nil 1386 } 1387 1388 func (n *Node) FabricOrdererMigrationV2_0(instance *current.IBPOrderer) error { 1389 log.Info(fmt.Sprintf("Orderer instance '%s' migrating to v2", instance.GetName())) 1390 1391 initOrderer, err := n.Initializer.GetInitOrderer(instance, n.GetInitStoragePath(instance)) 1392 if err != nil { 1393 return err 1394 } 1395 initOrderer.UsingHSMProxy = instance.UsingHSMProxy() 1396 1397 ordererConfig := n.Config.OrdererInitConfig.OrdererFile 1398 if version.GetMajorReleaseVersion(instance.Spec.FabricVersion) == version.V2 { 1399 currentVer := version.String(instance.Spec.FabricVersion) 1400 if currentVer.EqualWithoutTag(version.V2_4_1) || currentVer.GreaterThan(version.V2_4_1) { 1401 ordererConfig = n.Config.OrdererInitConfig.OrdererV24File 1402 } else { 1403 ordererConfig = n.Config.OrdererInitConfig.OrdererV2File 1404 } 1405 } 1406 1407 switch version.GetMajorReleaseVersion(instance.Spec.FabricVersion) { 1408 case version.V2: 1409 currentVer := version.String(instance.Spec.FabricVersion) 1410 if currentVer.EqualWithoutTag(version.V2_4_1) || currentVer.GreaterThan(version.V2_4_1) { 1411 log.Info("v2.4.x Fabric Orderer requested") 1412 v24config, err := v24ordererconfig.ReadOrdererFile(ordererConfig) 1413 if err != nil { 1414 return errors.Wrap(err, "failed to read v2.4.x default config file") 1415 } 1416 initOrderer.Config = v24config 1417 } else if currentVer.LessThan(version.V2_4_1) { 1418 log.Info("v2.2.x Fabric Orderer requested") 1419 v2config, err := v2ordererconfig.ReadOrdererFile(ordererConfig) 1420 if err != nil { 1421 return errors.Wrap(err, "failed to read v2.2.x default config file") 1422 } 1423 initOrderer.Config = v2config 1424 } 1425 case version.V1: 1426 fallthrough 1427 default: 1428 // Choosing to default to v1.4 to not break backwards comptability, if coming 1429 // from a previous version of operator the 'FabricVersion' field would not be set and would 1430 // result in an error. // TODO: Determine if we want to throw error or handle setting 1431 // FabricVersion as part of migration logic. 1432 oconfig, err := ordererconfig.ReadOrdererFile(ordererConfig) 1433 if err != nil { 1434 return errors.Wrap(err, "failed to read v1.4 default config file") 1435 } 1436 initOrderer.Config = oconfig 1437 } 1438 1439 configOverride, err := instance.GetConfigOverride() 1440 if err != nil { 1441 return err 1442 } 1443 1444 err = initOrderer.OverrideConfig(configOverride.(OrdererConfig)) 1445 if err != nil { 1446 return err 1447 } 1448 1449 if instance.IsHSMEnabled() && !instance.UsingHSMProxy() { 1450 log.Info(fmt.Sprintf("During orderer '%s' migration, detected using HSM sidecar, setting library path", instance.GetName())) 1451 hsmConfig, err := commonconfig.ReadHSMConfig(n.Client, instance) 1452 if err != nil { 1453 return err 1454 } 1455 initOrderer.Config.SetBCCSPLibrary(filepath.Join("/hsm/lib", filepath.Base(hsmConfig.Library.FilePath))) 1456 } 1457 1458 err = n.Initializer.CreateOrUpdateConfigMap(instance, initOrderer.GetConfig()) 1459 if err != nil { 1460 return err 1461 } 1462 1463 return nil 1464 } 1465 1466 func (n *Node) FabricOrdererMigrationV2_4(instance *current.IBPOrderer) error { 1467 log.Info(fmt.Sprintf("Orderer instance '%s' migrating to v2.4.x", instance.GetName())) 1468 1469 initOrderer, err := n.Initializer.GetInitOrderer(instance, n.GetInitStoragePath(instance)) 1470 if err != nil { 1471 return err 1472 } 1473 1474 ordererConfig, err := v24ordererconfig.ReadOrdererFile(n.Config.OrdererInitConfig.OrdererV24File) 1475 if err != nil { 1476 return errors.Wrap(err, "failed to read v2.4.x default config file") 1477 } 1478 1479 // removed the field from the struct 1480 // ordererConfig.FileLedger.Prefix = "" 1481 1482 name := fmt.Sprintf("%s-env", instance.GetName()) 1483 namespacedName := types.NamespacedName{ 1484 Name: name, 1485 Namespace: instance.Namespace, 1486 } 1487 1488 cm := &corev1.ConfigMap{} 1489 err = n.Client.Get(context.TODO(), namespacedName, cm) 1490 if err != nil { 1491 return errors.Wrap(err, "failed to get env configmap") 1492 } 1493 1494 // Add configs for 2.4.x 1495 trueVal := true 1496 ordererConfig.Admin.TLs.Enabled = &trueVal 1497 ordererConfig.Admin.TLs.ClientAuthRequired = &trueVal 1498 1499 intermediateExists := util.IntermediateSecretExists(n.Client, instance.Namespace, fmt.Sprintf("ecert-%s-intercerts", instance.Name)) && 1500 util.IntermediateSecretExists(n.Client, instance.Namespace, fmt.Sprintf("tls-%s-intercerts", instance.Name)) 1501 intercertPath := "/certs/msp/tlsintermediatecerts/intercert-0.pem" 1502 currentVer := version.String(instance.Spec.FabricVersion) 1503 if currentVer.EqualWithoutTag(version.V2_4_1) || currentVer.GreaterThan(version.V2_4_1) { 1504 // Enable Channel participation for 2.4.x orderers 1505 cm.Data["ORDERER_CHANNELPARTICIPATION_ENABLED"] = "true" 1506 1507 cm.Data["ORDERER_ADMIN_TLS_ENABLED"] = "true" 1508 cm.Data["ORDERER_ADMIN_TLS_CERTIFICATE"] = "/certs/tls/signcerts/cert.pem" 1509 cm.Data["ORDERER_ADMIN_TLS_PRIVATEKEY"] = "/certs/tls/keystore/key.pem" 1510 cm.Data["ORDERER_ADMIN_TLS_CLIENTAUTHREQUIRED"] = "true" 1511 if intermediateExists { 1512 // override intermediate cert paths for root and clientroot cas 1513 cm.Data["ORDERER_ADMIN_TLS_ROOTCAS"] = intercertPath 1514 cm.Data["ORDERER_ADMIN_TLS_CLIENTROOTCAS"] = intercertPath 1515 } else { 1516 cm.Data["ORDERER_ADMIN_TLS_ROOTCAS"] = "/certs/msp/tlscacerts/cacert-0.pem" 1517 cm.Data["ORDERER_ADMIN_TLS_CLIENTROOTCAS"] = "/certs/msp/tlscacerts/cacert-0.pem" 1518 } 1519 } 1520 1521 err = n.Client.Update(context.TODO(), cm, controllerclient.UpdateOption{Owner: instance, Scheme: n.Scheme}) 1522 if err != nil { 1523 return errors.Wrap(err, "failed to update env configmap") 1524 } 1525 1526 initOrderer.Config = ordererConfig 1527 configOverride, err := instance.GetConfigOverride() 1528 if err != nil { 1529 return err 1530 } 1531 1532 err = initOrderer.OverrideConfig(configOverride.(OrdererConfig)) 1533 if err != nil { 1534 return err 1535 } 1536 1537 if instance.IsHSMEnabled() && !instance.UsingHSMProxy() { 1538 log.Info(fmt.Sprintf("During orderer '%s' migration, detected using HSM sidecar, setting library path", instance.GetName())) 1539 hsmConfig, err := commonconfig.ReadHSMConfig(n.Client, instance) 1540 if err != nil { 1541 return err 1542 } 1543 initOrderer.Config.SetBCCSPLibrary(filepath.Join("/hsm/lib", filepath.Base(hsmConfig.Library.FilePath))) 1544 } 1545 1546 err = n.Initializer.CreateOrUpdateConfigMap(instance, initOrderer.GetConfig()) 1547 if err != nil { 1548 return err 1549 } 1550 return nil 1551 } 1552 1553 func (n *Node) ReconcileHSMImages(instance *current.IBPOrderer) bool { 1554 hsmConfig, err := commonconfig.ReadHSMConfig(n.Client, instance) 1555 if err != nil { 1556 return false 1557 } 1558 1559 if hsmConfig.Library.AutoUpdateDisabled { 1560 return false 1561 } 1562 1563 updated := false 1564 if hsmConfig.Library.Image != "" { 1565 hsmImage := hsmConfig.Library.Image 1566 lastIndex := strings.LastIndex(hsmImage, ":") 1567 image := hsmImage[:lastIndex] 1568 tag := hsmImage[lastIndex+1:] 1569 1570 if instance.Spec.Images.HSMImage != image { 1571 instance.Spec.Images.HSMImage = image 1572 updated = true 1573 } 1574 1575 if instance.Spec.Images.HSMTag != tag { 1576 instance.Spec.Images.HSMTag = tag 1577 updated = true 1578 } 1579 } 1580 1581 return updated 1582 } 1583 1584 func (n *Node) HandleActions(instance *current.IBPOrderer, update Update) error { 1585 orig := instance.DeepCopy() 1586 1587 if update.EcertReenrollNeeded() { 1588 if err := n.ReenrollEcert(instance); err != nil { 1589 log.Error(err, "Resetting action flag on failure") 1590 instance.ResetEcertReenroll() 1591 return err 1592 } 1593 instance.ResetEcertReenroll() 1594 } 1595 1596 if update.TLScertReenrollNeeded() { 1597 if err := n.ReenrollTLSCert(instance); err != nil { 1598 log.Error(err, "Resetting action flag on failure") 1599 instance.ResetTLSReenroll() 1600 return err 1601 } 1602 instance.ResetTLSReenroll() 1603 } 1604 1605 if update.EcertNewKeyReenroll() { 1606 if err := n.ReenrollEcertNewKey(instance); err != nil { 1607 log.Error(err, "Resetting action flag on failure") 1608 instance.ResetEcertReenroll() 1609 return err 1610 } 1611 instance.ResetEcertReenroll() 1612 } 1613 1614 if update.TLScertNewKeyReenroll() { 1615 if err := n.ReenrollTLSCertNewKey(instance); err != nil { 1616 log.Error(err, "Resetting action flag on failure") 1617 instance.ResetTLSReenroll() 1618 return err 1619 } 1620 instance.ResetTLSReenroll() 1621 } 1622 1623 if update.EcertEnroll() { 1624 if err := n.EnrollForEcert(instance); err != nil { 1625 log.Error(err, "Resetting action flag on failure") 1626 instance.ResetEcertEnroll() 1627 return err 1628 } 1629 instance.ResetEcertEnroll() 1630 } 1631 1632 if update.TLScertEnroll() { 1633 if err := n.EnrollForTLSCert(instance); err != nil { 1634 log.Error(err, "Resetting action flag on failure") 1635 instance.ResetTLSEnroll() 1636 return err 1637 } 1638 instance.ResetTLSEnroll() 1639 } 1640 1641 // This should be the last action checked 1642 if update.RestartNeeded() { 1643 if err := n.RestartAction(instance); err != nil { 1644 log.Error(err, "Resetting action flag on failure") 1645 instance.ResetRestart() 1646 return err 1647 } 1648 instance.ResetRestart() 1649 } 1650 1651 if err := n.Client.Patch(context.TODO(), instance, k8sclient.MergeFrom(orig)); err != nil { 1652 return errors.Wrap(err, "failed to reset action flags") 1653 } 1654 1655 return nil 1656 } 1657 1658 func (n *Node) ReenrollEcert(instance *current.IBPOrderer) error { 1659 log.Info("Ecert reenroll triggered via action parameter") 1660 if err := n.reenrollCert(instance, commoninit.ECERT, false); err != nil { 1661 return errors.Wrap(err, "ecert reenroll reusing existing private key action failed") 1662 } 1663 return nil 1664 } 1665 1666 func (n *Node) ReenrollEcertNewKey(instance *current.IBPOrderer) error { 1667 log.Info("Ecert with new key reenroll triggered via action parameter") 1668 if err := n.reenrollCert(instance, commoninit.ECERT, true); err != nil { 1669 return errors.Wrap(err, "ecert reenroll with new key action failed") 1670 } 1671 return nil 1672 } 1673 1674 func (n *Node) ReenrollTLSCert(instance *current.IBPOrderer) error { 1675 log.Info("TLS reenroll triggered via action parameter") 1676 if err := n.reenrollCert(instance, commoninit.TLS, false); err != nil { 1677 return errors.Wrap(err, "tls reenroll reusing existing private key action failed") 1678 } 1679 return nil 1680 } 1681 1682 func (n *Node) ReenrollTLSCertNewKey(instance *current.IBPOrderer) error { 1683 log.Info("TLS with new key reenroll triggered via action parameter") 1684 if err := n.reenrollCert(instance, commoninit.TLS, true); err != nil { 1685 return errors.Wrap(err, "tls reenroll with new key action failed") 1686 } 1687 return nil 1688 } 1689 1690 func (n *Node) reenrollCert(instance *current.IBPOrderer, certType commoninit.SecretType, newKey bool) error { 1691 return action.Reenroll(n, n.Client, certType, instance, newKey) 1692 } 1693 1694 func (n *Node) RestartAction(instance *current.IBPOrderer) error { 1695 log.Info("Restart triggered via action parameter") 1696 if err := n.Restart.ForRestartAction(instance); err != nil { 1697 return errors.Wrap(err, "failed to restart orderer node pods") 1698 } 1699 return nil 1700 } 1701 1702 func (n *Node) HandleRestart(instance *current.IBPOrderer, update Update) error { 1703 // If restart is disabled for components, can return immediately 1704 if n.Config.Operator.Restart.Disable.Components { 1705 return nil 1706 } 1707 1708 err := n.Restart.TriggerIfNeeded(instance) 1709 if err != nil { 1710 return errors.Wrap(err, "failed to restart deployment") 1711 } 1712 1713 return nil 1714 } 1715 1716 func (n *Node) CustomLogic(instance *current.IBPOrderer, update Update) (*current.CRStatus, *common.Result, error) { 1717 var status *current.CRStatus 1718 var err error 1719 return status, nil, err 1720 }