Remove ServiceMetadata dependency while resolving signing region#7163
Conversation
| endpointParams)); | ||
| List<EndpointAuthScheme> authSchemes = endpoint.attribute(AwsEndpointAttribute.AUTH_SCHEMES); | ||
| if (authSchemes != null && !authSchemes.isEmpty()) { | ||
| EndpointAuthScheme firstScheme = authSchemes.get(0); |
There was a problem hiding this comment.
Should we loop over authSchemes instead of doing get(0)? Some services put sigv4a first on their default endpoints, for example sustainability, partnercentralchannel, and partnercentralrevenuemeasurement. SigV4aAuthScheme is not a SigV4AuthScheme , so for these services the instanceof check fails and the block falls back to the client region, even though a sigv4 scheme with a declared signing region is next in the list. For sustainability with region eu-west-1, the list is [sigv4a, sigv4(signingRegion=us-east-1)]: get(0) gives eu-west-1, looping to the first SigV4AuthScheme gives us-east-1.
Also add test case for same ?
There was a problem hiding this comment.
Hmm, in that case ([sigv4a, sigv4(signingRegion=us-east-1)]), sigv4a is the auth scheme used since it's first and sigv4a gets its signing region from the region set, not from SIGNING_REGION. This check here is only for global services which use sigv4 and need the correct global signing region (e.g., us-east-1 instead of aws-global). For all other cases, client region is the correct value, it matches what ServiceMetadata returned before. Looping to pick up us-east-1 from the sigv4 entry would be a behavioral change for a value that doesn't get used for signing in this scenario.
There was a problem hiding this comment.
Thanks for the explanation
Can you please show me a table with regions assigned before and after the change for services like sustainability, partnercentralchannel, and partnercentralrevenuemeasurement at the build time ?
| builder.lazyOptionIfAbsent( | ||
| AwsClientOption.SIGNING_REGION, | ||
| c -> { | ||
| Region region = c.get(AwsClientOption.AWS_REGION); |
There was a problem hiding this comment.
Nit/ Good to have : Should we move the endpoint-to-signing-region extraction into a shared @SdkProtectedApi helper in aws-core, for example a static method on the existing AwsEndpointProviderUtils or AwsEndpointAuthSchemeUtils Or any suitable util class? The generated block then shrinks to params construction plus one call. This gives one place to fix scheme election and avoids repeating these multiple lines in every service's generated builder. WDYT ?
There was a problem hiding this comment.
yeah good idea, for now the logic is simple so kept it as-is, but makes sense to extract if we need to change it later. Will keep in mind.
…pal/remove-servicemetadata-usage-from-signing-region-resolution
| endpointParams)); | ||
| List<EndpointAuthScheme> authSchemes = endpoint.attribute(AwsEndpointAttribute.AUTH_SCHEMES); | ||
| if (authSchemes != null && !authSchemes.isEmpty()) { | ||
| EndpointAuthScheme firstScheme = authSchemes.get(0); |
There was a problem hiding this comment.
Thanks for the explanation
Can you please show me a table with regions assigned before and after the change for services like sustainability, partnercentralchannel, and partnercentralrevenuemeasurement at the build time ?
| endpointParams)); | ||
| List<EndpointAuthScheme> authSchemes = endpoint.attribute(AwsEndpointAttribute.AUTH_SCHEMES); | ||
| if (authSchemes != null && !authSchemes.isEmpty()) { | ||
| EndpointAuthScheme firstScheme = authSchemes.get(0); |
There was a problem hiding this comment.
I think we should iterate the authSchemes here and look for Sigv4. For a service with Sigv4a and Sigv4, sigv4a can appear first.
There was a problem hiding this comment.
Yeah, semantically that is right, iterating to find the SigV4 entry makes sense since SIGNING_REGION is a SigV4 concept. For a service like Sustainability that returns [sigv4a, sigv4(signingRegion=us-east-1)], iterating would give us us-east-1.
But the previous ServiceMetadata behavior only returned a different signing region for global services (like aws-global - us-east-1 for IAM/Route53). For services like Sustainability that aren't even in endpoints.json, ServiceMetadata just returned client region as-is. So get(0) falling through to client region actually preserves
parity with what customers were getting before.
Since this value gets overridden at request time by EndpointResolutionStage anyway, this build-time value only matters for custom interceptors or legacy signers that read SIGNING_REGION early, I kept it matching the old behavior.
| return ClientEndpointProvider.create(clientEndpointUri, false); | ||
| }); | ||
| builder.lazyOptionIfAbsent( | ||
| AwsClientOption.SIGNING_REGION, |
There was a problem hiding this comment.
This block is fully duplicating what we're doing in the CLIENT_ENDPOINT_PROVIDER block to get the clientEndpointUri right? Is there a reasonable way we could reduce that duplication and only resolve the endpoint once per initialization?
Maybe cache the resolved endpoint (not the url, the result w/ auth scheme as well) in a local lazy?
There was a problem hiding this comment.
Yeah I looked into this. The challenge is these are independent lazyOptionIfAbsent blocks - each lambda receives its own LazyValueSource (c) which is the only way to read config values like region and fips. so we can't share a resolved endpoint between them because the config reader doesn't exist outside the lambdas. So couldnt find a better way to do this rather than duplicating :(
Motivation and Context
resolveSigningRegion()inAwsDefaultClientBuilderusesServiceMetadata.of(serviceEndpointPrefix()).signingRegion(region)to determine the signing region at client build time. This loads per-service metadata classes generated from endpoints.json, adding unnecessary class loading overhead to client initialization.This signing region is a build-time that gets overridden at request time by EndpointResolutionStage, which resolves the correct signing region from the service's endpoint rules. The build-time value is still needed for validation (client won't build without it) and as an initial value in execution attributes for customers with custom interceptors or overridden signers that read SIGNING_REGION before pipeline stages run.
Modifications
Testing
Added unit tests in DefaultAwsClientBuilderTest:
resolveSigningRegion_withGlobalRegion_resolvesCorrectlyFromEndpointRules — verifies endpoint rules correctly resolve AWS_GLOBAL → us-east-1 for global services
signingRegionFromEndpointRules_fallsBackToClientRegionOnFailure — verifies fallback to client region when endpoint resolution doesn't set signing region
Screenshots (if appropriate)
Types of changes
Checklist
mvn installsucceedsscripts/new-changescript and following the instructions. Commit the new file created by the script in.changes/next-releasewith your changes.License