github.com/vchain-us/vcn@v0.9.11-0.20210921212052-a2484d23c0b3/pkg/api/lc_client.go (about)

     1  /*
     2   * Copyright (c) 2018-2020 vChain, Inc. All Rights Reserved.
     3   * This software is released under GPL3.
     4   * The full license information can be found under:
     5   * https://www.gnu.org/licenses/gpl-3.0.en.html
     6   *
     7   */
     8  
     9  package api
    10  
    11  import (
    12  	"crypto/ecdsa"
    13  	"crypto/tls"
    14  	"crypto/x509"
    15  	"errors"
    16  	"fmt"
    17  	"io/ioutil"
    18  	"strconv"
    19  	"time"
    20  
    21  	sdk "github.com/vchain-us/ledger-compliance-go/grpcclient"
    22  	"github.com/vchain-us/vcn/pkg/meta"
    23  	"github.com/vchain-us/vcn/pkg/store"
    24  	"google.golang.org/grpc"
    25  	"google.golang.org/grpc/credentials"
    26  	"google.golang.org/grpc/keepalive"
    27  )
    28  
    29  func NewLcClientByContext(context store.CurrentContext, lcApiKey string, lcLedger string, signingPubKey *ecdsa.PublicKey) (*sdk.LcClient, error) {
    30  	return NewLcClient(lcApiKey, lcLedger, context.LcHost, context.LcPort, context.LcCert, context.LcSkipTlsVerify, context.LcNoTls, signingPubKey)
    31  }
    32  
    33  func NewLcClient(lcApiKey, lcLedger, host, port, lcCertPath string, skipTlsVerify, noTls bool, signingPubKey *ecdsa.PublicKey) (*sdk.LcClient, error) {
    34  	if skipTlsVerify && noTls {
    35  		return nil, errors.New("illegal parameters submitted: lc-skip-tls-verify and lc-no-tls arguments are both provided")
    36  	}
    37  
    38  	p, err := strconv.Atoi(port)
    39  	if err != nil {
    40  		return nil, errors.New("ledger compliance port is invalid")
    41  	}
    42  	defaultOptions := []grpc.DialOption{
    43  		grpc.WithKeepaliveParams(keepalive.ClientParameters{
    44  			Time:                20 * time.Second,
    45  			Timeout:             10 * time.Second,
    46  			PermitWithoutStream: true,
    47  		}),
    48  	}
    49  
    50  	currentOptions := []grpc.DialOption{}
    51  	currentOptions = append(currentOptions, defaultOptions...)
    52  	if !skipTlsVerify {
    53  		if lcCertPath != "" {
    54  			tlsCredentials, err := loadTLSCertificate(lcCertPath)
    55  			if err != nil {
    56  				return nil, fmt.Errorf("cannot load TLS credentials: %s", err)
    57  			}
    58  			currentOptions = append(currentOptions, grpc.WithTransportCredentials(tlsCredentials))
    59  		} else {
    60  			// automatic loading of local CA in os
    61  			currentOptions = append(currentOptions, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{})))
    62  		}
    63  	} else {
    64  		currentOptions = append(currentOptions, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{InsecureSkipVerify: true})))
    65  	}
    66  
    67  	if noTls {
    68  		currentOptions = []grpc.DialOption{grpc.WithInsecure()}
    69  		currentOptions = append(currentOptions, defaultOptions...)
    70  	}
    71  
    72  	return sdk.NewLcClient(
    73  		sdk.ApiKey(lcApiKey),
    74  		sdk.MetadataPairs([]string{
    75  			meta.VcnLCLedgerHeaderName, lcLedger,
    76  			meta.VcnLCVersionHeaderName, meta.Version(),
    77  		}),
    78  		sdk.Host(host),
    79  		sdk.Port(p),
    80  		sdk.Dir(store.CurrentConfigFilePath()),
    81  		sdk.DialOptions(currentOptions),
    82  		sdk.ServerSigningPubKey(signingPubKey),
    83  	), nil
    84  }
    85  
    86  func loadTLSCertificate(certPath string) (credentials.TransportCredentials, error) {
    87  	cert, err := ioutil.ReadFile(certPath)
    88  	if err != nil {
    89  		return nil, err
    90  	}
    91  	certPool := x509.NewCertPool()
    92  	if !certPool.AppendCertsFromPEM(cert) {
    93  		return nil, fmt.Errorf("failed to add server CA's certificate")
    94  	}
    95  	config := &tls.Config{
    96  		RootCAs: certPool,
    97  	}
    98  	return credentials.NewTLS(config), nil
    99  }