ClientHandshake performs the TLS handshake on the client-side. It looks for the presence of a HandshakeInfo value in the passed in context (added using a call to NewContextWithHandshakeInfo()), and retrieves identity and root certificates from there. It also retrieves a list of acceptable SANs and
(ctx context.Context, authority string, rawConn net.Conn)
| 91 | // by the peer. It uses fallback credentials if no HandshakeInfo is present in |
| 92 | // the passed in context. |
| 93 | func (c *credsImpl) ClientHandshake(ctx context.Context, authority string, rawConn net.Conn) (net.Conn, credentials.AuthInfo, error) { |
| 94 | if !c.isClient { |
| 95 | return nil, nil, errors.New("ClientHandshake() is not supported for server credentials") |
| 96 | } |
| 97 | |
| 98 | // The clusterimpl balancer constructs a new HandshakeInfo using a call to |
| 99 | // NewHandshakeInfo(), and then adds it to the attributes field of the |
| 100 | // resolver.Address when handling calls to NewSubConn(). The transport layer |
| 101 | // takes care of shipping these attributes in the context to this handshake |
| 102 | // function. We first read the credentials.ClientHandshakeInfo type from the |
| 103 | // context, which contains the attributes added by the clusterimpl balancer. |
| 104 | // We then read the HandshakeInfo from the attributes to get to the actual |
| 105 | // data that we need here for the handshake. |
| 106 | chi := credentials.ClientHandshakeInfoFromContext(ctx) |
| 107 | // If there are no attributes in the received context or the attributes does |
| 108 | // not contain a HandshakeInfo, it could either mean that the user did not |
| 109 | // specify an `xds` scheme in their dial target or that the xDS server did |
| 110 | // not provide any security configuration. In both of these cases, we use |
| 111 | // the fallback credentials specified by the user. |
| 112 | if chi.Attributes == nil { |
| 113 | return c.fallback.ClientHandshake(ctx, authority, rawConn) |
| 114 | } |
| 115 | |
| 116 | hi := xdsinternal.HandshakeInfoFromAttributes(chi.Attributes).Load() |
| 117 | if hi == nil { |
| 118 | return c.fallback.ClientHandshake(ctx, authority, rawConn) |
| 119 | } |
| 120 | if hi.UseFallbackCreds() { |
| 121 | return c.fallback.ClientHandshake(ctx, authority, rawConn) |
| 122 | } |
| 123 | |
| 124 | // We build the tls.Config with the following values |
| 125 | // 1. Root certificate as returned by the root provider. |
| 126 | // 2. Identity certificate as returned by the identity provider. This may be |
| 127 | // empty on the client side, if the client is not doing mTLS. |
| 128 | // 3. InsecureSkipVerify to true. Certificates used in Mesh environments |
| 129 | // usually contains the identity of the workload presenting the |
| 130 | // certificate as a SAN (instead of a hostname in the CommonName field). |
| 131 | // This means that normal certificate verification as done by the |
| 132 | // standard library will fail. |
| 133 | // 4. Key usage to match whether client/server usage. |
| 134 | // 5. A `VerifyPeerCertificate` function which performs normal peer |
| 135 | // cert verification using configured roots, and the custom SAN checks. |
| 136 | hostname := xdsinternal.Hostname(chi.Attributes) |
| 137 | cfg, err := hi.ClientSideTLSConfig(ctx, hostname) |
| 138 | if err != nil { |
| 139 | return nil, nil, err |
| 140 | } |
| 141 | |
| 142 | // Perform the TLS handshake with the tls.Config that we have. We run the |
| 143 | // actual Handshake() function in a goroutine because we need to respect the |
| 144 | // deadline specified on the passed in context, and we need a way to cancel |
| 145 | // the handshake if the context is cancelled. |
| 146 | conn := tls.Client(rawConn, cfg) |
| 147 | errCh := make(chan error, 1) |
| 148 | go func() { |
| 149 | errCh <- conn.Handshake() |
| 150 | close(errCh) |
nothing calls this directly
no test coverage detected