Skip to content

fix: S2A- Check if a default endpoint has been set #3784

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged

Conversation

rmehta19
Copy link
Contributor

@rmehta19 rmehta19 commented May 6, 2025

Certain handwritten client libraries set this field to the (TLS) endpoint via GrpcTransportOptions.setUpChannelProvider.

This isn't really a custom endpoint, so we should be able to use S2A when this is set.

Example with Cloud Logging: https://github.com/googleapis/java-logging/blob/644ebd756d44ffc02b58aa30d9a07c8afe700981/google-cloud-logging/src/main/java/com/google/cloud/logging/spi/v2/GrpcLoggingRpc.java#L137

@product-auto-label product-auto-label bot added the size: s Pull request size is small. label May 6, 2025
@rmehta19
Copy link
Contributor Author

rmehta19 commented May 7, 2025

@lqiu96 , would you be able to review this? Thanks!

@lqiu96
Copy link
Contributor

lqiu96 commented May 8, 2025

Certain handwritten client libraries set this field to the (TLS) endpoint via GrpcTransportOptions.setUpChannelProvider.

I see, I wasn't aware of this use case. However, if a user does create their own TransportChannelProvider with a custom endpoint, then it wouldn't skip S2A.

Can you remind me again what the original rationale was for skipping a custom endpoint?

@rmehta19
Copy link
Contributor Author

Can you remind me again what the original rationale was for skipping a custom endpoint?

When a user is setting a custom endpoint, we can't be sure this is a MTLS endpoint, therefore we can't use S2A. We only want to use S2A when we can use the MTLS endpoint.

However, if a user does create their own TransportChannelProvider with a custom endpoint, then it wouldn't skip S2A.

This is true, if a hw client library does this (say they set it to something foo.xyz.com) then S2A wouldn't get skipped, and S2A would be used to connect to MTLS endpoint of api (foo.mtls.googleapis.com) which isn't our desired behavior (we want to respect custom set endpoint and skip S2A in this case). Perhaps we could add some extra field (GAXProvidedEndpoint) to the TransportChannelProvider interface and GrpcTransportOptions.setUpChannelProvider can set that field instead? Then we could keep the S2A logic in EndpointContext as is. WDYT @lqiu96?

@rmehta19
Copy link
Contributor Author

Friendly ping on this @lqiu96. Thank you!

@@ -327,8 +327,7 @@ boolean shouldUseS2A() {
}

