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  }