boto3-refresh-session 1.0.41__py3-none-any.whl → 1.1.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.
- boto3_refresh_session/__init__.py +3 -5
- boto3_refresh_session/session.py +118 -122
- boto3_refresh_session/sts.py +124 -0
- {boto3_refresh_session-1.0.41.dist-info → boto3_refresh_session-1.1.1.dist-info}/METADATA +28 -32
- boto3_refresh_session-1.1.1.dist-info/RECORD +8 -0
- boto3_refresh_session-1.0.41.dist-info/RECORD +0 -7
- {boto3_refresh_session-1.0.41.dist-info → boto3_refresh_session-1.1.1.dist-info}/LICENSE +0 -0
- {boto3_refresh_session-1.0.41.dist-info → boto3_refresh_session-1.1.1.dist-info}/NOTICE +0 -0
- {boto3_refresh_session-1.0.41.dist-info → boto3_refresh_session-1.1.1.dist-info}/WHEEL +0 -0
@@ -1,8 +1,6 @@
|
|
1
|
-
__all__ = []
|
2
|
-
|
3
|
-
from . import session
|
4
1
|
from .session import RefreshableSession
|
2
|
+
from .sts import STSRefreshableSession
|
5
3
|
|
6
|
-
__all__
|
7
|
-
__version__ = "1.
|
4
|
+
__all__ = ["RefreshableSession"]
|
5
|
+
__version__ = "1.1.1"
|
8
6
|
__author__ = "Mike Letts"
|
boto3_refresh_session/session.py
CHANGED
@@ -1,159 +1,155 @@
|
|
1
1
|
from __future__ import annotations
|
2
2
|
|
3
3
|
__doc__ = """
|
4
|
-
|
5
|
-
|
4
|
+
boto3_refresh_session.session
|
5
|
+
=============================
|
6
|
+
|
7
|
+
This module provides the main interface for constructing refreshable boto3 sessions.
|
8
|
+
|
9
|
+
The ``RefreshableSession`` class serves as a factory that dynamically selects the appropriate
|
10
|
+
credential refresh strategy based on the ``method`` parameter, e.g., ``sts``.
|
11
|
+
|
12
|
+
Users can interact with AWS services just like they would with a normal :class:`boto3.session.Session`,
|
13
|
+
with the added benefit of automatic credential refreshing.
|
14
|
+
|
15
|
+
Examples
|
16
|
+
--------
|
17
|
+
>>> from boto3_refresh_session import RefreshableSession
|
18
|
+
>>> session = RefreshableSession(
|
19
|
+
... assume_role_kwargs={"RoleArn": "...", "RoleSessionName": "..."},
|
20
|
+
... region_name="us-east-1"
|
21
|
+
... )
|
22
|
+
>>> s3 = session.client("s3")
|
23
|
+
>>> s3.list_buckets()
|
24
|
+
|
25
|
+
.. seealso::
|
26
|
+
:class:`boto3_refresh_session.sts.STSRefreshableSession`
|
27
|
+
|
28
|
+
Factory interface
|
29
|
+
-----------------
|
30
|
+
.. autosummary::
|
31
|
+
:toctree: generated/
|
32
|
+
:nosignatures:
|
33
|
+
|
34
|
+
RefreshableSession
|
6
35
|
"""
|
36
|
+
|
7
37
|
__all__ = ["RefreshableSession"]
|
8
38
|
|
9
|
-
from
|
39
|
+
from abc import ABC, abstractmethod
|
40
|
+
from typing import Any, Callable, ClassVar, Literal, get_args
|
10
41
|
from warnings import warn
|
11
42
|
|
12
|
-
from boto3 import client
|
13
43
|
from boto3.session import Session
|
14
44
|
from botocore.credentials import (
|
15
45
|
DeferredRefreshableCredentials,
|
16
46
|
RefreshableCredentials,
|
17
47
|
)
|
18
48
|
|
49
|
+
#: Type alias for all currently available credential refresh methods.
|
50
|
+
Method = Literal["sts"]
|
51
|
+
RefreshMethod = Literal["sts-assume-role"]
|
52
|
+
|
53
|
+
|
54
|
+
class BaseRefreshableSession(ABC, Session):
|
55
|
+
"""Abstract base class for implementing refreshable AWS sessions.
|
19
56
|
|
20
|
-
|
21
|
-
|
22
|
-
|
57
|
+
Provides a common interface and factory registration mechanism
|
58
|
+
for subclasses that generate temporary credentials using various
|
59
|
+
AWS authentication methods (e.g., STS).
|
60
|
+
|
61
|
+
Subclasses must implement ``_get_credentials()`` and ``get_identity()``.
|
62
|
+
They should also register themselves using the ``method=...`` argument
|
63
|
+
to ``__init_subclass__``.
|
23
64
|
|
24
65
|
Parameters
|
25
66
|
----------
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
If ``True`` then temporary credentials are not automatically refreshed until
|
30
|
-
they are explicitly needed. If ``False`` then temporary credentials refresh
|
31
|
-
immediately upon expiration. It is highly recommended that you use ``True``.
|
32
|
-
Default is ``True``.
|
33
|
-
sts_client_kwargs : dict, optional
|
34
|
-
Optional keyword arguments for the :class:`STS.Client` object. Do not provide
|
35
|
-
values for ``service_name``. Default is None.
|
67
|
+
registry : dict[str, type[BaseRefreshableSession]]
|
68
|
+
Class-level registry mapping method names to registered session types.
|
69
|
+
"""
|
36
70
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
Optional keyword arguments for the :class:`boto3.session.Session` object.
|
71
|
+
# adding this and __init_subclass__ to avoid circular imports
|
72
|
+
# as well as simplify future addition of new methods
|
73
|
+
registry: ClassVar[dict[Method, type[BaseRefreshableSession]]] = {}
|
41
74
|
|
42
|
-
|
43
|
-
|
44
|
-
Check the :ref:`authorization documentation <authorization>` for additional
|
45
|
-
information concerning how to authorize access to AWS.
|
75
|
+
def __init_subclass__(cls, method: Method):
|
76
|
+
super().__init_subclass__()
|
46
77
|
|
47
|
-
|
48
|
-
|
78
|
+
# guarantees that methods are unique
|
79
|
+
if method in BaseRefreshableSession.registry:
|
80
|
+
warn(f"Method '{method}' is already registered. Overwriting.")
|
49
81
|
|
50
|
-
|
51
|
-
--------
|
52
|
-
In order to use this object, you are required to configure parameters for the
|
53
|
-
:meth:`STS.Client.assume_role` method.
|
54
|
-
|
55
|
-
>>> assume_role_kwargs = {
|
56
|
-
>>> 'RoleArn': '<your-role-arn>',
|
57
|
-
>>> 'RoleSessionName': '<your-role-session-name>',
|
58
|
-
>>> 'DurationSeconds': '<your-selection>',
|
59
|
-
>>> ...
|
60
|
-
>>> }
|
61
|
-
|
62
|
-
You may also want to provide optional parameters for the :class:`STS.Client` object.
|
63
|
-
|
64
|
-
>>> sts_client_kwargs = {
|
65
|
-
>>> ...
|
66
|
-
>>> }
|
67
|
-
|
68
|
-
You may also provide optional parameters for the :class:`boto3.session.Session` object
|
69
|
-
when initializing the ``RefreshableSession`` object. Below, we use the ``region_name``
|
70
|
-
parameter for illustrative purposes.
|
71
|
-
|
72
|
-
>>> session = boto3_refresh_session.RefreshableSession(
|
73
|
-
>>> assume_role_kwargs=assume_role_kwargs,
|
74
|
-
>>> sts_client_kwargs=sts_client_kwargs,
|
75
|
-
>>> region_name='us-east-1',
|
76
|
-
>>> )
|
77
|
-
|
78
|
-
Using the ``session`` variable that you just created, you can now use all of the methods
|
79
|
-
available from the :class:`boto3.session.Session` object. In the below example, we
|
80
|
-
initialize an S3 client and list all available buckets.
|
81
|
-
|
82
|
-
>>> s3 = session.client(service_name='s3')
|
83
|
-
>>> buckets = s3.list_buckets()
|
84
|
-
|
85
|
-
There are two ways of refreshing temporary credentials automatically with the
|
86
|
-
``RefreshableSession`` object: refresh credentials the moment they expire, or wait until
|
87
|
-
temporary credentials are explicitly needed. The latter is the default. The former must
|
88
|
-
be configured using the ``defer_refresh`` parameter, as shown below.
|
89
|
-
|
90
|
-
>>> session = boto3_refresh_session.RefreshableSession(
|
91
|
-
>>> defer_refresh=False,
|
92
|
-
>>> assume_role_kwargs=assume_role_kwargs,
|
93
|
-
>>> sts_client_kwargs=sts_client_kwargs,
|
94
|
-
>>> region_name='us-east-1',
|
95
|
-
>>> )
|
96
|
-
"""
|
82
|
+
BaseRefreshableSession.registry[method] = cls
|
97
83
|
|
98
|
-
def __init__(
|
99
|
-
self,
|
100
|
-
assume_role_kwargs: Dict[Any],
|
101
|
-
defer_refresh: bool = None,
|
102
|
-
sts_client_kwargs: Dict[Any] = None,
|
103
|
-
**kwargs,
|
104
|
-
):
|
105
|
-
# inheriting from boto3.session.Session
|
84
|
+
def __init__(self, **kwargs):
|
106
85
|
super().__init__(**kwargs)
|
107
86
|
|
108
|
-
|
109
|
-
|
110
|
-
defer_refresh = True
|
111
|
-
|
112
|
-
# initializing custom parameters that are necessary outside of __init__
|
113
|
-
self.assume_role_kwargs = assume_role_kwargs
|
114
|
-
|
115
|
-
# initializing the STS client
|
116
|
-
if sts_client_kwargs is not None:
|
117
|
-
# overwriting 'service_name' in case it appears in sts_client_kwargs
|
118
|
-
if "service_name" in sts_client_kwargs:
|
119
|
-
warn(
|
120
|
-
"The sts_client_kwargs parameter cannot contain values for service_name. Reverting to service_name = 'sts'."
|
121
|
-
)
|
122
|
-
del sts_client_kwargs["service_name"]
|
123
|
-
self._sts_client = client(service_name="sts", **sts_client_kwargs)
|
124
|
-
else:
|
125
|
-
self._sts_client = client(service_name="sts")
|
87
|
+
@abstractmethod
|
88
|
+
def _get_credentials(self) -> dict[str, str]: ...
|
126
89
|
|
90
|
+
@abstractmethod
|
91
|
+
def get_identity(self) -> dict[str, Any]: ...
|
92
|
+
|
93
|
+
def _refresh_using(
|
94
|
+
self,
|
95
|
+
credentials_method: Callable,
|
96
|
+
defer_refresh: bool,
|
97
|
+
refresh_method: RefreshMethod,
|
98
|
+
):
|
127
99
|
# determining how exactly to refresh expired temporary credentials
|
128
100
|
if not defer_refresh:
|
129
|
-
self.
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
method="sts-assume-role",
|
134
|
-
)
|
101
|
+
self._credentials = RefreshableCredentials.create_from_metadata(
|
102
|
+
metadata=credentials_method(),
|
103
|
+
refresh_using=credentials_method,
|
104
|
+
method=refresh_method,
|
135
105
|
)
|
136
106
|
else:
|
137
|
-
self.
|
138
|
-
refresh_using=
|
107
|
+
self._credentials = DeferredRefreshableCredentials(
|
108
|
+
refresh_using=credentials_method, method=refresh_method
|
139
109
|
)
|
140
110
|
|
141
|
-
|
142
|
-
|
111
|
+
|
112
|
+
class RefreshableSession:
|
113
|
+
"""Factory class for constructing refreshable boto3 sessions using various authentication
|
114
|
+
methods, e.g. STS.
|
115
|
+
|
116
|
+
This class provides a unified interface for creating boto3 sessions whose credentials are
|
117
|
+
automatically refreshed in the background.
|
118
|
+
|
119
|
+
Use ``RefreshableSession(method="...")`` to construct an instance using the desired method.
|
120
|
+
|
121
|
+
For additional information on required parameters, refer to the See Also section below.
|
122
|
+
|
123
|
+
Parameters
|
124
|
+
----------
|
125
|
+
method : Method
|
126
|
+
The authentication and refresh method to use for the session. Must match a registered method name.
|
127
|
+
Default is "sts".
|
128
|
+
|
129
|
+
Other Parameters
|
130
|
+
----------------
|
131
|
+
**kwargs : dict
|
132
|
+
Additional keyword arguments forwarded to the constructor of the selected session class.
|
133
|
+
|
134
|
+
See Also
|
135
|
+
--------
|
136
|
+
boto3_refresh_session.sts.STSRefreshableSession
|
137
|
+
"""
|
138
|
+
|
139
|
+
def __new__(
|
140
|
+
cls, method: Method = "sts", **kwargs
|
141
|
+
) -> BaseRefreshableSession:
|
142
|
+
obj = BaseRefreshableSession.registry[method]
|
143
|
+
return obj(**kwargs)
|
144
|
+
|
145
|
+
@classmethod
|
146
|
+
def get_available_methods(cls) -> list[str]:
|
147
|
+
"""Lists all currently available credential refresh methods.
|
143
148
|
|
144
149
|
Returns
|
145
150
|
-------
|
146
|
-
|
147
|
-
|
151
|
+
list[str]
|
152
|
+
A list of all currently available credential refresh methods, e.g. 'sts'.
|
148
153
|
"""
|
149
154
|
|
150
|
-
|
151
|
-
temporary_credentials = self._sts_client.assume_role(
|
152
|
-
**self.assume_role_kwargs
|
153
|
-
)["Credentials"]
|
154
|
-
return {
|
155
|
-
"access_key": temporary_credentials.get("AccessKeyId"),
|
156
|
-
"secret_key": temporary_credentials.get("SecretAccessKey"),
|
157
|
-
"token": temporary_credentials.get("SessionToken"),
|
158
|
-
"expiry_time": temporary_credentials.get("Expiration").isoformat(),
|
159
|
-
}
|
155
|
+
return list(get_args(Method))
|
@@ -0,0 +1,124 @@
|
|
1
|
+
from __future__ import annotations
|
2
|
+
|
3
|
+
__doc__ = """
|
4
|
+
boto3_refresh_session.sts
|
5
|
+
=========================
|
6
|
+
|
7
|
+
Implements the STS-based credential refresh strategy for use with
|
8
|
+
:class:`boto3_refresh_session.session.RefreshableSession`.
|
9
|
+
|
10
|
+
This module defines the :class:`STSRefreshableSession` class, which uses
|
11
|
+
IAM role assumption via STS to automatically refresh temporary credentials
|
12
|
+
in the background.
|
13
|
+
|
14
|
+
.. versionadded:: 1.1.0
|
15
|
+
|
16
|
+
Examples
|
17
|
+
--------
|
18
|
+
>>> from boto3_refresh_session import RefreshableSession
|
19
|
+
>>> session = RefreshableSession(
|
20
|
+
... method="sts",
|
21
|
+
... assume_role_kwargs={
|
22
|
+
... "RoleArn": "arn:aws:iam::123456789012:role/MyRole",
|
23
|
+
... "RoleSessionName": "my-session"
|
24
|
+
... },
|
25
|
+
... region_name="us-east-1"
|
26
|
+
... )
|
27
|
+
>>> s3 = session.client("s3")
|
28
|
+
>>> s3.list_buckets()
|
29
|
+
|
30
|
+
.. seealso::
|
31
|
+
:class:`boto3_refresh_session.session.RefreshableSession`
|
32
|
+
|
33
|
+
STS
|
34
|
+
---
|
35
|
+
|
36
|
+
.. autosummary::
|
37
|
+
:toctree: generated/
|
38
|
+
:nosignatures:
|
39
|
+
|
40
|
+
STSRefreshableSession
|
41
|
+
"""
|
42
|
+
__all__ = ["STSRefreshableSession"]
|
43
|
+
|
44
|
+
from typing import Any
|
45
|
+
from warnings import warn
|
46
|
+
|
47
|
+
from .session import BaseRefreshableSession
|
48
|
+
|
49
|
+
|
50
|
+
class STSRefreshableSession(BaseRefreshableSession, method="sts"):
|
51
|
+
"""A :class:`boto3.session.Session` object that automatically refreshes temporary AWS
|
52
|
+
credentials using an IAM role that is assumed via STS.
|
53
|
+
|
54
|
+
Parameters
|
55
|
+
----------
|
56
|
+
assume_role_kwargs : dict
|
57
|
+
Required keyword arguments for :meth:`STS.Client.assume_role` (i.e. boto3 STS client).
|
58
|
+
defer_refresh : bool, optional
|
59
|
+
If ``True`` then temporary credentials are not automatically refreshed until
|
60
|
+
they are explicitly needed. If ``False`` then temporary credentials refresh
|
61
|
+
immediately upon expiration. It is highly recommended that you use ``True``.
|
62
|
+
Default is ``True``.
|
63
|
+
sts_client_kwargs : dict, optional
|
64
|
+
Optional keyword arguments for the :class:`STS.Client` object. Do not provide
|
65
|
+
values for ``service_name`` as they are unnecessary. Default is None.
|
66
|
+
|
67
|
+
Other Parameters
|
68
|
+
----------------
|
69
|
+
kwargs : dict
|
70
|
+
Optional keyword arguments for the :class:`boto3.session.Session` object.
|
71
|
+
"""
|
72
|
+
|
73
|
+
def __init__(
|
74
|
+
self,
|
75
|
+
assume_role_kwargs: dict,
|
76
|
+
defer_refresh: bool = None,
|
77
|
+
sts_client_kwargs: dict | None = None,
|
78
|
+
**kwargs,
|
79
|
+
):
|
80
|
+
super().__init__(**kwargs)
|
81
|
+
defer_refresh = defer_refresh is not False
|
82
|
+
self.assume_role_kwargs = assume_role_kwargs
|
83
|
+
|
84
|
+
if sts_client_kwargs is not None:
|
85
|
+
# overwriting 'service_name' in case it appears in sts_client_kwargs
|
86
|
+
if "service_name" in sts_client_kwargs:
|
87
|
+
warn(
|
88
|
+
"The sts_client_kwargs parameter cannot contain values for service_name. Reverting to service_name = 'sts'."
|
89
|
+
)
|
90
|
+
del sts_client_kwargs["service_name"]
|
91
|
+
self._sts_client = self.client(
|
92
|
+
service_name="sts", **sts_client_kwargs
|
93
|
+
)
|
94
|
+
else:
|
95
|
+
self._sts_client = self.client(service_name="sts")
|
96
|
+
|
97
|
+
# mounting refreshable credentials
|
98
|
+
self._refresh_using(
|
99
|
+
credentials_method=self._get_credentials,
|
100
|
+
defer_refresh=defer_refresh,
|
101
|
+
refresh_method="sts-assume-role",
|
102
|
+
)
|
103
|
+
|
104
|
+
def _get_credentials(self) -> dict[str, str]:
|
105
|
+
temporary_credentials = self._sts_client.assume_role(
|
106
|
+
**self.assume_role_kwargs
|
107
|
+
)["Credentials"]
|
108
|
+
return {
|
109
|
+
"access_key": temporary_credentials.get("AccessKeyId"),
|
110
|
+
"secret_key": temporary_credentials.get("SecretAccessKey"),
|
111
|
+
"token": temporary_credentials.get("SessionToken"),
|
112
|
+
"expiry_time": temporary_credentials.get("Expiration").isoformat(),
|
113
|
+
}
|
114
|
+
|
115
|
+
def get_identity(self) -> dict[str, Any]:
|
116
|
+
"""Returns metadata about the identity assumed.
|
117
|
+
|
118
|
+
Returns
|
119
|
+
-------
|
120
|
+
dict[str, Any]
|
121
|
+
Dict containing caller identity according to AWS STS.
|
122
|
+
"""
|
123
|
+
|
124
|
+
return self._sts_client.get_caller_identity()
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.3
|
2
2
|
Name: boto3-refresh-session
|
3
|
-
Version: 1.
|
3
|
+
Version: 1.1.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
|
@@ -56,7 +56,7 @@ Description-Content-Type: text/markdown
|
|
56
56
|
</a>
|
57
57
|
|
58
58
|
<a href="https://pepy.tech/project/boto3-refresh-session">
|
59
|
-
<img src="https://img.shields.io/badge/downloads-
|
59
|
+
<img src="https://img.shields.io/badge/downloads-57.4K-red?logo=python&color=%23FF0000&label=Downloads" alt="Downloads"/>
|
60
60
|
</a>
|
61
61
|
|
62
62
|
<a href="https://michaelthomasletts.github.io/boto3-refresh-session/index.html">
|
@@ -79,28 +79,23 @@ Description-Content-Type: text/markdown
|
|
79
79
|
- Drop-in replacement for `boto3.session.Session`
|
80
80
|
- Supports `assume_role` configuration, custom STS clients, and profile / region configuration, as well as all other parameters supported by `boto3.session.Session`
|
81
81
|
- Tested, documented, and published to PyPI
|
82
|
-
- Used in production at major tech companies
|
83
82
|
|
84
|
-
## Adoption and
|
83
|
+
## Recognition, Adoption, and Testimonials
|
85
84
|
|
86
|
-
[
|
85
|
+
[Featured in TL;DR Sec.](https://tldrsec.com/p/tldr-sec-282)
|
87
86
|
|
88
|
-
|
87
|
+
Recognized during AWS Community Day Midwest on June 5th, 2025.
|
89
88
|
|
90
|
-
|
89
|
+
A testimonial from a Cyber Security Engineer at a FAANG company:
|
91
90
|
|
92
|
-
|
91
|
+
> _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._
|
92
|
+
|
93
|
+
The following line plot illustrates the adoption of BRS over the last three months in terms of average daily downloads over a rolling seven day window.
|
93
94
|
|
94
95
|
<p align="center">
|
95
96
|
<img src="https://raw.githubusercontent.com/michaelthomasletts/boto3-refresh-session/refs/heads/main/doc/downloads.png" />
|
96
97
|
</p>
|
97
98
|
|
98
|
-
## Testimonials
|
99
|
-
|
100
|
-
From a Cyber Security Engineer at a FAANG company:
|
101
|
-
|
102
|
-
> _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._
|
103
|
-
|
104
99
|
## Installation
|
105
100
|
|
106
101
|
```bash
|
@@ -148,27 +143,28 @@ buckets = s3.list_buckets()
|
|
148
143
|
|
149
144
|
## Raison d'être
|
150
145
|
|
151
|
-
|
152
|
-
|
153
|
-
expire
|
146
|
+
Long-running data pipelines, security tooling, ETL jobs, and cloud automation scripts frequently interact with the AWS API using boto3 — and often run into the same problem:
|
147
|
+
|
148
|
+
**Temporary credentials expire.**
|
149
|
+
|
150
|
+
When that happens, engineers typically fall back on one of two strategies:
|
151
|
+
|
152
|
+
- Wrapping AWS calls in try/except blocks that catch ClientError exceptions
|
153
|
+
- Writing ad hoc logic to refresh credentials using botocore credentials internals
|
154
154
|
|
155
|
-
|
155
|
+
Both approaches are fragile, tedious to maintain, and error-prone at scale.
|
156
156
|
|
157
|
-
|
158
|
-
-
|
159
|
-
|
160
|
-
|
161
|
-
Speaking personally, variations of the code found herein exists in code bases at
|
162
|
-
nearly every company where I have worked. Sometimes, I turned that code into a module;
|
163
|
-
other times, I wrote it from scratch. Clearly, that is inefficient.
|
157
|
+
Over the years, I noticed that every company I worked for — whether a scrappy startup or FAANG — ended up with some variation of the same pattern:
|
158
|
+
a small in-house module to manage credential refresh, written in haste, duplicated across services, and riddled with edge cases. Things only
|
159
|
+
got more strange and difficult when I needed to run things in parallel.
|
164
160
|
|
165
|
-
I decided to
|
166
|
-
automatic documentation, and quality checks; the idea being that, henceforth, depending
|
167
|
-
on my employer's open source policy, I may simply import this package instead of
|
168
|
-
reproducing the code herein for the Nth time.
|
161
|
+
Eventually, I decided to build boto3-refresh-session as a proper open-source Python package:
|
169
162
|
|
170
|
-
|
163
|
+
- Fully tested
|
164
|
+
- Extensible
|
165
|
+
- Integrated with boto3 idioms
|
166
|
+
- Equipped with automatic documentation and CI tooling
|
171
167
|
|
172
|
-
|
168
|
+
**The goal:** to solve a real, recurring problem once — cleanly, consistently, and for everyone - with multiple refresh strategies.
|
173
169
|
|
174
|
-
|
170
|
+
If you've ever written the same AWS credential-refresh boilerplate more than once, this library is for you.
|
@@ -0,0 +1,8 @@
|
|
1
|
+
boto3_refresh_session/__init__.py,sha256=fNXIqvmUf8kJOrnVb13wLI5njrl3ApC9mn2D7OEV-T8,161
|
2
|
+
boto3_refresh_session/session.py,sha256=J3FW6nkc_s9C0gj1Xs1wKaCWQMzR6S4ncDKDqu1DYxk,4879
|
3
|
+
boto3_refresh_session/sts.py,sha256=P8lWxQLslXDeYSuvHuy0Le6CC5SIXxQ9D5DZFmwwE1Q,4057
|
4
|
+
boto3_refresh_session-1.1.1.dist-info/LICENSE,sha256=I3ZYTXAjbIly6bm6J-TvFTuuHwTKws4h89QaY5c5HiY,1067
|
5
|
+
boto3_refresh_session-1.1.1.dist-info/METADATA,sha256=tsA-RTs1WXeTICfNn-N9DlUCavxfla4SN0Au41p6__U,7533
|
6
|
+
boto3_refresh_session-1.1.1.dist-info/NOTICE,sha256=1s8r33qbl1z0YvPB942iWgvbkP94P_e8AnROr1qXXuw,939
|
7
|
+
boto3_refresh_session-1.1.1.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
|
8
|
+
boto3_refresh_session-1.1.1.dist-info/RECORD,,
|
@@ -1,7 +0,0 @@
|
|
1
|
-
boto3_refresh_session/__init__.py,sha256=NryXLl4sSu3AO_-yrcFsiWU09XnHr-ap4-qr39btGLI,158
|
2
|
-
boto3_refresh_session/session.py,sha256=ZB1X0ajFZSpuRKi4N3KGg56Y7ZJPMN3jwjMh-6grbvo,5881
|
3
|
-
boto3_refresh_session-1.0.41.dist-info/LICENSE,sha256=I3ZYTXAjbIly6bm6J-TvFTuuHwTKws4h89QaY5c5HiY,1067
|
4
|
-
boto3_refresh_session-1.0.41.dist-info/METADATA,sha256=GJZhfPAymeIm1kWAzY4GDrvO_biuYWVMgp4ep28qclA,7406
|
5
|
-
boto3_refresh_session-1.0.41.dist-info/NOTICE,sha256=1s8r33qbl1z0YvPB942iWgvbkP94P_e8AnROr1qXXuw,939
|
6
|
-
boto3_refresh_session-1.0.41.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
|
7
|
-
boto3_refresh_session-1.0.41.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|