Skip to content

Conversation

@dfawley
Copy link
Member

@dfawley dfawley commented Aug 4, 2025

Before this change, credentials would ignore the channel's understanding of the server name if the user configured them to do so. This is a mistake. The credentials should use the channel's setting. The channel already reads the credentials' preference and includes that in its logic.

A summary of how this worked:

  • User creates credentials, optionally configuring a server name override at configuration.
  • Optionally, user calls creds.OverrideServerName, which can/should be implemented such that it affects the server name override. It does this by setting the ProtocolInfo.ServerName field that is returned by its Info method.
  • gRPC has a list of precedence for determining the authority of the channel: grpc.WithAuthority; credentials; name resolver; channel default based on target string.
  • gRPC passes the determined authority to creds.ClientHandshake. The creds should honor the value passed in.

I also tidied up the documentation a bit and added a deprecation notice to ProtocolInfo.ServerName.

@gtcooke94 since this impacts advancedtls.

cc @ejona86 FYI

RELEASE NOTES:

  • credentials: properly apply grpc.WithAuthority as the highest-priority option for setting authority, above the setting in the credentials themselves. Now that this WithAuthority is available, the credentials should not be used to override the authority. Also, properly percent-encode the port (if needed, which is very unlikely) when the target string omits the hostname and only specifies a port (grpc.NewClient(":<port-number-or-name>")).
@dfawley dfawley added this to the 1.75 Release milestone Aug 4, 2025
@dfawley dfawley requested a review from arjan-bal August 4, 2025 23:30
@dfawley dfawley added the Type: Behavior Change Behavior changes not categorized as bugs label Aug 4, 2025
@codecov
Copy link

codecov bot commented Aug 4, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 82.43%. Comparing base (85240a5) to head (ef25aa4).
⚠️ Report is 3 commits behind head on master.

Additional details and impacted files
@@            Coverage Diff             @@
##           master    #8488      +/-   ##
==========================================
- Coverage   82.48%   82.43%   -0.05%     
==========================================
  Files         413      413              
  Lines       40518    40534      +16     
==========================================
- Hits        33422    33415       -7     
- Misses       5738     5759      +21     
- Partials     1358     1360       +2     
Files with missing lines Coverage Δ
clientconn.go 90.52% <100.00%> (-0.28%) ⬇️
credentials/credentials.go 88.57% <ø> (ø)
credentials/tls.go 90.56% <100.00%> (+0.05%) ⬆️
dialoptions.go 87.40% <ø> (ø)
experimental/credentials/tls.go 79.20% <100.00%> (+3.39%) ⬆️
resolver/resolver.go 100.00% <ø> (ø)

... and 24 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
@arjan-bal arjan-bal assigned dfawley and unassigned arjan-bal Aug 5, 2025
@dfawley dfawley assigned arjan-bal and unassigned dfawley Aug 5, 2025
@arjan-bal arjan-bal removed their assignment Aug 5, 2025
// Deprecated: please use Peer.AuthInfo.
SecurityVersion string
// ServerName is the user-configured server name.
// ServerName is the user-configured server name. If set, this overrides
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My first reading of this comment made me think that this is a value that the user can set. But that is not the case. This is a value returned by gRPC to the user. Would it be possible to reword this a little so that it is clear that this only conveys the creds' view of things.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think your initial understanding was correct.

This is returned by the credentials implementation and read by gRPC. The user controls how this is set by configuring the credentials directly.

cc.authority = auth.OverrideAuthority(cc.parsedTarget)
} else if strings.HasPrefix(endpoint, ":") {
cc.authority = "localhost" + endpoint
cc.authority = "localhost" + encodeAuthority(endpoint)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this a breaking change? Should this be release noted?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's a behavior change. Unclear if it's breaking; I would call it a bug fix. I'll mention it in the notes.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added:

Also, properly percent-encode the port (if needed, which is very unlikely) when the target string omits the hostname and only specifies a port (grpc.NewClient(":<port-number-or-name>")).

serverName = authority
}
cfg.ServerName = serverName

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we document on the NewTLS function that config.ServerName is ignored?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not ignored, actually. It's used by the channel in the logic mentioned in the first PR comment, as long as the user didn't manually override the channel's authority.

grpc-go/clientconn.go

Lines 1810 to 1813 in 9fa3267

authorityFromCreds := ""
if creds := dopts.copts.TransportCredentials; creds != nil && creds.Info().ServerName != "" {
authorityFromCreds = creds.Info().ServerName
}

ServerName: c.config.ServerName,

Copy link
Contributor

@gtcooke94 gtcooke94 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This LGTM, I do worry about breakages from small behavior changes, but this is a bug so if a breakage does happen it's probably good in the end to discover it?

cc: @matthewstevenson88 for awareness

@dfawley
Copy link
Member Author

dfawley commented Aug 5, 2025

but this is a bug so if a breakage does happen it's probably good in the end to discover it?

It's definitely a bug in that the credentials override is currently winning against the channel's override for handshaking, but what is used for RPCs is something else. The intent was for grpc.WithAuthority (fairly recently added) to be the highest priority for the channel, with the CallOption taking even high precedence. This change enacts that intent.

Thanks!

@dfawley dfawley merged commit 2bd74b2 into grpc:master Aug 5, 2025
16 checks passed
@dfawley dfawley deleted the credshandshake branch August 5, 2025 22:04
dimpavloff pushed a commit to dimpavloff/grpc-go that referenced this pull request Aug 22, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Type: Behavior Change Behavior changes not categorized as bugs

4 participants