boto3-refresh-session 1.3.11__py3-none-any.whl β†’ 7.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.

Potentially problematic release.


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

@@ -1,108 +0,0 @@
1
- from __future__ import annotations
2
-
3
- __all__ = ["CustomRefreshableSession"]
4
-
5
- from typing import Any, Callable
6
-
7
- from .exceptions import BRSError
8
- from .session import BaseRefreshableSession
9
-
10
-
11
- class CustomRefreshableSession(BaseRefreshableSession, method="custom"):
12
- """A :class:`boto3.session.Session` object that automatically refreshes temporary credentials
13
- returned by a custom credential getter provided by the user. Useful for users with highly
14
- sophisticated or idiosyncratic authentication flows.
15
-
16
- Parameters
17
- ----------
18
- custom_credentials_method: Callable
19
- Required. Accepts a callable object that returns temporary AWS security credentials. That
20
- object must return a dictionary containing 'access_key', 'secret_key', 'token', and
21
- 'expiry_time' when called.
22
- custom_credentials_method_args : dict[str, Any], optional
23
- Optional keyword arguments for the function passed to the ``custom_credentials_method``
24
- parameter.
25
- defer_refresh : bool, optional
26
- If ``True`` then temporary credentials are not automatically refreshed until
27
- they are explicitly needed. If ``False`` then temporary credentials refresh
28
- immediately upon expiration. It is highly recommended that you use ``True``.
29
- Default is ``True``.
30
-
31
- Other Parameters
32
- ----------------
33
- kwargs : dict
34
- Optional keyword arguments for the :class:`boto3.session.Session` object.
35
-
36
- Examples
37
- --------
38
- Write (or import) the callable object for obtaining temporary AWS security credentials.
39
-
40
- >>> def your_custom_credential_getter(your_param, another_param):
41
- >>> ...
42
- >>> return {
43
- >>> 'access_key': ...,
44
- >>> 'secret_key': ...,
45
- >>> 'token': ...,
46
- >>> 'expiry_time': ...,
47
- >>> }
48
-
49
- Pass that callable object to ``RefreshableSession``.
50
-
51
- >>> sess = RefreshableSession(
52
- >>> method='custom',
53
- >>> custom_credentials_method=your_custom_credential_getter,
54
- >>> custom_credentials_method_args=...,
55
- >>> )
56
- """
57
-
58
- def __init__(
59
- self,
60
- custom_credentials_method: Callable,
61
- custom_credentials_method_args: dict[str, Any] | None = None,
62
- defer_refresh: bool | None = None,
63
- **kwargs,
64
- ):
65
- super().__init__(**kwargs)
66
-
67
- self._custom_get_credentials = custom_credentials_method
68
- self._custom_get_credentials_args = (
69
- custom_credentials_method_args
70
- if custom_credentials_method_args is not None
71
- else {}
72
- )
73
-
74
- self._refresh_using(
75
- credentials_method=self._get_credentials,
76
- defer_refresh=defer_refresh is not False,
77
- refresh_method="custom",
78
- )
79
-
80
- def _get_credentials(self) -> dict[str, str]:
81
- credentials = self._custom_get_credentials(
82
- **self._custom_get_credentials_args
83
- )
84
- required_keys = {"access_key", "secret_key", "token", "expiry_time"}
85
-
86
- if missing := required_keys - credentials.keys():
87
- raise BRSError(
88
- f"The dict returned by custom_credentials_method is missing these key-value pairs: "
89
- f"{', '.join(repr(param) for param in missing)}. "
90
- )
91
-
92
- return credentials
93
-
94
- def get_identity(self) -> dict[str, str]:
95
- """Returns metadata about the custom credential getter.
96
-
97
- Returns
98
- -------
99
- dict[str, str]
100
- Dict containing information about the custom credential getter.
101
- """
102
-
103
- source = getattr(
104
- self._custom_get_credentials,
105
- "__name__",
106
- repr(self._custom_get_credentials),
107
- )
108
- return {"method": "custom", "source": repr(source)}
@@ -1,109 +0,0 @@
1
- from __future__ import annotations
2
-
3
- __all__ = ["ECSRefreshableSession"]
4
-
5
- import os
6
-
7
- import requests
8
-
9
- from .exceptions import BRSError
10
- from .session import BaseRefreshableSession
11
-
12
- _ECS_CREDENTIALS_RELATIVE_URI = "AWS_CONTAINER_CREDENTIALS_RELATIVE_URI"
13
- _ECS_CREDENTIALS_FULL_URI = "AWS_CONTAINER_CREDENTIALS_FULL_URI"
14
- _ECS_AUTHORIZATION_TOKEN = "AWS_CONTAINER_AUTHORIZATION_TOKEN"
15
- _DEFAULT_ENDPOINT_BASE = "http://169.254.170.2"
16
-
17
-
18
- class ECSRefreshableSession(BaseRefreshableSession, method="ecs"):
19
- """A boto3 session that automatically refreshes temporary AWS credentials
20
- from the ECS container credentials metadata endpoint.
21
-
22
- Parameters
23
- ----------
24
- defer_refresh : bool, optional
25
- If ``True`` then temporary credentials are not automatically refreshed until
26
- they are explicitly needed. If ``False`` then temporary credentials refresh
27
- immediately upon expiration. It is highly recommended that you use ``True``.
28
- Default is ``True``.
29
-
30
- Other Parameters
31
- ----------------
32
- kwargs : dict
33
- Optional keyword arguments passed to :class:`boto3.session.Session`.
34
- """
35
-
36
- def __init__(self, defer_refresh: bool | None = None, **kwargs):
37
- super().__init__(**kwargs)
38
-
39
- self._endpoint = self._resolve_endpoint()
40
- self._headers = self._build_headers()
41
- self._http = self._init_http_session()
42
-
43
- self._refresh_using(
44
- credentials_method=self._get_credentials,
45
- defer_refresh=defer_refresh is not False,
46
- refresh_method="ecs-container-metadata",
47
- )
48
-
49
- def _resolve_endpoint(self) -> str:
50
- uri = os.environ.get(_ECS_CREDENTIALS_FULL_URI) or os.environ.get(
51
- _ECS_CREDENTIALS_RELATIVE_URI
52
- )
53
- if not uri:
54
- raise BRSError(
55
- "Neither AWS_CONTAINER_CREDENTIALS_FULL_URI nor "
56
- "AWS_CONTAINER_CREDENTIALS_RELATIVE_URI is set. "
57
- "Are you running inside an ECS container?"
58
- )
59
- if uri.startswith("http://") or uri.startswith("https://"):
60
- return uri
61
- return f"{_DEFAULT_ENDPOINT_BASE}{uri}"
62
-
63
- def _build_headers(self) -> dict[str, str]:
64
- token = os.environ.get(_ECS_AUTHORIZATION_TOKEN)
65
- if token:
66
- return {"Authorization": f"Bearer {token}"}
67
- return {}
68
-
69
- def _init_http_session(self) -> requests.Session:
70
- session = requests.Session()
71
- session.headers.update(self._headers)
72
- return session
73
-
74
- def _get_credentials(self) -> dict[str, str]:
75
- try:
76
- response = self._http.get(self._endpoint, timeout=3)
77
- response.raise_for_status()
78
- except requests.RequestException as exc:
79
- raise BRSError(
80
- f"Failed to retrieve ECS credentials from {self._endpoint}"
81
- ) from exc
82
-
83
- credentials = response.json()
84
- required = {
85
- "AccessKeyId",
86
- "SecretAccessKey",
87
- "SessionToken",
88
- "Expiration",
89
- }
90
- if not required.issubset(credentials):
91
- raise BRSError(f"Incomplete credentials received: {credentials}")
92
- return {
93
- "access_key": credentials.get("AccessKeyId"),
94
- "secret_key": credentials.get("SecretAccessKey"),
95
- "token": credentials.get("SessionToken"),
96
- "expiry_time": credentials.get("Expiration"), # already ISO8601
97
- }
98
-
99
- @staticmethod
100
- def get_identity() -> dict[str, str]:
101
- """Returns metadata about ECS.
102
-
103
- Returns
104
- -------
105
- dict[str, str]
106
- Dict containing metadata about ECS.
107
- """
108
-
109
- return {"method": "ecs", "source": "ecs-container-metadata"}
@@ -1,85 +0,0 @@
1
- from __future__ import annotations
2
-
3
- __all__ = ["STSRefreshableSession"]
4
-
5
- from typing import Any
6
-
7
- from .exceptions import BRSWarning
8
- from .session import BaseRefreshableSession
9
-
10
-
11
- class STSRefreshableSession(BaseRefreshableSession, method="sts"):
12
- """A :class:`boto3.session.Session` object that automatically refreshes temporary AWS
13
- credentials using an IAM role that is assumed via STS.
14
-
15
- Parameters
16
- ----------
17
- assume_role_kwargs : dict
18
- Required keyword arguments for :meth:`STS.Client.assume_role` (i.e. boto3 STS client).
19
- defer_refresh : bool, optional
20
- If ``True`` then temporary credentials are not automatically refreshed until
21
- they are explicitly needed. If ``False`` then temporary credentials refresh
22
- immediately upon expiration. It is highly recommended that you use ``True``.
23
- Default is ``True``.
24
- sts_client_kwargs : dict, optional
25
- Optional keyword arguments for the :class:`STS.Client` object. Do not provide
26
- values for ``service_name`` as they are unnecessary. Default is None.
27
-
28
- Other Parameters
29
- ----------------
30
- kwargs : dict
31
- Optional keyword arguments for the :class:`boto3.session.Session` object.
32
- """
33
-
34
- def __init__(
35
- self,
36
- assume_role_kwargs: dict,
37
- defer_refresh: bool | None = None,
38
- sts_client_kwargs: dict | None = None,
39
- **kwargs,
40
- ):
41
- super().__init__(**kwargs)
42
- defer_refresh = defer_refresh is not False
43
- self.assume_role_kwargs = assume_role_kwargs
44
-
45
- if sts_client_kwargs is not None:
46
- # overwriting 'service_name' in case it appears in sts_client_kwargs
47
- if "service_name" in sts_client_kwargs:
48
- BRSWarning(
49
- "'sts_client_kwargs' cannot contain values for 'service_name'. Reverting to service_name = 'sts'."
50
- )
51
- del sts_client_kwargs["service_name"]
52
- self._sts_client = self.client(
53
- service_name="sts", **sts_client_kwargs
54
- )
55
- else:
56
- self._sts_client = self.client(service_name="sts")
57
-
58
- # mounting refreshable credentials
59
- self._refresh_using(
60
- credentials_method=self._get_credentials,
61
- defer_refresh=defer_refresh,
62
- refresh_method="sts-assume-role",
63
- )
64
-
65
- def _get_credentials(self) -> dict[str, str]:
66
- temporary_credentials = self._sts_client.assume_role(
67
- **self.assume_role_kwargs
68
- )["Credentials"]
69
- return {
70
- "access_key": temporary_credentials.get("AccessKeyId"),
71
- "secret_key": temporary_credentials.get("SecretAccessKey"),
72
- "token": temporary_credentials.get("SessionToken"),
73
- "expiry_time": temporary_credentials.get("Expiration").isoformat(),
74
- }
75
-
76
- def get_identity(self) -> dict[str, Any]:
77
- """Returns metadata about the identity assumed.
78
-
79
- Returns
80
- -------
81
- dict[str, Any]
82
- Dict containing caller identity according to AWS STS.
83
- """
84
-
85
- return self._sts_client.get_caller_identity()
@@ -1,21 +0,0 @@
1
- MIT License
2
-
3
- Copyright (c) 2025 Mike Letts
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.
@@ -1,178 +0,0 @@
1
- Metadata-Version: 2.3
2
- Name: boto3-refresh-session
3
- Version: 1.3.11
4
- Summary: A simple Python package for refreshing the temporary security credentials in a boto3.session.Session object automatically.
5
- License: MIT
6
- Keywords: boto3,botocore,aws
7
- Author: Mike Letts
8
- Author-email: lettsmt@gmail.com
9
- Maintainer: Michael Letts
10
- Maintainer-email: lettsmt@gmail.com
11
- Requires-Python: >=3.10
12
- Classifier: License :: OSI Approved :: MIT License
13
- Classifier: Programming Language :: Python :: 3
14
- Classifier: Programming Language :: Python :: 3.10
15
- Classifier: Programming Language :: Python :: 3.11
16
- Classifier: Programming Language :: Python :: 3.12
17
- Classifier: Programming Language :: Python :: 3.13
18
- Requires-Dist: boto3
19
- Requires-Dist: botocore
20
- Project-URL: Documentation, https://michaelthomasletts.github.io/boto3-refresh-session/index.html
21
- Project-URL: Repository, https://github.com/michaelthomasletts/boto3-refresh-session
22
- Description-Content-Type: text/markdown
23
-
24
- <div align="center">
25
- <img src="https://raw.githubusercontent.com/michaelthomasletts/boto3-refresh-session/refs/heads/main/doc/brs.png" />
26
- </div>
27
-
28
- </br>
29
-
30
- <div align="center"><em>
31
- A simple Python package for refreshing the temporary security credentials in a <code>boto3.session.Session</code> object automatically.
32
- </em></div>
33
-
34
- </br>
35
-
36
- <div align="center">
37
-
38
- <a href="https://pypi.org/project/boto3-refresh-session/">
39
- <img src="https://img.shields.io/pypi/v/boto3-refresh-session?color=%23FF0000FF&logo=python&label=Latest%20Version" alt="PyPI - Version"/>
40
- </a>
41
-
42
- <a href="https://pypi.org/project/boto3-refresh-session/">
43
- <img src="https://img.shields.io/pypi/pyversions/boto3-refresh-session?style=pypi&color=%23FF0000FF&logo=python&label=Compatible%20Python%20Versions" alt="Python Version"/>
44
- </a>
45
-
46
- <a href="https://github.com/michaelthomasletts/boto3-refresh-session/actions/workflows/push.yml">
47
- <img src="https://img.shields.io/github/actions/workflow/status/michaelthomasletts/boto3-refresh-session/push.yml?logo=github&color=%23FF0000FF&label=Build" alt="Workflow"/>
48
- </a>
49
-
50
- <a href="https://github.com/michaelthomasletts/boto3-refresh-session/commits/main">
51
- <img src="https://img.shields.io/github/last-commit/michaelthomasletts/boto3-refresh-session?logo=github&color=%23FF0000FF&label=Last%20Commit" alt="GitHub last commit"/>
52
- </a>
53
-
54
- <a href="https://github.com/michaelthomasletts/boto3-refresh-session/stargazers">
55
- <img src="https://img.shields.io/github/stars/michaelthomasletts/boto3-refresh-session?style=flat&logo=github&labelColor=555&color=FF0000&label=Stars" alt="Stars"/>
56
- </a>
57
-
58
- <a href="https://pepy.tech/project/boto3-refresh-session">
59
- <img src="https://img.shields.io/badge/downloads-62.9K-red?logo=python&color=%23FF0000&label=Downloads" alt="Downloads"/>
60
- </a>
61
-
62
- <a href="https://michaelthomasletts.github.io/boto3-refresh-session/index.html">
63
- <img src="https://img.shields.io/badge/Official%20Documentation-πŸ“˜-FF0000?style=flat&labelColor=555&logo=readthedocs" alt="Documentation Badge"/>
64
- </a>
65
-
66
- <a href="https://github.com/michaelthomasletts/boto3-refresh-session">
67
- <img src="https://img.shields.io/badge/Source%20Code-πŸ’»-FF0000?style=flat&labelColor=555&logo=github" alt="Source Code Badge"/>
68
- </a>
69
-
70
- <a href="https://michaelthomasletts.github.io/boto3-refresh-session/qanda.html">
71
- <img src="https://img.shields.io/badge/Q%26A-❔-FF0000?style=flat&labelColor=555&logo=vercel&label=Q%26A" alt="Q&A Badge"/>
72
- </a>
73
-
74
- <a href="https://medium.com/@lettsmt/you-shouldnt-have-to-think-about-refreshing-aws-credentials-214f7cbbd83b">
75
- <img src="https://img.shields.io/badge/Medium%20Article-πŸ“˜-FF0000?style=flat&labelColor=555&logo=readthedocs" alt="Medium Article"/>
76
- </a>
77
-
78
- </div>
79
-
80
- ## Features
81
-
82
- - Drop-in replacement for `boto3.session.Session`
83
- - Supports automatic credential refresh methods for various AWS services:
84
- - STS
85
- - ECS
86
- - Supports custom authentication methods for complicated authentication flows
87
- - Natively supports all parameters supported by `boto3.session.Session`
88
- - Tested, documented, and published to PyPI
89
- - Future releases will include support for EC2, IoT, SSO, and OIDC
90
-
91
- ## Recognition, Adoption, and Testimonials
92
-
93
- [Featured in TL;DR Sec.](https://tldrsec.com/p/tldr-sec-282)
94
-
95
- [Featured in CloudSecList.](https://cloudseclist.com/issues/issue-290)
96
-
97
- Recognized during AWS Community Day Midwest on June 5th, 2025.
98
-
99
- A testimonial from a Cyber Security Engineer at a FAANG company:
100
-
101
- > _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._
102
-
103
- ## Installation
104
-
105
- ```bash
106
- pip install boto3-refresh-session
107
- ```
108
-
109
- ## Usage (STS)
110
-
111
- ```python
112
- import boto3_refresh_session as brs
113
-
114
- # you can pass all of the params normally associated with boto3.session.Session
115
- profile_name = "<your-profile-name>"
116
- region_name = "us-east-1"
117
- ...
118
-
119
- # as well as all of the params associated with STS.Client.assume_role
120
- assume_role_kwargs = {
121
- "RoleArn": "<your-role-arn>",
122
- "RoleSessionName": "<your-role-session-name>",
123
- "DurationSeconds": "<your-selection>",
124
- ...
125
- }
126
-
127
- # as well as all of the params associated with STS.Client, except for 'service_name'
128
- sts_client_kwargs = {
129
- "region_name": region_name,
130
- ...
131
- }
132
-
133
- # basic initialization of boto3.session.Session
134
- session = brs.RefreshableSession(
135
- assume_role_kwargs=assume_role_kwargs, # required
136
- sts_client_kwargs=sts_client_kwargs,
137
- region_name=region_name,
138
- profile_name=profile_name,
139
- ...
140
- )
141
- ```
142
-
143
- ## Usage (ECS)
144
-
145
- ```python
146
- session = RefreshableSession(
147
- method="ecs",
148
- region_name=region_name,
149
- profile_name=profile_name,
150
- ...
151
- )
152
- ```
153
-
154
- ## Usage (Custom)
155
-
156
- If you have a highly sophisticated, novel, or idiosyncratic authentication flow not included in boto3-refresh-session then you will need to provide your own custom temporary credentials callable object. `RefreshableSession` accepts custom credentials callable objects, as shown below.
157
-
158
- ```python
159
- # create (or import) your custom credential method
160
- def your_custom_credential_getter(...):
161
- ...
162
- return {
163
- "access_key": ...,
164
- "secret_key": ...,
165
- "token": ...,
166
- "expiry_time": ...,
167
- }
168
-
169
- # and pass it to RefreshableSession
170
- session = RefreshableSession(
171
- method="custom",
172
- custom_credentials_method=your_custom_credential_getter,
173
- custom_credentials_method_args=...,
174
- region_name=region_name,
175
- profile_name=profile_name,
176
- ...
177
- )
178
- ```
@@ -1,12 +0,0 @@
1
- boto3-refresh-session
2
- Copyright 2024 Michael Letts
3
-
4
- boto3-refresh-session (BRS) includes software designed and developed by Michael Letts (the author).
5
-
6
- Although the author was formerly employed by Amazon, this project was conceived, designed, developed, and released independently after that period of employment. It is not affiliated with or endorsed by Amazon Web Services (AWS), Amazon, or any contributors to boto3 or botocore, regardless of their employment status.
7
-
8
- Developers are welcome and encouraged to modify and adapt this software to suit their needs β€” this is in fact already common practice among some of the largest users of BRS.
9
-
10
- If you find boto3-refresh-session (BRS) helpful in your work, a note of thanks or a mention in your project’s documentation or acknowledgments is appreciated β€” though not required under the terms of the MIT License.
11
-
12
- Licensed under the MIT License. See the LICENSE file for details.
@@ -1,11 +0,0 @@
1
- boto3_refresh_session/__init__.py,sha256=DohG-bMPXA_oNxVdsxqkhkP2WTht4ZhPYZnvr2TOHnk,246
2
- boto3_refresh_session/custom.py,sha256=L3kQ_6e-lmIGgm1GHLngOqJOzeS-oDFoVCPTkva0-PA,3760
3
- boto3_refresh_session/ecs.py,sha256=WIC5mlbcEnM1oo-QXmmtiw2mjFDn01hBfcFh67ku42A,3713
4
- boto3_refresh_session/exceptions.py,sha256=qcFzdIuK5PZirs77H_Kb64S9QFb6cn2OJtirjvaRLiY,972
5
- boto3_refresh_session/session.py,sha256=u1gSsYH3OpcbIurMS2nstPbQtOO-S9GZsuk_yhjEqAI,5304
6
- boto3_refresh_session/sts.py,sha256=paIgbmn9a3cATNX-6AEGxnSGNZnX1pj4rRQmh8gQSKs,3132
7
- boto3_refresh_session-1.3.11.dist-info/LICENSE,sha256=I3ZYTXAjbIly6bm6J-TvFTuuHwTKws4h89QaY5c5HiY,1067
8
- boto3_refresh_session-1.3.11.dist-info/METADATA,sha256=uAQ4YUTH7odAThp-TeiUizKkJMGHmM9ERtcx86atqOU,7052
9
- boto3_refresh_session-1.3.11.dist-info/NOTICE,sha256=1s8r33qbl1z0YvPB942iWgvbkP94P_e8AnROr1qXXuw,939
10
- boto3_refresh_session-1.3.11.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
11
- boto3_refresh_session-1.3.11.dist-info/RECORD,,