boto3-refresh-session 7.0.1__py3-none-any.whl → 7.1.6__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.

Potentially problematic release.


This version of boto3-refresh-session might be problematic. Click here for more details.

@@ -13,7 +13,7 @@ from .session import *
13
13
 
14
14
  __all__.extend(session.__all__)
15
15
  __all__.extend(exceptions.__all__)
16
- __version__ = "7.0.1"
16
+ __version__ = "7.1.6"
17
17
  __title__ = "boto3-refresh-session"
18
18
  __author__ = "Mike Letts"
19
19
  __maintainer__ = "Mike Letts"
@@ -5,15 +5,15 @@
5
5
  """Custom exception and warning types for boto3-refresh-session."""
6
6
 
7
7
  __all__ = [
8
- "BRSError",
9
- "BRSValidationError",
8
+ "BRSCacheError",
9
+ "BRSCacheExistsError",
10
+ "BRSCacheNotFoundError",
10
11
  "BRSConfigurationError",
11
- "BRSCredentialError",
12
12
  "BRSConnectionError",
13
+ "BRSCredentialError",
14
+ "BRSError",
13
15
  "BRSRequestError",
14
- "BRSCacheError",
15
- "BRSCacheNotFoundError",
16
- "BRSCacheExistsError",
16
+ "BRSValidationError",
17
17
  "BRSWarning",
18
18
  ]
19
19
 
@@ -10,12 +10,11 @@ from typing import Callable
10
10
 
11
11
  from ..exceptions import BRSConfigurationError, BRSValidationError, BRSWarning
