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  }