github.com/IBM-Blockchain/fabric-operator@v1.0.4/pkg/initializer/common/common.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 common 20 21 import ( 22 "bytes" 23 "context" 24 "fmt" 25 "path/filepath" 26 27 "github.com/pkg/errors" 28 29 current "github.com/IBM-Blockchain/fabric-operator/api/v1beta1" 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/mspparser" 33 "github.com/IBM-Blockchain/fabric-operator/pkg/initializer/validator" 34 k8sclient "github.com/IBM-Blockchain/fabric-operator/pkg/k8s/controllerclient" 35 "github.com/IBM-Blockchain/fabric-operator/pkg/util" 36 37 corev1 "k8s.io/api/core/v1" 38 k8serrors "k8s.io/apimachinery/pkg/api/errors" 39 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 40 v1 "k8s.io/apimachinery/pkg/apis/meta/v1" 41 "k8s.io/apimachinery/pkg/runtime" 42 "k8s.io/apimachinery/pkg/types" 43 44 logf "sigs.k8s.io/controller-runtime/pkg/log" 45 ) 46 47 var log = logf.Log.WithName("initializer") 48 49 type SecretType string 50 51 var ( 52 ECERT SecretType = "ecert" 53 TLS SecretType = "tls" 54 ) 55 56 type Instance interface { 57 metav1.Object 58 runtime.Object 59 EnrollerImage() string 60 GetPullSecrets() []corev1.LocalObjectReference 61 IsHSMEnabled() bool 62 UsingHSMProxy() bool 63 GetConfigOverride() (interface{}, error) 64 } 65 66 // NOTE: Modifies cryptos object passed as param 67 func GetCommonEnrollers(cryptos *config.Cryptos, enrollmentSpec *current.EnrollmentSpec, storagePath string) error { 68 if enrollmentSpec.TLS != nil && cryptos.TLS == nil { 69 bytes, err := enrollmentSpec.TLS.GetCATLSBytes() 70 if err != nil { 71 return err 72 } 73 74 caClient := enroller.NewFabCAClient( 75 enrollmentSpec.TLS, 76 filepath.Join(storagePath, "tls"), 77 nil, 78 bytes, 79 ) 80 cryptos.TLS = enroller.New(enroller.NewSWEnroller(caClient)) 81 } 82 83 if enrollmentSpec.ClientAuth != nil && cryptos.ClientAuth == nil { 84 bytes, err := enrollmentSpec.ClientAuth.GetCATLSBytes() 85 if err != nil { 86 return err 87 } 88 89 caClient := enroller.NewFabCAClient( 90 enrollmentSpec.ClientAuth, 91 filepath.Join(storagePath, "clientauth"), 92 nil, 93 bytes, 94 ) 95 cryptos.ClientAuth = enroller.New(enroller.NewSWEnroller(caClient)) 96 } 97 98 return nil 99 } 100 101 // NOTE: Modifies cryptos object passed as param 102 func GetMSPCrypto(cryptos *config.Cryptos, mspSpec *current.MSPSpec) error { 103 if mspSpec != nil { 104 if mspSpec.Component != nil { 105 cryptos.Enrollment = mspparser.New(mspSpec.Component) 106 } 107 108 if mspSpec.TLS != nil { 109 cryptos.TLS = mspparser.New(mspSpec.TLS) 110 } 111 112 if mspSpec.ClientAuth != nil { 113 cryptos.ClientAuth = mspparser.New(mspSpec.ClientAuth) 114 } 115 } 116 117 return nil 118 } 119 120 //go:generate counterfeiter -o mocks/cryptovalidator.go -fake-name CryptoValidator . CryptoValidator 121 type CryptoValidator interface { 122 CheckEcertCrypto(v1.Object, string) error 123 CheckTLSCrypto(v1.Object, string) error 124 CheckClientAuthCrypto(v1.Object, string) error 125 SetHSMEnabled(bool) 126 } 127 128 func CheckCrypto(cryptoValidator CryptoValidator, instance v1.Object, checkClientAuth bool) error { 129 name := instance.GetName() 130 131 err := cryptoValidator.CheckEcertCrypto(instance, name) 132 if err != nil { 133 if validator.CheckError(err) { 134 return errors.Wrap(err, "missing ecert crypto") 135 } 136 } 137 138 err = cryptoValidator.CheckTLSCrypto(instance, name) 139 if err != nil { 140 if validator.CheckError(err) { 141 log.Info(fmt.Sprintf("missing TLS crypto: %s", err.Error())) 142 return errors.Wrap(err, "missing TLS crypto") 143 } 144 } 145 146 if checkClientAuth { 147 err := cryptoValidator.CheckClientAuthCrypto(instance, name) 148 if validator.CheckError(err) { 149 log.Info(fmt.Sprintf("missing Client Auth crypto: %s", err.Error())) 150 return errors.Wrap(err, "missing Client Auth crypto") 151 } 152 } 153 154 return nil 155 } 156 157 func GetAdminCertsFromSecret(client k8sclient.Client, instance v1.Object) map[string][]byte { 158 prefix := "ecert-" + instance.GetName() 159 namespacedName := types.NamespacedName{ 160 Name: prefix + "-admincerts", 161 Namespace: instance.GetNamespace(), 162 } 163 164 certs := &corev1.Secret{} 165 err := client.Get(context.TODO(), namespacedName, certs) 166 if err != nil { 167 if !k8serrors.IsNotFound(err) { 168 return nil 169 } 170 171 return map[string][]byte{} 172 } 173 174 return certs.Data 175 } 176 177 func GetAdminCertsFromSpec(spec *current.SecretSpec) []string { 178 adminCerts := []string{} 179 if spec != nil { 180 if spec.MSP != nil { 181 if spec.MSP.Component != nil { 182 adminCerts = append(adminCerts, spec.MSP.Component.AdminCerts...) 183 } 184 } else if spec.Enrollment != nil { 185 if spec.Enrollment.Component != nil { 186 adminCerts = append(adminCerts, spec.Enrollment.Component.AdminCerts...) 187 } 188 } 189 } 190 191 return adminCerts 192 } 193 194 // Check for equality between two list of certificates. Order of certificates in the lists 195 // is ignored, if the two lists contain the same exact certificates this returns true 196 func CheckIfCertsDifferent(current map[string][]byte, updated []string) (bool, error) { 197 // Only detect a difference if the list of updated certificates is not empty 198 if len(current) != len(updated) && len(updated) > 0 { 199 return true, nil 200 } 201 202 for _, newCert := range updated { 203 certFound := false 204 newCertBytes, err := util.Base64ToBytes(newCert) 205 if err != nil { 206 return false, err 207 } 208 209 for _, certBytes := range current { 210 if bytes.Equal(certBytes, newCertBytes) { 211 certFound = true 212 break 213 } 214 } 215 216 if !certFound { 217 return true, nil 218 } 219 } 220 221 return false, nil 222 } 223 224 func ConvertCertsToBytes(certs []string) ([][]byte, error) { 225 certBytes := [][]byte{} 226 for _, cert := range certs { 227 bytes, err := util.Base64ToBytes(cert) 228 if err != nil { 229 return nil, err 230 } 231 certBytes = append(certBytes, bytes) 232 } 233 return certBytes, nil 234 } 235 236 func GetConfigFromConfigMap(client k8sclient.Client, instance v1.Object) (*corev1.ConfigMap, error) { 237 name := fmt.Sprintf("%s-config", instance.GetName()) 238 log.Info(fmt.Sprintf("Get config map '%s'...", name)) 239 240 cm := &corev1.ConfigMap{} 241 n := types.NamespacedName{ 242 Name: name, 243 Namespace: instance.GetNamespace(), 244 } 245 246 err := client.Get(context.TODO(), n, cm) 247 if err != nil { 248 return nil, err 249 } 250 251 return cm, nil 252 253 }