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 }