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 }