google.golang.org/grpc@v1.62.1/credentials/google/xds.go (about) 1 /* 2 * 3 * Copyright 2021 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 google 20 21 import ( 22 "context" 23 "net" 24 "net/url" 25 "strings" 26 27 "google.golang.org/grpc/credentials" 28 "google.golang.org/grpc/internal" 29 ) 30 31 const cfeClusterNamePrefix = "google_cfe_" 32 const cfeClusterResourceNamePrefix = "/envoy.config.cluster.v3.Cluster/google_cfe_" 33 const cfeClusterAuthorityName = "traffic-director-c2p.xds.googleapis.com" 34 35 // clusterTransportCreds is a combo of TLS + ALTS. 36 // 37 // On the client, ClientHandshake picks TLS or ALTS based on address attributes. 38 // - if attributes has cluster name 39 // - if cluster name has prefix "google_cfe_", or 40 // "xdstp://traffic-director-c2p.xds.googleapis.com/envoy.config.cluster.v3.Cluster/google_cfe_", 41 // use TLS 42 // - otherwise, use ALTS 43 // 44 // - else, do TLS 45 // 46 // On the server, ServerHandshake always does TLS. 47 type clusterTransportCreds struct { 48 tls credentials.TransportCredentials 49 alts credentials.TransportCredentials 50 } 51 52 func newClusterTransportCreds(tls, alts credentials.TransportCredentials) *clusterTransportCreds { 53 return &clusterTransportCreds{ 54 tls: tls, 55 alts: alts, 56 } 57 } 58 59 // clusterName returns the xDS cluster name stored in the attributes in the 60 // context. 61 func clusterName(ctx context.Context) string { 62 chi := credentials.ClientHandshakeInfoFromContext(ctx) 63 if chi.Attributes == nil { 64 return "" 65 } 66 cluster, _ := internal.GetXDSHandshakeClusterName(chi.Attributes) 67 return cluster 68 } 69 70 // isDirectPathCluster returns true if the cluster in the context is a 71 // directpath cluster, meaning ALTS should be used. 72 func isDirectPathCluster(ctx context.Context) bool { 73 cluster := clusterName(ctx) 74 if cluster == "" { 75 // No cluster; not xDS; use TLS. 76 return false 77 } 78 if strings.HasPrefix(cluster, cfeClusterNamePrefix) { 79 // xDS cluster prefixed by "google_cfe_"; use TLS. 80 return false 81 } 82 if !strings.HasPrefix(cluster, "xdstp:") { 83 // Other xDS cluster name; use ALTS. 84 return true 85 } 86 u, err := url.Parse(cluster) 87 if err != nil { 88 // Shouldn't happen, but assume ALTS. 89 return true 90 } 91 // If authority AND path match our CFE checks, use TLS; otherwise use ALTS. 92 return u.Host != cfeClusterAuthorityName || !strings.HasPrefix(u.Path, cfeClusterResourceNamePrefix) 93 } 94 95 func (c *clusterTransportCreds) ClientHandshake(ctx context.Context, authority string, rawConn net.Conn) (net.Conn, credentials.AuthInfo, error) { 96 if isDirectPathCluster(ctx) { 97 // If attributes have cluster name, and cluster name is not cfe, it's a 98 // backend address, use ALTS. 99 return c.alts.ClientHandshake(ctx, authority, rawConn) 100 } 101 return c.tls.ClientHandshake(ctx, authority, rawConn) 102 } 103 104 func (c *clusterTransportCreds) ServerHandshake(conn net.Conn) (net.Conn, credentials.AuthInfo, error) { 105 return c.tls.ServerHandshake(conn) 106 } 107 108 func (c *clusterTransportCreds) Info() credentials.ProtocolInfo { 109 // TODO: this always returns tls.Info now, because we don't have a cluster 110 // name to check when this method is called. This method doesn't affect 111 // anything important now. We may want to revisit this if it becomes more 112 // important later. 113 return c.tls.Info() 114 } 115 116 func (c *clusterTransportCreds) Clone() credentials.TransportCredentials { 117 return &clusterTransportCreds{ 118 tls: c.tls.Clone(), 119 alts: c.alts.Clone(), 120 } 121 } 122 123 func (c *clusterTransportCreds) OverrideServerName(s string) error { 124 if err := c.tls.OverrideServerName(s); err != nil { 125 return err 126 } 127 return c.alts.OverrideServerName(s) 128 }