github.com/IBM-Blockchain/fabric-operator@v1.0.4/pkg/initializer/peer/initializer.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 initializer 20 21 import ( 22 "context" 23 "fmt" 24 "os" 25 "path/filepath" 26 27 current "github.com/IBM-Blockchain/fabric-operator/api/v1beta1" 28 commonapi "github.com/IBM-Blockchain/fabric-operator/pkg/apis/common" 29 "github.com/IBM-Blockchain/fabric-operator/pkg/initializer/common" 30 "github.com/IBM-Blockchain/fabric-operator/pkg/initializer/common/config" 31 "github.com/IBM-Blockchain/fabric-operator/pkg/initializer/common/enroller" 32 "github.com/IBM-Blockchain/fabric-operator/pkg/initializer/common/secretmanager" 33 configv1 "github.com/IBM-Blockchain/fabric-operator/pkg/initializer/peer/config/v1" 34 k8sclient "github.com/IBM-Blockchain/fabric-operator/pkg/k8s/controllerclient" 35 "github.com/pkg/errors" 36 37 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 38 "k8s.io/apimachinery/pkg/runtime" 39 40 logf "sigs.k8s.io/controller-runtime/pkg/log" 41 ) 42 43 var log = logf.Log.WithName("peer_initializer") 44 45 type Config struct { 46 OUFile string 47 InterOUFile string 48 CorePeerFile string 49 CorePeerV2File string 50 DeploymentFile string 51 PVCFile string 52 CouchDBPVCFile string 53 ServiceFile string 54 RoleFile string 55 ServiceAccountFile string 56 RoleBindingFile string 57 FluentdConfigMapFile string 58 CouchContainerFile string 59 CouchInitContainerFile string 60 IngressFile string 61 Ingressv1beta1File string 62 CCLauncherFile string 63 RouteFile string 64 StoragePath string 65 } 66 67 //go:generate counterfeiter -o mocks/ibppeer.go -fake-name IBPPeer . IBPPeer 68 69 type IBPPeer interface { 70 DeliveryClientCrypto() map[string][]byte 71 OverrideConfig(CoreConfig) error 72 GenerateCrypto() (*config.CryptoResponse, error) 73 GetConfig() CoreConfig 74 } 75 76 type PeerConfig interface { 77 MergeWith(interface{}, bool) error 78 GetAddressOverrides() []configv1.AddressOverride 79 ToBytes() ([]byte, error) 80 UsingPKCS11() bool 81 SetPKCS11Defaults(bool) 82 GetBCCSPSection() *commonapi.BCCSP 83 GetMaxNameLength() *int 84 SetDefaultKeyStore() 85 } 86 87 type Initializer struct { 88 Config *Config 89 Scheme *runtime.Scheme 90 GetLabels func(instance metav1.Object) map[string]string 91 coreConfigMap *CoreConfigMap 92 Timeouts enroller.HSMEnrollJobTimeouts 93 94 Client k8sclient.Client 95 Validator common.CryptoValidator 96 SecretManager *secretmanager.SecretManager 97 } 98 99 func New(config *Config, scheme *runtime.Scheme, client k8sclient.Client, labels func(instance metav1.Object) map[string]string, validator common.CryptoValidator, timeouts enroller.HSMEnrollJobTimeouts) *Initializer { 100 secretManager := secretmanager.New(client, scheme, labels) 101 102 return &Initializer{ 103 Client: client, 104 Config: config, 105 Scheme: scheme, 106 GetLabels: labels, 107 Validator: validator, 108 SecretManager: secretManager, 109 coreConfigMap: &CoreConfigMap{Config: config, Scheme: scheme, GetLabels: labels, Client: client}, 110 Timeouts: timeouts, 111 } 112 } 113 114 type Response struct { 115 Config CoreConfig 116 Crypto *config.CryptoResponse 117 DeliveryClientCerts map[string][]byte 118 } 119 120 func (i *Initializer) Create(overrides CoreConfig, peer IBPPeer, storagePath string) (*Response, error) { 121 var err error 122 123 err = os.RemoveAll(storagePath) 124 if err != nil { 125 return nil, err 126 } 127 128 err = peer.OverrideConfig(overrides) 129 if err != nil { 130 return nil, err 131 } 132 133 cresp, err := peer.GenerateCrypto() 134 if err != nil { 135 return nil, err 136 } 137 138 err = os.RemoveAll(storagePath) 139 if err != nil { 140 return nil, err 141 } 142 143 return &Response{ 144 Config: peer.GetConfig(), 145 DeliveryClientCerts: peer.DeliveryClientCrypto(), 146 Crypto: cresp, 147 }, nil 148 } 149 150 func (i *Initializer) CoreConfigMap() *CoreConfigMap { 151 return i.coreConfigMap 152 } 153 154 func (i *Initializer) Update(overrides CoreConfig, peer IBPPeer) (*Response, error) { 155 var err error 156 157 err = peer.OverrideConfig(overrides) 158 if err != nil { 159 return nil, err 160 } 161 162 return &Response{ 163 Config: peer.GetConfig(), 164 DeliveryClientCerts: peer.DeliveryClientCrypto(), 165 }, nil 166 } 167 168 func (i *Initializer) GetEnrollers(cryptos *config.Cryptos, instance *current.IBPPeer, storagePath string) error { 169 // If no enrollment information provided, don't need to proceed further 170 if instance.Spec.Secret == nil || instance.Spec.Secret.Enrollment == nil { 171 return nil 172 } 173 174 enrollmentSpec := instance.Spec.Secret.Enrollment 175 if enrollmentSpec.Component != nil && cryptos.Enrollment == nil { 176 bytes, err := enrollmentSpec.Component.GetCATLSBytes() 177 if err != nil { 178 return err 179 } 180 181 // Factory will determine if HSM or non-HSM enroller needed and return back appropriate type 182 cryptos.Enrollment, err = enroller.Factory(enrollmentSpec.Component, i.Client, instance, 183 filepath.Join(storagePath, "ecert"), 184 i.Scheme, 185 bytes, 186 i.Timeouts, 187 ) 188 if err != nil { 189 return err 190 } 191 } 192 193 // Common enrollers get software based enrollers for TLS and clientauth crypto, 194 // these types are not supported for HSM 195 err := common.GetCommonEnrollers(cryptos, enrollmentSpec, storagePath) 196 if err != nil { 197 return err 198 } 199 200 return nil 201 } 202 203 func (i *Initializer) GetMSPCrypto(cryptos *config.Cryptos, instance *current.IBPPeer) error { 204 if instance.Spec.Secret == nil || instance.Spec.Secret.MSP == nil { 205 return nil 206 } 207 208 mspSpec := instance.Spec.Secret.MSP 209 err := common.GetMSPCrypto(cryptos, mspSpec) 210 if err != nil { 211 return err 212 } 213 214 return nil 215 } 216 217 func (i *Initializer) GetInitPeer(instance *current.IBPPeer, storagePath string) (*Peer, error) { 218 cryptos := &config.Cryptos{} 219 220 if instance.Spec.Secret != nil { 221 // Prioritize any crypto passed through MSP spec first 222 err := i.GetMSPCrypto(cryptos, instance) 223 if err != nil { 224 return nil, errors.Wrap(err, "failed to populate init peer with MSP spec") 225 } 226 227 err = i.GetEnrollers(cryptos, instance, storagePath) 228 if err != nil { 229 return nil, errors.Wrap(err, "failed to populate init peer with Enrollment spec") 230 } 231 } 232 233 return &Peer{ 234 Cryptos: cryptos, 235 }, nil 236 } 237 238 func (i *Initializer) GetUpdatedPeer(instance *current.IBPPeer) (*Peer, error) { 239 cryptos := &config.Cryptos{} 240 241 // Only check for any new certs passed through MSP spec 242 err := i.GetMSPCrypto(cryptos, instance) 243 if err != nil { 244 return nil, errors.Wrap(err, "failed to populate updated init peer with MSP spec") 245 } 246 247 return &Peer{ 248 Cryptos: cryptos, 249 }, nil 250 } 251 252 func (i *Initializer) GenerateSecrets(prefix common.SecretType, instance metav1.Object, crypto *config.Response) error { 253 if crypto == nil { 254 return nil 255 } 256 return i.SecretManager.GenerateSecrets(prefix, instance, crypto) 257 } 258 259 func (i *Initializer) GenerateSecretsFromResponse(instance *current.IBPPeer, cryptoResponse *config.CryptoResponse) error { 260 return i.SecretManager.GenerateSecretsFromResponse(instance, cryptoResponse) 261 } 262 263 func (i *Initializer) UpdateSecrets(prefix common.SecretType, instance *current.IBPPeer, crypto *config.Response) error { 264 if crypto == nil { 265 return nil 266 } 267 return i.SecretManager.UpdateSecrets(prefix, instance, crypto) 268 } 269 270 func (i *Initializer) UpdateSecretsFromResponse(instance *current.IBPPeer, cryptoResponse *config.CryptoResponse) error { 271 return i.SecretManager.UpdateSecretsFromResponse(instance, cryptoResponse) 272 } 273 274 func (i *Initializer) GetCrypto(instance *current.IBPPeer) (*config.CryptoResponse, error) { 275 return i.SecretManager.GetCryptoResponseFromSecrets(instance) 276 } 277 278 func (i *Initializer) GenerateOrdererCACertsSecret(instance *current.IBPPeer, certs map[string][]byte) error { 279 secretName := fmt.Sprintf("%s-orderercacerts", instance.GetName()) 280 err := i.CreateOrUpdateSecret(instance, secretName, certs) 281 if err != nil { 282 return err 283 } 284 285 return nil 286 } 287 288 func (i *Initializer) MissingCrypto(instance *current.IBPPeer) bool { 289 if instance.IsHSMEnabled() { 290 i.Validator.SetHSMEnabled(true) 291 } 292 293 checkClientAuth := instance.ClientAuthCryptoSet() 294 err := common.CheckCrypto(i.Validator, instance, checkClientAuth) 295 if err != nil { 296 log.Info(err.Error()) 297 return true 298 } 299 300 return false 301 } 302 303 func (i *Initializer) CheckIfAdminCertsUpdated(instance *current.IBPPeer) (bool, error) { 304 current := common.GetAdminCertsFromSecret(i.Client, instance) 305 updated := common.GetAdminCertsFromSpec(instance.Spec.Secret) 306 307 return common.CheckIfCertsDifferent(current, updated) 308 } 309 310 func (i *Initializer) UpdateAdminSecret(instance *current.IBPPeer) error { 311 return i.SecretManager.UpdateAdminCertSecret(instance, instance.Spec.Secret) 312 } 313 314 func (i *Initializer) CreateOrUpdateSecret(instance *current.IBPPeer, name string, data map[string][]byte) error { 315 log.Info(fmt.Sprintf("Creating secret '%s'", name)) 316 317 secret := i.SecretManager.BuildSecret(instance, name, data, i.GetLabels(instance)) 318 err := i.Client.CreateOrUpdate(context.TODO(), secret, k8sclient.CreateOrUpdateOption{ 319 Owner: instance, 320 Scheme: i.Scheme, 321 }) 322 if err != nil { 323 return err 324 } 325 326 return nil 327 }