TestClientCredsProviderSwitch verifies the case where the first attempt of ClientHandshake fails because of a handshake failure. Then we update the certificate provider and the second attempt succeeds. This is an approximation of the flow of events when the control plane specifies new security confi
(t *testing.T)
| 598 | // approximation of the flow of events when the control plane specifies new |
| 599 | // security config which results in new certificate providers being used. |
| 600 | func (s) TestClientCredsProviderSwitch(t *testing.T) { |
| 601 | ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout) |
| 602 | defer cancel() |
| 603 | ts := newTestServerWithHandshakeFunc(ctx, testServerTLSHandshake) |
| 604 | defer ts.stop() |
| 605 | |
| 606 | opts := ClientOptions{FallbackCreds: makeFallbackClientCreds(t)} |
| 607 | creds, err := NewClientCredentials(opts) |
| 608 | if err != nil { |
| 609 | t.Fatalf("NewClientCredentials(%v) failed: %v", opts, err) |
| 610 | } |
| 611 | |
| 612 | conn, err := net.Dial("tcp", ts.address) |
| 613 | if err != nil { |
| 614 | t.Fatalf("net.Dial(%s) failed: %v", ts.address, err) |
| 615 | } |
| 616 | defer conn.Close() |
| 617 | |
| 618 | // Create a root provider which will fail the handshake because it does not |
| 619 | // use the correct trust roots. |
| 620 | root1 := makeRootProvider(t, "x509/client_ca_cert.pem") |
| 621 | handshakeInfo := xdsinternal.NewHandshakeInfo(root1, nil, []matcher.StringMatcher{matcher.NewExactStringMatcher(defaultTestCertSAN, false)}, false, "", false, false) |
| 622 | // We need to repeat most of what newTestContextWithHandshakeInfo() does |
| 623 | // here because we need access to the underlying HandshakeInfo so that we |
| 624 | // can update it before the next call to ClientHandshake(). |
| 625 | var hiPtr atomic.Pointer[xdsinternal.HandshakeInfo] |
| 626 | hiPtr.Store(handshakeInfo) |
| 627 | addr := xdsinternal.SetHandshakeInfo(resolver.Address{}, &hiPtr) |
| 628 | ctx = icredentials.NewClientHandshakeInfoContext(ctx, credentials.ClientHandshakeInfo{Attributes: addr.Attributes}) |
| 629 | if _, _, err := creds.ClientHandshake(ctx, authority, conn); err == nil { |
| 630 | t.Fatal("ClientHandshake() succeeded when expected to fail") |
| 631 | } |
| 632 | // Drain the result channel on the test server so that we can inspect the |
| 633 | // result for the next handshake. |
| 634 | _, err = ts.hsResult.Receive(ctx) |
| 635 | if err != nil { |
| 636 | t.Errorf("testServer failed to return handshake result: %v", err) |
| 637 | } |
| 638 | |
| 639 | conn, err = net.Dial("tcp", ts.address) |
| 640 | if err != nil { |
| 641 | t.Fatalf("net.Dial(%s) failed: %v", ts.address, err) |
| 642 | } |
| 643 | defer conn.Close() |
| 644 | |
| 645 | // Create a new root provider which uses the correct trust roots. And update |
| 646 | // the HandshakeInfo with the new provider. |
| 647 | root2 := makeRootProvider(t, "x509/server_ca_cert.pem") |
| 648 | handshakeInfo = xdsinternal.NewHandshakeInfo(root2, nil, []matcher.StringMatcher{matcher.NewExactStringMatcher(defaultTestCertSAN, false)}, false, "", false, false) |
| 649 | // Update the existing pointer, which address attribute will continue to |
| 650 | // point to. |
| 651 | hiPtr.Store(handshakeInfo) |
| 652 | _, ai, err := creds.ClientHandshake(ctx, authority, conn) |
| 653 | if err != nil { |
| 654 | t.Fatalf("ClientHandshake() returned failed: %q", err) |
| 655 | } |
| 656 | if err := compareAuthInfo(ctx, ts, ai); err != nil { |
| 657 | t.Fatal(err) |
nothing calls this directly
no test coverage detected