Skip to content

Commit

Permalink
Account ID Based Endpoint Routing (#3400)
Browse files Browse the repository at this point in the history
  • Loading branch information
alexgromero authored Feb 21, 2025
1 parent ebec9a3 commit 1941b2b
Show file tree
Hide file tree
Showing 16 changed files with 1,037 additions and 24 deletions.
5 changes: 5 additions & 0 deletions .changes/next-release/feature-Endpoints-14344.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"type": "feature",
"category": "Endpoints",
"description": "Generate and use AWS-account-based endpoints for compatible services when the account ID is available. At launch, DynamoDB is the first and only compatible service. The new endpoint URL pattern will be ``https://<account-id>.ddb.<region>.amazonaws.com``. Additional services may be added in the future. See the documentation for details: https://docs.aws.amazon.com/sdkref/latest/guide/feature-account-endpoints.html"
}
53 changes: 53 additions & 0 deletions botocore/args.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,12 @@
'ec2',
)

VALID_ACCOUNT_ID_ENDPOINT_MODE_CONFIG = (
'preferred',
'disabled',
'required',
)


class ClientArgsCreator:
def __init__(
Expand Down Expand Up @@ -136,6 +142,7 @@ def get_client_args(
configured_endpoint_url = final_args['configured_endpoint_url']
signing_region = endpoint_config['signing_region']
endpoint_region_name = endpoint_config['region_name']
account_id_endpoint_mode = config_kwargs['account_id_endpoint_mode']

event_emitter = copy.copy(self._event_emitter)
signer = RequestSigner(
Expand Down Expand Up @@ -183,6 +190,8 @@ def get_client_args(
is_secure,
endpoint_bridge,
event_emitter,
credentials,
account_id_endpoint_mode,
)

# Copy the session's user agent factory and adds client configuration.
Expand Down Expand Up @@ -294,13 +303,15 @@ def compute_client_args(
response_checksum_validation=(
client_config.response_checksum_validation
),
account_id_endpoint_mode=client_config.account_id_endpoint_mode,
)
self._compute_retry_config(config_kwargs)
self._compute_connect_timeout(config_kwargs)
self._compute_user_agent_appid_config(config_kwargs)
self._compute_request_compression_config(config_kwargs)
self._compute_sigv4a_signing_region_set_config(config_kwargs)
self._compute_checksum_config(config_kwargs)
self._compute_account_id_endpoint_mode_config(config_kwargs)
s3_config = self.compute_s3_config(client_config)

is_s3_service = self._is_s3_service(service_name)
Expand Down Expand Up @@ -645,6 +656,8 @@ def _build_endpoint_resolver(
is_secure,
endpoint_bridge,
event_emitter,
credentials,
account_id_endpoint_mode,
):
if endpoints_ruleset_data is None:
return None
Expand All @@ -669,6 +682,8 @@ def _build_endpoint_resolver(
endpoint_bridge=endpoint_bridge,
client_endpoint_url=endpoint_url,
legacy_endpoint_url=endpoint.host,
credentials=credentials,
account_id_endpoint_mode=account_id_endpoint_mode,
)
# Client context params for s3 conflict with the available settings
# in the `s3` parameter on the `Config` object. If the same parameter
Expand Down Expand Up @@ -704,6 +719,8 @@ def compute_endpoint_resolver_builtin_defaults(
endpoint_bridge,
client_endpoint_url,
legacy_endpoint_url,
credentials,
account_id_endpoint_mode,
):
# EndpointRulesetResolver rulesets may accept an "SDK::Endpoint" as
# input. If the endpoint_url argument of create_client() is set, it
Expand Down Expand Up @@ -778,6 +795,12 @@ def compute_endpoint_resolver_builtin_defaults(
's3_disable_multiregion_access_points', False
),
EPRBuiltins.SDK_ENDPOINT: given_endpoint,
EPRBuiltins.ACCOUNT_ID: credentials.get_deferred_property(
'account_id'
)
if credentials
else None,
EPRBuiltins.ACCOUNT_ID_ENDPOINT_MODE: account_id_endpoint_mode,
}

def _compute_user_agent_appid_config(self, config_kwargs):
Expand Down Expand Up @@ -855,3 +878,33 @@ def _handle_checksum_config(
valid_options=valid_options,
)
config_kwargs[config_key] = value

def _compute_account_id_endpoint_mode_config(self, config_kwargs):
config_key = 'account_id_endpoint_mode'

# Disable account id based endpoint routing for unsigned requests
# since there are no credentials to resolve.
signature_version = config_kwargs.get('signature_version')
if signature_version is botocore.UNSIGNED:
config_kwargs[config_key] = 'disabled'
return

account_id_endpoint_mode = config_kwargs.get(config_key)
if account_id_endpoint_mode is None:
account_id_endpoint_mode = self._config_store.get_config_variable(
config_key
)

if isinstance(account_id_endpoint_mode, str):
account_id_endpoint_mode = account_id_endpoint_mode.lower()

if (
account_id_endpoint_mode
not in VALID_ACCOUNT_ID_ENDPOINT_MODE_CONFIG
):
raise botocore.exceptions.InvalidConfigError(
error_msg=f"The configured value '{account_id_endpoint_mode}' for '{config_key}' is "
f"invalid. Valid values are: {VALID_ACCOUNT_ID_ENDPOINT_MODE_CONFIG}."
)

config_kwargs[config_key] = account_id_endpoint_mode
14 changes: 14 additions & 0 deletions botocore/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,19 @@ class Config:
supported and the ``requestValidationModeMember`` member is set to ``ENABLED``.
Defaults to None.
:type account_id_endpoint_mode: str
:param account_id_endpoint_mode: The value used to determine the client's
behavior for account ID based endpoint routing. Valid values are:
* ``preferred`` - The endpoint should include account ID if available.
* ``disabled`` - A resolved endpoint does not include account ID.
* ``required`` - The endpoint must include account ID. If the account ID
isn't available, an exception will be raised.
If a value is not provided, the client will default to ``preferred``.
Defaults to None.
"""

OPTION_DEFAULTS = OrderedDict(
Expand Down Expand Up @@ -297,6 +310,7 @@ class Config:
('sigv4a_signing_region_set', None),
('request_checksum_calculation', None),
('response_checksum_validation', None),
('account_id_endpoint_mode', None),
]
)

Expand Down
6 changes: 6 additions & 0 deletions botocore/configprovider.py
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,12 @@
"when_supported",
None,
),
'account_id_endpoint_mode': (
'account_id_endpoint_mode',
'AWS_ACCOUNT_ID_ENDPOINT_MODE',
'preferred',
None,
),
}

# Evaluate AWS_STS_REGIONAL_ENDPOINTS settings
Expand Down
Loading

0 comments on commit 1941b2b

Please sign in to comment.