github.com/IBM-Blockchain/fabric-operator@v1.0.4/pkg/initializer/validator/validator.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 validator 20 21 import ( 22 "context" 23 "crypto/x509" 24 "encoding/pem" 25 "strings" 26 27 k8sclient "github.com/IBM-Blockchain/fabric-operator/pkg/k8s/controllerclient" 28 "github.com/pkg/errors" 29 corev1 "k8s.io/api/core/v1" 30 v1 "k8s.io/apimachinery/pkg/apis/meta/v1" 31 "k8s.io/apimachinery/pkg/types" 32 ) 33 34 type Validator struct { 35 Client k8sclient.Client 36 HSMEnabled bool 37 } 38 39 func (v *Validator) CheckAdminCerts(instance v1.Object, prefix string) error { 40 //No-op 41 return nil 42 } 43 44 func (v *Validator) CheckEcertCrypto(instance v1.Object, name string) error { 45 prefix := "ecert-" + name 46 47 // CA certs verification 48 err := v.CheckCACerts(instance, prefix) 49 if err != nil { 50 return err 51 } 52 53 if v.HSMEnabled { 54 err = v.CheckCert(instance, prefix) 55 if err != nil { 56 return err 57 } 58 } else { 59 err = v.CheckCertAndKey(instance, prefix) 60 if err != nil { 61 return err 62 } 63 } 64 65 return nil 66 } 67 68 func (v *Validator) CheckTLSCrypto(instance v1.Object, name string) error { 69 prefix := "tls-" + name 70 71 // CA certs verification 72 err := v.CheckCACerts(instance, prefix) 73 if err != nil { 74 return err 75 } 76 77 err = v.CheckCertAndKey(instance, prefix) 78 if err != nil { 79 return err 80 } 81 82 return nil 83 } 84 85 func (v *Validator) CheckClientAuthCrypto(instance v1.Object, name string) error { 86 prefix := "clientauth-" + name 87 88 // CA cert verification 89 err := v.CheckCACerts(instance, prefix) 90 if err != nil { 91 return err 92 } 93 94 err = v.CheckCertAndKey(instance, prefix) 95 if err != nil { 96 return err 97 } 98 99 return nil 100 } 101 102 func (v *Validator) CheckCACerts(instance v1.Object, prefix string) error { 103 namespacedName := types.NamespacedName{ 104 Name: prefix + "-cacerts", 105 Namespace: instance.GetNamespace(), 106 } 107 108 caCerts := &corev1.Secret{} 109 err := v.Client.Get(context.TODO(), namespacedName, caCerts) 110 if err != nil { 111 return err 112 } 113 114 if caCerts.Data == nil || len(caCerts.Data) == 0 { 115 return errors.New("no ca certificates found in cacerts secret") 116 } 117 118 err = ValidateCerts(caCerts.Data) 119 if err != nil { 120 return errors.Wrap(err, "not a proper ca cert") 121 } 122 123 return nil 124 } 125 126 func (v *Validator) CheckCertAndKey(instance v1.Object, prefix string) error { 127 var err error 128 129 // Sign cert verification 130 err = v.CheckCert(instance, prefix) 131 if err != nil { 132 return err 133 } 134 135 // Key verification 136 err = v.CheckKey(instance, prefix) 137 if err != nil { 138 return err 139 } 140 141 return nil 142 } 143 144 func (v *Validator) CheckCert(instance v1.Object, prefix string) error { 145 namespacedName := types.NamespacedName{ 146 Namespace: instance.GetNamespace(), 147 } 148 149 signCert := &corev1.Secret{} 150 namespacedName.Name = prefix + "-signcert" 151 err := v.Client.Get(context.TODO(), namespacedName, signCert) 152 if err != nil { 153 return err 154 } 155 156 err = ValidateCert(signCert.Data["cert.pem"]) 157 if err != nil { 158 return errors.Wrap(err, "not a proper sign cert") 159 } 160 161 return nil 162 } 163 164 func (v *Validator) CheckKey(instance v1.Object, prefix string) error { 165 namespacedName := types.NamespacedName{ 166 Namespace: instance.GetNamespace(), 167 } 168 169 key := &corev1.Secret{} 170 namespacedName.Name = prefix + "-keystore" 171 err := v.Client.Get(context.TODO(), namespacedName, key) 172 if err != nil { 173 return err 174 } 175 176 err = ValidateKey(key.Data["key.pem"]) 177 if err != nil { 178 return errors.Wrap(err, "not a proper key") 179 } 180 181 return nil 182 } 183 184 func (v *Validator) SetHSMEnabled(enabled bool) { 185 v.HSMEnabled = enabled 186 } 187 188 func CheckError(err error) bool { 189 if err == nil { 190 return false 191 } 192 193 if strings.Contains(err.Error(), "not found") || strings.Contains(err.Error(), "not valid") { 194 return true 195 } 196 197 return false 198 } 199 200 func ValidateCerts(certs map[string][]byte) error { 201 for _, cert := range certs { 202 err := ValidateCert(cert) 203 if err != nil { 204 return err 205 } 206 } 207 208 return nil 209 } 210 211 func ValidateCert(cert []byte) error { 212 block, _ := pem.Decode(cert) 213 if block == nil { 214 return errors.New("failed to get certificate block") 215 } 216 217 _, err := x509.ParseCertificate(block.Bytes) 218 if err != nil { 219 return errors.Wrap(err, "not valid") 220 } 221 222 return nil 223 } 224 225 func ValidateKey(key []byte) error { 226 block, _ := pem.Decode(key) 227 if block == nil { 228 return errors.New("failed to get key block") 229 } 230 231 _, err := x509.ParsePKCS8PrivateKey(block.Bytes) 232 if err != nil { 233 return errors.Wrap(err, "not valid") 234 } 235 236 return nil 237 }