tls.go (8694B)
1 /* 2 * 3 * Copyright 2014 gRPC authors. 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 * 17 */ 18 19 package credentials 20 21 import ( 22 "context" 23 "crypto/tls" 24 "crypto/x509" 25 "fmt" 26 "net" 27 "net/url" 28 "os" 29 30 credinternal "google.golang.org/grpc/internal/credentials" 31 ) 32 33 // TLSInfo contains the auth information for a TLS authenticated connection. 34 // It implements the AuthInfo interface. 35 type TLSInfo struct { 36 State tls.ConnectionState 37 CommonAuthInfo 38 // This API is experimental. 39 SPIFFEID *url.URL 40 } 41 42 // AuthType returns the type of TLSInfo as a string. 43 func (t TLSInfo) AuthType() string { 44 return "tls" 45 } 46 47 // GetSecurityValue returns security info requested by channelz. 48 func (t TLSInfo) GetSecurityValue() ChannelzSecurityValue { 49 v := &TLSChannelzSecurityValue{ 50 StandardName: cipherSuiteLookup[t.State.CipherSuite], 51 } 52 // Currently there's no way to get LocalCertificate info from tls package. 53 if len(t.State.PeerCertificates) > 0 { 54 v.RemoteCertificate = t.State.PeerCertificates[0].Raw 55 } 56 return v 57 } 58 59 // tlsCreds is the credentials required for authenticating a connection using TLS. 60 type tlsCreds struct { 61 // TLS configuration 62 config *tls.Config 63 } 64 65 func (c tlsCreds) Info() ProtocolInfo { 66 return ProtocolInfo{ 67 SecurityProtocol: "tls", 68 SecurityVersion: "1.2", 69 ServerName: c.config.ServerName, 70 } 71 } 72 73 func (c *tlsCreds) ClientHandshake(ctx context.Context, authority string, rawConn net.Conn) (_ net.Conn, _ AuthInfo, err error) { 74 // use local cfg to avoid clobbering ServerName if using multiple endpoints 75 cfg := credinternal.CloneTLSConfig(c.config) 76 if cfg.ServerName == "" { 77 serverName, _, err := net.SplitHostPort(authority) 78 if err != nil { 79 // If the authority had no host port or if the authority cannot be parsed, use it as-is. 80 serverName = authority 81 } 82 cfg.ServerName = serverName 83 } 84 conn := tls.Client(rawConn, cfg) 85 errChannel := make(chan error, 1) 86 go func() { 87 errChannel <- conn.Handshake() 88 close(errChannel) 89 }() 90 select { 91 case err := <-errChannel: 92 if err != nil { 93 conn.Close() 94 return nil, nil, err 95 } 96 case <-ctx.Done(): 97 conn.Close() 98 return nil, nil, ctx.Err() 99 } 100 tlsInfo := TLSInfo{ 101 State: conn.ConnectionState(), 102 CommonAuthInfo: CommonAuthInfo{ 103 SecurityLevel: PrivacyAndIntegrity, 104 }, 105 } 106 id := credinternal.SPIFFEIDFromState(conn.ConnectionState()) 107 if id != nil { 108 tlsInfo.SPIFFEID = id 109 } 110 return credinternal.WrapSyscallConn(rawConn, conn), tlsInfo, nil 111 } 112 113 func (c *tlsCreds) ServerHandshake(rawConn net.Conn) (net.Conn, AuthInfo, error) { 114 conn := tls.Server(rawConn, c.config) 115 if err := conn.Handshake(); err != nil { 116 conn.Close() 117 return nil, nil, err 118 } 119 tlsInfo := TLSInfo{ 120 State: conn.ConnectionState(), 121 CommonAuthInfo: CommonAuthInfo{ 122 SecurityLevel: PrivacyAndIntegrity, 123 }, 124 } 125 id := credinternal.SPIFFEIDFromState(conn.ConnectionState()) 126 if id != nil { 127 tlsInfo.SPIFFEID = id 128 } 129 return credinternal.WrapSyscallConn(rawConn, conn), tlsInfo, nil 130 } 131 132 func (c *tlsCreds) Clone() TransportCredentials { 133 return NewTLS(c.config) 134 } 135 136 func (c *tlsCreds) OverrideServerName(serverNameOverride string) error { 137 c.config.ServerName = serverNameOverride 138 return nil 139 } 140 141 // NewTLS uses c to construct a TransportCredentials based on TLS. 142 func NewTLS(c *tls.Config) TransportCredentials { 143 tc := &tlsCreds{credinternal.CloneTLSConfig(c)} 144 tc.config.NextProtos = credinternal.AppendH2ToNextProtos(tc.config.NextProtos) 145 return tc 146 } 147 148 // NewClientTLSFromCert constructs TLS credentials from the provided root 149 // certificate authority certificate(s) to validate server connections. If 150 // certificates to establish the identity of the client need to be included in 151 // the credentials (eg: for mTLS), use NewTLS instead, where a complete 152 // tls.Config can be specified. 153 // serverNameOverride is for testing only. If set to a non empty string, 154 // it will override the virtual host name of authority (e.g. :authority header 155 // field) in requests. 156 func NewClientTLSFromCert(cp *x509.CertPool, serverNameOverride string) TransportCredentials { 157 return NewTLS(&tls.Config{ServerName: serverNameOverride, RootCAs: cp}) 158 } 159 160 // NewClientTLSFromFile constructs TLS credentials from the provided root 161 // certificate authority certificate file(s) to validate server connections. If 162 // certificates to establish the identity of the client need to be included in 163 // the credentials (eg: for mTLS), use NewTLS instead, where a complete 164 // tls.Config can be specified. 165 // serverNameOverride is for testing only. If set to a non empty string, 166 // it will override the virtual host name of authority (e.g. :authority header 167 // field) in requests. 168 func NewClientTLSFromFile(certFile, serverNameOverride string) (TransportCredentials, error) { 169 b, err := os.ReadFile(certFile) 170 if err != nil { 171 return nil, err 172 } 173 cp := x509.NewCertPool() 174 if !cp.AppendCertsFromPEM(b) { 175 return nil, fmt.Errorf("credentials: failed to append certificates") 176 } 177 return NewTLS(&tls.Config{ServerName: serverNameOverride, RootCAs: cp}), nil 178 } 179 180 // NewServerTLSFromCert constructs TLS credentials from the input certificate for server. 181 func NewServerTLSFromCert(cert *tls.Certificate) TransportCredentials { 182 return NewTLS(&tls.Config{Certificates: []tls.Certificate{*cert}}) 183 } 184 185 // NewServerTLSFromFile constructs TLS credentials from the input certificate file and key 186 // file for server. 187 func NewServerTLSFromFile(certFile, keyFile string) (TransportCredentials, error) { 188 cert, err := tls.LoadX509KeyPair(certFile, keyFile) 189 if err != nil { 190 return nil, err 191 } 192 return NewTLS(&tls.Config{Certificates: []tls.Certificate{cert}}), nil 193 } 194 195 // TLSChannelzSecurityValue defines the struct that TLS protocol should return 196 // from GetSecurityValue(), containing security info like cipher and certificate used. 197 // 198 // # Experimental 199 // 200 // Notice: This type is EXPERIMENTAL and may be changed or removed in a 201 // later release. 202 type TLSChannelzSecurityValue struct { 203 ChannelzSecurityValue 204 StandardName string 205 LocalCertificate []byte 206 RemoteCertificate []byte 207 } 208 209 var cipherSuiteLookup = map[uint16]string{ 210 tls.TLS_RSA_WITH_RC4_128_SHA: "TLS_RSA_WITH_RC4_128_SHA", 211 tls.TLS_RSA_WITH_3DES_EDE_CBC_SHA: "TLS_RSA_WITH_3DES_EDE_CBC_SHA", 212 tls.TLS_RSA_WITH_AES_128_CBC_SHA: "TLS_RSA_WITH_AES_128_CBC_SHA", 213 tls.TLS_RSA_WITH_AES_256_CBC_SHA: "TLS_RSA_WITH_AES_256_CBC_SHA", 214 tls.TLS_RSA_WITH_AES_128_GCM_SHA256: "TLS_RSA_WITH_AES_128_GCM_SHA256", 215 tls.TLS_RSA_WITH_AES_256_GCM_SHA384: "TLS_RSA_WITH_AES_256_GCM_SHA384", 216 tls.TLS_ECDHE_ECDSA_WITH_RC4_128_SHA: "TLS_ECDHE_ECDSA_WITH_RC4_128_SHA", 217 tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA: "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA", 218 tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA: "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA", 219 tls.TLS_ECDHE_RSA_WITH_RC4_128_SHA: "TLS_ECDHE_RSA_WITH_RC4_128_SHA", 220 tls.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA: "TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA", 221 tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA: "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA", 222 tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA: "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA", 223 tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256: "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", 224 tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256: "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", 225 tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384: "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384", 226 tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384: "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384", 227 tls.TLS_FALLBACK_SCSV: "TLS_FALLBACK_SCSV", 228 tls.TLS_RSA_WITH_AES_128_CBC_SHA256: "TLS_RSA_WITH_AES_128_CBC_SHA256", 229 tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256: "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256", 230 tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256: "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256", 231 tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305: "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305", 232 tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305: "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305", 233 tls.TLS_AES_128_GCM_SHA256: "TLS_AES_128_GCM_SHA256", 234 tls.TLS_AES_256_GCM_SHA384: "TLS_AES_256_GCM_SHA384", 235 tls.TLS_CHACHA20_POLY1305_SHA256: "TLS_CHACHA20_POLY1305_SHA256", 236 }