12
12
  from ..utils import (
13
- MFA_SERIAL_PATTERN,
14
- ROLE_ARN_PATTERN,
15
- ROLE_SESSION_NAME_PATTERN,
13
+ AssumeRoleConfig,
16
14
  AssumeRoleParams,
17
15
  BaseRefreshableSession,
18
16
  Identity,
17
+ STSClientConfig,
19
18
  STSClientParams,
20
19
  TemporaryCredentials,
21
20
  refreshable_session,
@@ -29,7 +28,7 @@ class STSRefreshableSession(BaseRefreshableSession, registry_key="sts"):
29
28
 
30
29
  Parameters
31
30
  ----------
32
- assume_role_kwargs : AssumeRoleParams
31
+ assume_role_kwargs : AssumeRoleParams | AssumeRoleConfig
33
32
  Required keyword arguments for :meth:`STS.Client.assume_role` (i.e.
34
33
  boto3 STS client). ``RoleArn`` is required. ``RoleSessionName`` will
35
34
  default to 'boto3-refresh-session' if not provided.
@@ -45,7 +44,7 @@ class STSRefreshableSession(BaseRefreshableSession, registry_key="sts"):
45
44
  ``TokenCode`` in ``assume_role_kwargs``. You are responsible for
46
45
  updating ``assume_role_kwargs["TokenCode"]`` before the token
47
46
  expires.
48
- sts_client_kwargs : STSClientParams, optional
47
+ sts_client_kwargs : STSClientParams | STSClientConfig, optional
49
48
  Optional keyword arguments for the :class:`STS.Client` object. Do not
50
49
  provide values for ``service_name`` as they are unnecessary. Default
51
50
  is None.
@@ -86,16 +85,39 @@ class STSRefreshableSession(BaseRefreshableSession, registry_key="sts"):
86
85
  kwargs : dict
87
86
  Optional keyword arguments for the :class:`boto3.session.Session`
88
87
  object.
88
+
89
+ See Also
90
+ --------
91
+ boto3_refresh_session.utils.config.config.AssumeRoleConfig
92
+ boto3_refresh_session.utils.config.config.STSClientConfig
89
93
  """
90
94
 
91
95
  def __init__(
92
96
  self,
93
- assume_role_kwargs: AssumeRoleParams,
94
- sts_client_kwargs: STSClientParams | None = None,
97
+ assume_role_kwargs: AssumeRoleParams | AssumeRoleConfig,
98
+ sts_client_kwargs: STSClientParams | STSClientConfig | None = None,
95
99
  mfa_token_provider: Callable[[], str] | None = None,
96
100
  mfa_token_provider_kwargs: dict | None = None,
97
101
  **kwargs,
98
102
  ):
103
+ # initializing asssume_role_kwargs attribute
104
+ match assume_role_kwargs:
105
+ case AssumeRoleConfig():
106
+ self.assume_role_kwargs = assume_role_kwargs
107
+ case _:
108
+ self.assume_role_kwargs = AssumeRoleConfig(
109
+ **assume_role_kwargs
110
+ )
111
+
112
+ # initializing sts_client_kwargs attribute
113
+ match sts_client_kwargs:
114
+ case STSClientConfig():
115
+ self.sts_client_kwargs = sts_client_kwargs
116
+ case None:
117
+ self.sts_client_kwargs = STSClientConfig()
118
+ case _:
119
+ self.sts_client_kwargs = STSClientConfig(**sts_client_kwargs)
120
+
99
121
  # ensuring 'refresh_method' is not set manually
100
122
  if "refresh_method" in kwargs:
101
123
  BRSWarning.warn(
@@ -104,43 +126,10 @@ class STSRefreshableSession(BaseRefreshableSession, registry_key="sts"):
104
126
  )
105
127
  del kwargs["refresh_method"]
106
128
 
107
- # verifying 'RoleArn' is provided in 'assume_role_kwargs'
108
- if "RoleArn" not in assume_role_kwargs:
109
- raise BRSConfigurationError(
110
- "'RoleArn' must be provided in 'assume_role_kwargs'!",
111
- param="RoleArn",
112
- )
113
-
114
- # verifying 'RoleArn' format
115
- if not ROLE_ARN_PATTERN.match(assume_role_kwargs["RoleArn"]):
116
- raise BRSValidationError(
117
- "'RoleArn' in 'assume_role_kwargs' is not a valid AWS "
118
- "Role ARN!",
119
- param="RoleArn",
120
- value=assume_role_kwargs.get("RoleArn"),
121
- )
122
-
123
- # setting default 'RoleSessionName' if not provided
124
- if "RoleSessionName" not in assume_role_kwargs:
125
- BRSWarning.warn(
126
- "'RoleSessionName' not provided in "
127
- "'assume_role_kwargs'! Defaulting to "
128
- "'boto3-refresh-session'."
129
- )
130
- assume_role_kwargs["RoleSessionName"] = "boto3-refresh-session"
131
-
132
- # verifying 'RoleSessionName' format
133
- if not ROLE_SESSION_NAME_PATTERN.match(
134
- assume_role_kwargs["RoleSessionName"]
135
- ):
136
- raise BRSValidationError(
137
- "'RoleSessionName' in 'assume_role_kwargs' is not valid! "
138
- "It must be 2-64 characters long and can contain only "
139
- "alphanumeric characters and the following symbols: "
140
- "'+=,.@-'.",
141
- param="RoleSessionName",
142
- value=assume_role_kwargs.get("RoleSessionName"),
143
- )
129
+ # setting 'RoleSessionName' if not provided
130
+ self.assume_role_kwargs.RoleSessionName = self.assume_role_kwargs.get(
131
+ "RoleSessionName", "boto3-refresh-session"
132
+ )
144
133
 
145
134
  # store MFA token provider
146
135
  try:
@@ -158,26 +147,12 @@ class STSRefreshableSession(BaseRefreshableSession, registry_key="sts"):
158
147
  ) from err
159
148
 
160
149
  # storing mfa_token_provider_kwargs
161
- self.mfa_token_provider_kwargs = (
162
- mfa_token_provider_kwargs if mfa_token_provider_kwargs else {}
163
- )
164
-
165
- # verifying 'SerialNumber' format if provided
166
- if "SerialNumber" in assume_role_kwargs:
167
- if not MFA_SERIAL_PATTERN.match(
168
- assume_role_kwargs["SerialNumber"]
169
- ):
170
- raise BRSValidationError(
171
- "'SerialNumber' in 'assume_role_kwargs' is not a valid "
172
- "AWS MFA device ARN!",
173
- param="SerialNumber",
174
- value=assume_role_kwargs.get("SerialNumber"),
175
- )
150
+ self.mfa_token_provider_kwargs = mfa_token_provider_kwargs or {}
176
151
 
177
152
  # ensure SerialNumber is set appropriately with mfa_token_provider
178
153
  if (
179
154
  self.mfa_token_provider
180
- and "SerialNumber" not in assume_role_kwargs
155
+ and self.assume_role_kwargs.SerialNumber is None
181
156
  ):
182
157
  raise BRSConfigurationError(
183
158
  "'SerialNumber' must be provided in 'assume_role_kwargs' "
@@ -185,77 +160,53 @@ class STSRefreshableSession(BaseRefreshableSession, registry_key="sts"):
185
160
  param="SerialNumber",
186
161
  )
187
162
 
188
- # ensure SerialNumber and TokenCode are set without mfa_token_provider
163
+ # ensure SerialNumber and TokenCode are set in the absence of
164
+ # mfa_token_provider
189
165
  if (
190
166
  self.mfa_token_provider is None
191
167
  and (
192
- "SerialNumber" in assume_role_kwargs
193
- and "TokenCode" not in assume_role_kwargs
168
+ self.assume_role_kwargs.SerialNumber is not None
169
+ and self.assume_role_kwargs.TokenCode is None
194
170
  )
195
171
  or (
196
- "SerialNumber" not in assume_role_kwargs
197
- and "TokenCode" in assume_role_kwargs
172
+ self.assume_role_kwargs.SerialNumber is None
173
+ and self.assume_role_kwargs.TokenCode is not None
198
174
  )
199
175
  ):
200
176
  raise BRSConfigurationError(
201
177
  "'SerialNumber' and 'TokenCode' must be provided in "
202
- "'assume_role_kwargs' when 'mfa_token_provider' is not set!",
178
+ "'assume_role_kwargs' when 'mfa_token_provider' is not set "
179
+ "and 'SerialNumber' or 'TokenCode' is missing!",
203
180
  param="SerialNumber/TokenCode",
204
181
  )
205
182
 
206
183
  # warn if TokenCode provided with mfa_token_provider
207
- if self.mfa_token_provider and "TokenCode" in assume_role_kwargs:
184
+ if (
185
+ self.mfa_token_provider
186
+ and self.assume_role_kwargs.TokenCode is not None
187
+ ):
208
188
  BRSWarning.warn(
209
189
  "'TokenCode' provided in 'assume_role_kwargs' will be "
210
190
  "ignored and overridden by 'mfa_token_provider' on each "
211
191
  "refresh."
212
192
  )
213
193
 
214
- # initializing assume role kwargs attribute
215
- self.assume_role_kwargs = assume_role_kwargs
216
-
217
194
  # initializing BRSSession
218
195
  super().__init__(refresh_method="sts-assume-role", **kwargs)
219
196
 
220
- if sts_client_kwargs is not None:
221
- # overwriting 'service_name' if if appears in sts_client_kwargs
222
- if "service_name" in sts_client_kwargs:
223
- BRSWarning.warn(
224
- "'sts_client_kwargs' cannot contain values for "
225
- "'service_name'. Reverting to service_name = 'sts'."
226
- )
227
- del sts_client_kwargs["service_name"]
228
- self._sts_client = self.client(
229
- service_name="sts", **sts_client_kwargs
230
- )
231
- else:
232
- self._sts_client = self.client(service_name="sts")
197
+ # initializing STS client attribute
198
+ self._sts_client = self.client(**self.sts_client_kwargs)
233
199
 
234
200
  def _get_credentials(self) -> TemporaryCredentials:
235
- params = dict(self.assume_role_kwargs)
236
-
237
201
  # override TokenCode with fresh token from provider if configured
238
- if self.mfa_token_provider:
239
- params["TokenCode"] = self.mfa_token_provider(
202
+ if self.mfa_token_provider is not None:
203
+ self.assume_role_kwargs.TokenCode = self.mfa_token_provider(
240
204
  **self.mfa_token_provider_kwargs
241
205
  )
242
206
 
243
- # validating TokenCode format
244
- if (token_code := params.get("TokenCode")) is not None:
245
- if (
246
- not isinstance(token_code, str)
247
- or len(token_code) != 6
248
- or not token_code.isdigit()
249
- ):
250
- raise BRSValidationError(
251
- "'TokenCode' must be a 6-digit string per AWS MFA "
252
- "token specifications!",
253
- param="TokenCode",
254
- )
255
-
256
- temporary_credentials = self._sts_client.assume_role(**params)[
257
- "Credentials"
258
- ]
207
+ temporary_credentials = self._sts_client.assume_role(
208
+ **self.assume_role_kwargs
209
+ )["Credentials"]
259
210
 
260
211
  return {
261
212
  "access_key": temporary_credentials.get("AccessKeyId"),
@@ -66,6 +66,18 @@ class RefreshableSession:
66
66
  boto3_refresh_session.methods.custom.CustomRefreshableSession
67
67
  boto3_refresh_session.methods.iot.x509.IOTX509RefreshableSession
68
68
  boto3_refresh_session.methods.sts.STSRefreshableSession
69
+
70
+ Examples
71
+ --------
72
+
73
+ Basic initialization using STS AssumeRole (i.e. ``method="sts"``):
74
+
75
+ >>> from boto3_refresh_session import AssumeRoleConfig, RefreshableSession
76
+ >>> session = RefreshableSession(
77
+ ... AssumeRoleConfig(RoleArn="<your-role-arn>"),
78
+ ... region_name="us-east-1"
79
+ ... )
80
+ >>> s3 = session.client("s3")
69
81
  """
70
82
 
71
83
  def __new__(
@@ -4,13 +4,15 @@
4
4
 
5
5
  __all__ = []
6
6
 
7
- from . import cache, constants, internal, typing
7
+ from . import cache, config, constants, internal, typing
8
8
  from .cache import *
9
+ from .config import *
9
10
  from .constants import *
10
11
  from .internal import *
11
12
  from .typing import *
12
13
 
13
14
  __all__.extend(cache.__all__)
15
+ __all__.extend(config.__all__)
14
16
  __all__.extend(constants.__all__)
15
17
  __all__.extend(internal.__all__)
16
18
  __all__.extend(typing.__all__)
@@ -0,0 +1,274 @@
1
+ # This Source Code Form is subject to the terms of the Mozilla Public
2
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
3
+ # file, You can obtain one at https://mozilla.org/MPL/2.0/.
4
+
5
+ """Configurations for AWS STS AssumeRole and STS Client.
6
+
7
+ The following configuration classes do not validate most user inputs except
8
+ 'TokenCode' in `AssumeRoleConfig` and `service_name` in `STSClientConfig`.
9
+ It is the user's responsibility to ensure that the provided values conform
10
+ to AWS and boto specifications. The purpose of these configurations is to
11
+ provide a structured way to manage parameters when working with AWS STS.
12
+
13
+ For additional information on AWS specifications, refer to the
14
+ `API Reference for AssumeRole <https://docs.aws.amazon.com/STS/latest/APIReference/API_AssumeRole.html>`_.
15
+ """
16
+
17
+ __all__ = ["AssumeRoleConfig", "STSClientConfig"]
18
+
19
+ from abc import ABC, abstractmethod
20
+ from typing import Any
21
+
22
+ from botocore.config import Config
23
+
24
+ from ..exceptions import BRSValidationError, BRSWarning
25
+ from .constants import (
26
+ ASSUME_ROLE_CONFIG_PARAMETERS,
27
+ STS_CLIENT_CONFIG_PARAMETERS,
28
+ )
29
+ from .typing import PolicyDescriptorType, ProvidedContext, Tag
30
+
31
+
32
+ class BaseConfig(dict, ABC):
33
+ """Base configuration class."""
34
+
35
+ def __init__(self, **kwargs):
36
+ super().__init__()
37
+ self.update(kwargs)
38
+
39
+ def __setitem__(self, key: str, value: Any) -> None:
40
+ self._validate(key, value)
41
+ if value is None:
42
+ if key in self:
43
+ super().__delitem__(key)
44
+ return
45
+ super().__setitem__(key, value)
46
+
47
+ def __getattr__(self, name: str) -> Any:
48
+ try:
49
+ return self[name]
50
+ except KeyError:
51
+ try:
52
+ self._validate(name, None)
53
+ except BRSValidationError as exc:
54
+ raise AttributeError(
55
+ f"'{name}' is an unknown attribute."
56
+ ) from exc
57
+ return None
58
+
59
+ def __setattr__(self, name: str, value: Any) -> None:
60
+ self.__setitem__(name, value)
61
+
62
+ def update(self, *args, **kwargs) -> None:
63
+ for key, value in dict(*args, **kwargs).items():
64
+ self.__setitem__(key, value)
65
+
66
+ def setdefault(self, key: str, default: Any = None):
67
+ if key in self:
68
+ return super().setdefault(key, default)
69
+ self._validate(key, default)
70
+ return super().setdefault(key, default)
71
+
72
+ @abstractmethod
73
+ def _validate(self, key: str, value: Any) -> None: ...
74
+
75
+
76
+ class AssumeRoleConfig(BaseConfig):
77
+ """Configuration for AWS STS AssumeRole API.
78
+
79
+ Attributes
80
+ ----------
81
+ RoleArn : str
82
+ The Amazon Resource Name (ARN) of the role to assume.
83
+ RoleSessionName : str, optional
84
+ An identifier for the assumed role session.
85
+ PolicyArns : list of PolicyDescriptorType, optional
86
+ The Amazon Resource Names (ARNs) of the IAM managed policies to
87
+ use as managed session policies.
88
+ Policy : str, optional
89
+ An IAM policy in JSON format to use as an inline session policy.
90
+ DurationSeconds : int, optional
91
+ The duration, in seconds, of the role session.
92
+ ExternalId : str, optional
93
+ A unique identifier that might be required when you assume a role
94
+ in another account.
95
+ SerialNumber : str, optional
96
+ The identification number of the MFA device.
97
+ TokenCode : str, optional
98
+ The value provided by the MFA device. Must be a 6-digit numeric
99
+ string.
100
+ Tags : list of Tag, optional
101
+ A list of session tags.
102
+ TransitiveTagKeys : list of str, optional
103
+ A list of keys for session tags that you want to pass to the role
104
+ session.
105
+ SourceIdentity : str, optional
106
+ A unique identifier that is passed in the AssumeRole call.
107
+ ProvidedContexts : list of ProvidedContext, optional
108
+ A list of context keys and values for the session.
109
+
110
+ Notes
111
+ -----
112
+ Values can be accessed via dot-notation (e.g., ``config.RoleArn``)
113
+ or dictionary-style access (e.g., ``config['RoleArn']``).
114
+
115
+ Accessing a valid but unset attribute (e.g., ``SerialNumber``) via
116
+ dot-notation returns ``None`` instead of raising an error. While this
117
+ behavior is convenient, it may surprise users accustomed to seeing
118
+ ``AttributeError`` exceptions in similar contexts.
119
+
120
+ For additional information on AWS specifications, refer to the
121
+ `API Reference for AssumeRole <https://docs.aws.amazon.com/STS/latest/APIReference/API_AssumeRole.html>`_.
122
+ """
123
+
124
+ def __init__(
125
+ self,
126
+ *, # enforce keyword-only arguments
127
+ RoleArn: str,
128
+ RoleSessionName: str | None = None,
129
+ PolicyArns: list[PolicyDescriptorType] | None = None,
130
+ Policy: str | None = None,
131
+ DurationSeconds: int | None = None,
132
+ ExternalId: str | None = None,
133
+ SerialNumber: str | None = None,
134
+ TokenCode: str | None = None,
135
+ Tags: list[Tag] | None = None,
136
+ TransitiveTagKeys: list[str] | None = None,
137
+ SourceIdentity: str | None = None,
138
+ ProvidedContexts: list[ProvidedContext] | None = None,
139
+ ):
140
+ super().__init__(
141
+ RoleArn=RoleArn,
142
+ RoleSessionName=RoleSessionName,
143
+ PolicyArns=PolicyArns,
144
+ Policy=Policy,
145
+ DurationSeconds=DurationSeconds,
146
+ ExternalId=ExternalId,
147
+ SerialNumber=SerialNumber,
148
+ TokenCode=TokenCode,
149
+ Tags=Tags,
150
+ TransitiveTagKeys=TransitiveTagKeys,
151
+ SourceIdentity=SourceIdentity,
152
+ ProvidedContexts=ProvidedContexts,
153
+ )
154
+
155
+ def _validate(self, key: str, value: Any) -> None:
156
+ if not isinstance(key, str):
157
+ raise BRSValidationError("Attribute name must be a string.")
158
+
159
+ if key not in ASSUME_ROLE_CONFIG_PARAMETERS:
160
+ raise BRSValidationError(
161
+ f"'{key}' is not a valid attribute for AssumeRoleConfig."
162
+ )
163
+
164
+ if (
165
+ key == "TokenCode"
166
+ and isinstance(value, str)
167
+ and (len(value) != 6 or not value.isdigit())
168
+ ):
169
+ raise BRSValidationError(
170
+ f"'{key}' must be a 6-digit numeric string."
171
+ )
172
+
173
+
174
+ class STSClientConfig(BaseConfig):
175
+ """Configuration for boto3 STS Client.
176
+
177
+ Attributes
178
+ ----------
179
+ service_name : str, optional
180
+ The name of the AWS service. Defaults to 'sts'.
181
+ region_name : str, optional
182
+ The AWS region name.
183
+ api_version : str, optional
184
+ The API version to use.
185
+ use_ssl : bool, optional
186
+ Whether to use SSL.
187
+ verify : bool or str, optional
188
+ Whether to verify SSL certificates or a path to a CA bundle.
189
+ endpoint_url : str, optional
190
+ The complete URL to use for the constructed client.
191
+ aws_access_key_id : str, optional
192
+ The AWS access key ID.
193
+ aws_secret_access_key : str, optional
194
+ The AWS secret access key.
195
+ aws_session_token : str, optional
196
+ The AWS session token.
197
+ config : botocore.config.Config, optional
198
+ Advanced client configuration options.
199
+ aws_account_id : str, optional
200
+ The AWS account ID associated with the credentials.
201
+
202
+ Notes
203
+ -----
204
+ Values can be accessed via dot-notation (e.g., ``config.RoleArn``)
205
+ or dictionary-style access (e.g., ``config['RoleArn']``).
206
+
207
+ Accessing a valid but unset attribute (e.g., ``SerialNumber``) via
208
+ dot-notation returns ``None`` instead of raising an error. While this
209
+ behavior is convenient, it may surprise users accustomed to seeing
210
+ ``AttributeError`` exceptions in similar contexts.
211
+
212
+ ``service_name`` is enforced to be 'sts'. If a different value is
213
+ provided, it will be overridden to 'sts' with a warning.
214
+ """
215
+
216
+ def __init__(
217
+ self,
218
+ *, # enforce keyword-only arguments
219
+ service_name: str | None = None,
220
+ region_name: str | None = None,
221
+ api_version: str | None = None,
222
+ use_ssl: bool | None = None,
223
+ verify: bool | str | None = None,
224
+ endpoint_url: str | None = None,
225
+ aws_access_key_id: str | None = None,
226
+ aws_secret_access_key: str | None = None,
227
+ aws_session_token: str | None = None,
228
+ config: Config | None = None,
229
+ aws_account_id: str | None = None,
230
+ ):
231
+ super().__init__(
232
+ service_name=service_name,
233
+ region_name=region_name,
234
+ api_version=api_version,
235
+ use_ssl=use_ssl,
236
+ verify=verify,
237
+ endpoint_url=endpoint_url,
238
+ aws_access_key_id=aws_access_key_id,
239
+ aws_secret_access_key=aws_secret_access_key,
240
+ aws_session_token=aws_session_token,
241
+ config=config,
242
+ aws_account_id=aws_account_id,
243
+ )
244
+
245
+ def __setitem__(self, key: str, value: Any) -> None:
246
+ """Override to enforce 'sts' as service_name."""
247
+
248
+ if key == "service_name":
249
+ match value:
250
+ case None:
251
+ value = "sts"
252
+ case str() if value != "sts":
253
+ BRSWarning.warn(
254
+ "The 'service_name' for STSClientConfig should be "
255
+ "'sts'. Overriding to 'sts'."
256
+ )
257
+ value = "sts"
258
+ case str():
259
+ ...
260
+ case _:
261
+ raise BRSValidationError(
262
+ "'service_name' must be a string."
263
+ )
264
+
265
+ super().__setitem__(key, value)
266
+
267
+ def _validate(self, key: str, value: Any) -> None:
268
+ if not isinstance(key, str):
269
+ raise BRSValidationError("Attribute name must be a string.")
270
+
271
+ if key not in STS_CLIENT_CONFIG_PARAMETERS:
272
+ raise BRSValidationError(
273
+ f"'{key}' is not a valid attribute for STSClientConfig."
274
+ )
@@ -2,15 +2,40 @@
2
2
  # License, v. 2.0. If a copy of the MPL was not distributed with this
3
3
  # file, You can obtain one at https://mozilla.org/MPL/2.0/.
4
4
 
5
- __all__ = [
6
- "ROLE_ARN_PATTERN",
7
- "MFA_SERIAL_PATTERN",
8
- "ROLE_SESSION_NAME_PATTERN",
9
- ]
5
+ __all__ = ["ASSUME_ROLE_CONFIG_PARAMETERS", "STS_CLIENT_CONFIG_PARAMETERS"]
10
6
 
11
7
  from re import compile
12
8
 
13
- # AWS ARN validation patterns
9
+ # THESE CONSTANTS WILL BE DEPRECATED IN A FUTURE RELEASE!!
14
10
  ROLE_ARN_PATTERN = compile(r"^arn:aws[a-z-]*:iam::\d{12}:role/[\w+=,.@-]+$")
15
11
  MFA_SERIAL_PATTERN = compile(r"^arn:aws[a-z-]*:iam::\d{12}:mfa/[\w+=,.@-]+$")
16
12
  ROLE_SESSION_NAME_PATTERN = compile(r"^[a-zA-Z0-9+=,.@-]{2,64}$")
13
+
14
+ # config parameter names
15
+ ASSUME_ROLE_CONFIG_PARAMETERS = (
16
+ "RoleArn",
17
+ "RoleSessionName",
18
+ "PolicyArns",
19
+ "Policy",
20
+ "DurationSeconds",
21
+ "ExternalId",
22
+ "SerialNumber",
23
+ "TokenCode",
24
+ "Tags",
25
+ "TransitiveTagKeys",
26
+ "SourceIdentity",
27
+ "ProvidedContexts",
28
+ )
29
+ STS_CLIENT_CONFIG_PARAMETERS = (
30
+ "service_name",
31
+ "region_name",
32
+ "api_version",
33
+ "use_ssl",
34
+ "verify",
35
+ "endpoint_url",
36
+ "aws_access_key_id",
37
+ "aws_secret_access_key",
38
+ "aws_session_token",
39
+ "config",
40
+ "aws_account_id",
41
+ )
@@ -36,9 +36,9 @@ common surface and registration behavior for subclasses like STS or IoT X.509.
36
36
 
37
37
  __all__ = [
38
38
  "AWSCRTResponse",
39
+ "BRSSession",
39
40
  "BaseIoTRefreshableSession",
40
41
  "BaseRefreshableSession",
41
- "BRSSession",
42
42
  "CredentialProvider",
43
43
  "Registry",
44
44
  "refreshable_session",
@@ -276,9 +276,9 @@ class BRSSession(Session):
276
276
  Parameters
277
277
  ----------
278
278
  *args : Any
279
- Positional arguments for :class:`boto3.session.Session.client`.
279
+ Positional arguments for :meth:`boto3.session.Session.client`.
280
280
  **kwargs : Any
281
- Keyword arguments for :class:`boto3.session.Session.client`.
281
+ Keyword arguments for :meth:`boto3.session.Session.client`.
282
282
 
283
283
  Returns
284
284
  -------
@@ -117,6 +117,7 @@ class AssumeRoleParams(TypedDict):
117
117
 
118
118
 
119
119
  class STSClientParams(TypedDict):
120
+ service_name: NotRequired[str]
120
121
  region_name: NotRequired[str]
121
122
  api_version: NotRequired[str]
122
123
  use_ssl: NotRequired[bool]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: boto3-refresh-session
3
- Version: 7.0.1
3
+ Version: 7.1.6
4
4
  Summary: A simple Python package for refreshing the temporary security credentials in a boto3.session.Session object automatically.
5
5
  License: MPL-2.0
6
6
  License-File: LICENSE
@@ -109,7 +109,7 @@ Description-Content-Type: text/markdown
109
109
 
110
110
  <a href="https://github.com/michaelthomasletts/boto3-refresh-session/blob/main/LICENSE">
111
111
  <img
112
- src="https://img.shields.io/github/license/michaelthomasletts/boto3-refresh-session?style=flat&labelColor=555&color=FF0000&label=📜%20License"
112
+ src="https://img.shields.io/static/v1?label=License&message=MPL-2.0&color=FF0000&labelColor=555&logo=github&style=flat"
113
113
  alt="license"
114
114
  />
115
115
  </a>
@@ -123,7 +123,7 @@ Description-Content-Type: text/markdown
123
123
 
124
124
  </div>
125
125
 
126
- ## 😛 Features
126
+ ## Features
127
127
 
128
128
  - Drop-in replacement for `boto3.session.Session`
129
129
  - MFA support included for STS
@@ -136,7 +136,7 @@ Description-Content-Type: text/markdown
136
136
  - MQTT actions are available!
137
137
  - [Tested](https://github.com/michaelthomasletts/boto3-refresh-session/tree/main/tests), [documented](https://michaelthomasletts.github.io/boto3-refresh-session/index.html), and [published to PyPI](https://pypi.org/project/boto3-refresh-session/)
138
138
 
139
- ## 😌 Recognition and Testimonials
139
+ ## Recognition and Testimonials
140
140
 
141
141
  [Featured in TL;DR Sec.](https://tldrsec.com/p/tldr-sec-282)
142
142
 
@@ -148,19 +148,23 @@ A testimonial from a Cyber Security Engineer at a FAANG company:
148
148
 
149
149
  > _Most of my work is on tooling related to AWS security, so I'm pretty choosy about boto3 credentials-adjacent code. I often opt to just write this sort of thing myself so I at least know that I can reason about it. But I found boto3-refresh-session to be very clean and intuitive [...] We're using the RefreshableSession class as part of a client cache construct [...] We're using AWS Lambda to perform lots of operations across several regions in hundreds of accounts, over and over again, all day every day. And it turns out that there's a surprising amount of overhead to creating boto3 clients (mostly deserializing service definition json), so we can run MUCH more efficiently if we keep a cache of clients, all equipped with automatically refreshing sessions._
150
150
 
151
- ## 💻 Installation
151
+ ## Installation
152
+
153
+ boto3-refresh-session is available on PyPI:
152
154
 
153
155
  ```bash
154
156
  pip install boto3-refresh-session
155
157
  ```
156
158
 
157
- ## 📝 Usage
159
+ ## Usage
160
+
161
+ Refer to the [official usage documentation](https://michaelthomasletts.com/boto3-refresh-session/usage.html) for guidance on how to use boto3-refresh-session.
158
162
 
159
- Refer to the [official documentation](https://michaelthomasletts.com/boto3-refresh-session/usage.html) for guidance.
163
+ Refer to the [official API documentation](https://michaelthomasletts.com/boto3-refresh-session/modules/index.html) for technical information about boto3-refresh-session.
160
164
 
161
- ## ⚠️ Changes
165
+ ## Versions
162
166
 
163
- Refer to the [changelog](https://michaelthomasletts.com/boto3-refresh-session/changelog.html).
167
+ Refer to the [changelog](https://michaelthomasletts.com/boto3-refresh-session/changelog.html) for additional information on specific versions and releases.
164
168
 
165
169
  ## License
166
170
 
@@ -0,0 +1,20 @@
1
+ boto3_refresh_session/__init__.py,sha256=F4wjqFKsKQMumVe7ovMUKmPV1MQP2k4aDpt0OrvDqE4,620
2
+ boto3_refresh_session/exceptions.py,sha256=ypSr7p5Tf0k_E7cf5r-bl336vofNHGRGXsGdkQTyX58,4412
3
+ boto3_refresh_session/methods/__init__.py,sha256=18a2jb5VvY2FdUhHJ4T1lkfotHpbAb8zdMjqxZ3e6tc,394
4
+ boto3_refresh_session/methods/custom.py,sha256=jHRkleg9wvfJ9P0zsWezAr5-93CbXmVaWd5xYjiynBQ,5346
5
+ boto3_refresh_session/methods/iot/__init__.py,sha256=RI9zui9I1hEwkE5N8sAs94IGLCkHF3DxRnKg6MvPESE,348
6
+ boto3_refresh_session/methods/iot/core.py,sha256=6TInwBrNyLwQrcfLC76LRgCB75HFtF_spZ_2pCJKk0g,1532
7
+ boto3_refresh_session/methods/iot/x509.py,sha256=01iN_eSFV2xGPWHl_VgCpf6ojRnikFDC4vNb5v1tApo,22954
8
+ boto3_refresh_session/methods/sts.py,sha256=Z8oix37oK0ClHB_YVcsy5H2UCSJObbDbjNW3NTyNm98,9134
9
+ boto3_refresh_session/session.py,sha256=dqcKcC3mknrolpaBv-en67__Xsn0ocJtMF_PCJaim6E,3997
10
+ boto3_refresh_session/utils/__init__.py,sha256=B-bq0LB9XTlP6VjoGLdsIecWxzauULTRQRyEN1YYLfQ,546
11
+ boto3_refresh_session/utils/cache.py,sha256=3zgms7KZSwPMvTnc39ndPqByB7KqpMeZwuV_bv7S6y8,3126
12
+ boto3_refresh_session/utils/config.py,sha256=7fOD4ZjtCf4Ssgad83sIbUUmU2dMrinWoYmuprki4Qg,9861
13
+ boto3_refresh_session/utils/constants.py,sha256=iQ6XnSe8p9DH95Ylnhpp6-Pi6amgnBWJSBloHWBK_VA,1132
14
+ boto3_refresh_session/utils/internal.py,sha256=Xvo3D5_MFoldmqNISOmfQf7qydIbQOCVE-0EQY_8pjg,14755
15
+ boto3_refresh_session/utils/typing.py,sha256=pfUP9bGHoh5JlfMBJL-yDBLYykE2gu2A55uLsOS1tVs,3407
16
+ boto3_refresh_session-7.1.6.dist-info/METADATA,sha256=tH2ldzzAAcRW3UlCnXY43axP6O76ibOmhMp06jf1Isc,7172
17
+ boto3_refresh_session-7.1.6.dist-info/WHEEL,sha256=3ny-bZhpXrU6vSQ1UPG34FoxZBp3lVcvK0LkgUz6VLk,88
18
+ boto3_refresh_session-7.1.6.dist-info/licenses/LICENSE,sha256=hs-WVkefHtuCJFuYX0oswNUDuUV2br7aQmnGCzB2ma4,16725
19
+ boto3_refresh_session-7.1.6.dist-info/licenses/NOTICE,sha256=4nNFSLvbelWrxMEBMrkcmgi93AaF0NckUgNIf9i6Kbs,863
20
+ boto3_refresh_session-7.1.6.dist-info/RECORD,,
@@ -1,19 +0,0 @@
1
- boto3_refresh_session/__init__.py,sha256=tUnT4evpnXX_TNcqBXOmtziC02jrsCQ6ryCj33vEOwQ,620
2
- boto3_refresh_session/exceptions.py,sha256=y4jQ-kjbyprJxSD7HnqzoCZqMnmNqj6TgmTuua7ba2k,4412
3
- boto3_refresh_session/methods/__init__.py,sha256=18a2jb5VvY2FdUhHJ4T1lkfotHpbAb8zdMjqxZ3e6tc,394
4
- boto3_refresh_session/methods/custom.py,sha256=jHRkleg9wvfJ9P0zsWezAr5-93CbXmVaWd5xYjiynBQ,5346
5
- boto3_refresh_session/methods/iot/__init__.py,sha256=RI9zui9I1hEwkE5N8sAs94IGLCkHF3DxRnKg6MvPESE,348
6
- boto3_refresh_session/methods/iot/core.py,sha256=6TInwBrNyLwQrcfLC76LRgCB75HFtF_spZ_2pCJKk0g,1532
7
- boto3_refresh_session/methods/iot/x509.py,sha256=01iN_eSFV2xGPWHl_VgCpf6ojRnikFDC4vNb5v1tApo,22954
8
- boto3_refresh_session/methods/sts.py,sha256=ll6zjAuelUu-rNVKDn4PdUKu4YESafVFVJgWV--GnHw,11114
9
- boto3_refresh_session/session.py,sha256=5xg6SprpdPvGgAC1cPRZy983EnVh3z9xJ0PBRO5L7VI,3643
10
- boto3_refresh_session/utils/__init__.py,sha256=WWHRpVzj0HMqWCLhm4vr2aV678gqA5q-FN2-7OZJe-Q,485
11
- boto3_refresh_session/utils/cache.py,sha256=3zgms7KZSwPMvTnc39ndPqByB7KqpMeZwuV_bv7S6y8,3126
12
- boto3_refresh_session/utils/constants.py,sha256=3Kp4JVrDdeFCknb87wK0GjGzX8xMkkILxAYArIsP5mo,574
13
- boto3_refresh_session/utils/internal.py,sha256=HS1drA0F1kzsAG_i_MXN6n1LBmTEU5DLrv3SsSGvZK4,14757
14
- boto3_refresh_session/utils/typing.py,sha256=GPUADnET8WqNLt6k8sXNimRsCY9dZmxv-fV3g2dYBfY,3372
15
- boto3_refresh_session-7.0.1.dist-info/METADATA,sha256=nkutVfNQ9MeoyOkXIZ4IsrdNhYea47wu0EgSLagLAyk,6905
16
- boto3_refresh_session-7.0.1.dist-info/WHEEL,sha256=3ny-bZhpXrU6vSQ1UPG34FoxZBp3lVcvK0LkgUz6VLk,88
17
- boto3_refresh_session-7.0.1.dist-info/licenses/LICENSE,sha256=hs-WVkefHtuCJFuYX0oswNUDuUV2br7aQmnGCzB2ma4,16725
18
- boto3_refresh_session-7.0.1.dist-info/licenses/NOTICE,sha256=4nNFSLvbelWrxMEBMrkcmgi93AaF0NckUgNIf9i6Kbs,863
19
- boto3_refresh_session-7.0.1.dist-info/RECORD,,