Skip to content

Commit 2bd74b2

Browse files
authored
credentials: fix behavior of grpc.WithAuthority and credential handshake precedence (#8488)
1 parent 9fa3267 commit 2bd74b2

File tree

12 files changed

+62
-36
lines changed

12 files changed

+62
-36
lines changed

clientconn.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1824,7 +1824,7 @@ func (cc *ClientConn) initAuthority() error {
18241824
} else if auth, ok := cc.resolverBuilder.(resolver.AuthorityOverrider); ok {
18251825
cc.authority = auth.OverrideAuthority(cc.parsedTarget)
18261826
} else if strings.HasPrefix(endpoint, ":") {
1827-
cc.authority = "localhost" + endpoint
1827+
cc.authority = "localhost" + encodeAuthority(endpoint)
18281828
} else {
18291829
cc.authority = encodeAuthority(endpoint)
18301830
}

credentials/alts/alts_test.go

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -153,9 +153,6 @@ func (s) TestInfo(t *testing.T) {
153153
// use NewServerCreds and not NewClientCreds.
154154
c := NewServerCreds(DefaultServerOptions())
155155
info := c.Info()
156-
if got, want := info.ProtocolVersion, ""; got != want {
157-
t.Errorf("info.ProtocolVersion=%v, want %v", got, want)
158-
}
159156
if got, want := info.SecurityProtocol, "alts"; got != want {
160157
t.Errorf("info.SecurityProtocol=%v, want %v", got, want)
161158
}

credentials/credentials.go

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -96,10 +96,11 @@ func (c CommonAuthInfo) GetCommonAuthInfo() CommonAuthInfo {
9696
return c
9797
}
9898

99-
// ProtocolInfo provides information regarding the gRPC wire protocol version,
100-
// security protocol, security protocol version in use, server name, etc.
99+
// ProtocolInfo provides static information regarding transport credentials.
101100
type ProtocolInfo struct {
102101
// ProtocolVersion is the gRPC wire protocol version.
102+
//
103+
// Deprecated: this is unused by gRPC.
103104
ProtocolVersion string
104105
// SecurityProtocol is the security protocol in use.
105106
SecurityProtocol string
@@ -109,7 +110,16 @@ type ProtocolInfo struct {
109110
//
110111
// Deprecated: please use Peer.AuthInfo.
111112
SecurityVersion string
112-
// ServerName is the user-configured server name.
113+
// ServerName is the user-configured server name. If set, this overrides
114+
// the default :authority header used for all RPCs on the channel using the
115+
// containing credentials, unless grpc.WithAuthority is set on the channel,
116+
// in which case that setting will take precedence.
117+
//
118+
// This must be a valid `:authority` header according to
119+
// [RFC3986](https://datatracker.ietf.org/doc/html/rfc3986#section-3.2).
120+
//
121+
// Deprecated: Users should use grpc.WithAuthority to override the authority
122+
// on a channel instead of configuring the credentials.
113123
ServerName string
114124
}
115125

@@ -173,12 +183,17 @@ type TransportCredentials interface {
173183
// Clone makes a copy of this TransportCredentials.
174184
Clone() TransportCredentials
175185
// OverrideServerName specifies the value used for the following:
186+
//
176187
// - verifying the hostname on the returned certificates
177188
// - as SNI in the client's handshake to support virtual hosting
178189
// - as the value for `:authority` header at stream creation time
179190
//
180-
// Deprecated: use grpc.WithAuthority instead. Will be supported
181-
// throughout 1.x.
191+
// The provided string should be a valid `:authority` header according to
192+
// [RFC3986](https://datatracker.ietf.org/doc/html/rfc3986#section-3.2).
193+
//
194+
// Deprecated: this method is unused by gRPC. Users should use
195+
// grpc.WithAuthority to override the authority on a channel instead of
196+
// configuring the credentials.
182197
OverrideServerName(string) error
183198
}
184199

credentials/tls.go

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -110,14 +110,14 @@ func (c tlsCreds) Info() ProtocolInfo {
110110
func (c *tlsCreds) ClientHandshake(ctx context.Context, authority string, rawConn net.Conn) (_ net.Conn, _ AuthInfo, err error) {
111111
// use local cfg to avoid clobbering ServerName if using multiple endpoints
112112
cfg := credinternal.CloneTLSConfig(c.config)
113-
if cfg.ServerName == "" {
114-
serverName, _, err := net.SplitHostPort(authority)
115-
if err != nil {
116-
// If the authority had no host port or if the authority cannot be parsed, use it as-is.
117-
serverName = authority
118-
}
119-
cfg.ServerName = serverName
113+
114+
serverName, _, err := net.SplitHostPort(authority)
115+
if err != nil {
116+
// If the authority had no host port or if the authority cannot be parsed, use it as-is.
117+
serverName = authority
120118
}
119+
cfg.ServerName = serverName
120+
121121
conn := tls.Client(rawConn, cfg)
122122
errChannel := make(chan error, 1)
123123
go func() {
@@ -259,9 +259,11 @@ func applyDefaults(c *tls.Config) *tls.Config {
259259
// certificates to establish the identity of the client need to be included in
260260
// the credentials (eg: for mTLS), use NewTLS instead, where a complete
261261
// tls.Config can be specified.
262-
// serverNameOverride is for testing only. If set to a non empty string,
263-
// it will override the virtual host name of authority (e.g. :authority header
264-
// field) in requests.
262+
//
263+
// serverNameOverride is for testing only. If set to a non empty string, it will
264+
// override the virtual host name of authority (e.g. :authority header field) in
265+
// requests. Users should use grpc.WithAuthority passed to grpc.NewClient to
266+
// override the authority of the client instead.
265267
func NewClientTLSFromCert(cp *x509.CertPool, serverNameOverride string) TransportCredentials {
266268
return NewTLS(&tls.Config{ServerName: serverNameOverride, RootCAs: cp})
267269
}
@@ -271,9 +273,11 @@ func NewClientTLSFromCert(cp *x509.CertPool, serverNameOverride string) Transpor
271273
// certificates to establish the identity of the client need to be included in
272274
// the credentials (eg: for mTLS), use NewTLS instead, where a complete
273275
// tls.Config can be specified.
274-
// serverNameOverride is for testing only. If set to a non empty string,
275-
// it will override the virtual host name of authority (e.g. :authority header
276-
// field) in requests.
276+
//
277+
// serverNameOverride is for testing only. If set to a non empty string, it will
278+
// override the virtual host name of authority (e.g. :authority header field) in
279+
// requests. Users should use grpc.WithAuthority passed to grpc.NewClient to
280+
// override the authority of the client instead.
277281
func NewClientTLSFromFile(certFile, serverNameOverride string) (TransportCredentials, error) {
278282
b, err := os.ReadFile(certFile)
279283
if err != nil {

credentials/xds/xds_client_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ const (
4747
defaultTestTimeout = 1 * time.Second
4848
defaultTestShortTimeout = 10 * time.Millisecond
4949
defaultTestCertSAN = "abc.test.example.com"
50-
authority = "authority"
50+
authority = "x.test.example.com"
5151
)
5252

5353
type s struct {
@@ -61,7 +61,7 @@ func Test(t *testing.T) {
6161
// Helper function to create a real TLS client credentials which is used as
6262
// fallback credentials from multiple tests.
6363
func makeFallbackClientCreds(t *testing.T) credentials.TransportCredentials {
64-
creds, err := credentials.NewClientTLSFromFile(testdata.Path("x509/server_ca_cert.pem"), "x.test.example.com")
64+
creds, err := credentials.NewClientTLSFromFile(testdata.Path("x509/server_ca_cert.pem"), "")
6565
if err != nil {
6666
t.Fatal(err)
6767
}

dialoptions.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -608,6 +608,8 @@ func WithChainStreamInterceptor(interceptors ...StreamClientInterceptor) DialOpt
608608

609609
// WithAuthority returns a DialOption that specifies the value to be used as the
610610
// :authority pseudo-header and as the server name in authentication handshake.
611+
// This overrides all other ways of setting authority on the channel, but can be
612+
// overridden per-call by using grpc.CallAuthority.
611613
func WithAuthority(a string) DialOption {
612614
return newFuncDialOption(func(o *dialOptions) {
613615
o.authority = a

experimental/credentials/tls.go

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -56,14 +56,14 @@ func (c tlsCreds) Info() credentials.ProtocolInfo {
5656
func (c *tlsCreds) ClientHandshake(ctx context.Context, authority string, rawConn net.Conn) (_ net.Conn, _ credentials.AuthInfo, err error) {
5757
// use local cfg to avoid clobbering ServerName if using multiple endpoints
5858
cfg := cloneTLSConfig(c.config)
59-
if cfg.ServerName == "" {
60-
serverName, _, err := net.SplitHostPort(authority)
61-
if err != nil {
62-
// If the authority had no host port or if the authority cannot be parsed, use it as-is.
63-
serverName = authority
64-
}
65-
cfg.ServerName = serverName
59+
60+
serverName, _, err := net.SplitHostPort(authority)
61+
if err != nil {
62+
// If the authority had no host port or if the authority cannot be parsed, use it as-is.
63+
serverName = authority
6664
}
65+
cfg.ServerName = serverName
66+
6767
conn := tls.Client(rawConn, cfg)
6868
errChannel := make(chan error, 1)
6969
go func() {

resolver/resolver.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -332,6 +332,11 @@ type AuthorityOverrider interface {
332332
// OverrideAuthority returns the authority to use for a ClientConn with the
333333
// given target. The implementation must generate it without blocking,
334334
// typically in line, and must keep it unchanged.
335+
//
336+
// The returned string must be a valid ":authority" header value, i.e. be
337+
// encoded according to
338+
// [RFC3986](https://datatracker.ietf.org/doc/html/rfc3986#section-3.2) as
339+
// necessary.
335340
OverrideAuthority(Target) string
336341
}
337342

scripts/vet.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,7 @@ NewSubConn is deprecated:
179179
OverrideServerName is deprecated:
180180
RemoveSubConn is deprecated:
181181
SecurityVersion is deprecated:
182+
.ServerName is deprecated:
182183
stats.PickerUpdated is deprecated:
183184
Target is deprecated: Use the Target field in the BuildOptions instead.
184185
UpdateAddresses is deprecated:

security/advancedtls/advancedtls.go

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -430,11 +430,10 @@ func (c advancedTLSCreds) Info() credentials.ProtocolInfo {
430430
func (c *advancedTLSCreds) ClientHandshake(ctx context.Context, authority string, rawConn net.Conn) (net.Conn, credentials.AuthInfo, error) {
431431
// Use local cfg to avoid clobbering ServerName if using multiple endpoints.
432432
cfg := credinternal.CloneTLSConfig(c.config)
433-
// We return the full authority name to users if ServerName is empty without
434-
// stripping the trailing port.
435-
if cfg.ServerName == "" {
436-
cfg.ServerName = authority
437-
}
433+
// We return the full authority name to users without stripping the trailing
434+
// port.
435+
cfg.ServerName = authority
436+
438437
peerVerifiedChains := CertificateChains{}
439438
cfg.VerifyPeerCertificate = buildVerifyFunc(c, cfg.ServerName, rawConn, &peerVerifiedChains)
440439
conn := tls.Client(rawConn, cfg)

0 commit comments

Comments
 (0)