boto3-refresh-session 1.3.22__py3-none-any.whl → 2.0.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,10 +1,10 @@
1
- from .custom import CustomRefreshableSession
2
- from .ecs import ECSRefreshableSession
1
+ from .methods.custom import CustomRefreshableSession
2
+ from .methods.ecs import ECSRefreshableSession
3
+ from .methods.sts import STSRefreshableSession
3
4
  from .session import RefreshableSession
4
- from .sts import STSRefreshableSession
5
5
 
6
6
  __all__ = ["RefreshableSession"]
7
- __version__ = "1.3.22"
7
+ __version__ = "2.0.1"
8
8
  __title__ = "boto3-refresh-session"
9
9
  __author__ = "Mike Letts"
10
10
  __maintainer__ = "Mike Letts"
@@ -15,7 +15,7 @@ class BRSError(Exception):
15
15
  return self.message
16
16
 
17
17
  def __repr__(self) -> str:
18
- return f"{self.__class__.__name__}({repr(self.message)})"
18
+ return f"{self.__class__.__name__}({self.message!r})"
19
19
 
20
20
 
21
21
  class BRSWarning(UserWarning):
@@ -35,4 +35,4 @@ class BRSWarning(UserWarning):
35
35
  return self.message
36
36
 
37
37
  def __repr__(self) -> str:
38
- return f"{self.__class__.__name__}({repr(self.message)})"
38
+ return f"{self.__class__.__name__}({self.message!r})"
File without changes
@@ -4,11 +4,12 @@ __all__ = ["CustomRefreshableSession"]
4
4
 
5
5
  from typing import Any, Callable
6
6
 
7
- from .exceptions import BRSError
8
- from .session import BaseRefreshableSession, TemporaryCredentials
7
+ from ..exceptions import BRSError
8
+ from ..session import BaseRefreshableSession
9
+ from ..utils import TemporaryCredentials
9
10
 
10
11
 
11
- class CustomRefreshableSession(BaseRefreshableSession, method="custom"):
12
+ class CustomRefreshableSession(BaseRefreshableSession, registry_key="custom"):
12
13
  """A :class:`boto3.session.Session` object that automatically refreshes
13
14
  temporary credentials returned by a custom credential getter provided
14
15
  by the user. Useful for users with highly sophisticated or idiosyncratic
@@ -74,7 +75,7 @@ class CustomRefreshableSession(BaseRefreshableSession, method="custom"):
74
75
  else {}
75
76
  )
76
77
 
77
- self._refresh_using(
78
+ self.initialize(
78
79
  credentials_method=self._get_credentials,
79
80
  defer_refresh=defer_refresh is not False,
80
81
  refresh_method="custom",
@@ -6,8 +6,9 @@ import os
6
6
 
7
7
  import requests
8
8
 
9
- from .exceptions import BRSError
10
- from .session import BaseRefreshableSession, TemporaryCredentials
9
+ from ..exceptions import BRSError
10
+ from ..session import BaseRefreshableSession
11
+ from ..utils import TemporaryCredentials
11
12
 
12
13
  _ECS_CREDENTIALS_RELATIVE_URI = "AWS_CONTAINER_CREDENTIALS_RELATIVE_URI"
13
14
  _ECS_CREDENTIALS_FULL_URI = "AWS_CONTAINER_CREDENTIALS_FULL_URI"
@@ -15,7 +16,7 @@ _ECS_AUTHORIZATION_TOKEN = "AWS_CONTAINER_AUTHORIZATION_TOKEN"
15
16
  _DEFAULT_ENDPOINT_BASE = "http://169.254.170.2"
16
17
 
17
18
 
18
- class ECSRefreshableSession(BaseRefreshableSession, method="ecs"):
19
+ class ECSRefreshableSession(BaseRefreshableSession, registry_key="ecs"):
19
20
  """A boto3 session that automatically refreshes temporary AWS credentials
20
21
  from the ECS container credentials metadata endpoint.
21
22
 
@@ -40,7 +41,7 @@ class ECSRefreshableSession(BaseRefreshableSession, method="ecs"):
40
41
  self._headers = self._build_headers()