// If a custom endpoint is being used, skip S2A.
if (!Strings.isNullOrEmpty(clientSettingsEndpoint())
|| !Strings.isNullOrEmpty(transportChannelProviderEndpoint())) {
if (!Strings.isNullOrEmpty(clientSettingsEndpoint())) {
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm worried that this may only end up potentially resolving the issue for the GrpcTransportOptions.setUpChannelProvider case. IIRC, resolveEndpoint()'s logic still revolves around if either clientSettings' endpoint or transportChannelProvider's endpoint is set, and if so, then that's the resolved endpoint.

I'm worried that it would end up with s2a being enabled with the resolved endpoint still being the one configured in GrpcTransportOptions.setUpChannelProvider

Copy link
Contributor

Choose a reason for hiding this comment

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

Gax and the generator no longer provide a default non-mtls endpoint for the client libraries. The "default" endpoint that is intended to be used is constructed inside the EndpointContext. If you want to check, you can theoretically just check if clientSettingsEndpoint or transportChannelEndpoint == buildEndpointTemplate(serviceName(), resolvedUniverseDomain())

Copy link
Contributor Author

@rmehta19 rmehta19 May 28, 2025

Choose a reason for hiding this comment

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

I'm worried that it would end up with s2a being enabled with the resolved endpoint still being the one configured in GrpcTransportOptions.setUpChannelProvider

I believe our logic in InstantiatingGrpcChannelProvider prevents this from happening. If S2A is enabled, we use the mtlsEndpoint (that is plumbed separately from the endpoint; endpoint == resolvedEndpoint()):

if (useS2A) {
channelCredentials = createS2ASecuredChannelCredentials();
}
if (channelCredentials != null) {
// Create the channel using S2A-secured channel credentials.
if (mtlsS2ACallCredentials != null) {
// Set {@code mtlsS2ACallCredentials} to be per-RPC call credentials,
// which will be used to fetch MTLS_S2A hard bound tokens from the metdata server.
channelCredentials =
CompositeChannelCredentials.create(channelCredentials, mtlsS2ACallCredentials);
}
// Connect to the MTLS endpoint when using S2A because S2A is used to perform an MTLS
// handshake.
builder = Grpc.newChannelBuilder(mtlsEndpoint, channelCredentials);

WDYT @lqiu96 ?

Copy link
Contributor

Choose a reason for hiding this comment

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

Oh right, there is the custom logic for S2A. What about the case if a user has a custom TransportChannelProvider with a non-mtls endpoint configured? IIUC above, the intention would be not use S2A, but our checks in EndpointContext would have shouldUseS2A as true.

Copy link
Contributor Author

@rmehta19 rmehta19 May 29, 2025

Choose a reason for hiding this comment

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

Oh right, there is the custom logic for S2A. What about the case if a user has a custom TransportChannelProvider with a non-mtls endpoint configured? IIUC above, the intention would be not use S2A, but our checks in EndpointContext would have shouldUseS2A as true.

It is correct that if the user is intentionally setting a custom endpoint via their own TransportChannelProvider, that we want to skip S2A. With the latest changes, if they are setting the custom endpoint to be the same as the default non-mtls endpoint, we would end up using S2A. I believe this is ok, as my understanding is that if the user is setting an endpoint, it is usually something different than the default non-mtls endpoint.

Gax and the generator no longer provide a default non-mtls endpoint for the client libraries. The "default" endpoint that is intended to be used is constructed inside the EndpointContext. If you want to check, you can theoretically just check if clientSettingsEndpoint or transportChannelEndpoint == buildEndpointTemplate(serviceName(), resolvedUniverseDomain())

Apologies, I missed this comment of yours. Thanks for bringing this up! I tested this out internally and this works. The latest commit contains this logic, WDYT @lqiu96

@rmehta19 rmehta19 force-pushed the dont-check-transport-channel-endpoint branch from 981454b to 6ad5b8e Compare May 29, 2025 17:29
|| !Strings.isNullOrEmpty(transportChannelProviderEndpoint())) {
|| (!Strings.isNullOrEmpty(transportChannelProviderEndpoint())
&& !buildEndpointTemplate(serviceName(), resolvedUniverseDomain())
.contains(transportChannelProviderEndpoint()))) {
Copy link
Contributor Author

@rmehta19 rmehta19 May 29, 2025

Choose a reason for hiding this comment

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

Adding this "contains" logic, since buildEndpointTemplate adds 443 (https) as default port, and GrpcTransportOptions.setUpChannelProvider, for example, just sets the host.

In this way, we are sure to respect a custom endpoint set via TransportChannelProvider. For example, if client specified transportChannelProviderEndpoint as the http endpoint (default endpoint + port 80), shouldUseS2A would evaluate to false.

@lqiu96

Copy link
Contributor

Choose a reason for hiding this comment

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

Thanks! I think this does resolve the above concern. Could this check for both clientSettings and transportChannelProvider just to be safe? Or is there a specific reason for only doing this for the transportchannelprovider?

I think the contains logic is fine given the concerns with port. The string contains == resolved endpoint may not be completely fool proof (I can't think of counter example off the top of my head), but I think it's safer than removing the check for the transportchannelprovider endpoint.

Hopefully this helps unblock the issue with GrpcTransportOptions

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Could this check for both clientSettings and transportChannelProvider just to be safe? Or is there a specific reason for only doing this for the transportchannelprovider?

I don't see an issue for doing this check for both clientSettingsEndpoint and transportChannelProviderEndpoint, the reason I initially did it for the latter was because I ran into it in the GrpcTransportOptions case :). I tested this internally and verified that doing this check on both is ok. Added this in the latest commit.

Copy link
Contributor

Choose a reason for hiding this comment

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

FYI, Bigtable has custom code to setEndpoint via settings which I think would be an issue: https://github.com/googleapis/java-bigtable/blob/8d3dca43224179829829bcf91972610c666b130b/google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/data/v2/stub/EnhancedBigtableStubSettings.java#L807

May be an issue in the future as it auto sets a default. But you would prefer to handle those cases later on, then we can just proceed with this to unblock logging.

lqiu96
lqiu96 previously approved these changes May 29, 2025
Copy link
Contributor

@lqiu96 lqiu96 left a comment

Choose a reason for hiding this comment

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

Code LGTM, added a small comment if you could take a look.

I think it should be fine, but we can try to address any additional things after more testing.

@rmehta19
Copy link
Contributor Author

Code LGTM, added a small comment if you could take a look.

I think it should be fine, but we can try to address any additional things after more testing.

Thanks @lqiu96 ! Addressed your latest comment. PTAL when you get a chance.

@lqiu96
Copy link
Contributor

lqiu96 commented May 30, 2025

/gcbrun

@lqiu96
Copy link
Contributor

lqiu96 commented May 30, 2025

Re-running the failed showcase test. Not sure if it's flaky or not and we can see after this run.

Also, can you update the title to follow conventioncommits with the update changes? i.e. fix: S2A- Check if a default endpoint has been set or however you see fit. Thanks!

@rmehta19 rmehta19 changed the title s2a fix: don't check transport channel provider endpoint. fix: S2A- Check if a default endpoint has been set May 30, 2025
@rmehta19
Copy link
Contributor Author

Re-running the failed showcase test. Not sure if it's flaky or not and we can see after this run.

Also, can you update the title to follow conventioncommits with the update changes? i.e. fix: S2A- Check if a default endpoint has been set or however you see fit. Thanks!

Done, thanks @lqiu96 !

@lqiu96
Copy link
Contributor

lqiu96 commented Jun 2, 2025

Seeing some odd showcase errors. Can you try merging the latest into the branch and we can see if that resolves the CI issues?

@rmehta19
Copy link
Contributor Author

rmehta19 commented Jun 2, 2025

Seeing some odd showcase errors. Can you try merging the latest into the branch and we can see if that resolves the CI issues?

Merged the latest changes from main @lqiu96

@lqiu96
Copy link
Contributor

lqiu96 commented Jun 2, 2025

/gcbrun

@lqiu96 lqiu96 enabled auto-merge (squash) June 2, 2025 17:11
@lqiu96
Copy link
Contributor

lqiu96 commented Jun 2, 2025

Seeing some odd showcase errors. Can you try merging the latest into the branch and we can see if that resolves the CI issues?

Merged the latest changes from main @lqiu96

Thanks! Running the graalvm checks and should auto-merge after success

@lqiu96 lqiu96 merged commit 5b2ab82 into googleapis:main Jun 2, 2025
51 of 53 checks passed
jinseopkim0 pushed a commit that referenced this pull request Jun 13, 2025
🤖 I have created a release *beep* *boop*
---


<details><summary>2.59.1</summary>

##
[2.59.1](v2.59.0...v2.59.1)
(2025-06-12)


### Bug Fixes

* S2A- Check if a default endpoint has been set
([#3784](#3784))
([5b2ab82](5b2ab82))


### Dependencies

* update google auth library dependencies to v1.37.0
([#3830](#3830))
([8bf9d3c](8bf9d3c))
</details>

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
size: s Pull request size is small.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants