boto3-refresh-session 0.1.23__tar.gz → 1.0.0__tar.gz

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,7 +1,7 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: boto3-refresh-session
3
- Version: 0.1.23
4
- Summary: A simple Python package for refreshing AWS temporary credentials in boto3 automatically.
3
+ Version: 1.0.0
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
7
7
  Author: Mike Letts
@@ -15,7 +15,6 @@ Classifier: Programming Language :: Python :: 3.10
15
15
  Classifier: Programming Language :: Python :: 3.11
16
16
  Classifier: Programming Language :: Python :: 3.12
17
17
  Classifier: Programming Language :: Python :: 3.13
18
- Requires-Dist: attrs (>=24.3.0,<25.0.0)
19
18
  Requires-Dist: boto3
20
19
  Requires-Dist: botocore
21
20
  Project-URL: Documentation, https://michaelthomasletts.github.io/boto3-refresh-session/index.html
@@ -27,17 +26,16 @@ Description-Content-Type: text/markdown
27
26
  [![Workflow](https://img.shields.io/github/actions/workflow/status/michaelthomasletts/boto3-refresh-session/push.yml?logo=github)](https://github.com/michaelthomasletts/boto3-refresh-session/actions/workflows/push_pullrequest.yml)
28
27
  ![Python Version](https://img.shields.io/pypi/pyversions/boto3-refresh-session?style=pypi)
29
28
  ![GitHub last commit](https://img.shields.io/github/last-commit/michaelthomasletts/boto3-refresh-session?logo=github)
30
- ![GitHub Repo stars](https://img.shields.io/github/stars/michaelthomasletts/boto3-refresh-session?logo=github)
31
- ![GitHub forks](https://img.shields.io/github/forks/michaelthomasletts/boto3-refresh-session?logo=github)
32
29
  ![PyPI - Downloads](https://img.shields.io/pypi/dm/boto3-refresh-session?logo=pypi)
33
30
 
34
31
  ![BRS Image](https://raw.githubusercontent.com/michaelthomasletts/boto3-refresh-session/refs/heads/main/doc/brs.png)
35
32
 
36
- A simple Python package for refreshing AWS temporary credentials in ``boto3`` automatically.
33
+ A simple Python package for refreshing the temporary security credentials in a `boto3.session.Session` object automatically.
37
34
 
38
35
  - [Documentation](https://michaelthomasletts.github.io/boto3-refresh-session/index.html)
39
36
  - [Source Code](https://github.com/michaelthomasletts/boto3-refresh-session)
40
37
  - [PyPI](https://pypi.org/project/boto3-refresh-session/)
38
+ - [Contributing](https://michaelthomasletts.github.io/boto3-refresh-session/contributing.html)
41
39
 
42
40
  ### Why should I use this?
43
41
 
@@ -45,9 +43,9 @@ It is common for data pipelines and workflows that interact with the AWS API via
45
43
  `boto3` to run for a long time and, accordingly, for temporary credentials to
46
44
  expire.
47
45
 
48
- Usually, engineers deal with that problem one of two ways:
46
+ Usually, engineers deal with that problem one of two different ways:
49
47
 
50
- - `try except` blocks that catch `ClientError` exceptions
48
+ - A `try except` block that catches `botocore.exceptions.ClientError` exceptions
51
49
  - A similar approach as that used in this project -- that is, using methods available
52
50
  within `botocore` for refreshing temporary credentials automatically.
53
51
 
@@ -64,10 +62,10 @@ If any of that sounds relatable, then `boto3-refresh-session` should help you!
64
62
 
65
63
  ### Usage
66
64
 
67
- Simply pass the basic parameters and initialize the `AutoRefreshableSession` object;
65
+ Simply pass the basic parameters and initialize the `RefreshableSession` object;
68
66
  that's it! You're good to go!
69
67
 
70
- `AutoRefreshableSession` will refresh
68
+ `RefreshableSession` will refresh
71
69
  temporary credentials for you in the background. In the following example,
72
70
  continue using the `s3_client` object without worry of using `try` and
73
71
  `except` blocks!
@@ -79,13 +77,22 @@ machine, check [this documentation](https://boto3.amazonaws.com/v1/documentation
79
77
  ```python
80
78
  import boto3_refresh_session as brs
81
79
 
82
-
83
- sess = brs.AutoRefreshableSession(
84
- region="<your-region>",
85
- role_arn="<your-role-arn>",
86
- session_name="<your-session-name>",
80
+ assume_role_kwargs = {
81
+ 'RoleArn': '<your-role-arn>',
82
+ 'RoleSessionName': '<your-role-session-name>',
83
+ 'DurationSeconds': '<your-selection>',
84
+ ...
85
+ }
86
+ sts_client_kwargs = {
87
+ ...
88
+ }
89
+ session = brs.RefreshableSession(
90
+ assume_role_kwargs=assume_role_kwargs,
91
+ sts_client_kwargs=sts_client_kwargs,
92
+ region_name='us-east-1',
87
93
  )
88
- s3_client = sess.session.client(service_name="s3")
94
+ s3 = session.client(service_name='s3')
95
+ buckets = s3.list_buckets()
89
96
  ```
90
97
 
91
98
  ### Installation
@@ -3,17 +3,16 @@
3
3
  [![Workflow](https://img.shields.io/github/actions/workflow/status/michaelthomasletts/boto3-refresh-session/push.yml?logo=github)](https://github.com/michaelthomasletts/boto3-refresh-session/actions/workflows/push_pullrequest.yml)
4
4
  ![Python Version](https://img.shields.io/pypi/pyversions/boto3-refresh-session?style=pypi)
5
5
  ![GitHub last commit](https://img.shields.io/github/last-commit/michaelthomasletts/boto3-refresh-session?logo=github)
6
- ![GitHub Repo stars](https://img.shields.io/github/stars/michaelthomasletts/boto3-refresh-session?logo=github)
7
- ![GitHub forks](https://img.shields.io/github/forks/michaelthomasletts/boto3-refresh-session?logo=github)
8
6
  ![PyPI - Downloads](https://img.shields.io/pypi/dm/boto3-refresh-session?logo=pypi)
9
7
 
10
8
  ![BRS Image](https://raw.githubusercontent.com/michaelthomasletts/boto3-refresh-session/refs/heads/main/doc/brs.png)
11
9
 
12
- A simple Python package for refreshing AWS temporary credentials in ``boto3`` automatically.
10
+ A simple Python package for refreshing the temporary security credentials in a `boto3.session.Session` object automatically.
13
11
 
14
12
  - [Documentation](https://michaelthomasletts.github.io/boto3-refresh-session/index.html)
15
13
  - [Source Code](https://github.com/michaelthomasletts/boto3-refresh-session)
16
14
  - [PyPI](https://pypi.org/project/boto3-refresh-session/)
15
+ - [Contributing](https://michaelthomasletts.github.io/boto3-refresh-session/contributing.html)
17
16
 
18
17
  ### Why should I use this?
19
18
 
@@ -21,9 +20,9 @@ It is common for data pipelines and workflows that interact with the AWS API via
21
20
  `boto3` to run for a long time and, accordingly, for temporary credentials to
22
21
  expire.
23
22
 
24
- Usually, engineers deal with that problem one of two ways:
23
+ Usually, engineers deal with that problem one of two different ways:
25
24
 
26
- - `try except` blocks that catch `ClientError` exceptions
25
+ - A `try except` block that catches `botocore.exceptions.ClientError` exceptions
27
26
  - A similar approach as that used in this project -- that is, using methods available
28
27
  within `botocore` for refreshing temporary credentials automatically.
29
28
 
@@ -40,10 +39,10 @@ If any of that sounds relatable, then `boto3-refresh-session` should help you!
40
39
 
41
40
  ### Usage
42
41
 
43
- Simply pass the basic parameters and initialize the `AutoRefreshableSession` object;
42
+ Simply pass the basic parameters and initialize the `RefreshableSession` object;
44
43
  that's it! You're good to go!
45
44
 
46
- `AutoRefreshableSession` will refresh
45
+ `RefreshableSession` will refresh
47
46
  temporary credentials for you in the background. In the following example,
48
47
  continue using the `s3_client` object without worry of using `try` and
49
48
  `except` blocks!
@@ -55,13 +54,22 @@ machine, check [this documentation](https://boto3.amazonaws.com/v1/documentation
55
54
  ```python
56
55
  import boto3_refresh_session as brs
57
56
 
58
-
59
- sess = brs.AutoRefreshableSession(
60
- region="<your-region>",
61
- role_arn="<your-role-arn>",
62
- session_name="<your-session-name>",
57
+ assume_role_kwargs = {
58
+ 'RoleArn': '<your-role-arn>',
59
+ 'RoleSessionName': '<your-role-session-name>',
60
+ 'DurationSeconds': '<your-selection>',
61
+ ...
62
+ }
63
+ sts_client_kwargs = {
64
+ ...
65
+ }
66
+ session = brs.RefreshableSession(
67
+ assume_role_kwargs=assume_role_kwargs,
68
+ sts_client_kwargs=sts_client_kwargs,
69
+ region_name='us-east-1',
63
70
  )
64
- s3_client = sess.session.client(service_name="s3")
71
+ s3 = session.client(service_name='s3')
72
+ buckets = s3.list_buckets()
65
73
  ```
66
74
 
67
75
  ### Installation
@@ -0,0 +1,6 @@
1
+ __all__ = []
2
+
3
+ from . import session
4
+ from .session import RefreshableSession
5
+
6
+ __all__.extend(["session", "RefreshableSession"])
@@ -0,0 +1,145 @@
1
+ from __future__ import annotations
2
+
3
+ __doc__ = """
4
+ A :class:`boto3.session.Session` object that automatically refreshes temporary
5
+ credentials.
6
+ """
7
+ __all__ = ["RefreshableSession"]
8
+
9
+ from boto3 import client
10
+ from boto3.session import Session
11
+ from botocore.credentials import (
12
+ DeferredRefreshableCredentials,
13
+ RefreshableCredentials,
14
+ )
15
+
16
+
17
+ class RefreshableSession(Session):
18
+ """Returns a :class:`boto3.session.Session` object with temporary credentials
19
+ that refresh automatically.
20
+
21
+ Parameters
22
+ ----------
23
+ assume_role_kwargs : dict
24
+ Required keyword arguments for the :meth:`STS.Client.assume_role` method.
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
+ sts_client_kwargs : dict, optional
31
+ Optional keyword arguments for the :class:`STS.Client` object. Default is
32
+ an empty dictionary.
33
+
34
+ Other Parameters
35
+ ----------------
36
+ kwargs : dict
37
+ Optional keyword arguments for the :class:`boto3.session.Session` object.
38
+
39
+ Notes
40
+ -----
41
+ Check the :ref:`authorization documentation <authorization>` for additional
42
+ information concerning how to authorize access to AWS.
43
+
44
+ Check the `AWS documentation <https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp.html>`_
45
+ for additional information concerning temporary security credentials in IAM.
46
+
47
+ Examples
48
+ --------
49
+ In order to use this object, you are required to configure parameters for the
50
+ :meth:`STS.Client.assume_role` method.
51
+
52
+ >>> assume_role_kwargs = {
53
+ >>> 'RoleArn': '<your-role-arn>',
54
+ >>> 'RoleSessionName': '<your-role-session-name>',
55
+ >>> 'DurationSeconds': '<your-selection>',
56
+ >>> ...
57
+ >>> }
58
+
59
+ You may also want to provide optional parameters for the :class:`STS.Client` object.
60
+
61
+ >>> sts_client_kwargs = {
62
+ >>> ...
63
+ >>> }
64
+
65
+ You may also provide optional parameters for the :class:`boto3.session.Session` object
66
+ when initializing the ``RefreshableSession`` object. Below, we use the ``region_name``
67
+ parameter for illustrative purposes.
68
+
69
+ >>> session = boto3_refresh_session.RefreshableSession(
70
+ >>> assume_role_kwargs=assume_role_kwargs,
71
+ >>> sts_client_kwargs=sts_client_kwargs,
72
+ >>> region_name='us-east-1',
73
+ >>> )
74
+
75
+ Using the ``session`` variable that you just created, you can now use all of the methods
76
+ available from the :class:`boto3.session.Session` object. In the below example, we
77
+ initialize an S3 client and list all available buckets.
78
+
79
+ >>> s3 = session.client(service_name='s3')
80
+ >>> buckets = s3.list_buckets()
81
+
82
+ There are two ways of refreshing temporary credentials automatically with the
83
+ ``RefreshableSession`` object: refresh credentials the moment they expire, or wait until
84
+ temporary credentials are explicitly needed. The latter is the default. The former must
85
+ be configured using the ``defer_refresh`` parameter, as shown below.
86
+
87
+ >>> session = boto3_refresh_session.RefreshableSession(
88
+ >>> defer_refresh=False,
89
+ >>> assume_role_kwargs=assume_role_kwargs,
90
+ >>> sts_client_kwargs=sts_client_kwargs,
91
+ >>> region_name='us-east-1',
92
+ >>> )
93
+ """
94
+
95
+ def __init__(
96
+ self,
97
+ assume_role_kwargs: dict,
98
+ defer_refresh: bool = True,
99
+ sts_client_kwargs: dict = {},
100
+ **kwargs,
101
+ ):
102
+ # inheriting from boto3.session.Session
103
+ super().__init__(**kwargs)
104
+
105
+ # initializing custom parameters that are necessary outside of __init__
106
+ self.assume_role_kwargs = assume_role_kwargs
107
+
108
+ # initializing the STS client
109
+ self._sts_client = client(service_name="sts", **sts_client_kwargs)
110
+
111
+ # determining how exactly to refresh expired temporary credentials
112
+ if not defer_refresh:
113
+ self._session._credentials = (
114
+ RefreshableCredentials.create_from_metadata(
115
+ metadata=self._get_credentials(),
116
+ refresh_using=self._get_credentials,
117
+ method="sts-assume-role",
118
+ )
119
+ )
120
+ else:
121
+ self._session._credentials = DeferredRefreshableCredentials(
122
+ refresh_using=self._get_credentials, method="sts-assume-role"
123
+ )
124
+
125
+ def _get_credentials(self) -> dict:
126
+ """Returns temporary credentials via AWS STS.
127
+
128
+ Returns
129
+ -------
130
+ dict
131
+ AWS temporary credentials.
132
+ """
133
+
134
+ # fetching temporary credentials
135
+ _temporary_credentials = self._sts_client.assume_role(
136
+ **self.assume_role_kwargs
137
+ )["Credentials"]
138
+ return {
139
+ "access_key": _temporary_credentials.get("AccessKeyId"),
140
+ "secret_key": _temporary_credentials.get("SecretAccessKey"),
141
+ "token": _temporary_credentials.get("SessionToken"),
142
+ "expiry_time": _temporary_credentials.get(
143
+ "Expiration"
144
+ ).isoformat(),
145
+ }
@@ -1,14 +1,14 @@
1
1
  [project]
2
2
  name = "boto3-refresh-session"
3
- version = "0.1.23"
4
- description = "A simple Python package for refreshing AWS temporary credentials in boto3 automatically."
3
+ version = "1.0.0"
4
+ description = "A simple Python package for refreshing the temporary security credentials in a boto3.session.Session object automatically."
5
5
  authors = [
6
6
  {name = "Mike Letts",email = "lettsmt@gmail.com"}
7
7
  ]
8
8
  license = {text = "MIT"}
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10"
11
- dependencies = ["boto3", "botocore", "attrs (>=24.3.0,<25.0.0)"]
11
+ dependencies = ["boto3", "botocore"]
12
12
  keywords = ["boto3", "botocore", "aws"]
13
13
  maintainers = [
14
14
  {name="Michael Letts", email="lettsmt@gmail.com"},
@@ -1,6 +0,0 @@
1
- __all__ = []
2
-
3
- from . import session
4
- from .session import AutoRefreshableSession
5
-
6
- __all__.extend(["session", "AutoRefreshableSession"])
@@ -1,171 +0,0 @@
1
- from __future__ import annotations
2
-
3
- __doc__ = """
4
- Helper method for generating an automatically refreshing :class:`boto3.session.Session`
5
- object.
6
-
7
- .. warning::
8
- ``AutoRefreshableSession`` was not tested for manually passing hard-coded
9
- account credentials to the ``boto3.client`` object! There is an optional
10
- ``client_kwargs`` parameter available for doing so, which *should* work;
11
- however, that cannot be guaranteed as that functionality was not tested.
12
- Pass hard-coded credentials with the ``client_kwargs`` parameter at your
13
- own discretion.
14
- """
15
- __all__ = ["AutoRefreshableSession"]
16
-
17
- from logging import INFO, basicConfig, getLogger
18
- from typing import Type
19
-
20
- from attrs import define, field
21
- from attrs.validators import ge, instance_of, optional
22
- from boto3 import Session, client
23
- from botocore.credentials import (
24
- DeferredRefreshableCredentials,
25
- RefreshableCredentials,
26
- )
27
- from botocore.session import get_session
28
-
29
- # configuring logging
30
- basicConfig(
31
- level=INFO, format="%(asctime)s - %(name)s - %(levelname)s - %(message)s"
32
- )
33
-
34
- # creating logger
35
- logger = getLogger(__name__)
36
-
37
-
38
- @define
39
- class AutoRefreshableSession:
40
- """Returns a :class:`boto3.session.Session` object which refreshes automatically, no extra
41
- steps required.
42
-
43
- This object is useful for long-running processes where temporary credentials
44
- may expire.
45
-
46
- Parameters
47
- ----------
48
- region : str
49
- AWS region name.
50
- role_arn : str
51
- AWS role ARN.
52
- session_name : str
53
- Name for session.
54
- defer_refresh : bool, optional
55
- If ``True`` then temporary credentials are not automatically refreshed until
56
- they are explicitly needed. If ``False`` then temporary credentials refresh
57
- immediately upon expiration. Default is ``True``.
58
- ttl : int, optional
59
- Number of seconds until temporary credentials expire. Must be greater than or
60
- equal to 900 seconds. Default is 900.
61
- session_kwargs : dict, optional
62
- Optional keyword arguments for :class:`boto3.session.Session`.
63
- client_kwargs : dict, optional
64
- Optional keyword arguments for ``boto3.client``.
65
-
66
- Attributes
67
- ----------
68
- session
69
- Returns a :class:`boto3.session.Session` object with credentials which refresh
70
- automatically.
71
-
72
- Notes
73
- -----
74
- Check the :ref:`authorization documentation <authorization>` for additional
75
- information concerning how to authorize access to AWS.
76
-
77
- The default ``defer_refresh`` parameter value results in temporary credentials not
78
- being refreshed until they are explicitly requested; that is more efficient than
79
- refreshing expired temporary credentials automatically after they expire.
80
-
81
- Examples
82
- --------
83
- Here's how to initialize this object:
84
-
85
- >>> sess = brs.AutoRefreshableSession(
86
- >>> region="us-east-1",
87
- >>> role_arn="<your-arn>",
88
- >>> session_name="test",
89
- >>> )
90
- >>> s3_client = sess.session.client(service_name="s3")
91
- """
92
-
93
- region: str = field(validator=instance_of(str))
94
- role_arn: str = field(validator=instance_of(str))
95
- session_name: str = field(validator=instance_of(str))
96
- defer_refresh: bool = field(default=True, validator=instance_of(bool))
97
- ttl: int = field(
98
- default=900, validator=optional([instance_of(int), ge(900)])
99
- )
100
- session_kwargs: dict = field(
101
- default={}, validator=optional(instance_of(dict))
102
- )
103
- client_kwargs: dict = field(
104
- default={}, validator=optional(instance_of(dict))
105
- )
106
- session: Type[Session] = field(init=False)
107
- _creds_already_fetched: int = field(init=False, default=0)
108
- _sts_client: Type["botocore.client.STS"] = field(init=False)
109
-
110
- def __attrs_post_init__(self):
111
- # initializing session
112
- _session = get_session()
113
-
114
- # initializing STS client
115
- self._sts_client = client(
116
- service_name="sts", region_name=self.region, **self.client_kwargs
117
- )
118
-
119
- logger.info("Fetching temporary AWS credentials.")
120
-
121
- # determining how to refresh expired temporary credentials
122
- if not self.defer_refresh:
123
- __credentials = RefreshableCredentials.create_from_metadata(
124
- metadata=self._get_credentials(),
125
- refresh_using=self._get_credentials,
126
- method="sts-assume-role",
127
- )
128
- else:
129
- __credentials = DeferredRefreshableCredentials(
130
- refresh_using=self._get_credentials, method="sts-assume-role"
131
- )
132
-
133
- # mounting temporary credentials to session object
134
- _session._credentials = __credentials
135
-
136
- # initializing session using temporary credentials
137
- self.session = Session(
138
- botocore_session=_session, **self.session_kwargs
139
- )
140
-
141
- def _get_credentials(self) -> dict:
142
- """Returns temporary credentials via AWS STS.
143
-
144
- Returns
145
- -------
146
- dict
147
- AWS temporary credentials.
148
- """
149
-
150
- # being careful not to duplicate logs
151
- if (self.defer_refresh and self._creds_already_fetched) or (
152
- not self.defer_refresh and self._creds_already_fetched > 1
153
- ):
154
- logger.info("Refreshing temporary AWS credentials")
155
- else:
156
- self._creds_already_fetched += 1
157
-
158
- # fetching temporary credentials
159
- _temporary_credentials = self._sts_client.assume_role(
160
- RoleArn=self.role_arn,
161
- RoleSessionName=self.session_name,
162
- DurationSeconds=self.ttl,
163
- )["Credentials"]
164
- return {
165
- "access_key": _temporary_credentials.get("AccessKeyId"),
166
- "secret_key": _temporary_credentials.get("SecretAccessKey"),
167
- "token": _temporary_credentials.get("SessionToken"),
168
- "expiry_time": _temporary_credentials.get(
169
- "Expiration"
170
- ).isoformat(),
171
- }