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 }