diff --git a/packages/aws-credentials-http/.changes/next-release/aws-credentials-http-bugfix-bd4ef625870a44faa848494a7489ad19.json b/packages/aws-credentials-http/.changes/next-release/aws-credentials-http-bugfix-bd4ef625870a44faa848494a7489ad19.json new file mode 100644 index 00000000..b786adc3 --- /dev/null +++ b/packages/aws-credentials-http/.changes/next-release/aws-credentials-http-bugfix-bd4ef625870a44faa848494a7489ad19.json @@ -0,0 +1,4 @@ +{ + "type": "bugfix", + "description": "Normalize empty container credential URI query strings to `None`." +} diff --git a/packages/aws-credentials-http/src/aws_credentials_http/resolvers.py b/packages/aws-credentials-http/src/aws_credentials_http/resolvers.py index 1e6a7811..0dd3f8a9 100644 --- a/packages/aws-credentials-http/src/aws_credentials_http/resolvers.py +++ b/packages/aws-credentials-http/src/aws_credentials_http/resolvers.py @@ -95,7 +95,7 @@ async def _resolve_uri_from_env(self) -> URI: host=parsed.hostname or "", port=parsed.port, path=parsed.path, - query=parsed.query, + query=parsed.query or None, ) else: raise SmithyIdentityError( diff --git a/packages/aws-credentials-http/tests/unit/test_resolvers.py b/packages/aws-credentials-http/tests/unit/test_resolvers.py index f5dc5059..292d4d47 100644 --- a/packages/aws-credentials-http/tests/unit/test_resolvers.py +++ b/packages/aws-credentials-http/tests/unit/test_resolvers.py @@ -74,6 +74,35 @@ async def test_resolver_env_full() -> None: ) http_request = http_client.send.call_args_list[0].args[0] assert http_request.destination == expected_url + assert http_request.destination.query is None + _assert_expected_identity(identity) + + +async def test_resolver_env_full_with_query() -> None: + response_body = json.dumps(DEFAULT_RESPONSE_DATA) + http_client = mock_http_client_response(200, response_body.encode()) + + with patch.dict( + os.environ, + { + ContainerCredentialsResolver.ENV_VAR_FULL: ( + "http://169.254.170.23/full?role=task%2Fworker&version=1" + ) + }, + clear=True, + ): + resolver = ContainerCredentialsResolver(http_client) + identity = await resolver.get_identity(properties={}) + + expected_url = URI( + scheme="http", + host="169.254.170.23", + path="/full", + query="role=task%2Fworker&version=1", + ) + http_request = http_client.send.call_args_list[0].args[0] + assert http_request.destination == expected_url + assert http_request.destination.query == "role=task%2Fworker&version=1" _assert_expected_identity(identity) diff --git a/packages/aws-credentials-sts/.changes/next-release/aws-credentials-sts-dependency-f1c7b755958249a394c8fad72970ff83.json b/packages/aws-credentials-sts/.changes/next-release/aws-credentials-sts-dependency-f1c7b755958249a394c8fad72970ff83.json new file mode 100644 index 00000000..a220e70b --- /dev/null +++ b/packages/aws-credentials-sts/.changes/next-release/aws-credentials-sts-dependency-f1c7b755958249a394c8fad72970ff83.json @@ -0,0 +1,4 @@ +{ + "type": "dependency", + "description": "Update STS credential resolution to use the new async client configuration API." +} diff --git a/packages/aws-credentials-sts/src/aws_credentials_sts/resolvers.py b/packages/aws-credentials-sts/src/aws_credentials_sts/resolvers.py index 7aefe003..8e5725b3 100644 --- a/packages/aws-credentials-sts/src/aws_credentials_sts/resolvers.py +++ b/packages/aws-credentials-sts/src/aws_credentials_sts/resolvers.py @@ -126,16 +126,18 @@ async def get_identity( async def _assume_role(self) -> AWSCredentialsIdentity: from aws_sdk_sts.client import AsyncSTSClient - from aws_sdk_sts.config import Config + from aws_sdk_sts.config import AsyncSTSConfig from aws_sdk_sts.models import AssumeRoleInput if self._client is None: + overrides: dict[str, object] = { + "aws_credentials_identity_resolver": self._source_resolver, + "region": self._region, + } + if self._http_client is not None: + overrides["transport"] = self._http_client self._client = AsyncSTSClient( - config=Config( - aws_credentials_identity_resolver=self._source_resolver, - region=self._region, - transport=self._http_client, - ) + config=await AsyncSTSConfig.resolve(**overrides) ) response = await self._client.assume_role(