diff --git a/packages/aws-sdk-signers/src/aws_sdk_signers/interfaces/identity.py b/packages/aws-sdk-signers/src/aws_sdk_signers/interfaces/identity.py index 4ab4a9551..d5599ef90 100644 --- a/packages/aws-sdk-signers/src/aws_sdk_signers/interfaces/identity.py +++ b/packages/aws-sdk-signers/src/aws_sdk_signers/interfaces/identity.py @@ -4,7 +4,7 @@ from __future__ import annotations from datetime import datetime -from typing import Protocol +from typing import Protocol, runtime_checkable class Identity(Protocol): @@ -18,3 +18,24 @@ class Identity(Protocol): def is_expired(self) -> bool: """Whether the identity is expired.""" ... + + +@runtime_checkable +class AWSCredentialsIdentity(Protocol): + """AWS Credentials Identity.""" + + # The access key ID. + access_key_id: str + + # The secret access key. + secret_access_key: str + + # The session token. + session_token: str | None + + expiration: datetime | None = None + + @property + def is_expired(self) -> bool: + """Whether the identity is expired.""" + ... diff --git a/packages/aws-sdk-signers/src/aws_sdk_signers/signers.py b/packages/aws-sdk-signers/src/aws_sdk_signers/signers.py index 279528ea4..2740b4dbc 100644 --- a/packages/aws-sdk-signers/src/aws_sdk_signers/signers.py +++ b/packages/aws-sdk-signers/src/aws_sdk_signers/signers.py @@ -15,6 +15,7 @@ from .interfaces.io import AsyncSeekable, Seekable from ._http import URI, AWSRequest, Field from ._identity import AWSCredentialIdentity +from .interfaces.identity import AWSCredentialsIdentity as _AWSCredentialsIdentity from ._io import AsyncBytesReader from .exceptions import AWSSDKWarning, MissingExpectedParameterException @@ -49,14 +50,14 @@ def sign( self, *, signing_properties: SigV4SigningProperties, - request: AWSRequest, + http_request: AWSRequest, identity: AWSCredentialIdentity, ) -> AWSRequest: """Generate and apply a SigV4 Signature to a copy of the supplied request. :param signing_properties: SigV4SigningProperties to define signing primitives such as the target service, region, and date. - :param request: An AWSRequest to sign prior to sending to the service. + :param http_request: An AWSRequest to sign prior to sending to the service. :param identity: A set of credentials representing an AWS Identity or role capacity. """ @@ -68,7 +69,7 @@ def sign( ) assert "date" in new_signing_properties - new_request = self._generate_new_request(request=request) + new_request = self._generate_new_request(request=http_request) self._apply_required_fields( request=new_request, signing_properties=new_signing_properties, @@ -159,7 +160,7 @@ def _hash(self, key: bytes, value: str) -> bytes: def _validate_identity(self, *, identity: AWSCredentialIdentity) -> None: """Perform runtime and expiration checks before attempting signing.""" - if not isinstance(identity, AWSCredentialIdentity): # pyright: ignore + if not isinstance(identity, _AWSCredentialsIdentity): # pyright: ignore raise ValueError( "Received unexpected value for identity parameter. Expected " f"AWSCredentialIdentity but received {type(identity)}." @@ -413,14 +414,14 @@ async def sign( self, *, signing_properties: SigV4SigningProperties, - request: AWSRequest, + http_request: AWSRequest, identity: AWSCredentialIdentity, ) -> AWSRequest: """Generate and apply a SigV4 Signature to a copy of the supplied request. :param signing_properties: SigV4SigningProperties to define signing primitives such as the target service, region, and date. - :param request: An AWSRequest to sign prior to sending to the service. + :param http_request: An AWSRequest to sign prior to sending to the service. :param identity: A set of credentials representing an AWS Identity or role capacity. """ @@ -431,7 +432,7 @@ async def sign( new_signing_properties = await self._normalize_signing_properties( signing_properties=signing_properties ) - new_request = await self._generate_new_request(request=request) + new_request = await self._generate_new_request(request=http_request) await self._apply_required_fields( request=new_request, signing_properties=new_signing_properties, @@ -441,7 +442,7 @@ async def sign( # Construct core signing components canonical_request = await self.canonical_request( signing_properties=signing_properties, - request=request, + request=http_request, ) string_to_sign = await self.string_to_sign( canonical_request=canonical_request, @@ -453,7 +454,7 @@ async def sign( signing_properties=new_signing_properties, ) - signing_fields = await self._normalize_signing_fields(request=request) + signing_fields = await self._normalize_signing_fields(request=http_request) credential_scope = await self._scope(signing_properties=new_signing_properties) credential = f"{identity.access_key_id}/{credential_scope}" authorization = await self.generate_authorization_field( @@ -522,7 +523,7 @@ async def _hash(self, key: bytes, value: str) -> bytes: async def _validate_identity(self, *, identity: AWSCredentialIdentity) -> None: """Perform runtime and expiration checks before attempting signing.""" - if not isinstance(identity, AWSCredentialIdentity): # pyright: ignore + if not isinstance(identity, _AWSCredentialsIdentity): # pyright: ignore raise ValueError( "Received unexpected value for identity parameter. Expected " f"AWSCredentialIdentity but received {type(identity)}." diff --git a/packages/aws-sdk-signers/tests/unit/auth/test_sigv4.py b/packages/aws-sdk-signers/tests/unit/auth/test_sigv4.py index 49dda1269..fe636daf7 100644 --- a/packages/aws-sdk-signers/tests/unit/auth/test_sigv4.py +++ b/packages/aws-sdk-signers/tests/unit/auth/test_sigv4.py @@ -115,7 +115,7 @@ def _test_signature_version_4_sync(test_case_name: str, signer: SigV4Signer) -> with pytest.warns(AWSSDKWarning): signed_request = signer.sign( signing_properties=signing_props, - request=request, + http_request=request, identity=test_case.credentials, ) assert ( @@ -154,7 +154,7 @@ async def _test_signature_version_4_async( with pytest.warns(AWSSDKWarning): signed_request = await signer.sign( signing_properties=signing_props, - request=request, + http_request=request, identity=test_case.credentials, ) assert ( diff --git a/packages/aws-sdk-signers/tests/unit/test_signers.py b/packages/aws-sdk-signers/tests/unit/test_signers.py index 3b70c97db..68e60f9ff 100644 --- a/packages/aws-sdk-signers/tests/unit/test_signers.py +++ b/packages/aws-sdk-signers/tests/unit/test_signers.py @@ -67,7 +67,7 @@ def test_sign( ) -> None: signed_request = self.SIGV4_SYNC_SIGNER.sign( signing_properties=signing_properties, - request=aws_request, + http_request=aws_request, identity=aws_identity, ) assert isinstance(signed_request, AWSRequest) @@ -86,7 +86,7 @@ def test_sign_with_invalid_identity( with pytest.raises(ValueError): self.SIGV4_SYNC_SIGNER.sign( signing_properties=signing_properties, - request=aws_request, + http_request=aws_request, identity=identity, ) @@ -102,7 +102,7 @@ def test_sign_with_expired_identity( with pytest.raises(ValueError): self.SIGV4_SYNC_SIGNER.sign( signing_properties=signing_properties, - request=aws_request, + http_request=aws_request, identity=identity, ) @@ -118,7 +118,7 @@ async def test_sign( ) -> None: signed_request = await self.SIGV4_ASYNC_SIGNER.sign( signing_properties=signing_properties, - request=aws_request, + http_request=aws_request, identity=aws_identity, ) assert isinstance(signed_request, AWSRequest) @@ -137,7 +137,7 @@ async def test_sign_with_invalid_identity( with pytest.raises(ValueError): await self.SIGV4_ASYNC_SIGNER.sign( signing_properties=signing_properties, - request=aws_request, + http_request=aws_request, identity=identity, ) @@ -153,6 +153,6 @@ async def test_sign_with_expired_identity( with pytest.raises(ValueError): await self.SIGV4_ASYNC_SIGNER.sign( signing_properties=signing_properties, - request=aws_request, + http_request=aws_request, identity=identity, )