github.com/myafeier/fabric@v1.0.1-0.20170722181825-3a4b1f2bce86/core/comm/connection.go (about)

     1  /*
     2  Copyright IBM Corp. All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package comm
     8  
     9  import (
    10  	"crypto/tls"
    11  	"crypto/x509"
    12  	"encoding/pem"
    13  	"fmt"
    14  	"os"
    15  	"sync"
    16  	"time"
    17  
    18  	"github.com/hyperledger/fabric/common/flogging"
    19  	"github.com/hyperledger/fabric/core/config"
    20  	"github.com/spf13/viper"
    21  	"google.golang.org/grpc"
    22  	"google.golang.org/grpc/credentials"
    23  	"google.golang.org/grpc/grpclog"
    24  )
    25  
    26  const defaultTimeout = time.Second * 3
    27  
    28  var commLogger = flogging.MustGetLogger("comm")
    29  var caSupport *CASupport
    30  var once sync.Once
    31  
    32  // CASupport type manages certificate authorities scoped by channel
    33  type CASupport struct {
    34  	sync.RWMutex
    35  	AppRootCAsByChain     map[string][][]byte
    36  	OrdererRootCAsByChain map[string][][]byte
    37  	ClientRootCAs         [][]byte
    38  	ServerRootCAs         [][]byte
    39  }
    40  
    41  // GetCASupport returns the signleton CASupport instance
    42  func GetCASupport() *CASupport {
    43  
    44  	once.Do(func() {
    45  		caSupport = &CASupport{
    46  			AppRootCAsByChain:     make(map[string][][]byte),
    47  			OrdererRootCAsByChain: make(map[string][][]byte),
    48  		}
    49  	})
    50  	return caSupport
    51  }
    52  
    53  // GetServerRootCAs returns the PEM-encoded root certificates for all of the
    54  // application and orderer organizations defined for all chains.  The root
    55  // certificates returned should be used to set the trusted server roots for
    56  // TLS clients.
    57  func (cas *CASupport) GetServerRootCAs() (appRootCAs, ordererRootCAs [][]byte) {
    58  	cas.RLock()
    59  	defer cas.RUnlock()
    60  
    61  	appRootCAs = [][]byte{}
    62  	ordererRootCAs = [][]byte{}
    63  
    64  	for _, appRootCA := range cas.AppRootCAsByChain {
    65  		appRootCAs = append(appRootCAs, appRootCA...)
    66  	}
    67  
    68  	for _, ordererRootCA := range cas.OrdererRootCAsByChain {
    69  		ordererRootCAs = append(ordererRootCAs, ordererRootCA...)
    70  	}
    71  
    72  	// also need to append statically configured root certs
    73  	appRootCAs = append(appRootCAs, cas.ServerRootCAs...)
    74  	return appRootCAs, ordererRootCAs
    75  }
    76  
    77  // GetDeliverServiceCredentials returns GRPC transport credentials for given channel to be used by GRPC
    78  // clients which communicate with ordering service endpoints.
    79  // If the channel isn't found, error is returned.
    80  func (cas *CASupport) GetDeliverServiceCredentials(channelID string) (credentials.TransportCredentials, error) {
    81  	cas.RLock()
    82  	defer cas.RUnlock()
    83  
    84  	var creds credentials.TransportCredentials
    85  	var tlsConfig = &tls.Config{}
    86  	var certPool = x509.NewCertPool()
    87  
    88  	rootCACerts, exists := cas.OrdererRootCAsByChain[channelID]
    89  	if !exists {
    90  		commLogger.Errorf("Attempted to obtain root CA certs of a non existent channel: %s", channelID)
    91  		return nil, fmt.Errorf("didn't find any root CA certs for channel %s", channelID)
    92  	}
    93  
    94  	for _, cert := range rootCACerts {
    95  		block, _ := pem.Decode(cert)
    96  		if block != nil {
    97  			cert, err := x509.ParseCertificate(block.Bytes)
    98  			if err == nil {
    99  				certPool.AddCert(cert)
   100  			} else {
   101  				commLogger.Warningf("Failed to add root cert to credentials (%s)", err)
   102  			}
   103  		} else {
   104  			commLogger.Warning("Failed to add root cert to credentials")
   105  		}
   106  	}
   107  	tlsConfig.RootCAs = certPool
   108  	creds = credentials.NewTLS(tlsConfig)
   109  	return creds, nil
   110  }
   111  
   112  // GetPeerCredentials returns GRPC transport credentials for use by GRPC
   113  // clients which communicate with remote peer endpoints.
   114  func (cas *CASupport) GetPeerCredentials(tlsCert tls.Certificate) credentials.TransportCredentials {
   115  	var creds credentials.TransportCredentials
   116  	var tlsConfig = &tls.Config{
   117  		Certificates: []tls.Certificate{tlsCert},
   118  	}
   119  	var certPool = x509.NewCertPool()
   120  	// loop through the orderer CAs
   121  	roots, _ := cas.GetServerRootCAs()
   122  	for _, root := range roots {
   123  		block, _ := pem.Decode(root)
   124  		if block != nil {
   125  			cert, err := x509.ParseCertificate(block.Bytes)
   126  			if err == nil {
   127  				certPool.AddCert(cert)
   128  			} else {
   129  				commLogger.Warningf("Failed to add root cert to credentials (%s)", err)
   130  			}
   131  		} else {
   132  			commLogger.Warning("Failed to add root cert to credentials")
   133  		}
   134  	}
   135  	tlsConfig.RootCAs = certPool
   136  	creds = credentials.NewTLS(tlsConfig)
   137  	return creds
   138  }
   139  
   140  // GetClientRootCAs returns the PEM-encoded root certificates for all of the
   141  // application and orderer organizations defined for all chains.  The root
   142  // certificates returned should be used to set the trusted client roots for
   143  // TLS servers.
   144  func (cas *CASupport) GetClientRootCAs() (appRootCAs, ordererRootCAs [][]byte) {
   145  	cas.RLock()
   146  	defer cas.RUnlock()
   147  
   148  	appRootCAs = [][]byte{}
   149  	ordererRootCAs = [][]byte{}
   150  
   151  	for _, appRootCA := range cas.AppRootCAsByChain {
   152  		appRootCAs = append(appRootCAs, appRootCA...)
   153  	}
   154  
   155  	for _, ordererRootCA := range cas.OrdererRootCAsByChain {
   156  		ordererRootCAs = append(ordererRootCAs, ordererRootCA...)
   157  	}
   158  
   159  	// also need to append statically configured root certs
   160  	appRootCAs = append(appRootCAs, cas.ClientRootCAs...)
   161  	return appRootCAs, ordererRootCAs
   162  }
   163  
   164  func getEnv(key, def string) string {
   165  	val := os.Getenv(key)
   166  	if len(val) > 0 {
   167  		return val
   168  	} else {
   169  		return def
   170  	}
   171  }
   172  
   173  func GetPeerTestingAddress(port string) string {
   174  	return getEnv("UNIT_TEST_PEER_IP", "localhost") + ":" + port
   175  }
   176  
   177  // NewClientConnectionWithAddress Returns a new grpc.ClientConn to the given address.
   178  func NewClientConnectionWithAddress(peerAddress string, block bool, tslEnabled bool, creds credentials.TransportCredentials) (*grpc.ClientConn, error) {
   179  	var opts []grpc.DialOption
   180  	if tslEnabled {
   181  		opts = append(opts, grpc.WithTransportCredentials(creds))
   182  	} else {
   183  		opts = append(opts, grpc.WithInsecure())
   184  	}
   185  	opts = append(opts, grpc.WithTimeout(defaultTimeout))
   186  	if block {
   187  		opts = append(opts, grpc.WithBlock())
   188  	}
   189  	opts = append(opts, grpc.WithDefaultCallOptions(grpc.MaxCallRecvMsgSize(MaxRecvMsgSize()),
   190  		grpc.MaxCallSendMsgSize(MaxSendMsgSize())))
   191  	conn, err := grpc.Dial(peerAddress, opts...)
   192  	if err != nil {
   193  		return nil, err
   194  	}
   195  	return conn, err
   196  }
   197  
   198  // InitTLSForPeer returns TLS credentials for peer
   199  func InitTLSForPeer() credentials.TransportCredentials {
   200  	var sn string
   201  	if viper.GetString("peer.tls.serverhostoverride") != "" {
   202  		sn = viper.GetString("peer.tls.serverhostoverride")
   203  	}
   204  	var creds credentials.TransportCredentials
   205  	if config.GetPath("peer.tls.rootcert.file") != "" {
   206  		var err error
   207  		creds, err = credentials.NewClientTLSFromFile(config.GetPath("peer.tls.rootcert.file"), sn)
   208  		if err != nil {
   209  			grpclog.Fatalf("Failed to create TLS credentials %v", err)
   210  		}
   211  	} else {
   212  		creds = credentials.NewClientTLSFromCert(nil, sn)
   213  	}
   214  	return creds
   215  }