github.com/IBM-Blockchain/fabric-operator@v1.0.4/pkg/initializer/common/enroller/fabcaclient.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 enroller
    20  
    21  import (
    22  	"context"
    23  	"crypto/tls"
    24  	"crypto/x509"
    25  	"fmt"
    26  	"net"
    27  	"net/http"
    28  	"time"
    29  
    30  	current "github.com/IBM-Blockchain/fabric-operator/api/v1beta1"
    31  	commonapi "github.com/IBM-Blockchain/fabric-operator/pkg/apis/common"
    32  	"github.com/hyperledger/fabric-ca/lib"
    33  	catls "github.com/hyperledger/fabric-ca/lib/tls"
    34  	"github.com/pkg/errors"
    35  )
    36  
    37  func NewFabCAClient(cfg *current.Enrollment, homeDir string, bccsp *commonapi.BCCSP, cert []byte) *FabCAClient {
    38  	client := &lib.Client{
    39  		HomeDir: homeDir,
    40  		Config: &lib.ClientConfig{
    41  			TLS: catls.ClientTLSConfig{
    42  				Enabled:   true,
    43  				CertFiles: []string{"tlsCert.pem"},
    44  			},
    45  			URL: fmt.Sprintf("https://%s:%s", cfg.CAHost, cfg.CAPort),
    46  		},
    47  	}
    48  
    49  	client = GetClient(client, bccsp)
    50  	return &FabCAClient{
    51  		Client:        client,
    52  		EnrollmentCfg: cfg,
    53  		CATLSCert:     cert,
    54  		BCCSP:         bccsp,
    55  	}
    56  }
    57  
    58  type FabCAClient struct {
    59  	*lib.Client
    60  
    61  	EnrollmentCfg *current.Enrollment
    62  	BCCSP         *commonapi.BCCSP
    63  	CATLSCert     []byte
    64  }
    65  
    66  func (c *FabCAClient) GetHomeDir() string {
    67  	return c.HomeDir
    68  }
    69  
    70  func (c *FabCAClient) SetURL(url string) {
    71  	c.Config.URL = url
    72  }
    73  
    74  func (c *FabCAClient) GetConfig() *lib.ClientConfig {
    75  	return c.Config
    76  }
    77  
    78  func (c *FabCAClient) GetTLSCert() []byte {
    79  	return c.CATLSCert
    80  }
    81  
    82  func (c *FabCAClient) GetEnrollmentRequest() *current.Enrollment {
    83  	return c.EnrollmentCfg
    84  }
    85  
    86  func (c *FabCAClient) SetHSMLibrary(library string) {
    87  	if c.BCCSP != nil {
    88  		c.BCCSP.PKCS11.Library = library
    89  		c.Client = GetClient(c.Client, c.BCCSP)
    90  	}
    91  }
    92  
    93  func (c *FabCAClient) PingCA(timeout time.Duration) error {
    94  	url := fmt.Sprintf("%s/cainfo", c.Client.Config.URL)
    95  	log.Info(fmt.Sprintf("Pinging CA at '%s' with timeout value of %s", url, timeout.String()))
    96  
    97  	rootCertPool := x509.NewCertPool()
    98  	rootCertPool.AppendCertsFromPEM(c.CATLSCert)
    99  	client := http.Client{
   100  		Transport: &http.Transport{
   101  			IdleConnTimeout: timeout,
   102  			Dial: (&net.Dialer{
   103  				Timeout:   timeout,
   104  				KeepAlive: timeout,
   105  			}).Dial,
   106  			TLSHandshakeTimeout: timeout / 2,
   107  			TLSClientConfig: &tls.Config{
   108  				RootCAs:    rootCertPool,
   109  				MinVersion: tls.VersionTLS12, // TLS 1.2 recommended, TLS 1.3 (current latest version) encouraged
   110  			},
   111  		},
   112  		Timeout: timeout,
   113  	}
   114  
   115  	if err := c.healthCheck(client, url); err != nil {
   116  		return errors.Wrapf(err, "pinging '%s' failed", url)
   117  	}
   118  
   119  	return nil
   120  }
   121  
   122  func (c *FabCAClient) healthCheck(client http.Client, healthURL string) error {
   123  	ctx, cancel := context.WithTimeout(context.Background(), client.Timeout)
   124  	defer cancel()
   125  
   126  	req, err := http.NewRequestWithContext(ctx, http.MethodGet, healthURL, nil)
   127  	if err != nil {
   128  		return errors.Wrap(err, "invalid http request")
   129  	}
   130  
   131  	resp, err := client.Do(req)
   132  	if err != nil {
   133  		return errors.Wrapf(err, "health check request failed")
   134  	}
   135  
   136  	if resp.StatusCode != http.StatusOK {
   137  		return errors.Wrapf(err, "failed health check, ca is not running")
   138  	}
   139  
   140  	return nil
   141  }