github.com/leonlxy/hyperledger@v1.0.0-alpha.0.20170427033203-34922035d248/core/comm/connection.go (about)

     1  /*
     2  Copyright IBM Corp. 2016 All Rights Reserved.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8  		 http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package comm
    18  
    19  import (
    20  	"crypto/tls"
    21  	"crypto/x509"
    22  	"encoding/pem"
    23  	"os"
    24  	"sync"
    25  	"time"
    26  
    27  	"google.golang.org/grpc"
    28  	"google.golang.org/grpc/credentials"
    29  	"google.golang.org/grpc/grpclog"
    30  
    31  	"github.com/hyperledger/fabric/common/flogging"
    32  	"github.com/hyperledger/fabric/core/config"
    33  	"github.com/spf13/viper"
    34  )
    35  
    36  const defaultTimeout = time.Second * 3
    37  
    38  var commLogger = flogging.MustGetLogger("comm")
    39  var caSupport *CASupport
    40  var once sync.Once
    41  
    42  // CASupport type manages certificate authorities scoped by channel
    43  type CASupport struct {
    44  	sync.RWMutex
    45  	AppRootCAsByChain     map[string][][]byte
    46  	OrdererRootCAsByChain map[string][][]byte
    47  	ClientRootCAs         [][]byte
    48  	ServerRootCAs         [][]byte
    49  }
    50  
    51  // GetCASupport returns the signleton CASupport instance
    52  func GetCASupport() *CASupport {
    53  
    54  	once.Do(func() {
    55  		caSupport = &CASupport{
    56  			AppRootCAsByChain:     make(map[string][][]byte),
    57  			OrdererRootCAsByChain: make(map[string][][]byte),
    58  		}
    59  	})
    60  	return caSupport
    61  }
    62  
    63  // GetServerRootCAs returns the PEM-encoded root certificates for all of the
    64  // application and orderer organizations defined for all chains.  The root
    65  // certificates returned should be used to set the trusted server roots for
    66  // TLS clients.
    67  func (cas *CASupport) GetServerRootCAs() (appRootCAs, ordererRootCAs [][]byte) {
    68  	cas.RLock()
    69  	defer cas.RUnlock()
    70  
    71  	appRootCAs = [][]byte{}
    72  	ordererRootCAs = [][]byte{}
    73  
    74  	for _, appRootCA := range cas.AppRootCAsByChain {
    75  		appRootCAs = append(appRootCAs, appRootCA...)
    76  	}
    77  
    78  	for _, ordererRootCA := range cas.AppRootCAsByChain {
    79  		ordererRootCAs = append(ordererRootCAs, ordererRootCA...)
    80  	}
    81  
    82  	// also need to append statically configured root certs
    83  	appRootCAs = append(appRootCAs, cas.ServerRootCAs...)
    84  	ordererRootCAs = append(ordererRootCAs, cas.ServerRootCAs...)
    85  	return appRootCAs, ordererRootCAs
    86  }
    87  
    88  // GetDeliverServiceCredentials returns GRPC transport credentials for use by GRPC
    89  // clients which communicate with ordering service endpoints.
    90  func (cas *CASupport) GetDeliverServiceCredentials() credentials.TransportCredentials {
    91  	var creds credentials.TransportCredentials
    92  	var tlsConfig = &tls.Config{}
    93  	var certPool = x509.NewCertPool()
    94  	// loop through the orderer CAs
    95  	_, roots := cas.GetServerRootCAs()
    96  	for _, root := range roots {
    97  		block, _ := pem.Decode(root)
    98  		if block != nil {
    99  			cert, err := x509.ParseCertificate(block.Bytes)
   100  			if err == nil {
   101  				certPool.AddCert(cert)
   102  			} else {
   103  				commLogger.Warningf("Failed to add root cert to credentials (%s)", err)
   104  			}
   105  		} else {
   106  			commLogger.Warning("Failed to add root cert to credentials")
   107  		}
   108  	}
   109  	tlsConfig.RootCAs = certPool
   110  	creds = credentials.NewTLS(tlsConfig)
   111  	return creds
   112  }
   113  
   114  // GetClientRootCAs returns the PEM-encoded root certificates for all of the
   115  // application and orderer organizations defined for all chains.  The root
   116  // certificates returned should be used to set the trusted client roots for
   117  // TLS servers.
   118  func (cas *CASupport) GetClientRootCAs() (appRootCAs, ordererRootCAs [][]byte) {
   119  	cas.RLock()
   120  	defer cas.RUnlock()
   121  
   122  	appRootCAs = [][]byte{}
   123  	ordererRootCAs = [][]byte{}
   124  
   125  	for _, appRootCA := range cas.AppRootCAsByChain {
   126  		appRootCAs = append(appRootCAs, appRootCA...)
   127  	}
   128  
   129  	for _, ordererRootCA := range cas.AppRootCAsByChain {
   130  		ordererRootCAs = append(ordererRootCAs, ordererRootCA...)
   131  	}
   132  
   133  	// also need to append statically configured root certs
   134  	appRootCAs = append(appRootCAs, cas.ClientRootCAs...)
   135  	ordererRootCAs = append(ordererRootCAs, cas.ClientRootCAs...)
   136  	return appRootCAs, ordererRootCAs
   137  }
   138  
   139  func getEnv(key, def string) string {
   140  	val := os.Getenv(key)
   141  	if len(val) > 0 {
   142  		return val
   143  	} else {
   144  		return def
   145  	}
   146  }
   147  
   148  func GetPeerTestingAddress(port string) string {
   149  	return getEnv("UNIT_TEST_PEER_IP", "localhost") + ":" + port
   150  }
   151  
   152  // NewClientConnectionWithAddress Returns a new grpc.ClientConn to the given address.
   153  func NewClientConnectionWithAddress(peerAddress string, block bool, tslEnabled bool, creds credentials.TransportCredentials) (*grpc.ClientConn, error) {
   154  	var opts []grpc.DialOption
   155  	if tslEnabled {
   156  		opts = append(opts, grpc.WithTransportCredentials(creds))
   157  	} else {
   158  		opts = append(opts, grpc.WithInsecure())
   159  	}
   160  	opts = append(opts, grpc.WithTimeout(defaultTimeout))
   161  	if block {
   162  		opts = append(opts, grpc.WithBlock())
   163  	}
   164  	conn, err := grpc.Dial(peerAddress, opts...)
   165  	if err != nil {
   166  		return nil, err
   167  	}
   168  	return conn, err
   169  }
   170  
   171  // InitTLSForPeer returns TLS credentials for peer
   172  func InitTLSForPeer() credentials.TransportCredentials {
   173  	var sn string
   174  	if viper.GetString("peer.tls.serverhostoverride") != "" {
   175  		sn = viper.GetString("peer.tls.serverhostoverride")
   176  	}
   177  	var creds credentials.TransportCredentials
   178  	if config.GetPath("peer.tls.rootcert.file") != "" {
   179  		var err error
   180  		creds, err = credentials.NewClientTLSFromFile(config.GetPath("peer.tls.rootcert.file"), sn)
   181  		if err != nil {
   182  			grpclog.Fatalf("Failed to create TLS credentials %v", err)
   183  		}
   184  	} else {
   185  		creds = credentials.NewClientTLSFromCert(nil, sn)
   186  	}
   187  	return creds
   188  }