lupaxa-aws-authenticate 0.1.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.
- lupaxa_aws_authenticate-0.1.0/.gitignore +22 -0
- lupaxa_aws_authenticate-0.1.0/LICENCE +21 -0
- lupaxa_aws_authenticate-0.1.0/PKG-INFO +488 -0
- lupaxa_aws_authenticate-0.1.0/README.md +453 -0
- lupaxa_aws_authenticate-0.1.0/docs/README.md +23 -0
- lupaxa_aws_authenticate-0.1.0/pyproject.toml +87 -0
- lupaxa_aws_authenticate-0.1.0/src/lupaxa/aws_authenticate/__init__.py +24 -0
- lupaxa_aws_authenticate-0.1.0/src/lupaxa/aws_authenticate/credentials.py +12 -0
- lupaxa_aws_authenticate-0.1.0/src/lupaxa/aws_authenticate/errors.py +21 -0
- lupaxa_aws_authenticate-0.1.0/src/lupaxa/aws_authenticate/mfa.py +15 -0
- lupaxa_aws_authenticate-0.1.0/src/lupaxa/aws_authenticate/py.typed +0 -0
- lupaxa_aws_authenticate-0.1.0/src/lupaxa/aws_authenticate/session.py +571 -0
- lupaxa_aws_authenticate-0.1.0/src/lupaxa/aws_authenticate/sso.py +295 -0
- lupaxa_aws_authenticate-0.1.0/src/lupaxa/aws_authenticate/version.py +8 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) The Lupaxa Project
|
|
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.
|
|
@@ -0,0 +1,488 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: lupaxa-aws-authenticate
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Resolve any AWS credential source into one boto3 session.
|
|
5
|
+
Project-URL: Homepage, https://github.com/lupaxa-aws-toolbox/aws-authenticate
|
|
6
|
+
Project-URL: Repository, https://github.com/lupaxa-aws-toolbox/aws-authenticate
|
|
7
|
+
Project-URL: Issues, https://github.com/lupaxa-aws-toolbox/aws-authenticate/issues
|
|
8
|
+
Author: The Lupaxa Project
|
|
9
|
+
Maintainer: The Lupaxa Project
|
|
10
|
+
License-Expression: MIT
|
|
11
|
+
License-File: LICENCE
|
|
12
|
+
Keywords: authentication,aws,boto3
|
|
13
|
+
Classifier: Development Status :: 3 - Alpha
|
|
14
|
+
Classifier: Intended Audience :: Developers
|
|
15
|
+
Classifier: Natural Language :: English
|
|
16
|
+
Classifier: Operating System :: MacOS
|
|
17
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
18
|
+
Classifier: Programming Language :: Python :: 3
|
|
19
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
22
|
+
Classifier: Topic :: Software Development
|
|
23
|
+
Requires-Python: >=3.13
|
|
24
|
+
Requires-Dist: boto3<2,>=1.35.0
|
|
25
|
+
Provides-Extra: dev
|
|
26
|
+
Requires-Dist: hatch>=1.12.0; extra == 'dev'
|
|
27
|
+
Requires-Dist: mypy<2.0.0,>=1.17.0; extra == 'dev'
|
|
28
|
+
Requires-Dist: pytest-cov<7.0.0,>=6.2.0; extra == 'dev'
|
|
29
|
+
Requires-Dist: pytest<9.0.0,>=8.4.0; extra == 'dev'
|
|
30
|
+
Requires-Dist: ruff<1.0.0,>=0.12.0; extra == 'dev'
|
|
31
|
+
Provides-Extra: test
|
|
32
|
+
Requires-Dist: pytest-cov<7.0.0,>=6.2.0; extra == 'test'
|
|
33
|
+
Requires-Dist: pytest<9.0.0,>=8.4.0; extra == 'test'
|
|
34
|
+
Description-Content-Type: text/markdown
|
|
35
|
+
|
|
36
|
+
<p align="center">
|
|
37
|
+
<a href="https://github.com/lupaxa-aws-toolbox">
|
|
38
|
+
<img src="https://raw.githubusercontent.com/the-lupaxa-project/brand-assets/master/logos/organisations/aws-toolbox/readme-logo.png" alt="AWS Toolbox" />
|
|
39
|
+
</a>
|
|
40
|
+
</p>
|
|
41
|
+
|
|
42
|
+
<h1 align="center">Aws Authenticate</h1>
|
|
43
|
+
|
|
44
|
+
Resolve AWS credentials and hand back one boto3 session. Callers do not branch on how the keys were obtained. Every constructor returns an `AuthenticatedSession`.
|
|
45
|
+
|
|
46
|
+
The session is a boto3 `Session`. It adds two attributes:
|
|
47
|
+
|
|
48
|
+
- `method` is the credential source that won. It is fixed when the session is created. A later refresh does not change it.
|
|
49
|
+
- `credentials` is a fresh `AwsCredentials` snapshot: `access_key_id`, `secret_access_key`, and `token` (`None` when there is no session token). Read it again after a refresh.
|
|
50
|
+
|
|
51
|
+
`method` is one of `explicit`, `env`, `shared-credentials-file`, `assume-role`, `assume-role-with-web-identity`, `sso`, `saml`, `custom-process`, `iam-role`, or `container-role`.
|
|
52
|
+
`from_chain` and `from_profile` keep whichever of those botocore selects.
|
|
53
|
+
|
|
54
|
+
An explicit constructor uses only the source you name. `from_chain` and `from_profile` use botocore's standard chain, and they open a browser once when an IAM Identity Center token is missing or expired.
|
|
55
|
+
|
|
56
|
+
Requires Python 3.13 or newer.
|
|
57
|
+
|
|
58
|
+
## Install
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
pip install lupaxa-aws-authenticate
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
```python
|
|
65
|
+
from lupaxa.aws_authenticate import AuthenticatedSession
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
Pass `region=` when the source does not already carry one. EC2 and RDS clients need a region.
|
|
69
|
+
|
|
70
|
+
## Errors
|
|
71
|
+
|
|
72
|
+
Authentication failures subclass `AuthenticationError`. The original botocore or STS error is `__cause__`.
|
|
73
|
+
A missing or blank argument raises `ValueError` before any AWS call.
|
|
74
|
+
API calls you make afterwards raise boto3's own errors.
|
|
75
|
+
This library does not call `sts:GetCallerIdentity`.
|
|
76
|
+
|
|
77
|
+
- `CredentialsNotFoundError` means the source has no keys: unknown profile, empty chain, blank SAML assertion, missing web identity file, unreachable instance metadata or container endpoint, or a credential process with no keys.
|
|
78
|
+
- `LoginError` means IAM Identity Center login is denied, cancelled, or times out, or no browser can be opened.
|
|
79
|
+
- `MfaRequiredError` means assume-role was given `mfa_serial` and no code, and there is no terminal or the answer is empty. It also means STS says MFA is required and no code was sent.
|
|
80
|
+
- `RoleAssumptionError` means STS or IAM Identity Center rejects the role, including a wrong MFA code, external id, or duration.
|
|
81
|
+
- `ValueError` means a required argument is missing or blank, such as a role ARN, a source session, an access key, or a process command. It is also raised when web identity is given both `token` and `token_file`, or neither.
|
|
82
|
+
|
|
83
|
+
## Static Keys
|
|
84
|
+
|
|
85
|
+
`method` is `explicit`. Only the keys you pass are used.
|
|
86
|
+
|
|
87
|
+
### Example
|
|
88
|
+
|
|
89
|
+
```python
|
|
90
|
+
from lupaxa.aws_authenticate import AuthenticatedSession
|
|
91
|
+
|
|
92
|
+
session = AuthenticatedSession.from_keys(
|
|
93
|
+
"AKIAIOSFODNN7EXAMPLE",
|
|
94
|
+
"wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY",
|
|
95
|
+
session_token=None,
|
|
96
|
+
region="eu-west-1",
|
|
97
|
+
)
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
### Config
|
|
101
|
+
|
|
102
|
+
No config file and no environment variables. A whitespace-only `session_token` is stored as `None`.
|
|
103
|
+
|
|
104
|
+
## Environment Variables
|
|
105
|
+
|
|
106
|
+
`method` is `env`. Only `EnvProvider` is consulted.
|
|
107
|
+
|
|
108
|
+
### Example
|
|
109
|
+
|
|
110
|
+
```python
|
|
111
|
+
from lupaxa.aws_authenticate import AuthenticatedSession
|
|
112
|
+
|
|
113
|
+
session = AuthenticatedSession.from_environment(region="eu-west-1")
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
### Config
|
|
117
|
+
|
|
118
|
+
```bash
|
|
119
|
+
export AWS_ACCESS_KEY_ID=AKIAIOSFODNN7EXAMPLE
|
|
120
|
+
export AWS_SECRET_ACCESS_KEY=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
|
|
121
|
+
export AWS_SESSION_TOKEN= # optional
|
|
122
|
+
export AWS_DEFAULT_REGION=eu-west-1
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
`AWS_PROFILE` and the shared credentials file are ignored by this constructor.
|
|
126
|
+
|
|
127
|
+
## Shared Profile and the Default Chain
|
|
128
|
+
|
|
129
|
+
`from_profile` checks the name, strips surrounding spaces, and calls `from_chain`.
|
|
130
|
+
`from_chain()` with no profile uses the default credential chain: environment variables, the shared credentials file, a web identity token, IAM Identity Center, a credential process, container credentials, then instance metadata.
|
|
131
|
+
|
|
132
|
+
When the winning provider is a shared credentials profile, `method` is `shared-credentials-file`. Otherwise `method` is whatever botocore sets.
|
|
133
|
+
|
|
134
|
+
If the profile's IAM Identity Center token is missing or expired, the library opens a browser, waits up to 10 minutes, writes `~/.aws/sso/cache`, and resolves once more.
|
|
135
|
+
|
|
136
|
+
### Example
|
|
137
|
+
|
|
138
|
+
```python
|
|
139
|
+
from lupaxa.aws_authenticate import AuthenticatedSession
|
|
140
|
+
|
|
141
|
+
session = AuthenticatedSession.from_profile("prod", region="eu-west-1")
|
|
142
|
+
default_session = AuthenticatedSession.from_chain(region="eu-west-1")
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
`region=` overrides the region on the botocore session. Omit it to keep the region from the profile or from `AWS_DEFAULT_REGION`.
|
|
146
|
+
|
|
147
|
+
### Config
|
|
148
|
+
|
|
149
|
+
Default files are `~/.aws/credentials` and `~/.aws/config`. Override them with `AWS_SHARED_CREDENTIALS_FILE` and `AWS_CONFIG_FILE`.
|
|
150
|
+
|
|
151
|
+
`~/.aws/credentials`:
|
|
152
|
+
|
|
153
|
+
```ini
|
|
154
|
+
[default]
|
|
155
|
+
aws_access_key_id = AKIAIOSFODNN7EXAMPLE
|
|
156
|
+
aws_secret_access_key = wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
|
|
157
|
+
|
|
158
|
+
[prod]
|
|
159
|
+
aws_access_key_id = AKIAIOSFODNN7EXAMPLE
|
|
160
|
+
aws_secret_access_key = wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
|
|
161
|
+
aws_session_token = IQoJb3JpZ2luX2VjEExample
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
`~/.aws/config`:
|
|
165
|
+
|
|
166
|
+
```ini
|
|
167
|
+
[default]
|
|
168
|
+
region = eu-west-1
|
|
169
|
+
|
|
170
|
+
[profile prod]
|
|
171
|
+
region = eu-west-1
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
A profile that assumes a role, uses SSO, or runs a credential process is valid here too. Those shapes are shown under Assume Role, IAM Identity Center, and Credential Process. `from_profile("prod")` follows whichever shape that profile has.
|
|
175
|
+
|
|
176
|
+
## Assume Role
|
|
177
|
+
|
|
178
|
+
`method` is `assume-role`. The source session supplies the keys that call STS. This constructor does not read `~/.aws/config`.
|
|
179
|
+
|
|
180
|
+
Omitted `role_session_name` is `aws-authenticate`. Omitted `duration_seconds` is left out of the STS call, so AWS applies its default. `ExternalId` and `SerialNumber` are sent only when you pass them.
|
|
181
|
+
|
|
182
|
+
If `mfa_serial` is set and `mfa_code` is omitted, the library prompts on the terminal.
|
|
183
|
+
A code without `mfa_serial` raises `ValueError`.
|
|
184
|
+
The code is not placed in the STS arguments up front. Botocore asks the prompter when `SerialNumber` is set.
|
|
185
|
+
|
|
186
|
+
### Example
|
|
187
|
+
|
|
188
|
+
```python
|
|
189
|
+
from lupaxa.aws_authenticate import AuthenticatedSession
|
|
190
|
+
|
|
191
|
+
source = AuthenticatedSession.from_profile("prod")
|
|
192
|
+
session = AuthenticatedSession.from_assume_role(
|
|
193
|
+
source,
|
|
194
|
+
"arn:aws:iam::123456789012:role/Admin",
|
|
195
|
+
mfa_serial="arn:aws:iam::111122223333:mfa/ada",
|
|
196
|
+
external_id="outside",
|
|
197
|
+
duration_seconds=3600,
|
|
198
|
+
role_session_name="inventory",
|
|
199
|
+
region="eu-west-1",
|
|
200
|
+
)
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
Pass `mfa_code="123456"` when the process has no terminal.
|
|
204
|
+
|
|
205
|
+
### Config
|
|
206
|
+
|
|
207
|
+
Use this profile with `from_profile` when you want botocore to assume the role from the config file instead of calling `from_assume_role`:
|
|
208
|
+
|
|
209
|
+
```ini
|
|
210
|
+
[profile prod-admin]
|
|
211
|
+
role_arn = arn:aws:iam::123456789012:role/Admin
|
|
212
|
+
source_profile = prod
|
|
213
|
+
mfa_serial = arn:aws:iam::111122223333:mfa/ada
|
|
214
|
+
external_id = outside
|
|
215
|
+
duration_seconds = 3600
|
|
216
|
+
role_session_name = inventory
|
|
217
|
+
region = eu-west-1
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
## Web Identity
|
|
221
|
+
|
|
222
|
+
`method` is `assume-role-with-web-identity`. Pass exactly one of `token` or `token_file`.
|
|
223
|
+
The file is read as UTF-8 at construction, and later refreshes read it again.
|
|
224
|
+
An empty file, a missing file, or an unreadable path raises `CredentialsNotFoundError`.
|
|
225
|
+
|
|
226
|
+
Omitted `role_session_name` is `aws-authenticate`. Omitted `duration_seconds` is left out of the STS call.
|
|
227
|
+
|
|
228
|
+
### Example
|
|
229
|
+
|
|
230
|
+
```python
|
|
231
|
+
from lupaxa.aws_authenticate import AuthenticatedSession
|
|
232
|
+
|
|
233
|
+
session = AuthenticatedSession.from_web_identity(
|
|
234
|
+
"arn:aws:iam::123456789012:role/Eks",
|
|
235
|
+
token_file="/var/run/secrets/eks.amazonaws.com/serviceaccount/token",
|
|
236
|
+
region="eu-west-1",
|
|
237
|
+
)
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
A token you already hold:
|
|
241
|
+
|
|
242
|
+
```python
|
|
243
|
+
session = AuthenticatedSession.from_web_identity(
|
|
244
|
+
"arn:aws:iam::123456789012:role/Eks",
|
|
245
|
+
token=open("token.jwt", encoding="utf-8").read(),
|
|
246
|
+
region="eu-west-1",
|
|
247
|
+
)
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
### Config
|
|
251
|
+
|
|
252
|
+
This constructor ignores `AWS_ROLE_ARN` and `AWS_WEB_IDENTITY_TOKEN_FILE`. The default chain does honour them, so `from_chain()` on EKS picks them up with no arguments.
|
|
253
|
+
|
|
254
|
+
The same data as a profile, for `from_profile`:
|
|
255
|
+
|
|
256
|
+
```ini
|
|
257
|
+
[profile eks]
|
|
258
|
+
role_arn = arn:aws:iam::123456789012:role/Eks
|
|
259
|
+
web_identity_token_file = /var/run/secrets/eks.amazonaws.com/serviceaccount/token
|
|
260
|
+
role_session_name = eks
|
|
261
|
+
region = eu-west-1
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
## SAML
|
|
265
|
+
|
|
266
|
+
`method` is `saml`. You pass a base64 SAML assertion, the role ARN, and the SAML provider ARN.
|
|
267
|
+
There is no identity-provider browser.
|
|
268
|
+
A blank assertion raises `CredentialsNotFoundError` before STS is called.
|
|
269
|
+
Omitted `duration_seconds` is left out of the STS call.
|
|
270
|
+
|
|
271
|
+
### Example
|
|
272
|
+
|
|
273
|
+
```python
|
|
274
|
+
from lupaxa.aws_authenticate import AuthenticatedSession
|
|
275
|
+
|
|
276
|
+
assertion = open("assertion.txt", encoding="utf-8").read()
|
|
277
|
+
session = AuthenticatedSession.from_saml(
|
|
278
|
+
"arn:aws:iam::123456789012:role/SamlAdmin",
|
|
279
|
+
"arn:aws:iam::123456789012:saml-provider/Example",
|
|
280
|
+
assertion,
|
|
281
|
+
duration_seconds=3600,
|
|
282
|
+
region="eu-west-1",
|
|
283
|
+
)
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
### Config
|
|
287
|
+
|
|
288
|
+
No config file. The assertion comes from your identity provider. The two ARNs are the role and the IAM SAML provider that trusts that provider.
|
|
289
|
+
|
|
290
|
+
## Credential Process
|
|
291
|
+
|
|
292
|
+
`method` is `custom-process`. The command is the only source. Environment keys set beside it are ignored.
|
|
293
|
+
|
|
294
|
+
The process must print a JSON document on stdout:
|
|
295
|
+
|
|
296
|
+
```json
|
|
297
|
+
{
|
|
298
|
+
"Version": 1,
|
|
299
|
+
"AccessKeyId": "ASIAEXAMPLE",
|
|
300
|
+
"SecretAccessKey": "secret",
|
|
301
|
+
"SessionToken": "token",
|
|
302
|
+
"Expiration": "2999-01-01T00:00:00Z"
|
|
303
|
+
}
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
`SessionToken` and `Expiration` are optional. A failing process, or JSON with no keys, raises `CredentialsNotFoundError`.
|
|
307
|
+
|
|
308
|
+
### Example
|
|
309
|
+
|
|
310
|
+
```python
|
|
311
|
+
from lupaxa.aws_authenticate import AuthenticatedSession
|
|
312
|
+
|
|
313
|
+
session = AuthenticatedSession.from_process(
|
|
314
|
+
"/usr/local/bin/issue-keys --json",
|
|
315
|
+
region="eu-west-1",
|
|
316
|
+
)
|
|
317
|
+
```
|
|
318
|
+
|
|
319
|
+
### Config
|
|
320
|
+
|
|
321
|
+
The same command as a profile, for `from_profile`:
|
|
322
|
+
|
|
323
|
+
```ini
|
|
324
|
+
[profile tools]
|
|
325
|
+
credential_process = /usr/local/bin/issue-keys --json
|
|
326
|
+
region = eu-west-1
|
|
327
|
+
```
|
|
328
|
+
|
|
329
|
+
## Instance Metadata
|
|
330
|
+
|
|
331
|
+
`method` is `iam-role`. The session uses the IAM role attached to the EC2 instance. An empty response from the metadata service raises `CredentialsNotFoundError`.
|
|
332
|
+
|
|
333
|
+
### Example
|
|
334
|
+
|
|
335
|
+
```python
|
|
336
|
+
from lupaxa.aws_authenticate import AuthenticatedSession
|
|
337
|
+
|
|
338
|
+
session = AuthenticatedSession.from_instance_metadata(region="eu-west-1")
|
|
339
|
+
```
|
|
340
|
+
|
|
341
|
+
### Config
|
|
342
|
+
|
|
343
|
+
No config file. The instance needs an instance profile. Leave `AWS_EC2_METADATA_DISABLED` unset. This constructor does not change that variable. `from_chain()` skips instance metadata when `AWS_EC2_METADATA_DISABLED=true`.
|
|
344
|
+
|
|
345
|
+
## Container Credentials
|
|
346
|
+
|
|
347
|
+
`method` is `container-role`. Used for ECS, EKS pods that use the container credential endpoint, and App Runner. If neither URI variable is set, this raises `CredentialsNotFoundError`.
|
|
348
|
+
|
|
349
|
+
### Example
|
|
350
|
+
|
|
351
|
+
```python
|
|
352
|
+
from lupaxa.aws_authenticate import AuthenticatedSession
|
|
353
|
+
|
|
354
|
+
session = AuthenticatedSession.from_container(region="eu-west-1")
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
### Config
|
|
358
|
+
|
|
359
|
+
The runtime sets one of these. A relative URI is the path on `169.254.170.2`. A full URI is an absolute URL, and it may need an authorization token.
|
|
360
|
+
|
|
361
|
+
```bash
|
|
362
|
+
export AWS_CONTAINER_CREDENTIALS_RELATIVE_URI=/v2/credentials/task-id
|
|
363
|
+
# or
|
|
364
|
+
export AWS_CONTAINER_CREDENTIALS_FULL_URI=http://169.254.170.2/v1/credentials
|
|
365
|
+
export AWS_CONTAINER_AUTHORIZATION_TOKEN=token
|
|
366
|
+
# or, instead of the token value:
|
|
367
|
+
export AWS_CONTAINER_AUTHORIZATION_TOKEN_FILE=/var/run/secrets/pods.eks.amazonaws.com/serviceaccount/eks-pod-identity-token
|
|
368
|
+
```
|
|
369
|
+
|
|
370
|
+
## IAM Identity Center
|
|
371
|
+
|
|
372
|
+
`method` is `sso`. `from_sso` takes the start URL, the Identity Center region, the account id, and the role name. It does not read your config file. It writes a temporary profile, then resolves only the SSO provider.
|
|
373
|
+
|
|
374
|
+
When `~/.aws/sso/cache` has no usable token, the library registers a public client and opens the browser for an authorization-code login with PKCE.
|
|
375
|
+
It waits on `127.0.0.1` for up to 10 minutes.
|
|
376
|
+
The token is cached under `~/.aws/sso/cache`. The next call reuses it until it expires, then logs in again.
|
|
377
|
+
A denied, cancelled, or timed-out login raises `LoginError`.
|
|
378
|
+
|
|
379
|
+
`from_profile` and `from_chain` do the same login when the profile they resolve is an SSO profile.
|
|
380
|
+
|
|
381
|
+
### Example
|
|
382
|
+
|
|
383
|
+
```python
|
|
384
|
+
from lupaxa.aws_authenticate import AuthenticatedSession
|
|
385
|
+
|
|
386
|
+
session = AuthenticatedSession.from_sso(
|
|
387
|
+
"https://my-org.awsapps.com/start",
|
|
388
|
+
"eu-west-1",
|
|
389
|
+
"123456789012",
|
|
390
|
+
"ReadOnly",
|
|
391
|
+
region="eu-west-1",
|
|
392
|
+
)
|
|
393
|
+
```
|
|
394
|
+
|
|
395
|
+
### Config
|
|
396
|
+
|
|
397
|
+
No config file is required for `from_sso`. To select the same role with `from_profile`, use an `sso-session` block:
|
|
398
|
+
|
|
399
|
+
```ini
|
|
400
|
+
[sso-session work]
|
|
401
|
+
sso_start_url = https://my-org.awsapps.com/start
|
|
402
|
+
sso_region = eu-west-1
|
|
403
|
+
sso_registration_scopes = sso:account:access
|
|
404
|
+
|
|
405
|
+
[profile work-readonly]
|
|
406
|
+
sso_session = work
|
|
407
|
+
sso_account_id = 123456789012
|
|
408
|
+
sso_role_name = ReadOnly
|
|
409
|
+
region = eu-west-1
|
|
410
|
+
```
|
|
411
|
+
|
|
412
|
+
A legacy profile without an `sso-session` block also works with `from_profile`:
|
|
413
|
+
|
|
414
|
+
```ini
|
|
415
|
+
[profile work-readonly]
|
|
416
|
+
sso_start_url = https://my-org.awsapps.com/start
|
|
417
|
+
sso_region = eu-west-1
|
|
418
|
+
sso_account_id = 123456789012
|
|
419
|
+
sso_role_name = ReadOnly
|
|
420
|
+
region = eu-west-1
|
|
421
|
+
```
|
|
422
|
+
|
|
423
|
+
## Example Scripts
|
|
424
|
+
|
|
425
|
+
Any constructor can replace the session line. The client calls are ordinary boto3 calls.
|
|
426
|
+
|
|
427
|
+
### List EC2 Instances
|
|
428
|
+
|
|
429
|
+
Uses a shared profile. Swap `from_profile` for `from_environment`, `from_instance_metadata`, or `from_container` when the process is already running with those credentials.
|
|
430
|
+
|
|
431
|
+
```python
|
|
432
|
+
"""List running EC2 instances."""
|
|
433
|
+
|
|
434
|
+
from lupaxa.aws_authenticate import AuthenticatedSession
|
|
435
|
+
|
|
436
|
+
session = AuthenticatedSession.from_profile("prod", region="eu-west-1")
|
|
437
|
+
ec2 = session.client("ec2")
|
|
438
|
+
pages = ec2.get_paginator("describe_instances").paginate(
|
|
439
|
+
Filters=[{"Name": "instance-state-name", "Values": ["running"]}],
|
|
440
|
+
)
|
|
441
|
+
for page in pages:
|
|
442
|
+
for reservation in page["Reservations"]:
|
|
443
|
+
for instance in reservation["Instances"]:
|
|
444
|
+
name = next(
|
|
445
|
+
(
|
|
446
|
+
tag["Value"]
|
|
447
|
+
for tag in instance.get("Tags", [])
|
|
448
|
+
if tag["Key"] == "Name"
|
|
449
|
+
),
|
|
450
|
+
"",
|
|
451
|
+
)
|
|
452
|
+
print(
|
|
453
|
+
instance["InstanceId"],
|
|
454
|
+
name,
|
|
455
|
+
instance.get("PrivateIpAddress", ""),
|
|
456
|
+
)
|
|
457
|
+
```
|
|
458
|
+
|
|
459
|
+
### List RDS Instances
|
|
460
|
+
|
|
461
|
+
Uses IAM Identity Center. The first run opens a browser when the cached token is missing or expired.
|
|
462
|
+
|
|
463
|
+
```python
|
|
464
|
+
"""List RDS DB instances."""
|
|
465
|
+
|
|
466
|
+
from lupaxa.aws_authenticate import AuthenticatedSession
|
|
467
|
+
|
|
468
|
+
session = AuthenticatedSession.from_sso(
|
|
469
|
+
"https://my-org.awsapps.com/start",
|
|
470
|
+
"eu-west-1",
|
|
471
|
+
"123456789012",
|
|
472
|
+
"ReadOnly",
|
|
473
|
+
region="eu-west-1",
|
|
474
|
+
)
|
|
475
|
+
rds = session.client("rds")
|
|
476
|
+
pages = rds.get_paginator("describe_db_instances").paginate()
|
|
477
|
+
for page in pages:
|
|
478
|
+
for database in page["DBInstances"]:
|
|
479
|
+
print(
|
|
480
|
+
database["DBInstanceIdentifier"],
|
|
481
|
+
database["Engine"],
|
|
482
|
+
database["DBInstanceStatus"],
|
|
483
|
+
)
|
|
484
|
+
```
|
|
485
|
+
|
|
486
|
+
<a href="https://github.com/the-lupaxa-project">
|
|
487
|
+
<img src="https://raw.githubusercontent.com/the-lupaxa-project/brand-assets/master/logos/components/footer-for-child-orgs.svg" alt="The Lupaxa Project Footer" width="100%" />
|
|
488
|
+
</a>
|