41
42
  self._http = self._init_http_session()
42
43
 
43
- self._refresh_using(
44
+ self.initialize(
44
45
  credentials_method=self._get_credentials,
45
46
  defer_refresh=defer_refresh is not False,
46
47
  refresh_method="ecs-container-metadata",
@@ -0,0 +1,4 @@
1
+ from .certificate import IoTCertificateRefreshableSession
2
+ from .core import IoTRefreshableSession
3
+
4
+ __all__ = ["IoTRefreshableSession"]
@@ -0,0 +1,54 @@
1
+ __all__ = ["IoTCertificateRefreshableSession"]
2
+
3
+ from pathlib import Path
4
+ from typing import Any
5
+
6
+ from ...exceptions import BRSError
7
+ from ...utils import PKCS11, TemporaryCredentials
8
+ from .core import BaseIoTRefreshableSession
9
+
10
+
11
+ class IoTCertificateRefreshableSession(
12
+ BaseIoTRefreshableSession, registry_key="certificate"
13
+ ):
14
+ def __init__(
15
+ self,
16
+ endpoint: str,
17
+ role_alias: str,
18
+ thing_name: str,
19
+ certificate: str | bytes,
20
+ private_key: str | bytes | None = None,
21
+ pkcs11: PKCS11 | None = None,
22
+ ca: bytes | None = None,
23
+ verify_peer: bool = True,
24
+ ):
25
+ self.endpoint = endpoint
26
+ self.role_alias = role_alias
27
+ self.thing_name = thing_name
28
+ self.certificate = certificate
29
+ self.private_key = private_key
30
+ self.pkcs11 = pkcs11
31
+ self.ca = ca
32
+ self.verify_peer = verify_peer
33
+
34
+ if self.certificate and isinstance(self.certificate, str):
35
+ with open(Path(self.certificate), "rb") as cert_pem_file:
36
+ self.certificate = cert_pem_file.read()
37
+
38
+ if self.private_key is None and self.pkcs11 is None:
39
+ raise BRSError(
40
+ "Either 'private_key' or 'pkcs11' must be provided."
41
+ )
42
+
43
+ if self.private_key is not None and self.pkcs11 is not None:
44
+ raise BRSError(
45
+ "Only one of 'private_key' or 'pkcs11' can be provided."
46
+ )
47
+
48
+ if self.private_key and isinstance(self.private_key, str):
49
+ with open(Path(self.private_key), "rb") as private_key_pem_file:
50
+ self.private_key = private_key_pem_file.read()
51
+
52
+ def _get_credentials(self) -> TemporaryCredentials: ...
53
+
54
+ def get_identity(self) -> dict[str, Any]: ...
@@ -0,0 +1,16 @@
1
+ __all__ = ["IoTCognitoRefreshableSession"]
2
+
3
+ from typing import Any
4
+
5
+ from ...utils import TemporaryCredentials
6
+ from .core import BaseIoTRefreshableSession
7
+
8
+
9
+ class IoTCognitoRefreshableSession(
10
+ BaseIoTRefreshableSession, registry_key="cognito"
11
+ ):
12
+ def __init__(self): ...
13
+
14
+ def _get_credentials(self) -> TemporaryCredentials: ...
15
+
16
+ def get_identity(self) -> dict[str, Any]: ...
@@ -0,0 +1,50 @@
1
+ from __future__ import annotations
2
+
3
+ __all__ = ["IoTRefreshableSession"]
4
+
5
+ from typing import get_args
6
+
7
+ from ...exceptions import BRSError
8
+ from ...session import BaseRefreshableSession
9
+ from ...utils import (
10
+ IoTAuthenticationMethod,
11
+ BRSSession,
12
+ CredentialProvider,
13
+ Registry,
14
+ )
15
+
16
+
17
+ class BaseIoTRefreshableSession(
18
+ Registry[IoTAuthenticationMethod],
19
+ CredentialProvider,
20
+ BRSSession,
21
+ registry_key="__iot_sentinel__",
22
+ ):
23
+ def __init__(self, **kwargs):
24
+ super().__init__(**kwargs)
25
+
26
+
27
+ class IoTRefreshableSession(BaseRefreshableSession, registry_key="iot"):
28
+ def __new__(
29
+ cls,
30
+ authentication_method: IoTAuthenticationMethod = "certificate",
31
+ **kwargs,
32
+ ) -> BaseIoTRefreshableSession:
33
+ if authentication_method not in (
34
+ methods := cls.get_available_authentication_methods()
35
+ ):
36
+ raise BRSError(
37
+ f"{authentication_method!r} is an invalid authentication "
38
+ "method parameter. Available authentication methods are "
39
+ f"{', '.join(repr(meth) for meth in methods)}."
40
+ )
41
+
42
+ return BaseIoTRefreshableSession.registry[authentication_method](
43
+ **kwargs
44
+ )
45
+
46
+ @classmethod
47
+ def get_available_authentication_methods(cls) -> list[str]:
48
+ args = list(get_args(IoTAuthenticationMethod))
49
+ args.remove("__iot_sentinel__")
50
+ return args
@@ -4,17 +4,18 @@ __all__ = ["STSRefreshableSession"]
4
4
 
5
5
  from typing import Any
6
6
 
7
- from .exceptions import BRSWarning
8
- from .session import BaseRefreshableSession, TemporaryCredentials
7
+ from ..exceptions import BRSWarning
8
+ from ..session import BaseRefreshableSession
9
+ from ..utils import AssumeRoleParams, STSClientParams, TemporaryCredentials
9
10
 
10
11
 
11
- class STSRefreshableSession(BaseRefreshableSession, method="sts"):
12
+ class STSRefreshableSession(BaseRefreshableSession, registry_key="sts"):
12
13
  """A :class:`boto3.session.Session` object that automatically refreshes
13
14
  temporary AWS credentials using an IAM role that is assumed via STS.
14
15
 
15
16
  Parameters
16
17
  ----------
17
- assume_role_kwargs : dict
18
+ assume_role_kwargs : AssumeRoleParams
18
19
  Required keyword arguments for :meth:`STS.Client.assume_role` (i.e.
19
20
  boto3 STS client).
20
21
  defer_refresh : bool, optional
@@ -22,7 +23,7 @@ class STSRefreshableSession(BaseRefreshableSession, method="sts"):
22
23
  until they are explicitly needed. If ``False`` then temporary
23
24
  credentials refresh immediately upon expiration. It is highly
24
25
  recommended that you use ``True``. Default is ``True``.
25
- sts_client_kwargs : dict, optional
26
+ sts_client_kwargs : STSClientParams, optional
26
27
  Optional keyword arguments for the :class:`STS.Client` object. Do not
27
28
  provide values for ``service_name`` as they are unnecessary. Default
28
29
  is None.
@@ -36,13 +37,12 @@ class STSRefreshableSession(BaseRefreshableSession, method="sts"):
36
37
 
37
38
  def __init__(
38
39
  self,
39
- assume_role_kwargs: dict,
40
+ assume_role_kwargs: AssumeRoleParams,
40
41
  defer_refresh: bool | None = None,
41
- sts_client_kwargs: dict | None = None,
42
+ sts_client_kwargs: STSClientParams | None = None,
42
43
  **kwargs,
43
44
  ):
44
45
  super().__init__(**kwargs)
45
- defer_refresh = defer_refresh is not False
46
46
  self.assume_role_kwargs = assume_role_kwargs
47
47
 
48
48
  if sts_client_kwargs is not None:
@@ -60,9 +60,9 @@ class STSRefreshableSession(BaseRefreshableSession, method="sts"):
60
60
  self._sts_client = self.client(service_name="sts")
61
61
 
62
62
  # mounting refreshable credentials
63
- self._refresh_using(
63
+ self.initialize(
64
64
  credentials_method=self._get_credentials,
65
- defer_refresh=defer_refresh,
65
+ defer_refresh=defer_refresh is not False,
66
66
  refresh_method="sts-assume-role",
67
67
  )
68
68
 
@@ -2,33 +2,18 @@ from __future__ import annotations
2
2
 
3
3
  __all__ = ["RefreshableSession"]
4
4
 
5
- from abc import ABC, abstractmethod
6
- from datetime import datetime
7
- from typing import Any, Callable, ClassVar, Literal, TypedDict, get_args
5
+ from typing import get_args
8
6
 
9
- from boto3.session import Session
10
- from botocore.credentials import (
11
- DeferredRefreshableCredentials,
12
- RefreshableCredentials,
13
- )
7
+ from .exceptions import BRSError
8
+ from .utils import BRSSession, CredentialProvider, Method, Registry
14
9
 
15
- from .exceptions import BRSError, BRSWarning
16
10
 
17
- #: Type alias for all currently available credential refresh methods.
18
- Method = Literal["sts", "ecs", "custom"]
19
- RefreshMethod = Literal["sts-assume-role", "ecs-container-metadata", "custom"]
20
-
21
-
22
- class TemporaryCredentials(TypedDict):
23
- """Temporary IAM credentials."""
24
-
25
- access_key: str
26
- secret_key: str
27
- token: str
28
- expiry_time: datetime | str
29
-
30
-
31
- class BaseRefreshableSession(ABC, Session):
11
+ class BaseRefreshableSession(
12
+ Registry[Method],
13
+ CredentialProvider,
14
+ BRSSession,
15
+ registry_key="__sentinel__",
16
+ ):
32
17
  """Abstract base class for implementing refreshable AWS sessions.
33
18
 
34
19
  Provides a common interface and factory registration mechanism
@@ -45,76 +30,9 @@ class BaseRefreshableSession(ABC, Session):
45
30
  Class-level registry mapping method names to registered session types.
46
31
  """
47
32
 
48
- # adding this and __init_subclass__ to avoid circular imports
49
- # as well as simplify future addition of new methods
50
- registry: ClassVar[dict[Method, type[BaseRefreshableSession]]] = {}
51
-
52
- def __init_subclass__(cls, method: Method):
53
- super().__init_subclass__()
54
-
55
- # guarantees that methods are unique
56
- if method in BaseRefreshableSession.registry:
57
- BRSWarning(
58
- f"Method {repr(method)} is already registered. Overwriting."
59
- )
60
-
61
- BaseRefreshableSession.registry[method] = cls
62
-
63
33
  def __init__(self, **kwargs):
64
34
  super().__init__(**kwargs)
65
35
 
66
- @abstractmethod
67
- def _get_credentials(self) -> TemporaryCredentials: ...
68
-
69
- @abstractmethod
70
- def get_identity(self) -> dict[str, Any]: ...
71
-
72
- def _refresh_using(
73
- self,
74
- credentials_method: Callable,
75
- defer_refresh: bool,
76
- refresh_method: RefreshMethod,
77
- ):
78
- # determining how exactly to refresh expired temporary credentials
79
- if not defer_refresh:
80
- self._credentials = RefreshableCredentials.create_from_metadata(
81
- metadata=credentials_method(),
82
- refresh_using=credentials_method,
83
- method=refresh_method,
84
- )
85
- else:
86
- self._credentials = DeferredRefreshableCredentials(
87
- refresh_using=credentials_method, method=refresh_method
88
- )
89
-
90
- def refreshable_credentials(self) -> dict[str, str]:
91
- """The current temporary AWS security credentials.
92
-
93
- Returns
94
- -------
95
- dict[str, str]
96
- Temporary AWS security credentials containing:
97
- AWS_ACCESS_KEY_ID : str
98
- AWS access key identifier.
99
- AWS_SECRET_ACCESS_KEY : str
100
- AWS secret access key.
101
- AWS_SESSION_TOKEN : str
102
- AWS session token.
103
- """
104
-
105
- creds = self.get_credentials().get_frozen_credentials()
106
- return {
107
- "AWS_ACCESS_KEY_ID": creds.access_key,
108
- "AWS_SECRET_ACCESS_KEY": creds.secret_key,
109
- "AWS_SESSION_TOKEN": creds.token,
110
- }
111
-
112
- @property
113
- def credentials(self) -> dict[str, str]:
114
- """The current temporary AWS security credentials."""
115
-
116
- return self.refreshable_credentials()
117
-
118
36
 
119
37
  class RefreshableSession:
120
38
  """Factory class for constructing refreshable boto3 sessions using various
@@ -143,9 +61,9 @@ class RefreshableSession:
143
61
 
144
62
  See Also
145
63
  --------
146
- boto3_refresh_session.custom.CustomRefreshableSession
147
- boto3_refresh_session.sts.STSRefreshableSession
148
- boto3_refresh_session.ecs.ECSRefreshableSession
64
+ boto3_refresh_session.methods.custom.CustomRefreshableSession
65
+ boto3_refresh_session.methods.sts.STSRefreshableSession
66
+ boto3_refresh_session.methods.ecs.ECSRefreshableSession
149
67
  """
150
68
 
151
69
  def __new__(
@@ -153,13 +71,12 @@ class RefreshableSession:
153
71
  ) -> BaseRefreshableSession:
154
72
  if method not in (methods := cls.get_available_methods()):
155
73
  raise BRSError(
156
- f"{repr(method)} is an invalid method parameter. "
74
+ f"{method!r} is an invalid method parameter. "
157
75
  "Available methods are "
158
76
  f"{', '.join(repr(meth) for meth in methods)}."
159
77
  )
160
78
 
161
- obj = BaseRefreshableSession.registry[method]
162
- return obj(**kwargs)
79
+ return BaseRefreshableSession.registry[method](**kwargs)
163
80
 
164
81
  @classmethod
165
82
  def get_available_methods(cls) -> list[str]:
@@ -169,7 +86,9 @@ class RefreshableSession:
169
86
  -------
170
87
  list[str]
171
88
  A list of all currently available credential refresh methods,
172
- e.g. 'sts'.
89
+ e.g. 'sts', 'ecs', 'custom'.
173
90
  """
174
91
 
175
- return list(get_args(Method))
92
+ args = list(get_args(Method))
93
+ args.remove("__sentinel__")
94
+ return args
@@ -0,0 +1,212 @@
1
+ from abc import ABC, abstractmethod
2
+ from datetime import datetime
3
+ from typing import (
4
+ Any,
5
+ Callable,
6
+ ClassVar,
7
+ Generic,
8
+ List,
9
+ Literal,
10
+ TypedDict,
11
+ TypeVar,
12
+ )
13
+
14
+ from boto3.session import Session
15
+ from botocore.credentials import (
16
+ DeferredRefreshableCredentials,
17
+ RefreshableCredentials,
18
+ )
19
+
20
+ from .exceptions import BRSWarning
21
+
22
+ try:
23
+ from typing import NotRequired # type: ignore[import]
24
+ except ImportError:
25
+ from typing_extensions import NotRequired
26
+
27
+ #: Type alias for all currently available IoT authentication methods.
28
+ IoTAuthenticationMethod = Literal["certificate", "cognito", "__iot_sentinel__"]
29
+
30
+ #: Type alias for all currently available credential refresh methods.
31
+ Method = Literal[
32
+ "sts",
33
+ "ecs",
34
+ "custom",
35
+ "__sentinel__",
36
+ ] # TODO: Add iot when implemented
37
+
38
+ #: Type alias for all refresh method names.
39
+ RefreshMethod = Literal[
40
+ "sts-assume-role",
41
+ "ecs-container-metadata",
42
+ "custom",
43
+ ] # Add iot-certificate and iot-cognito when iot implemented
44
+
45
+ #: Type alias for all currently registered credential refresh methods.
46
+ RegistryKey = TypeVar("RegistryKey", bound=str)
47
+
48
+
49
+ class Registry(Generic[RegistryKey]):
50
+ """Gives any hierarchy a class-level registry."""
51
+
52
+ registry: ClassVar[dict[str, type]] = {}
53
+
54
+ def __init_subclass__(cls, *, registry_key: RegistryKey, **kwargs: Any):
55
+ super().__init_subclass__(**kwargs)
56
+
57
+ if registry_key in cls.registry:
58
+ BRSWarning(f"{registry_key!r} already registered. Overwriting.")
59
+
60
+ if "sentinel" not in registry_key:
61
+ cls.registry[registry_key] = cls
62
+
63
+ @classmethod
64
+ def items(cls) -> dict[str, type]:
65
+ """Typed accessor for introspection / debugging."""
66
+
67
+ return dict(cls.registry)
68
+
69
+
70
+ class TemporaryCredentials(TypedDict):
71
+ """Temporary IAM credentials."""
72
+
73
+ access_key: str
74
+ secret_key: str
75
+ token: str
76
+ expiry_time: datetime | str
77
+
78
+
79
+ class RefreshableTemporaryCredentials(TypedDict):
80
+ """Refreshable IAM credentials.
81
+
82
+ Parameters
83
+ ----------
84
+ AWS_ACCESS_KEY_ID : str
85
+ AWS access key identifier.
86
+ AWS_SECRET_ACCESS_KEY : str
87
+ AWS secret access key.
88
+ AWS_SESSION_TOKEN : str
89
+ AWS session token.
90
+ """
91
+
92
+ AWS_ACCESS_KEY_ID: str
93
+ AWS_SECRET_ACCESS_KEY: str
94
+ AWS_SESSION_TOKEN: str
95
+
96
+
97
+ class CredentialProvider(ABC):
98
+ """Defines the abstract surface every refreshable session must expose."""
99
+
100
+ @abstractmethod
101
+ def _get_credentials(self) -> TemporaryCredentials: ...
102
+
103
+ @abstractmethod
104
+ def get_identity(self) -> dict[str, Any]: ...
105
+
106
+
107
+ class BRSSession(Session):
108
+ """Wrapper for boto3.session.Session.
109
+
110
+ Other Parameters
111
+ ----------------
112
+ kwargs : Any
113
+ Optional keyword arguments for initializing boto3.session.Session."""
114
+
115
+ def __init__(self, **kwargs):
116
+ super().__init__(**kwargs)
117
+
118
+ def initialize(
119
+ self,
120
+ credentials_method: Callable,
121
+ defer_refresh: bool,
122
+ refresh_method: RefreshMethod,
123
+ ):
124
+ # determining how exactly to refresh expired temporary credentials
125
+ if not defer_refresh:
126
+ self._credentials = RefreshableCredentials.create_from_metadata(
127
+ metadata=credentials_method(),
128
+ refresh_using=credentials_method,
129
+ method=refresh_method,
130
+ )
131
+ else:
132
+ self._credentials = DeferredRefreshableCredentials(
133
+ refresh_using=credentials_method, method=refresh_method
134
+ )
135
+
136
+ def refreshable_credentials(self) -> RefreshableTemporaryCredentials:
137
+ """The current temporary AWS security credentials.
138
+
139
+ Returns
140
+ -------
141
+ RefreshableTemporaryCredentials
142
+ Temporary AWS security credentials containing:
143
+ AWS_ACCESS_KEY_ID : str
144
+ AWS access key identifier.
145
+ AWS_SECRET_ACCESS_KEY : str
146
+ AWS secret access key.
147
+ AWS_SESSION_TOKEN : str
148
+ AWS session token.
149
+ """
150
+
151
+ creds = self.get_credentials().get_frozen_credentials()
152
+ return {
153
+ "AWS_ACCESS_KEY_ID": creds.access_key,
154
+ "AWS_SECRET_ACCESS_KEY": creds.secret_key,
155
+ "AWS_SESSION_TOKEN": creds.token,
156
+ }
157
+
158
+ @property
159
+ def credentials(self) -> RefreshableTemporaryCredentials:
160
+ """The current temporary AWS security credentials."""
161
+
162
+ return self.refreshable_credentials()
163
+
164
+
165
+ class Tag(TypedDict):
166
+ Key: str
167
+ Value: str
168
+
169
+
170
+ class PolicyDescriptorType(TypedDict):
171
+ arn: str
172
+
173
+
174
+ class ProvidedContext(TypedDict):
175
+ ProviderArn: str
176
+ ContextAssertion: str
177
+
178
+
179
+ class AssumeRoleParams(TypedDict):
180
+ RoleArn: str
181
+ RoleSessionName: str
182
+ PolicyArns: NotRequired[List[PolicyDescriptorType]]
183
+ Policy: NotRequired[str]
184
+ DurationSeconds: NotRequired[int]
185
+ ExternalId: NotRequired[str]
186
+ SerialNumber: NotRequired[str]
187
+ TokenCode: NotRequired[str]
188
+ Tags: NotRequired[List[Tag]]
189
+ TransitiveTagKeys: NotRequired[List[str]]
190
+ SourceIdentity: NotRequired[str]
191
+ ProvidedContexts: NotRequired[List[ProvidedContext]]
192
+
193
+
194
+ class STSClientParams(TypedDict):
195
+ region_name: NotRequired[str]
196
+ api_version: NotRequired[str]
197
+ use_ssl: NotRequired[bool]
198
+ verify: NotRequired[bool | str]
199
+ endpoint_url: NotRequired[str]
200
+ aws_access_key_id: NotRequired[str]
201
+ aws_secret_access_key: NotRequired[str]
202
+ aws_session_token: NotRequired[str]
203
+ config: NotRequired[Any]
204
+ aws_account_id: NotRequired[str]
205
+
206
+
207
+ class PKCS11(TypedDict):
208
+ pkcs11_loc: str
209
+ user_pin: NotRequired[str]
210
+ slot_id: NotRequired[int]
211
+ token_label: NotRequired[str | None]
212
+ private_key_label: NotRequired[str | None]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: boto3-refresh-session
3
- Version: 1.3.22
3
+ Version: 2.0.1
4
4
  Summary: A simple Python package for refreshing the temporary security credentials in a boto3.session.Session object automatically.
5
5
  License: MIT
6
6
  Keywords: boto3,botocore,aws,sts,ecs,credentials,token,refresh
@@ -18,6 +18,7 @@ Classifier: Programming Language :: Python :: 3.13
18
18
  Requires-Dist: boto3
19
19
  Requires-Dist: botocore
20
20
  Requires-Dist: requests
21
+ Requires-Dist: typing-extensions
21
22
  Project-URL: Documentation, https://michaelthomasletts.github.io/boto3-refresh-session/index.html
22
23
  Project-URL: Repository, https://github.com/michaelthomasletts/boto3-refresh-session
23
24
  Description-Content-Type: text/markdown
@@ -57,7 +58,7 @@ Description-Content-Type: text/markdown
57
58
  </a>
58
59
 
59
60
  <a href="https://pepy.tech/projects/boto3-refresh-session">
60
- <img src="https://img.shields.io/badge/downloads-76.9K-red?logo=python&color=%23FF0000&label=Downloads" alt="Downloads"/>
61
+ <img src="https://img.shields.io/badge/downloads-85.0K-red?logo=python&color=%23FF0000&label=Downloads" alt="Downloads"/>
61
62
  </a>
62
63
 
63
64
  <a href="https://michaelthomasletts.github.io/boto3-refresh-session/index.html">
@@ -83,6 +84,16 @@ Description-Content-Type: text/markdown
83
84
 
84
85
  </div>
85
86
 
87
+ ---
88
+
89
+ ## ⚠️ Important Update
90
+
91
+ I am currently grappling with a serious medical condition that negatively impacts my vision. Accordingly, development of the `iot` and `ec2` modules has been delayed. Expect delayed responses to issues and pull requests until my health stabilizes.
92
+
93
+ Thank you for supporting this project.
94
+
95
+ ---
96
+
86
97
  ## Features
87
98
 
88
99
  - Drop-in replacement for `boto3.session.Session`
@@ -0,0 +1,17 @@
1
+ boto3_refresh_session/__init__.py,sha256=R7O6fs-G6dGNu2w76a3-5ctRTVCa8JFuTYRit1nsVH4,387
2
+ boto3_refresh_session/exceptions.py,sha256=cP5d9S8QnUEwXIU3pzMGr6jMOz447kddNJ_UIRERMrk,964
3
+ boto3_refresh_session/methods/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
+ boto3_refresh_session/methods/custom.py,sha256=ZJAHgAajz9w6lohDeN-NWrxmZ2LaDxLfGWT2jmoTilQ,3868
5
+ boto3_refresh_session/methods/ecs.py,sha256=yAfQbFXMB_RDk-uX_zVVgOt2Lc-1SVx4PJmFyLuDbms,3750
6
+ boto3_refresh_session/methods/iot/__init__.typed,sha256=Z33nIB6oCsz9TZwikHfNHgY1SKxkSCdB5rwdPSUl3C4,135
7
+ boto3_refresh_session/methods/iot/certificate.typed,sha256=yvKptwH-GagBREI_1AXs_mCaU6vL3AcUDQ58vn7V8QM,1774
8
+ boto3_refresh_session/methods/iot/cognito.typed,sha256=0VorzOXHpsVemiGWZzHE9fuX-MZcpqzWQ4nK3gNDUMg,389
9
+ boto3_refresh_session/methods/iot/core.typed,sha256=tL-ngB2XYq0XtxhS9mbggCJYdX3eEE0u1Gvcq8sEYGE,1422
10
+ boto3_refresh_session/methods/sts.py,sha256=uWvT-ybRVZBusr4jNHyfHOB_AKhs6t0dN_fNI-gkUKM,3268
11
+ boto3_refresh_session/session.py,sha256=_Z3uB5Xq3S-dFqOFmWhMQbcd__NPGThjULLPStHI6E4,2914
12
+ boto3_refresh_session/utils.py,sha256=ME3sNWZc6oTNUdoRmiNOVmLLp9iSqJe-yfudRV0A46U,5729
13
+ boto3_refresh_session-2.0.1.dist-info/LICENSE,sha256=I3ZYTXAjbIly6bm6J-TvFTuuHwTKws4h89QaY5c5HiY,1067
14
+ boto3_refresh_session-2.0.1.dist-info/METADATA,sha256=1cAoUQV7MYHj6Fu41GxqTMTaFq3o7RrLYm7yqtEXPXQ,8570
15
+ boto3_refresh_session-2.0.1.dist-info/NOTICE,sha256=1s8r33qbl1z0YvPB942iWgvbkP94P_e8AnROr1qXXuw,939
16
+ boto3_refresh_session-2.0.1.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
17
+ boto3_refresh_session-2.0.1.dist-info/RECORD,,
@@ -1,11 +0,0 @@
1
- boto3_refresh_session/__init__.py,sha256=WW-YPxwblDXCjhzR9VclZPfz_g0i_YcHrAMK8JIMwOs,364
2
- boto3_refresh_session/custom.py,sha256=wR7122COYuFkmVprORfz-mPRqH4XeTH8Uw8_2QUYWUg,3845
3
- boto3_refresh_session/ecs.py,sha256=npuMlooixhB7qXYACsPDRx8A2xhFTrRgcAPFZK1P9i8,3727
4
- boto3_refresh_session/exceptions.py,sha256=qcFzdIuK5PZirs77H_Kb64S9QFb6cn2OJtirjvaRLiY,972
5
- boto3_refresh_session/session.py,sha256=TGI3-Zv52kGigw0f-mUNBkB2nqM632gCRZgY6KhZd-A,5564
6
- boto3_refresh_session/sts.py,sha256=f9dtJMfs5bYWfZAcKuANAe0InjmNjZfKyqt5LpHFDxk,3202
7
- boto3_refresh_session-1.3.22.dist-info/LICENSE,sha256=I3ZYTXAjbIly6bm6J-TvFTuuHwTKws4h89QaY5c5HiY,1067
8
- boto3_refresh_session-1.3.22.dist-info/METADATA,sha256=kH4EJR3iEgSslxmBxmhy53q4jNKp3q9Gg6bj5PxSld0,8209
9
- boto3_refresh_session-1.3.22.dist-info/NOTICE,sha256=1s8r33qbl1z0YvPB942iWgvbkP94P_e8AnROr1qXXuw,939
10
- boto3_refresh_session-1.3.22.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
11
- boto3_refresh_session-1.3.22.dist-info/RECORD,,