Repository: grpc/grpc-go
File: credentials/credentials_ext_test.go (Go)

Code before:
// AuthType returns the authentication type.
func (testAuthInfoNoValidator) AuthType() string {
	return "test"
}

// testAuthInfoWithValidator implements both credentials.AuthInfo and
// credentials.AuthorityValidator.
type testAuthInfoWithValidator struct{}

// AuthType returns the authentication type.
func (testAuthInfoWithValidator) AuthType() string {
	return "test"
}

// ValidateAuthority implements credentials.AuthorityValidator.
func (testAuthInfoWithValidator) ValidateAuthority(authority string) error {
	if authority == "auth.test.example.com" {
		return nil
	}
	return fmt.Errorf("invalid authority")
}

// testCreds is a test TransportCredentials that can optionally support
// authority validation.
type testCreds struct {
	WithValidator bool
}

// ClientHandshake performs the client-side handshake.
func (c *testCreds) ClientHandshake(ctx context.Context, authority string, rawConn net.Conn) (net.Conn, credentials.AuthInfo, error) {
	if c.WithValidator {
		return rawConn, testAuthInfoWithValidator{}, nil
	}
	return rawConn, testAuthInfoNoValidator{}, nil
}

// ServerHandshake performs the server-side handshake.
func (c *testCreds) ServerHandshake(rawConn net.Conn) (net.Conn, credentials.AuthInfo, error) {
	if c.WithValidator {
		return rawConn, testAuthInfoWithValidator{}, nil
	}
	return rawConn, testAuthInfoNoValidator{}, nil
}

// Clone creates a copy of testCreds.
func (c *testCreds) Clone() credentials.TransportCredentials {
	return &testCreds{WithValidator: c.WithValidator}
}

// Info provides protocol information.
func (c *testCreds) Info() credentials.ProtocolInfo {

Review comment (security):
Since this is the type that creates the `testAuthInfoWithValidator`, you would need to have a field for the supported authority here too.

Doing so makes it clear when reading the test as to what authority is supported by the creds, and what is specified by the test, and therefore whether the case is expected to pass or not.

Code after:
		},
	}
	if err := ss.Start(nil); err != nil {
		t.Fatalf("Error starting endpoint server: %v", err)
	}
	defer ss.Stop()

	cc, err := grpc.NewClient(ss.Address, grpc.WithTransportCredentials(insecure.NewCredentials()))
	if err != nil {
		t.Fatalf("grpc.NewClient(%q) = %v", ss.Address, err)
	}
	defer cc.Close()

	ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout)
	defer cancel()
	if _, err = testgrpc.NewTestServiceClient(cc).EmptyCall(ctx, &testpb.Empty{}, grpc.CallAuthority(authority)); err != nil {
		t.Fatalf("EmptyCall() rpc failed: %v", err)
	}
}

// testAuthInfoNoValidator implements only credentials.AuthInfo and not
// credentials.AuthorityValidator.
type testAuthInfoNoValidator struct{}

// AuthType returns the authentication type.
func (testAuthInfoNoValidator) AuthType() string {
	return "test"
}

// testAuthInfoWithValidator implements both credentials.AuthInfo and
// credentials.AuthorityValidator.
type testAuthInfoWithValidator struct {
	validAuthority string
}

// AuthType returns the authentication type.
func (testAuthInfoWithValidator) AuthType() string {
	return "test"
}

// ValidateAuthority implements credentials.AuthorityValidator.
func (v testAuthInfoWithValidator) ValidateAuthority(authority string) error {
	if authority == v.validAuthority {
		return nil
	}
	return fmt.Errorf("invalid authority %q, want %q", authority, v.validAuthority)
}

// testCreds is a test TransportCredentials that can optionally support
// authority validation.
type testCreds struct {