github.com/IBM-Blockchain/fabric-operator@v1.0.4/pkg/initializer/common/secretmanager/secretmanager.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 secretmanager 20 21 import ( 22 "context" 23 "fmt" 24 25 current "github.com/IBM-Blockchain/fabric-operator/api/v1beta1" 26 "github.com/IBM-Blockchain/fabric-operator/pkg/initializer/common" 27 "github.com/IBM-Blockchain/fabric-operator/pkg/initializer/common/config" 28 k8sclient "github.com/IBM-Blockchain/fabric-operator/pkg/k8s/controllerclient" 29 "github.com/pkg/errors" 30 corev1 "k8s.io/api/core/v1" 31 k8serrors "k8s.io/apimachinery/pkg/api/errors" 32 v1 "k8s.io/apimachinery/pkg/apis/meta/v1" 33 "k8s.io/apimachinery/pkg/runtime" 34 "k8s.io/apimachinery/pkg/types" 35 logf "sigs.k8s.io/controller-runtime/pkg/log" 36 ) 37 38 var log = logf.Log.WithName("secret_manager") 39 40 type SecretManager struct { 41 Client k8sclient.Client 42 Scheme *runtime.Scheme 43 GetLabels func(instance v1.Object) map[string]string 44 } 45 46 func New(client k8sclient.Client, scheme *runtime.Scheme, labels func(instance v1.Object) map[string]string) *SecretManager { 47 return &SecretManager{ 48 Client: client, 49 Scheme: scheme, 50 GetLabels: labels, 51 } 52 } 53 54 func (s *SecretManager) GenerateSecrets(prefix common.SecretType, instance v1.Object, crypto *config.Response) error { 55 if crypto == nil { 56 return nil 57 } 58 59 if prefix != common.TLS { 60 err := s.CreateAdminSecret(fmt.Sprintf("%s-%s-%s", prefix, instance.GetName(), "admincerts"), instance, crypto.AdminCerts) 61 if err != nil { 62 return errors.Wrap(err, "failed to create admin certs secret") 63 } 64 } 65 66 err := s.CreateCACertsSecret(fmt.Sprintf("%s-%s-%s", prefix, instance.GetName(), "cacerts"), instance, crypto.CACerts) 67 if err != nil { 68 return errors.Wrap(err, "failed to create ca certs secret") 69 } 70 71 err = s.CreateIntermediateCertsSecret(fmt.Sprintf("%s-%s-%s", prefix, instance.GetName(), "intercerts"), instance, crypto.IntermediateCerts) 72 if err != nil { 73 return errors.Wrap(err, "failed to create intermediate ca certs secret") 74 } 75 76 err = s.CreateSignCert(fmt.Sprintf("%s-%s-%s", prefix, instance.GetName(), "signcert"), instance, crypto.SignCert) 77 if err != nil { 78 return errors.Wrap(err, "failed to create signing cert secret") 79 } 80 81 err = s.CreateKey(fmt.Sprintf("%s-%s-%s", prefix, instance.GetName(), "keystore"), instance, crypto.Keystore) 82 if err != nil { 83 return errors.Wrap(err, "failed to create key secret") 84 } 85 86 return nil 87 } 88 89 func (s *SecretManager) UpdateSecrets(prefix common.SecretType, instance v1.Object, crypto *config.Response) error { 90 // AdminCert updates are checked in base Initialize() code 91 92 err := s.CreateCACertsSecret(fmt.Sprintf("%s-%s-%s", prefix, instance.GetName(), "cacerts"), instance, crypto.CACerts) 93 if err != nil { 94 return errors.Wrap(err, "failed to create ca certs secret") 95 } 96 97 err = s.CreateIntermediateCertsSecret(fmt.Sprintf("%s-%s-%s", prefix, instance.GetName(), "intercerts"), instance, crypto.IntermediateCerts) 98 if err != nil { 99 return errors.Wrap(err, "failed to create intermediate ca certs secret") 100 } 101 102 err = s.CreateSignCert(fmt.Sprintf("%s-%s-%s", prefix, instance.GetName(), "signcert"), instance, crypto.SignCert) 103 if err != nil { 104 return errors.Wrap(err, "failed to create signing cert secret") 105 } 106 107 err = s.CreateKey(fmt.Sprintf("%s-%s-%s", prefix, instance.GetName(), "keystore"), instance, crypto.Keystore) 108 if err != nil { 109 return errors.Wrap(err, "failed to create key secret") 110 } 111 112 return nil 113 } 114 115 func (s *SecretManager) CreateAdminSecret(name string, instance v1.Object, adminCerts [][]byte) error { 116 if len(adminCerts) == 0 || string(adminCerts[0]) == "" { 117 return nil 118 } 119 120 data := s.GetCertsData("admincert", adminCerts) 121 err := s.CreateOrUpdateSecret(instance, name, data) 122 if err != nil { 123 return err 124 } 125 126 return nil 127 } 128 129 func (s *SecretManager) CreateCACertsSecret(name string, instance v1.Object, caCerts [][]byte) error { 130 if len(caCerts) == 0 { 131 return nil 132 } 133 134 data := s.GetCertsData("cacert", caCerts) 135 err := s.CreateOrUpdateSecret(instance, name, data) 136 if err != nil { 137 return err 138 } 139 140 return nil 141 } 142 143 func (s *SecretManager) CreateIntermediateCertsSecret(name string, instance v1.Object, interCerts [][]byte) error { 144 if len(interCerts) == 0 { 145 return nil 146 } 147 148 data := s.GetCertsData("intercert", interCerts) 149 err := s.CreateOrUpdateSecret(instance, name, data) 150 if err != nil { 151 return err 152 } 153 154 return nil 155 } 156 157 func (s *SecretManager) CreateSignCert(name string, instance v1.Object, cert []byte) error { 158 if cert == nil || len(cert) == 0 { 159 return nil 160 } 161 162 data := map[string][]byte{ 163 "cert.pem": cert, 164 } 165 err := s.CreateOrUpdateSecret(instance, name, data) 166 if err != nil { 167 return err 168 } 169 170 return nil 171 } 172 173 func (s *SecretManager) CreateKey(name string, instance v1.Object, key []byte) error { 174 if key == nil { 175 return nil 176 } 177 178 data := map[string][]byte{ 179 "key.pem": key, 180 } 181 err := s.CreateOrUpdateSecret(instance, name, data) 182 if err != nil { 183 return err 184 } 185 186 return nil 187 } 188 189 func (s *SecretManager) CreateOrUpdateSecret(instance v1.Object, name string, data map[string][]byte) error { 190 log.Info(fmt.Sprintf("Create/Update secret '%s'", name)) 191 192 secret := s.BuildSecret(instance, name, data, s.GetLabels(instance)) 193 err := s.Client.CreateOrUpdate(context.TODO(), secret, k8sclient.CreateOrUpdateOption{ 194 Owner: instance, 195 Scheme: s.Scheme, 196 }) 197 if err != nil { 198 return err 199 } 200 201 return nil 202 } 203 204 func (s *SecretManager) UpdateAdminCertSecret(instance v1.Object, secretSpec *current.SecretSpec) error { 205 name := fmt.Sprintf("ecert-%s-admincerts", instance.GetName()) 206 207 adminCerts := common.GetAdminCertsFromSpec(secretSpec) 208 209 if len(adminCerts) == 0 || string(adminCerts[0]) == "" { 210 return nil 211 } 212 213 adminCertsBytes, err := common.ConvertCertsToBytes(adminCerts) 214 if err != nil { 215 return err 216 } 217 218 data := s.GetCertsData("admincert", adminCertsBytes) 219 err = s.CreateOrUpdateSecret(instance, name, data) 220 if err != nil { 221 return err 222 } 223 224 return nil 225 } 226 227 func (s *SecretManager) BuildSecret(instance v1.Object, name string, data map[string][]byte, labels map[string]string) *corev1.Secret { 228 return &corev1.Secret{ 229 ObjectMeta: v1.ObjectMeta{ 230 Name: name, 231 Namespace: instance.GetNamespace(), 232 Labels: labels, 233 }, 234 Data: data, 235 Type: corev1.SecretTypeOpaque, 236 } 237 } 238 239 func (s *SecretManager) GetSecret(name string, instance v1.Object) (*corev1.Secret, error) { 240 n := types.NamespacedName{ 241 Name: name, 242 Namespace: instance.GetNamespace(), 243 } 244 245 secret := &corev1.Secret{} 246 err := s.Client.Get(context.TODO(), n, secret) 247 if err != nil { 248 if k8serrors.IsNotFound(err) { 249 return nil, nil 250 } 251 return nil, err 252 } 253 254 return secret, nil 255 } 256 257 func (s *SecretManager) GetCertsData(certType string, certs [][]byte) map[string][]byte { 258 data := map[string][]byte{} 259 for i, cert := range certs { 260 if string(cert) == "" { 261 continue 262 } 263 data[fmt.Sprintf("%s-%d.pem", certType, i)] = cert 264 } 265 266 return data 267 } 268 269 func (s *SecretManager) DeleteSecrets(prefix string, instance v1.Object, name string) error { 270 secret := &corev1.Secret{} 271 secret.Namespace = instance.GetNamespace() 272 273 secret.Name = fmt.Sprintf("%s-%s-%s", prefix, name, "admincerts") 274 err := s.Client.Delete(context.TODO(), secret) 275 if err != nil { 276 if !k8serrors.IsNotFound(err) { 277 return errors.Wrapf(err, "failed to delete secret '%s'", secret.Name) 278 } 279 } 280 281 secret.Name = fmt.Sprintf("%s-%s-%s", prefix, name, "cacerts") 282 err = s.Client.Delete(context.TODO(), secret) 283 if err != nil { 284 if !k8serrors.IsNotFound(err) { 285 return errors.Wrapf(err, "failed to delete secret '%s'", secret.Name) 286 } 287 } 288 289 secret.Name = fmt.Sprintf("%s-%s-%s", prefix, name, "intercerts") 290 err = s.Client.Delete(context.TODO(), secret) 291 if err != nil { 292 if !k8serrors.IsNotFound(err) { 293 return errors.Wrapf(err, "failed to delete secret '%s'", secret.Name) 294 } 295 } 296 297 secret.Name = fmt.Sprintf("%s-%s-%s", prefix, name, "signcert") 298 err = s.Client.Delete(context.TODO(), secret) 299 if err != nil { 300 if !k8serrors.IsNotFound(err) { 301 return errors.Wrapf(err, "failed to delete secret '%s'", secret.Name) 302 } 303 } 304 305 secret.Name = fmt.Sprintf("%s-%s-%s", prefix, name, "keystore") 306 err = s.Client.Delete(context.TODO(), secret) 307 if err != nil { 308 if !k8serrors.IsNotFound(err) { 309 return errors.Wrapf(err, "failed to delete secret '%s'", secret.Name) 310 } 311 } 312 313 return nil 314 } 315 316 func (s *SecretManager) GetCryptoFromSecrets(prefix common.SecretType, instance v1.Object) (*config.Response, error) { 317 resp := &config.Response{} 318 319 admincerts, err := s.GetSecret(fmt.Sprintf("%s-%s-%s", prefix, instance.GetName(), "admincerts"), instance) 320 if err != nil { 321 return nil, err 322 } 323 if admincerts != nil { 324 resp.AdminCerts = s.GetCertBytesFromData(admincerts.Data) 325 } 326 327 cacerts, err := s.GetSecret(fmt.Sprintf("%s-%s-%s", prefix, instance.GetName(), "cacerts"), instance) 328 if err != nil { 329 return nil, err 330 } 331 if cacerts != nil { 332 resp.CACerts = s.GetCertBytesFromData(cacerts.Data) 333 } 334 335 intercerts, err := s.GetSecret(fmt.Sprintf("%s-%s-%s", prefix, instance.GetName(), "intercerts"), instance) 336 if err != nil { 337 return nil, err 338 } 339 if intercerts != nil { 340 resp.IntermediateCerts = s.GetCertBytesFromData(intercerts.Data) 341 } 342 343 signcert, err := s.GetSecret(fmt.Sprintf("%s-%s-%s", prefix, instance.GetName(), "signcert"), instance) 344 if err != nil { 345 return nil, err 346 } 347 if signcert != nil { 348 resp.SignCert = signcert.Data["cert.pem"] 349 } 350 351 keystore, err := s.GetSecret(fmt.Sprintf("%s-%s-%s", prefix, instance.GetName(), "keystore"), instance) 352 if err != nil { 353 return nil, err 354 } 355 if keystore != nil { 356 resp.Keystore = keystore.Data["key.pem"] 357 } 358 359 return resp, nil 360 } 361 362 func (s *SecretManager) GetCertBytesFromData(data map[string][]byte) [][]byte { 363 bytes := [][]byte{} 364 for _, cert := range data { 365 bytes = append(bytes, cert) 366 } 367 return bytes 368 } 369 370 func (s *SecretManager) GenerateSecretsFromResponse(instance v1.Object, cryptoResponse *config.CryptoResponse) error { 371 if cryptoResponse != nil { 372 err := s.GenerateSecrets("ecert", instance, cryptoResponse.Enrollment) 373 if err != nil { 374 return errors.Wrap(err, "failed to generate ecert secrets") 375 } 376 377 err = s.GenerateSecrets("tls", instance, cryptoResponse.TLS) 378 if err != nil { 379 return errors.Wrap(err, "failed to generate tls secrets") 380 } 381 382 err = s.GenerateSecrets("clientauth", instance, cryptoResponse.ClientAuth) 383 if err != nil { 384 return errors.Wrap(err, "failed to generate client auth secrets") 385 } 386 } 387 return nil 388 } 389 390 func (s *SecretManager) UpdateSecretsFromResponse(instance v1.Object, cryptoResponse *config.CryptoResponse) error { 391 if cryptoResponse != nil { 392 err := s.UpdateSecrets("ecert", instance, cryptoResponse.Enrollment) 393 if err != nil { 394 return errors.Wrap(err, "failed to update ecert secrets") 395 } 396 397 err = s.UpdateSecrets("tls", instance, cryptoResponse.TLS) 398 if err != nil { 399 return errors.Wrap(err, "failed to update tls secrets") 400 } 401 402 err = s.UpdateSecrets("clientauth", instance, cryptoResponse.ClientAuth) 403 if err != nil { 404 return errors.Wrap(err, "failed to update client auth secrets") 405 } 406 } 407 return nil 408 } 409 410 func (s *SecretManager) GetCryptoResponseFromSecrets(instance v1.Object) (*config.CryptoResponse, error) { 411 var err error 412 cryptoResponse := &config.CryptoResponse{} 413 414 cryptoResponse.Enrollment, err = s.GetCryptoFromSecrets("ecert", instance) 415 if err != nil { 416 return nil, errors.Wrap(err, "failed to get ecert crypto") 417 } 418 cryptoResponse.TLS, err = s.GetCryptoFromSecrets("tls", instance) 419 if err != nil { 420 return nil, errors.Wrap(err, "failed to get tls crypto") 421 } 422 cryptoResponse.ClientAuth, err = s.GetCryptoFromSecrets("clientauth", instance) 423 if err != nil { 424 return nil, errors.Wrap(err, "failed to get client auth crypto") 425 } 426 427 return cryptoResponse, nil 428 }