boto3-assist 0.15.0__tar.gz → 0.16.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.
- {boto3_assist-0.15.0 → boto3_assist-0.16.0}/.gitignore +2 -1
- {boto3_assist-0.15.0 → boto3_assist-0.16.0}/PKG-INFO +1 -1
- {boto3_assist-0.15.0 → boto3_assist-0.16.0}/pyproject.toml +1 -1
- boto3_assist-0.16.0/src/boto3_assist/aws_config.py +199 -0
- boto3_assist-0.16.0/src/boto3_assist/dynamodb/troubleshooting.md +7 -0
- boto3_assist-0.16.0/src/boto3_assist/session_setup_mixin.py +70 -0
- {boto3_assist-0.15.0 → boto3_assist-0.16.0}/src/boto3_assist/utilities/serialization_utility.py +9 -2
- boto3_assist-0.16.0/src/boto3_assist/version.py +1 -0
- boto3_assist-0.16.0/tests/unit/aws_config_test.py +81 -0
- boto3_assist-0.16.0/tests/unit/session_tests/test_boto3_session_manager.py +177 -0
- boto3_assist-0.15.0/src/boto3_assist/dynamodb/troubleshooting.md +0 -5
- boto3_assist-0.15.0/src/boto3_assist/session_setup_mixin.py +0 -29
- boto3_assist-0.15.0/src/boto3_assist/version.py +0 -1
- {boto3_assist-0.15.0 → boto3_assist-0.16.0}/.env.docker +0 -0
- {boto3_assist-0.15.0 → boto3_assist-0.16.0}/.env.docker.001 +0 -0
- {boto3_assist-0.15.0 → boto3_assist-0.16.0}/.env.docker.nosql.workbench +0 -0
- {boto3_assist-0.15.0 → boto3_assist-0.16.0}/.env.unittest +0 -0
- {boto3_assist-0.15.0 → boto3_assist-0.16.0}/.vscode/launch.json +0 -0
- {boto3_assist-0.15.0 → boto3_assist-0.16.0}/.vscode/settings.json +0 -0
- {boto3_assist-0.15.0 → boto3_assist-0.16.0}/.vscode/tasks.json +0 -0
- {boto3_assist-0.15.0 → boto3_assist-0.16.0}/LICENSE-EXPLAINED.txt +0 -0
- {boto3_assist-0.15.0 → boto3_assist-0.16.0}/LICENSE.txt +0 -0
- {boto3_assist-0.15.0 → boto3_assist-0.16.0}/README.md +0 -0
- {boto3_assist-0.15.0 → boto3_assist-0.16.0}/aws_regions_with_status.csv +0 -0
- {boto3_assist-0.15.0 → boto3_assist-0.16.0}/aws_regions_with_status.json +0 -0
- {boto3_assist-0.15.0 → boto3_assist-0.16.0}/devops/build.py +0 -0
- {boto3_assist-0.15.0 → boto3_assist-0.16.0}/devops/readme.md +0 -0
- {boto3_assist-0.15.0 → boto3_assist-0.16.0}/examples/__init__.py +0 -0
- {boto3_assist-0.15.0 → boto3_assist-0.16.0}/examples/cloudwatch/log_report.py +0 -0
- {boto3_assist-0.15.0 → boto3_assist-0.16.0}/examples/dynamodb/models/order_item_model.py +0 -0
- {boto3_assist-0.15.0 → boto3_assist-0.16.0}/examples/dynamodb/models/order_model.py +0 -0
- {boto3_assist-0.15.0 → boto3_assist-0.16.0}/examples/dynamodb/models/product_model.py +0 -0
- {boto3_assist-0.15.0 → boto3_assist-0.16.0}/examples/dynamodb/models/user_model.py +0 -0
- {boto3_assist-0.15.0 → boto3_assist-0.16.0}/examples/dynamodb/models/user_post_model.py +0 -0
- {boto3_assist-0.15.0 → boto3_assist-0.16.0}/examples/dynamodb/order_example/main.py +0 -0
- {boto3_assist-0.15.0 → boto3_assist-0.16.0}/examples/dynamodb/order_example/products.json +0 -0
- {boto3_assist-0.15.0 → boto3_assist-0.16.0}/examples/dynamodb/services/order_item_service.py +0 -0
- {boto3_assist-0.15.0 → boto3_assist-0.16.0}/examples/dynamodb/services/order_service.py +0 -0
- {boto3_assist-0.15.0 → boto3_assist-0.16.0}/examples/dynamodb/services/product_service.py +0 -0
- {boto3_assist-0.15.0 → boto3_assist-0.16.0}/examples/dynamodb/services/table_service.py +0 -0
- {boto3_assist-0.15.0 → boto3_assist-0.16.0}/examples/dynamodb/services/user_post_service.py +0 -0
- {boto3_assist-0.15.0 → boto3_assist-0.16.0}/examples/dynamodb/services/user_service.py +0 -0
- {boto3_assist-0.15.0 → boto3_assist-0.16.0}/examples/dynamodb/services/user_service_client_example.py +0 -0
- {boto3_assist-0.15.0 → boto3_assist-0.16.0}/examples/dynamodb/services/user_service_resource_example.py +0 -0
- {boto3_assist-0.15.0 → boto3_assist-0.16.0}/examples/dynamodb/user_post_example/main.py +0 -0
- {boto3_assist-0.15.0 → boto3_assist-0.16.0}/examples/ec2/regions_report.py +0 -0
- {boto3_assist-0.15.0 → boto3_assist-0.16.0}/module-headers.txt +0 -0
- {boto3_assist-0.15.0 → boto3_assist-0.16.0}/mypy.ini +0 -0
- {boto3_assist-0.15.0 → boto3_assist-0.16.0}/requirements-dev.txt +0 -0
- {boto3_assist-0.15.0 → boto3_assist-0.16.0}/requirements.txt +0 -0
- {boto3_assist-0.15.0 → boto3_assist-0.16.0}/run-checks.sh +0 -0
- {boto3_assist-0.15.0 → boto3_assist-0.16.0}/run_unit_tests.sh +0 -0
- {boto3_assist-0.15.0 → boto3_assist-0.16.0}/src/boto3_assist/__init__.py +0 -0
- {boto3_assist-0.15.0 → boto3_assist-0.16.0}/src/boto3_assist/aws_lambda/event_info.py +0 -0
- {boto3_assist-0.15.0 → boto3_assist-0.16.0}/src/boto3_assist/aws_lambda/mock_context.py +0 -0
- {boto3_assist-0.15.0 → boto3_assist-0.16.0}/src/boto3_assist/boto3session.py +0 -0
- {boto3_assist-0.15.0 → boto3_assist-0.16.0}/src/boto3_assist/cloudwatch/cloudwatch_connection.py +0 -0
- {boto3_assist-0.15.0 → boto3_assist-0.16.0}/src/boto3_assist/cloudwatch/cloudwatch_connection_tracker.py +0 -0
- {boto3_assist-0.15.0 → boto3_assist-0.16.0}/src/boto3_assist/cloudwatch/cloudwatch_log_connection.py +0 -0
- {boto3_assist-0.15.0 → boto3_assist-0.16.0}/src/boto3_assist/cloudwatch/cloudwatch_logs.py +0 -0
- {boto3_assist-0.15.0 → boto3_assist-0.16.0}/src/boto3_assist/cloudwatch/cloudwatch_query.py +0 -0
- {boto3_assist-0.15.0 → boto3_assist-0.16.0}/src/boto3_assist/cognito/cognito_authorizer.py +0 -0
- {boto3_assist-0.15.0 → boto3_assist-0.16.0}/src/boto3_assist/cognito/cognito_connection.py +0 -0
- {boto3_assist-0.15.0 → boto3_assist-0.16.0}/src/boto3_assist/cognito/cognito_utility.py +0 -0
- {boto3_assist-0.15.0 → boto3_assist-0.16.0}/src/boto3_assist/cognito/jwks_cache.py +0 -0
- {boto3_assist-0.15.0 → boto3_assist-0.16.0}/src/boto3_assist/cognito/user.py +0 -0
- {boto3_assist-0.15.0 → boto3_assist-0.16.0}/src/boto3_assist/connection.py +0 -0
- {boto3_assist-0.15.0 → boto3_assist-0.16.0}/src/boto3_assist/connection_tracker.py +0 -0
- {boto3_assist-0.15.0 → boto3_assist-0.16.0}/src/boto3_assist/dynamodb/dynamodb.py +0 -0
- {boto3_assist-0.15.0 → boto3_assist-0.16.0}/src/boto3_assist/dynamodb/dynamodb_connection.py +0 -0
- {boto3_assist-0.15.0 → boto3_assist-0.16.0}/src/boto3_assist/dynamodb/dynamodb_helpers.py +0 -0
- {boto3_assist-0.15.0 → boto3_assist-0.16.0}/src/boto3_assist/dynamodb/dynamodb_importer.py +0 -0
- {boto3_assist-0.15.0 → boto3_assist-0.16.0}/src/boto3_assist/dynamodb/dynamodb_index.py +0 -0
- {boto3_assist-0.15.0 → boto3_assist-0.16.0}/src/boto3_assist/dynamodb/dynamodb_iservice.py +0 -0
- {boto3_assist-0.15.0 → boto3_assist-0.16.0}/src/boto3_assist/dynamodb/dynamodb_key.py +0 -0
- {boto3_assist-0.15.0 → boto3_assist-0.16.0}/src/boto3_assist/dynamodb/dynamodb_model_base.py +0 -0
- {boto3_assist-0.15.0 → boto3_assist-0.16.0}/src/boto3_assist/dynamodb/dynamodb_model_base_interfaces.py +0 -0
- {boto3_assist-0.15.0 → boto3_assist-0.16.0}/src/boto3_assist/dynamodb/dynamodb_reindexer.py +0 -0
- {boto3_assist-0.15.0 → boto3_assist-0.16.0}/src/boto3_assist/dynamodb/dynamodb_reserved_words.py +0 -0
- {boto3_assist-0.15.0 → boto3_assist-0.16.0}/src/boto3_assist/dynamodb/dynamodb_reserved_words.txt +0 -0
- {boto3_assist-0.15.0 → boto3_assist-0.16.0}/src/boto3_assist/dynamodb/readme.md +0 -0
- {boto3_assist-0.15.0 → boto3_assist-0.16.0}/src/boto3_assist/ec2/ec2_connection.py +0 -0
- {boto3_assist-0.15.0 → boto3_assist-0.16.0}/src/boto3_assist/environment_services/__init__.py +0 -0
- {boto3_assist-0.15.0 → boto3_assist-0.16.0}/src/boto3_assist/environment_services/environment_loader.py +0 -0
- {boto3_assist-0.15.0 → boto3_assist-0.16.0}/src/boto3_assist/environment_services/environment_variables.py +0 -0
- {boto3_assist-0.15.0 → boto3_assist-0.16.0}/src/boto3_assist/errors/custom_exceptions.py +0 -0
- {boto3_assist-0.15.0 → boto3_assist-0.16.0}/src/boto3_assist/http_status_codes.py +0 -0
- {boto3_assist-0.15.0 → boto3_assist-0.16.0}/src/boto3_assist/models/serializable_model.py +0 -0
- {boto3_assist-0.15.0 → boto3_assist-0.16.0}/src/boto3_assist/role_assumption_mixin.py +0 -0
- {boto3_assist-0.15.0 → boto3_assist-0.16.0}/src/boto3_assist/s3/s3.py +0 -0
- {boto3_assist-0.15.0 → boto3_assist-0.16.0}/src/boto3_assist/s3/s3_bucket.py +0 -0
- {boto3_assist-0.15.0 → boto3_assist-0.16.0}/src/boto3_assist/s3/s3_connection.py +0 -0
- {boto3_assist-0.15.0 → boto3_assist-0.16.0}/src/boto3_assist/s3/s3_event_data.py +0 -0
- {boto3_assist-0.15.0 → boto3_assist-0.16.0}/src/boto3_assist/s3/s3_object.py +0 -0
- {boto3_assist-0.15.0 → boto3_assist-0.16.0}/src/boto3_assist/securityhub/securityhub.py +0 -0
- {boto3_assist-0.15.0 → boto3_assist-0.16.0}/src/boto3_assist/securityhub/securityhub_connection.py +0 -0
- {boto3_assist-0.15.0 → boto3_assist-0.16.0}/src/boto3_assist/ssm/connection.py +0 -0
- {boto3_assist-0.15.0 → boto3_assist-0.16.0}/src/boto3_assist/ssm/parameter_store/parameter_store.py +0 -0
- {boto3_assist-0.15.0 → boto3_assist-0.16.0}/src/boto3_assist/utilities/datetime_utility.py +0 -0
- {boto3_assist-0.15.0 → boto3_assist-0.16.0}/src/boto3_assist/utilities/dictionary_utility.py +0 -0
- {boto3_assist-0.15.0 → boto3_assist-0.16.0}/src/boto3_assist/utilities/file_operations.py +0 -0
- {boto3_assist-0.15.0 → boto3_assist-0.16.0}/src/boto3_assist/utilities/http_utility.py +0 -0
- {boto3_assist-0.15.0 → boto3_assist-0.16.0}/src/boto3_assist/utilities/logging_utility.py +0 -0
- {boto3_assist-0.15.0 → boto3_assist-0.16.0}/src/boto3_assist/utilities/numbers_utility.py +0 -0
- {boto3_assist-0.15.0 → boto3_assist-0.16.0}/src/boto3_assist/utilities/string_utility.py +0 -0
- {boto3_assist-0.15.0 → boto3_assist-0.16.0}/tests/__init__.py +0 -0
- {boto3_assist-0.15.0 → boto3_assist-0.16.0}/tests/integration/cross_account_connection_test.py +0 -0
- {boto3_assist-0.15.0 → boto3_assist-0.16.0}/tests/integration/tenant.py +0 -0
- {boto3_assist-0.15.0 → boto3_assist-0.16.0}/tests/integration/tenant_services.py +0 -0
- {boto3_assist-0.15.0 → boto3_assist-0.16.0}/tests/unit/dynamodb_tests/__init__.py +0 -0
- {boto3_assist-0.15.0 → boto3_assist-0.16.0}/tests/unit/dynamodb_tests/dbmodels/cms/base.py +0 -0
- {boto3_assist-0.15.0 → boto3_assist-0.16.0}/tests/unit/dynamodb_tests/dbmodels/cms/content_block.py +0 -0
- {boto3_assist-0.15.0 → boto3_assist-0.16.0}/tests/unit/dynamodb_tests/dbmodels/cms/page.py +0 -0
- {boto3_assist-0.15.0 → boto3_assist-0.16.0}/tests/unit/dynamodb_tests/dbmodels/cms/template.py +0 -0
- {boto3_assist-0.15.0 → boto3_assist-0.16.0}/tests/unit/dynamodb_tests/dbmodels/simple_model.py +0 -0
- {boto3_assist-0.15.0 → boto3_assist-0.16.0}/tests/unit/dynamodb_tests/dbmodels/user_model.py +0 -0
- {boto3_assist-0.15.0 → boto3_assist-0.16.0}/tests/unit/dynamodb_tests/dbmodels/user_required_fields_model.py +0 -0
- {boto3_assist-0.15.0 → boto3_assist-0.16.0}/tests/unit/dynamodb_tests/dynamodb_model_base_test.py +0 -0
- {boto3_assist-0.15.0 → boto3_assist-0.16.0}/tests/unit/dynamodb_tests/dynamodb_model_projections_test.py +0 -0
- {boto3_assist-0.15.0 → boto3_assist-0.16.0}/tests/unit/dynamodb_tests/dynamodb_model_serializtion_test.py +0 -0
- {boto3_assist-0.15.0 → boto3_assist-0.16.0}/tests/unit/dynamodb_tests/dynamodb_moto_sorting_test.py +0 -0
- {boto3_assist-0.15.0 → boto3_assist-0.16.0}/tests/unit/dynamodb_tests/dynamodb_reindex_test.py +0 -0
- {boto3_assist-0.15.0 → boto3_assist-0.16.0}/tests/unit/examples_test/__init__.py +0 -0
- {boto3_assist-0.15.0 → boto3_assist-0.16.0}/tests/unit/examples_test/user_service_test.py +0 -0
- {boto3_assist-0.15.0 → boto3_assist-0.16.0}/tests/unit/lambda_tests/__init__.py +0 -0
- {boto3_assist-0.15.0 → boto3_assist-0.16.0}/tests/unit/lambda_tests/event_info_test.py +0 -0
- {boto3_assist-0.15.0 → boto3_assist-0.16.0}/tests/unit/models_tests/__init__.py +0 -0
- {boto3_assist-0.15.0 → boto3_assist-0.16.0}/tests/unit/models_tests/models/person.py +0 -0
- {boto3_assist-0.15.0 → boto3_assist-0.16.0}/tests/unit/models_tests/models/user.py +0 -0
- {boto3_assist-0.15.0 → boto3_assist-0.16.0}/tests/unit/models_tests/serializable_model_person_test.py +0 -0
- {boto3_assist-0.15.0 → boto3_assist-0.16.0}/tests/unit/models_tests/serializable_model_user_test.py +0 -0
- {boto3_assist-0.15.0 → boto3_assist-0.16.0}/tests/unit/models_tests/serializable_model_wide_test.py +0 -0
- {boto3_assist-0.15.0 → boto3_assist-0.16.0}/tests/unit/parameter_store/__init__.py +0 -0
- {boto3_assist-0.15.0 → boto3_assist-0.16.0}/tests/unit/parameter_store/parameter_store_test.py +0 -0
- {boto3_assist-0.15.0 → boto3_assist-0.16.0}/tests/unit/s3/__init__.py +0 -0
- {boto3_assist-0.15.0 → boto3_assist-0.16.0}/tests/unit/s3/files/test.txt +0 -0
- {boto3_assist-0.15.0 → boto3_assist-0.16.0}/tests/unit/s3/s3_event_data_test.py +0 -0
- {boto3_assist-0.15.0 → boto3_assist-0.16.0}/tests/unit/s3/s3_file_delete_test.py +0 -0
- {boto3_assist-0.15.0 → boto3_assist-0.16.0}/tests/unit/s3/s3_file_upload_test.py +0 -0
- {boto3_assist-0.15.0 → boto3_assist-0.16.0}/tests/unit/utilities/__init__.py +0 -0
- {boto3_assist-0.15.0 → boto3_assist-0.16.0}/tests/unit/utilities/serialization_utility_test.py +0 -0
- {boto3_assist-0.15.0 → boto3_assist-0.16.0}/tests/unit/utilities/string_utility_test.py +0 -0
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
import os
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
import configparser
|
|
4
|
+
from typing import Literal, Optional
|
|
5
|
+
from boto3_assist.utilities.serialization_utility import SerializableModel
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class AWSConfigProfile(SerializableModel):
|
|
9
|
+
def __init__(
|
|
10
|
+
self, region: Optional[str] = "us-east-1", output: Optional[str] = "json"
|
|
11
|
+
):
|
|
12
|
+
|
|
13
|
+
self.region: Optional[str] = region
|
|
14
|
+
self.output: Optional[str] = output
|
|
15
|
+
|
|
16
|
+
self.aws_access_key_id: Optional[str] = None
|
|
17
|
+
self.aws_secret_access_key: Optional[str] = None
|
|
18
|
+
self.aws_session_token: Optional[str] = None
|
|
19
|
+
|
|
20
|
+
self.sso_session: Optional[str] = None
|
|
21
|
+
self.sso_account_id: Optional[str] = None
|
|
22
|
+
self.sso_role_name: Optional[str] = None
|
|
23
|
+
|
|
24
|
+
self.credential_process: Optional[str] = None
|
|
25
|
+
self.credential_source: Optional[str] = None
|
|
26
|
+
self.role_arn: Optional[str] = None
|
|
27
|
+
self.source_profile: Optional[str] = None
|
|
28
|
+
self.external_id: Optional[str] = None
|
|
29
|
+
self.role_session_name: Optional[str] = None
|
|
30
|
+
self.duration_seconds: Optional[str] = None
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class AWSConfigSSOSession(SerializableModel):
|
|
34
|
+
def __init__(
|
|
35
|
+
self,
|
|
36
|
+
sso_start_url: Optional[str] = None,
|
|
37
|
+
sso_region: Optional[str] = None,
|
|
38
|
+
sso_registration_scopes: Optional[str] = None,
|
|
39
|
+
):
|
|
40
|
+
self.sso_start_url: Optional[str] = sso_start_url
|
|
41
|
+
self.sso_region: Optional[str] = sso_region
|
|
42
|
+
self.sso_registration_scopes: Optional[str] = sso_registration_scopes
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
class AWSConfig:
|
|
46
|
+
"""
|
|
47
|
+
Performs Operations on an AWS Config
|
|
48
|
+
"""
|
|
49
|
+
|
|
50
|
+
def __init__(self):
|
|
51
|
+
pass
|
|
52
|
+
|
|
53
|
+
def get_path(self) -> Path:
|
|
54
|
+
"""
|
|
55
|
+
Returns the path to the AWS config file, honoring AWS_CONFIG_FILE
|
|
56
|
+
and falling back to ~/.aws/config (or %USERPROFILE%\.aws\config on Windows).
|
|
57
|
+
"""
|
|
58
|
+
# 1) Check for explicit override
|
|
59
|
+
env_path = os.environ.get("AWS_CONFIG_FILE")
|
|
60
|
+
if env_path:
|
|
61
|
+
return Path(env_path).expanduser()
|
|
62
|
+
|
|
63
|
+
# 2) Default location
|
|
64
|
+
return os.path.join(Path.home(), ".aws", "config")
|
|
65
|
+
|
|
66
|
+
def path_exists(self) -> bool:
|
|
67
|
+
path = self.get_path()
|
|
68
|
+
|
|
69
|
+
return os.path.isfile(path)
|
|
70
|
+
|
|
71
|
+
def has_profile(self, profile_name: str) -> bool:
|
|
72
|
+
config = configparser.ConfigParser()
|
|
73
|
+
self.read_section(profile_name, config)
|
|
74
|
+
return profile_name in config.sections()
|
|
75
|
+
|
|
76
|
+
def upsert_profile(
|
|
77
|
+
self,
|
|
78
|
+
name: str,
|
|
79
|
+
profile: AWSConfigProfile,
|
|
80
|
+
config_path: Optional[str] = None,
|
|
81
|
+
):
|
|
82
|
+
self.write_section(name, profile, config_path)
|
|
83
|
+
|
|
84
|
+
def upsert_sso_session(
|
|
85
|
+
self,
|
|
86
|
+
profile_name: str,
|
|
87
|
+
sso_session: AWSConfigSSOSession,
|
|
88
|
+
profile: AWSConfigProfile | None = None,
|
|
89
|
+
config_path: Optional[str] = None,
|
|
90
|
+
):
|
|
91
|
+
"""
|
|
92
|
+
Insert / Update the SSO Session block in the aws config
|
|
93
|
+
Args:
|
|
94
|
+
Name (str): Required. Specifies the profile name. This is the init key
|
|
95
|
+
which is added to the section for both sso-session and profile
|
|
96
|
+
e.g. [profile {profile_name}] or [sso-session {profile_name}]
|
|
97
|
+
sso_session (AWSConfigSSOSession): Defines the values written to this session block
|
|
98
|
+
profile (AWSConfigProfile): Defines the values written to the profile block. Typically
|
|
99
|
+
you will need a profile block along with a session block when using sso-session
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
As a general rule you will typically need to build the following:
|
|
103
|
+
[profile {profile-name}]
|
|
104
|
+
sso_session = {optionally-use-profile-name}
|
|
105
|
+
sso_account_id = {aws-acount-id}
|
|
106
|
+
sso_role_name = {sso-role}
|
|
107
|
+
region = {region}
|
|
108
|
+
output = {output}
|
|
109
|
+
|
|
110
|
+
[sso-session {profile-name}]
|
|
111
|
+
sso_start_url = {sso_start_url} e.g. https://account-alias.awsapps.com/start
|
|
112
|
+
sso_region = {region}
|
|
113
|
+
sso_registration_scopes = {scopes}
|
|
114
|
+
|
|
115
|
+
"""
|
|
116
|
+
|
|
117
|
+
if not profile_name:
|
|
118
|
+
raise ValueError("Name is required")
|
|
119
|
+
|
|
120
|
+
self.write_section(profile_name, sso_session, config_path)
|
|
121
|
+
|
|
122
|
+
if profile:
|
|
123
|
+
self.write_section(profile_name, profile, config_path)
|
|
124
|
+
|
|
125
|
+
def write_section(
|
|
126
|
+
self,
|
|
127
|
+
profile_name: str | None,
|
|
128
|
+
section: AWSConfigProfile | AWSConfigSSOSession,
|
|
129
|
+
config_path: Optional[str] = None,
|
|
130
|
+
):
|
|
131
|
+
config = configparser.ConfigParser()
|
|
132
|
+
path = config_path or self.get_path()
|
|
133
|
+
|
|
134
|
+
if self.path_exists():
|
|
135
|
+
config.read(path) # or any INI file path
|
|
136
|
+
|
|
137
|
+
section_key = ""
|
|
138
|
+
|
|
139
|
+
if profile_name.startswith("sso-session "):
|
|
140
|
+
profile_name = profile_name.replace("sso-session ", "")
|
|
141
|
+
if profile_name.startswith("profile "):
|
|
142
|
+
profile_name = profile_name.replace("profile ", "")
|
|
143
|
+
|
|
144
|
+
if isinstance(section, AWSConfigProfile):
|
|
145
|
+
if profile_name:
|
|
146
|
+
section_key = f"profile {profile_name}"
|
|
147
|
+
else:
|
|
148
|
+
section_key = "default"
|
|
149
|
+
elif isinstance(section, AWSConfigSSOSession):
|
|
150
|
+
section_key = f"sso-session {profile_name}"
|
|
151
|
+
else:
|
|
152
|
+
raise ValueError("Invalid section type")
|
|
153
|
+
|
|
154
|
+
config = self._write_section(section_key, section, config)
|
|
155
|
+
|
|
156
|
+
with open(path, "w", encoding="utf-8") as cfg_file:
|
|
157
|
+
config.write(cfg_file)
|
|
158
|
+
|
|
159
|
+
def _write_section(
|
|
160
|
+
self,
|
|
161
|
+
section_key: str,
|
|
162
|
+
section: AWSConfigProfile | AWSConfigSSOSession,
|
|
163
|
+
config: configparser.ConfigParser,
|
|
164
|
+
) -> configparser.ConfigParser:
|
|
165
|
+
|
|
166
|
+
# always start with a "fresh" section
|
|
167
|
+
config[section_key] = {}
|
|
168
|
+
|
|
169
|
+
section_dictionary = section.to_dictionary()
|
|
170
|
+
for key, value in section_dictionary.items():
|
|
171
|
+
if value is not None:
|
|
172
|
+
config[section_key][key] = value
|
|
173
|
+
|
|
174
|
+
return config
|
|
175
|
+
|
|
176
|
+
def read_section(
|
|
177
|
+
self,
|
|
178
|
+
profile_name: Optional[str] = None,
|
|
179
|
+
config_path: Optional[str] = None,
|
|
180
|
+
section_type: Literal["profile", "sso-session"] = "profile",
|
|
181
|
+
) -> configparser.SectionProxy:
|
|
182
|
+
config = configparser.ConfigParser()
|
|
183
|
+
if not config_path:
|
|
184
|
+
config_path = self.get_path()
|
|
185
|
+
|
|
186
|
+
if not os.path.isfile(config_path):
|
|
187
|
+
return config
|
|
188
|
+
|
|
189
|
+
config.read(config_path)
|
|
190
|
+
profile_ini = f"{section_type} {profile_name}"
|
|
191
|
+
if profile_ini in config:
|
|
192
|
+
profile = config[profile_ini]
|
|
193
|
+
return profile
|
|
194
|
+
|
|
195
|
+
if profile_name in config:
|
|
196
|
+
profile = config[profile_name]
|
|
197
|
+
return profile
|
|
198
|
+
|
|
199
|
+
return {}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
|
|
2
|
+
|
|
3
|
+
1. Unable to locate credentials. You can configure credentials by running "aws configure".
|
|
4
|
+
|
|
5
|
+
- out of the blue, this started happening
|
|
6
|
+
- depending on how you are connecting boto3 may require a credentials file
|
|
7
|
+
- running "aws configure" and simply puttting in some garbage may fix the issue.
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Geek Cafe, LLC
|
|
3
|
+
Maintainers: Eric Wilson
|
|
4
|
+
MIT License. See Project Root for the license information.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import os
|
|
8
|
+
import boto3
|
|
9
|
+
from typing import Optional
|
|
10
|
+
from boto3_assist.aws_config import AWSConfig
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class SessionSetupMixin:
|
|
14
|
+
def _create_base_session(
|
|
15
|
+
self,
|
|
16
|
+
aws_profile: Optional[str],
|
|
17
|
+
aws_region: Optional[str],
|
|
18
|
+
aws_access_key_id: Optional[str],
|
|
19
|
+
aws_secret_access_key: Optional[str],
|
|
20
|
+
aws_session_token: Optional[str],
|
|
21
|
+
) -> boto3.Session:
|
|
22
|
+
try:
|
|
23
|
+
return boto3.Session(
|
|
24
|
+
profile_name=aws_profile,
|
|
25
|
+
region_name=aws_region,
|
|
26
|
+
aws_access_key_id=aws_access_key_id,
|
|
27
|
+
aws_secret_access_key=aws_secret_access_key,
|
|
28
|
+
aws_session_token=aws_session_token,
|
|
29
|
+
)
|
|
30
|
+
except Exception as e:
|
|
31
|
+
|
|
32
|
+
error_message = f"Failed to create boto3 session "
|
|
33
|
+
if "profile" in str(e).lower():
|
|
34
|
+
error_message += " due to a profile error "
|
|
35
|
+
|
|
36
|
+
error_message += f" with profile '{aws_profile}'."
|
|
37
|
+
config: AWSConfig = AWSConfig()
|
|
38
|
+
if not config.path_exists():
|
|
39
|
+
error_message += (
|
|
40
|
+
f" The AWS config file '{config.get_path()}' was not found. "
|
|
41
|
+
"Please ensure that the AWS CLI is installed and configured correctly. "
|
|
42
|
+
"You can install the AWS CLI by running 'pip install awscli' or 'pip install awscli --upgrade'. "
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
if (
|
|
46
|
+
os.getenv("HOME") == "/tmp"
|
|
47
|
+
or os.getenv("AWS_CONFIG_FILE") == "/tmp"
|
|
48
|
+
):
|
|
49
|
+
error_message += (
|
|
50
|
+
f'The environment HOME path is set to {os.getenv("HOME")}. '
|
|
51
|
+
)
|
|
52
|
+
if os.getenv("AWS_CONFIG_FILE"):
|
|
53
|
+
error_message += (
|
|
54
|
+
f"The environment AWS_CONFIG_FILE is set to {os.getenv('AWS_CONFIG_FILE')}. "
|
|
55
|
+
"The AWS_CONFIG_FILE overrides the HOME directory and path. "
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
error_message += (
|
|
59
|
+
"If you are running this locally and expecting it to be in your users home "
|
|
60
|
+
"directory, you may need to set the HOME or AWS_CONFIG_FILE environment variable manually. "
|
|
61
|
+
"There could be other actions such as a Lambda environment resetting the path to /tmp. "
|
|
62
|
+
"If you are running in a GitHub Actions environment, "
|
|
63
|
+
"you may need to set the HOME or AWS_CONFIG_FILE environment variable to '/home/runner'. "
|
|
64
|
+
)
|
|
65
|
+
elif not config.has_profile(aws_profile):
|
|
66
|
+
error_message += f" The profile '{aws_profile}' was not found in the AWS config file in {config.get_path()}."
|
|
67
|
+
|
|
68
|
+
# check for the existence of the profile and the path to the profile
|
|
69
|
+
|
|
70
|
+
raise RuntimeError(error_message) from e
|
{boto3_assist-0.15.0 → boto3_assist-0.16.0}/src/boto3_assist/utilities/serialization_utility.py
RENAMED
|
@@ -22,7 +22,7 @@ logger = Logger()
|
|
|
22
22
|
|
|
23
23
|
|
|
24
24
|
class SerializableModel:
|
|
25
|
-
"""Library to Serialize object to a DynamoDB Format"""
|
|
25
|
+
"""Library to Serialize object to a DynamoDB Format or other dictionary"""
|
|
26
26
|
|
|
27
27
|
T = TypeVar("T", bound="SerializableModel")
|
|
28
28
|
|
|
@@ -47,9 +47,16 @@ class SerializableModel:
|
|
|
47
47
|
|
|
48
48
|
return mapped
|
|
49
49
|
|
|
50
|
+
def dict(self) -> Dict[str, Any]:
|
|
51
|
+
"""
|
|
52
|
+
Same as .to_dictionary
|
|
53
|
+
|
|
54
|
+
"""
|
|
55
|
+
return self.to_dictionary()
|
|
56
|
+
|
|
50
57
|
def to_dictionary(self) -> Dict[str, Any]:
|
|
51
58
|
"""
|
|
52
|
-
Convert the object to a dictionary.
|
|
59
|
+
Convert the object to a dictionary. Same as .dict()
|
|
53
60
|
"""
|
|
54
61
|
# return Serialization.convert_object_to_dict(self)
|
|
55
62
|
return Serialization.to_dict(
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = '0.16.0'
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import unittest
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class AWSConfigTest(unittest.TestCase):
|
|
6
|
+
|
|
7
|
+
def setUp(self):
|
|
8
|
+
config_path_dir = (
|
|
9
|
+
Path(__file__).parent.joinpath(".outputs", "aws_config").resolve()
|
|
10
|
+
)
|
|
11
|
+
|
|
12
|
+
if not config_path_dir.exists():
|
|
13
|
+
config_path_dir.mkdir(parents=True, exist_ok=True)
|
|
14
|
+
|
|
15
|
+
self.config_path = config_path_dir.joinpath("config")
|
|
16
|
+
|
|
17
|
+
def test_import(self):
|
|
18
|
+
from boto3_assist.aws_config import AWSConfig
|
|
19
|
+
|
|
20
|
+
self.assertTrue(AWSConfig)
|
|
21
|
+
|
|
22
|
+
def test_init(self):
|
|
23
|
+
from boto3_assist.aws_config import AWSConfig
|
|
24
|
+
import os
|
|
25
|
+
|
|
26
|
+
aws_config = AWSConfig()
|
|
27
|
+
self.assertTrue(aws_config)
|
|
28
|
+
|
|
29
|
+
def test_path(self):
|
|
30
|
+
from boto3_assist.aws_config import AWSConfig
|
|
31
|
+
import os
|
|
32
|
+
|
|
33
|
+
aws_config = AWSConfig()
|
|
34
|
+
path = aws_config.get_path()
|
|
35
|
+
|
|
36
|
+
self.assertTrue(os.path.exists(path))
|
|
37
|
+
|
|
38
|
+
def test_config_upsert_profile(self):
|
|
39
|
+
from boto3_assist.aws_config import AWSConfig
|
|
40
|
+
from boto3_assist.aws_config import AWSConfigProfile
|
|
41
|
+
|
|
42
|
+
aws_config = AWSConfig()
|
|
43
|
+
profile = AWSConfigProfile("us-east-2", "json")
|
|
44
|
+
profile.aws_access_key_id = "111111111111"
|
|
45
|
+
profile.aws_secret_access_key = "22222222222"
|
|
46
|
+
aws_config.upsert_profile("unit-test-profile", profile)
|
|
47
|
+
|
|
48
|
+
def test_config_upsert_sso(self):
|
|
49
|
+
from boto3_assist.aws_config import AWSConfig
|
|
50
|
+
from boto3_assist.aws_config import AWSConfigSSOSession
|
|
51
|
+
|
|
52
|
+
aws_config = AWSConfig()
|
|
53
|
+
sso = AWSConfigSSOSession("us-east-1", "json")
|
|
54
|
+
sso.sso_start_url = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
|
|
55
|
+
sso.sso_region = "us-east-2"
|
|
56
|
+
sso.sso_registration_scopes = "scopes"
|
|
57
|
+
aws_config.upsert_sso_session("unit-test-sso", sso)
|
|
58
|
+
|
|
59
|
+
def test_config_upsert_sso_with_profile(self):
|
|
60
|
+
from boto3_assist.aws_config import AWSConfig
|
|
61
|
+
from boto3_assist.aws_config import AWSConfigSSOSession
|
|
62
|
+
from boto3_assist.aws_config import AWSConfigProfile
|
|
63
|
+
|
|
64
|
+
aws_config = AWSConfig()
|
|
65
|
+
sso = AWSConfigSSOSession("us-east-1", "json")
|
|
66
|
+
sso.sso_start_url = "https://<account-domain>.awsapps.com/start/#/?tab=accounts"
|
|
67
|
+
sso.sso_region = "us-east-1"
|
|
68
|
+
sso.sso_registration_scopes = "sso:account:access"
|
|
69
|
+
|
|
70
|
+
section_name = "test-tenant-001"
|
|
71
|
+
|
|
72
|
+
profile = AWSConfigProfile("us-east-1", "json")
|
|
73
|
+
profile.sso_session = section_name
|
|
74
|
+
profile.sso_account_id = "AAAAAAAAAAAAAAAAAA"
|
|
75
|
+
profile.sso_role_name = "SomeRoleName"
|
|
76
|
+
profile.region = "us-east-1"
|
|
77
|
+
profile.output = "json"
|
|
78
|
+
|
|
79
|
+
aws_config.upsert_sso_session(
|
|
80
|
+
section_name, sso_session=sso, profile=profile, config_path=self.config_path
|
|
81
|
+
)
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
import pytest
|
|
2
|
+
from unittest.mock import patch, MagicMock
|
|
3
|
+
from boto3 import Session as RealBoto3Session
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
@pytest.fixture
|
|
7
|
+
def mock_boto3_session():
|
|
8
|
+
"""Patch boto3.Session and simulate a base and an assumed session with separate client behaviors."""
|
|
9
|
+
with patch("boto3.Session", autospec=True) as mock_session_class:
|
|
10
|
+
# Create base and assumed session mocks
|
|
11
|
+
base_session = MagicMock(spec=RealBoto3Session)
|
|
12
|
+
assumed_session = MagicMock(spec=RealBoto3Session)
|
|
13
|
+
|
|
14
|
+
# STS client returns mocked credentials
|
|
15
|
+
mock_sts_client = MagicMock()
|
|
16
|
+
mock_sts_client.assume_role.return_value = {
|
|
17
|
+
"Credentials": {
|
|
18
|
+
"AccessKeyId": "mock-access-key",
|
|
19
|
+
"SecretAccessKey": "mock-secret-key",
|
|
20
|
+
"SessionToken": "mock-session-token",
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
# Assign isolated .client behavior per session
|
|
25
|
+
base_session.client.side_effect = lambda service_name: (
|
|
26
|
+
mock_sts_client if service_name == "sts" else MagicMock()
|
|
27
|
+
)
|
|
28
|
+
assumed_session.client.return_value = MagicMock()
|
|
29
|
+
|
|
30
|
+
# Simulate two sessions: base → assumed
|
|
31
|
+
mock_session_class.side_effect = [base_session, assumed_session]
|
|
32
|
+
|
|
33
|
+
yield base_session, assumed_session, mock_sts_client, mock_session_class
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def test_single_assume_role_chain(mock_boto3_session):
|
|
37
|
+
base_session, assumed_session, mock_sts_client, session_class = mock_boto3_session
|
|
38
|
+
|
|
39
|
+
from boto3_assist.boto3session import Boto3SessionManager
|
|
40
|
+
|
|
41
|
+
manager = Boto3SessionManager(
|
|
42
|
+
service_name="s3",
|
|
43
|
+
aws_region="us-east-1",
|
|
44
|
+
assume_role_chain=["arn:aws:iam::111111111111:role/TestRole"],
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
# Ensure base session initialized
|
|
48
|
+
assert session_class.call_args_list[0].kwargs["region_name"] == "us-east-1"
|
|
49
|
+
|
|
50
|
+
# Ensure assume_role called correctly
|
|
51
|
+
mock_sts_client.assume_role.assert_called_once_with(
|
|
52
|
+
RoleArn="arn:aws:iam::111111111111:role/TestRole",
|
|
53
|
+
RoleSessionName="AssumeRoleSessionFors3",
|
|
54
|
+
DurationSeconds=3600,
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
# Ensure second session created with correct credentials
|
|
58
|
+
assert session_class.call_args_list[1].kwargs == {
|
|
59
|
+
"aws_access_key_id": "mock-access-key",
|
|
60
|
+
"aws_secret_access_key": "mock-secret-key",
|
|
61
|
+
"aws_session_token": "mock-session-token",
|
|
62
|
+
"region_name": "us-east-1",
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
# Ensure client created from assumed session
|
|
66
|
+
_ = manager.client
|
|
67
|
+
assumed_session.client.assert_called_with("s3", config=None, endpoint_url=None)
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def test_no_assume_role(mock_boto3_session):
|
|
71
|
+
base_session, _, _, session_class = mock_boto3_session
|
|
72
|
+
|
|
73
|
+
from boto3_assist.boto3session import Boto3SessionManager
|
|
74
|
+
|
|
75
|
+
manager = Boto3SessionManager(
|
|
76
|
+
service_name="dynamodb",
|
|
77
|
+
aws_region="us-west-2",
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
# Only one session created
|
|
81
|
+
assert session_class.call_count == 1
|
|
82
|
+
assert session_class.call_args.kwargs == {
|
|
83
|
+
"profile_name": None,
|
|
84
|
+
"region_name": "us-west-2",
|
|
85
|
+
"aws_access_key_id": None,
|
|
86
|
+
"aws_secret_access_key": None,
|
|
87
|
+
"aws_session_token": None,
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
# Resource created from base session
|
|
91
|
+
_ = manager.resource
|
|
92
|
+
base_session.resource.assert_called_with("dynamodb", config=None, endpoint_url=None)
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
def test_multiple_assume_role_chain():
|
|
96
|
+
from boto3_assist.boto3session import Boto3SessionManager
|
|
97
|
+
from boto3 import Session as RealBoto3Session
|
|
98
|
+
|
|
99
|
+
with patch("boto3.Session", autospec=True) as mock_session_class:
|
|
100
|
+
# Create three sessions: base → first assume → second assume
|
|
101
|
+
base_session = MagicMock(spec=RealBoto3Session)
|
|
102
|
+
first_assumed_session = MagicMock(spec=RealBoto3Session)
|
|
103
|
+
second_assumed_session = MagicMock(spec=RealBoto3Session)
|
|
104
|
+
|
|
105
|
+
# Mock each session's client() behavior
|
|
106
|
+
first_sts = MagicMock()
|
|
107
|
+
second_sts = MagicMock()
|
|
108
|
+
|
|
109
|
+
# First assume_role returns first credentials
|
|
110
|
+
first_sts.assume_role.return_value = {
|
|
111
|
+
"Credentials": {
|
|
112
|
+
"AccessKeyId": "first-key",
|
|
113
|
+
"SecretAccessKey": "first-secret",
|
|
114
|
+
"SessionToken": "first-token",
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
# Second assume_role returns second credentials
|
|
119
|
+
second_sts.assume_role.return_value = {
|
|
120
|
+
"Credentials": {
|
|
121
|
+
"AccessKeyId": "second-key",
|
|
122
|
+
"SecretAccessKey": "second-secret",
|
|
123
|
+
"SessionToken": "second-token",
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
# Assign proper .client() behavior for each session
|
|
128
|
+
base_session.client.side_effect = lambda svc: (
|
|
129
|
+
first_sts if svc == "sts" else MagicMock()
|
|
130
|
+
)
|
|
131
|
+
first_assumed_session.client.side_effect = lambda svc: (
|
|
132
|
+
second_sts if svc == "sts" else MagicMock()
|
|
133
|
+
)
|
|
134
|
+
second_assumed_session.client.return_value = MagicMock()
|
|
135
|
+
|
|
136
|
+
# Setup session chain return order
|
|
137
|
+
mock_session_class.side_effect = [
|
|
138
|
+
base_session,
|
|
139
|
+
first_assumed_session,
|
|
140
|
+
second_assumed_session,
|
|
141
|
+
]
|
|
142
|
+
|
|
143
|
+
# Run session manager
|
|
144
|
+
manager = Boto3SessionManager(
|
|
145
|
+
service_name="s3",
|
|
146
|
+
aws_region="us-east-1",
|
|
147
|
+
assume_role_chain=[
|
|
148
|
+
"arn:aws:iam::111111111111:role/FirstRole",
|
|
149
|
+
"arn:aws:iam::222222222222:role/SecondRole",
|
|
150
|
+
],
|
|
151
|
+
)
|
|
152
|
+
|
|
153
|
+
# Assert role assumptions
|
|
154
|
+
first_sts.assume_role.assert_called_once_with(
|
|
155
|
+
RoleArn="arn:aws:iam::111111111111:role/FirstRole",
|
|
156
|
+
RoleSessionName="AssumeRoleSessionFors3",
|
|
157
|
+
DurationSeconds=3600,
|
|
158
|
+
)
|
|
159
|
+
second_sts.assume_role.assert_called_once_with(
|
|
160
|
+
RoleArn="arn:aws:iam::222222222222:role/SecondRole",
|
|
161
|
+
RoleSessionName="AssumeRoleSessionFors3",
|
|
162
|
+
DurationSeconds=3600,
|
|
163
|
+
)
|
|
164
|
+
|
|
165
|
+
# Assert final session creation used second credentials
|
|
166
|
+
assert mock_session_class.call_args_list[2].kwargs == {
|
|
167
|
+
"aws_access_key_id": "second-key",
|
|
168
|
+
"aws_secret_access_key": "second-secret",
|
|
169
|
+
"aws_session_token": "second-token",
|
|
170
|
+
"region_name": "us-east-1",
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
# Ensure client is created from final session
|
|
174
|
+
_ = manager.client
|
|
175
|
+
second_assumed_session.client.assert_called_with(
|
|
176
|
+
"s3", config=None, endpoint_url=None
|
|
177
|
+
)
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
Geek Cafe, LLC
|
|
3
|
-
Maintainers: Eric Wilson
|
|
4
|
-
MIT License. See Project Root for the license information.
|
|
5
|
-
"""
|
|
6
|
-
|
|
7
|
-
import boto3
|
|
8
|
-
from typing import Optional
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
class SessionSetupMixin:
|
|
12
|
-
def _create_base_session(
|
|
13
|
-
self,
|
|
14
|
-
aws_profile: Optional[str],
|
|
15
|
-
aws_region: Optional[str],
|
|
16
|
-
aws_access_key_id: Optional[str],
|
|
17
|
-
aws_secret_access_key: Optional[str],
|
|
18
|
-
aws_session_token: Optional[str],
|
|
19
|
-
) -> boto3.Session:
|
|
20
|
-
try:
|
|
21
|
-
return boto3.Session(
|
|
22
|
-
profile_name=aws_profile,
|
|
23
|
-
region_name=aws_region,
|
|
24
|
-
aws_access_key_id=aws_access_key_id,
|
|
25
|
-
aws_secret_access_key=aws_secret_access_key,
|
|
26
|
-
aws_session_token=aws_session_token,
|
|
27
|
-
)
|
|
28
|
-
except Exception as e:
|
|
29
|
-
raise RuntimeError(f"Failed to create boto3 session: {e}") from e
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = '0.15.0'
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{boto3_assist-0.15.0 → boto3_assist-0.16.0}/examples/dynamodb/services/order_item_service.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{boto3_assist-0.15.0 → boto3_assist-0.16.0}/src/boto3_assist/cloudwatch/cloudwatch_connection.py
RENAMED
|
File without changes
|
|
File without changes
|
{boto3_assist-0.15.0 → boto3_assist-0.16.0}/src/boto3_assist/cloudwatch/cloudwatch_log_connection.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{boto3_assist-0.15.0 → boto3_assist-0.16.0}/src/boto3_assist/dynamodb/dynamodb_connection.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{boto3_assist-0.15.0 → boto3_assist-0.16.0}/src/boto3_assist/dynamodb/dynamodb_model_base.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{boto3_assist-0.15.0 → boto3_assist-0.16.0}/src/boto3_assist/dynamodb/dynamodb_reserved_words.py
RENAMED
|
File without changes
|
{boto3_assist-0.15.0 → boto3_assist-0.16.0}/src/boto3_assist/dynamodb/dynamodb_reserved_words.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{boto3_assist-0.15.0 → boto3_assist-0.16.0}/src/boto3_assist/environment_services/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{boto3_assist-0.15.0 → boto3_assist-0.16.0}/src/boto3_assist/securityhub/securityhub_connection.py
RENAMED
|
File without changes
|
|
File without changes
|
{boto3_assist-0.15.0 → boto3_assist-0.16.0}/src/boto3_assist/ssm/parameter_store/parameter_store.py
RENAMED
|
File without changes
|
|
File without changes
|
{boto3_assist-0.15.0 → boto3_assist-0.16.0}/src/boto3_assist/utilities/dictionary_utility.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{boto3_assist-0.15.0 → boto3_assist-0.16.0}/tests/integration/cross_account_connection_test.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{boto3_assist-0.15.0 → boto3_assist-0.16.0}/tests/unit/dynamodb_tests/dbmodels/cms/content_block.py
RENAMED
|
File without changes
|
|
File without changes
|
{boto3_assist-0.15.0 → boto3_assist-0.16.0}/tests/unit/dynamodb_tests/dbmodels/cms/template.py
RENAMED
|
File without changes
|
{boto3_assist-0.15.0 → boto3_assist-0.16.0}/tests/unit/dynamodb_tests/dbmodels/simple_model.py
RENAMED
|
File without changes
|
{boto3_assist-0.15.0 → boto3_assist-0.16.0}/tests/unit/dynamodb_tests/dbmodels/user_model.py
RENAMED
|
File without changes
|
|
File without changes
|
{boto3_assist-0.15.0 → boto3_assist-0.16.0}/tests/unit/dynamodb_tests/dynamodb_model_base_test.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{boto3_assist-0.15.0 → boto3_assist-0.16.0}/tests/unit/dynamodb_tests/dynamodb_moto_sorting_test.py
RENAMED
|
File without changes
|
{boto3_assist-0.15.0 → boto3_assist-0.16.0}/tests/unit/dynamodb_tests/dynamodb_reindex_test.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{boto3_assist-0.15.0 → boto3_assist-0.16.0}/tests/unit/models_tests/serializable_model_user_test.py
RENAMED
|
File without changes
|
{boto3_assist-0.15.0 → boto3_assist-0.16.0}/tests/unit/models_tests/serializable_model_wide_test.py
RENAMED
|
File without changes
|
|
File without changes
|
{boto3_assist-0.15.0 → boto3_assist-0.16.0}/tests/unit/parameter_store/parameter_store_test.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{boto3_assist-0.15.0 → boto3_assist-0.16.0}/tests/unit/utilities/serialization_utility_test.py
RENAMED
|
File without changes
|
|
File without changes
|