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

Code before:

var logger = grpclog.Component("credentials")

// TLSInfo contains the auth information for a TLS authenticated connection.
// It implements the AuthInfo interface.
type TLSInfo struct {
	State tls.ConnectionState
	CommonAuthInfo
	// This API is experimental.
	SPIFFEID *url.URL
}

// AuthType returns the type of TLSInfo as a string.
func (t TLSInfo) AuthType() string {
	return "tls"
}

// ValidateAuthority validates the authority by checking it against the peer certificates.
func (t TLSInfo) ValidateAuthority(authority string) error {
	var err error
	for _, cert := range t.State.PeerCertificates {
		if err = cert.VerifyHostname(authority); err == nil {
			return nil
		}
	}
	return fmt.Errorf("credentials: failed to verify authority %s", err)
}

// cipherSuiteLookup returns the string version of a TLS cipher suite ID.
func cipherSuiteLookup(cipherSuiteID uint16) string {
	for _, s := range tls.CipherSuites() {
		if s.ID == cipherSuiteID {
			return s.Name
		}
	}
	for _, s := range tls.InsecureCipherSuites() {
		if s.ID == cipherSuiteID {
			return s.Name
		}
	}
	return fmt.Sprintf("unknown ID: %v", cipherSuiteID)
}

// GetSecurityValue returns security info requested by channelz.
func (t TLSInfo) GetSecurityValue() ChannelzSecurityValue {
	v := &TLSChannelzSecurityValue{
		StandardName: cipherSuiteLookup(t.State.CipherSuite),
	}
	// Currently there's no way to get LocalCertificate info from tls package.
	if len(t.State.PeerCertificates) > 0 {
		v.RemoteCertificate = t.State.PeerCertificates[0].Raw

Review comment (bug):
The `err` variable will only contain the last error here. Should we instead include all errors?

Code after:
const alpnFailureHelpMessage = "If you upgraded from a grpc-go version earlier than 1.67, your TLS connections may have stopped working due to ALPN enforcement. For more details, see: https://github.com/grpc/grpc-go/issues/434"

var logger = grpclog.Component("credentials")

// TLSInfo contains the auth information for a TLS authenticated connection.
// It implements the AuthInfo interface.
type TLSInfo struct {
	State tls.ConnectionState
	CommonAuthInfo
	// This API is experimental.
	SPIFFEID *url.URL
}

// AuthType returns the type of TLSInfo as a string.
func (t TLSInfo) AuthType() string {
	return "tls"
}

// ValidateAuthority validates the provided authority being used to override the
// :authority header by verifying it against the peer certificates. It returns a
// non-nil error if the validation fails.
func (t TLSInfo) ValidateAuthority(authority string) error {
	var errs []error
	for _, cert := range t.State.PeerCertificates {
		var err error
		if err = cert.VerifyHostname(authority); err == nil {
			return nil
		}
		errs = append(errs, err)
	}
	return fmt.Errorf("credentials: invalid authority %q: %v", authority, errors.Join(errs...))
}

// cipherSuiteLookup returns the string version of a TLS cipher suite ID.
func cipherSuiteLookup(cipherSuiteID uint16) string {
	for _, s := range tls.CipherSuites() {
		if s.ID == cipherSuiteID {
			return s.Name
		}
	}
	for _, s := range tls.InsecureCipherSuites() {
		if s.ID == cipherSuiteID {
			return s.Name
		}
	}
	return fmt.Sprintf("unknown ID: %v", cipherSuiteID)
}

// GetSecurityValue returns security info requested by channelz.
func (t TLSInfo) GetSecurityValue() ChannelzSecurityValue {
	v := &TLSChannelzSecurityValue{