localstack-core 4.10.1.dev7__py3-none-any.whl → 4.11.2.dev14__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.
- localstack/aws/api/acm/__init__.py +122 -122
- localstack/aws/api/apigateway/__init__.py +604 -561
- localstack/aws/api/cloudcontrol/__init__.py +63 -63
- localstack/aws/api/cloudformation/__init__.py +1201 -969
- localstack/aws/api/cloudwatch/__init__.py +375 -375
- localstack/aws/api/config/__init__.py +784 -786
- localstack/aws/api/dynamodb/__init__.py +753 -759
- localstack/aws/api/dynamodbstreams/__init__.py +74 -74
- localstack/aws/api/ec2/__init__.py +10062 -8826
- localstack/aws/api/es/__init__.py +453 -453
- localstack/aws/api/events/__init__.py +552 -552
- localstack/aws/api/firehose/__init__.py +541 -543
- localstack/aws/api/iam/__init__.py +866 -572
- localstack/aws/api/kinesis/__init__.py +235 -147
- localstack/aws/api/kms/__init__.py +341 -336
- localstack/aws/api/lambda_/__init__.py +974 -621
- localstack/aws/api/logs/__init__.py +988 -675
- localstack/aws/api/opensearch/__init__.py +903 -785
- localstack/aws/api/pipes/__init__.py +336 -336
- localstack/aws/api/redshift/__init__.py +1257 -1166
- localstack/aws/api/resource_groups/__init__.py +175 -175
- localstack/aws/api/resourcegroupstaggingapi/__init__.py +103 -67
- localstack/aws/api/route53/__init__.py +296 -254
- localstack/aws/api/route53resolver/__init__.py +397 -396
- localstack/aws/api/s3/__init__.py +1412 -1349
- localstack/aws/api/s3control/__init__.py +594 -594
- localstack/aws/api/scheduler/__init__.py +118 -118
- localstack/aws/api/secretsmanager/__init__.py +221 -216
- localstack/aws/api/ses/__init__.py +227 -227
- localstack/aws/api/sns/__init__.py +115 -115
- localstack/aws/api/sqs/__init__.py +100 -100
- localstack/aws/api/ssm/__init__.py +1977 -1971
- localstack/aws/api/stepfunctions/__init__.py +375 -333
- localstack/aws/api/sts/__init__.py +142 -66
- localstack/aws/api/support/__init__.py +112 -112
- localstack/aws/api/swf/__init__.py +378 -386
- localstack/aws/api/transcribe/__init__.py +425 -425
- localstack/aws/handlers/logging.py +8 -4
- localstack/aws/handlers/service.py +22 -3
- localstack/aws/protocol/parser.py +1 -1
- localstack/aws/protocol/serializer.py +1 -1
- localstack/aws/scaffold.py +15 -17
- localstack/cli/localstack.py +6 -1
- localstack/deprecations.py +0 -6
- localstack/dev/kubernetes/__main__.py +38 -3
- localstack/services/acm/provider.py +4 -0
- localstack/services/apigateway/helpers.py +5 -9
- localstack/services/apigateway/legacy/provider.py +60 -24
- localstack/services/apigateway/patches.py +0 -9
- localstack/services/cloudformation/engine/template_preparer.py +6 -2
- localstack/services/cloudformation/engine/v2/change_set_model_preproc.py +12 -0
- localstack/services/cloudformation/provider.py +2 -2
- localstack/services/cloudformation/v2/provider.py +6 -6
- localstack/services/cloudwatch/provider.py +10 -3
- localstack/services/cloudwatch/provider_v2.py +6 -3
- localstack/services/configservice/provider.py +5 -1
- localstack/services/dynamodb/provider.py +1 -0
- localstack/services/dynamodb/v2/provider.py +1 -0
- localstack/services/dynamodbstreams/provider.py +6 -0
- localstack/services/dynamodbstreams/v2/provider.py +6 -0
- localstack/services/ec2/provider.py +6 -0
- localstack/services/es/provider.py +6 -0
- localstack/services/events/provider.py +4 -0
- localstack/services/events/v1/provider.py +9 -0
- localstack/services/firehose/provider.py +5 -0
- localstack/services/iam/provider.py +4 -0
- localstack/services/kinesis/packages.py +1 -1
- localstack/services/kms/models.py +44 -24
- localstack/services/kms/provider.py +97 -16
- localstack/services/lambda_/api_utils.py +40 -21
- localstack/services/lambda_/event_source_mapping/pollers/stream_poller.py +1 -1
- localstack/services/lambda_/invocation/assignment.py +4 -1
- localstack/services/lambda_/invocation/execution_environment.py +21 -2
- localstack/services/lambda_/invocation/lambda_models.py +27 -2
- localstack/services/lambda_/invocation/lambda_service.py +51 -3
- localstack/services/lambda_/invocation/models.py +9 -1
- localstack/services/lambda_/invocation/version_manager.py +18 -3
- localstack/services/lambda_/packages.py +1 -1
- localstack/services/lambda_/provider.py +240 -96
- localstack/services/lambda_/resource_providers/aws_lambda_function.py +33 -1
- localstack/services/lambda_/runtimes.py +10 -3
- localstack/services/logs/provider.py +45 -19
- localstack/services/opensearch/provider.py +53 -3
- localstack/services/resource_groups/provider.py +5 -1
- localstack/services/resourcegroupstaggingapi/provider.py +6 -1
- localstack/services/s3/provider.py +29 -16
- localstack/services/s3/utils.py +35 -14
- localstack/services/s3control/provider.py +101 -2
- localstack/services/s3control/validation.py +50 -0
- localstack/services/sns/constants.py +3 -1
- localstack/services/sns/publisher.py +15 -6
- localstack/services/sns/v2/models.py +30 -1
- localstack/services/sns/v2/provider.py +794 -31
- localstack/services/sns/v2/utils.py +20 -0
- localstack/services/sqs/models.py +37 -10
- localstack/services/stepfunctions/asl/component/common/path/result_path.py +1 -1
- localstack/services/stepfunctions/asl/component/state/state_execution/execute_state.py +0 -1
- localstack/services/stepfunctions/asl/component/state/state_execution/state_map/state_map.py +0 -1
- localstack/services/stepfunctions/asl/component/state/state_execution/state_task/lambda_eval_utils.py +8 -8
- localstack/services/stepfunctions/asl/component/state/state_execution/state_task/{mock_eval_utils.py → local_mock_eval_utils.py} +13 -9
- localstack/services/stepfunctions/asl/component/state/state_execution/state_task/service/state_task_service.py +6 -6
- localstack/services/stepfunctions/asl/component/state/state_execution/state_task/service/state_task_service_callback.py +1 -1
- localstack/services/stepfunctions/asl/component/state/state_fail/state_fail.py +4 -0
- localstack/services/stepfunctions/asl/component/test_state/state/base_mock.py +118 -0
- localstack/services/stepfunctions/asl/component/test_state/state/common.py +82 -0
- localstack/services/stepfunctions/asl/component/test_state/state/execution.py +139 -0
- localstack/services/stepfunctions/asl/component/test_state/state/map.py +77 -0
- localstack/services/stepfunctions/asl/component/test_state/state/task.py +44 -0
- localstack/services/stepfunctions/asl/eval/environment.py +30 -22
- localstack/services/stepfunctions/asl/eval/states.py +1 -1
- localstack/services/stepfunctions/asl/eval/test_state/environment.py +49 -9
- localstack/services/stepfunctions/asl/eval/test_state/program_state.py +22 -0
- localstack/services/stepfunctions/asl/jsonata/jsonata.py +5 -1
- localstack/services/stepfunctions/asl/parse/preprocessor.py +67 -24
- localstack/services/stepfunctions/asl/parse/test_state/asl_parser.py +5 -4
- localstack/services/stepfunctions/asl/parse/test_state/preprocessor.py +222 -31
- localstack/services/stepfunctions/asl/static_analyser/test_state/test_state_analyser.py +170 -22
- localstack/services/stepfunctions/backend/execution.py +6 -6
- localstack/services/stepfunctions/backend/execution_worker.py +5 -5
- localstack/services/stepfunctions/backend/test_state/execution.py +36 -0
- localstack/services/stepfunctions/backend/test_state/execution_worker.py +33 -1
- localstack/services/stepfunctions/backend/test_state/test_state_mock.py +127 -0
- localstack/services/stepfunctions/local_mocking/__init__.py +9 -0
- localstack/services/stepfunctions/{mocking → local_mocking}/mock_config.py +24 -17
- localstack/services/stepfunctions/provider.py +78 -27
- localstack/services/stepfunctions/test_state/mock_config.py +47 -0
- localstack/testing/pytest/fixtures.py +28 -0
- localstack/testing/snapshots/transformer_utility.py +7 -0
- localstack/testing/testselection/matching.py +0 -1
- localstack/utils/analytics/publisher.py +37 -155
- localstack/utils/analytics/service_request_aggregator.py +6 -4
- localstack/utils/aws/arns.py +7 -0
- localstack/utils/aws/client_types.py +0 -8
- localstack/utils/batching.py +258 -0
- localstack/utils/catalog/catalog_loader.py +111 -3
- localstack/utils/collections.py +23 -11
- localstack/utils/crypto.py +109 -0
- localstack/version.py +2 -2
- {localstack_core-4.10.1.dev7.dist-info → localstack_core-4.11.2.dev14.dist-info}/METADATA +7 -6
- {localstack_core-4.10.1.dev7.dist-info → localstack_core-4.11.2.dev14.dist-info}/RECORD +149 -141
- localstack_core-4.11.2.dev14.dist-info/plux.json +1 -0
- localstack/services/stepfunctions/mocking/__init__.py +0 -0
- localstack/utils/batch_policy.py +0 -124
- localstack_core-4.10.1.dev7.dist-info/plux.json +0 -1
- /localstack/services/stepfunctions/{mocking → local_mocking}/mock_config_file.py +0 -0
- {localstack_core-4.10.1.dev7.data → localstack_core-4.11.2.dev14.data}/scripts/localstack +0 -0
- {localstack_core-4.10.1.dev7.data → localstack_core-4.11.2.dev14.data}/scripts/localstack-supervisor +0 -0
- {localstack_core-4.10.1.dev7.data → localstack_core-4.11.2.dev14.data}/scripts/localstack.bat +0 -0
- {localstack_core-4.10.1.dev7.dist-info → localstack_core-4.11.2.dev14.dist-info}/WHEEL +0 -0
- {localstack_core-4.10.1.dev7.dist-info → localstack_core-4.11.2.dev14.dist-info}/entry_points.txt +0 -0
- {localstack_core-4.10.1.dev7.dist-info → localstack_core-4.11.2.dev14.dist-info}/licenses/LICENSE.txt +0 -0
- {localstack_core-4.10.1.dev7.dist-info → localstack_core-4.11.2.dev14.dist-info}/top_level.txt +0 -0
|
@@ -1,11 +1,119 @@
|
|
|
1
1
|
import json
|
|
2
|
+
import logging
|
|
3
|
+
from json import JSONDecodeError
|
|
4
|
+
from pathlib import Path
|
|
2
5
|
|
|
6
|
+
import requests
|
|
7
|
+
from pydantic import BaseModel
|
|
8
|
+
|
|
9
|
+
from localstack import config, constants
|
|
3
10
|
from localstack.utils.catalog.common import AwsRemoteCatalog
|
|
11
|
+
from localstack.utils.http import get_proxies
|
|
12
|
+
from localstack.utils.json import FileMappedDocument
|
|
13
|
+
|
|
14
|
+
LOG = logging.getLogger(__name__)
|
|
15
|
+
|
|
16
|
+
AWS_CATALOG_FILE_NAME = "aws_catalog.json"
|
|
17
|
+
|
|
4
18
|
|
|
5
|
-
|
|
19
|
+
class RemoteCatalogVersionResponse(BaseModel):
|
|
20
|
+
emulator_type: str
|
|
21
|
+
version: str
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class AwsCatalogLoaderException(Exception):
|
|
25
|
+
def __init__(self, msg: str, *args):
|
|
26
|
+
super().__init__(msg, *args)
|
|
6
27
|
|
|
7
28
|
|
|
8
29
|
class RemoteCatalogLoader:
|
|
30
|
+
supported_schema_version = "v1"
|
|
31
|
+
api_endpoint_catalog = f"{constants.API_ENDPOINT}/license/catalog"
|
|
32
|
+
catalog_file_path = Path(config.dirs.cache) / AWS_CATALOG_FILE_NAME
|
|
33
|
+
|
|
9
34
|
def get_remote_catalog(self) -> AwsRemoteCatalog:
|
|
10
|
-
|
|
11
|
-
|
|
35
|
+
catalog_doc = FileMappedDocument(self.catalog_file_path)
|
|
36
|
+
cached_catalog = AwsRemoteCatalog(**catalog_doc) if catalog_doc else None
|
|
37
|
+
if cached_catalog:
|
|
38
|
+
cached_catalog_version = cached_catalog.localstack.version
|
|
39
|
+
if not self._should_update_cached_catalog(cached_catalog_version):
|
|
40
|
+
return cached_catalog
|
|
41
|
+
catalog = self._get_catalog_from_platform()
|
|
42
|
+
self._save_catalog_to_cache(catalog_doc, catalog)
|
|
43
|
+
return catalog
|
|
44
|
+
|
|
45
|
+
def _get_latest_localstack_version(self) -> str:
|
|
46
|
+
try:
|
|
47
|
+
proxies = get_proxies()
|
|
48
|
+
response = requests.get(
|
|
49
|
+
f"{self.api_endpoint_catalog}/aws/version",
|
|
50
|
+
verify=not config.is_env_true("SSL_NO_VERIFY"),
|
|
51
|
+
proxies=proxies,
|
|
52
|
+
)
|
|
53
|
+
if response.ok:
|
|
54
|
+
return RemoteCatalogVersionResponse.model_validate(response.content).version
|
|
55
|
+
self._raise_server_error(response)
|
|
56
|
+
except requests.exceptions.RequestException as e:
|
|
57
|
+
raise AwsCatalogLoaderException(
|
|
58
|
+
f"An unexpected network error occurred when trying to fetch latest localstack version: {e}"
|
|
59
|
+
) from e
|
|
60
|
+
|
|
61
|
+
def _should_update_cached_catalog(self, current_catalog_version: str) -> bool:
|
|
62
|
+
try:
|
|
63
|
+
latest_version = self._get_latest_localstack_version()
|
|
64
|
+
return latest_version != current_catalog_version
|
|
65
|
+
except Exception as e:
|
|
66
|
+
LOG.warning(
|
|
67
|
+
"Failed to retrieve the latest catalog version, cached catalog update skipped: %s",
|
|
68
|
+
e,
|
|
69
|
+
)
|
|
70
|
+
return False
|
|
71
|
+
|
|
72
|
+
def _save_catalog_to_cache(self, catalog_doc: FileMappedDocument, catalog: AwsRemoteCatalog):
|
|
73
|
+
catalog_doc.clear()
|
|
74
|
+
catalog_doc.update(catalog.model_dump())
|
|
75
|
+
catalog_doc.save()
|
|
76
|
+
|
|
77
|
+
def _get_catalog_from_platform(self) -> AwsRemoteCatalog:
|
|
78
|
+
try:
|
|
79
|
+
proxies = get_proxies()
|
|
80
|
+
response = requests.post(
|
|
81
|
+
self.api_endpoint_catalog,
|
|
82
|
+
verify=not config.is_env_true("SSL_NO_VERIFY"),
|
|
83
|
+
proxies=proxies,
|
|
84
|
+
)
|
|
85
|
+
|
|
86
|
+
if response.ok:
|
|
87
|
+
return self._parse_catalog(response.content)
|
|
88
|
+
self._raise_server_error(response)
|
|
89
|
+
except requests.exceptions.RequestException as e:
|
|
90
|
+
raise AwsCatalogLoaderException(
|
|
91
|
+
f"An unexpected network error occurred when trying to fetch remote catalog: {e}"
|
|
92
|
+
) from e
|
|
93
|
+
|
|
94
|
+
def _parse_catalog(self, document: bytes) -> AwsRemoteCatalog | None:
|
|
95
|
+
try:
|
|
96
|
+
catalog_json = json.loads(document)
|
|
97
|
+
except JSONDecodeError as e:
|
|
98
|
+
raise AwsCatalogLoaderException(f"Could not de-serialize json catalog: {e}") from e
|
|
99
|
+
remote_catalog = AwsRemoteCatalog.model_validate(catalog_json)
|
|
100
|
+
if remote_catalog.schema_version != self.supported_schema_version:
|
|
101
|
+
raise AwsCatalogLoaderException(
|
|
102
|
+
f"Unsupported schema version: '{remote_catalog.schema_version}'. Only '{self.supported_schema_version}' is supported"
|
|
103
|
+
)
|
|
104
|
+
return remote_catalog
|
|
105
|
+
|
|
106
|
+
def _raise_server_error(self, response: requests.Response):
|
|
107
|
+
try:
|
|
108
|
+
server_error = response.json()
|
|
109
|
+
if error_message := server_error.get("message"):
|
|
110
|
+
raise AwsCatalogLoaderException(
|
|
111
|
+
f"Unexpected AWS catalog server error: {response.text}"
|
|
112
|
+
)
|
|
113
|
+
raise AwsCatalogLoaderException(
|
|
114
|
+
f"A server error occurred while calling remote catalog API (HTTP {response.status_code}): {error_message}"
|
|
115
|
+
)
|
|
116
|
+
except Exception:
|
|
117
|
+
raise AwsCatalogLoaderException(
|
|
118
|
+
f"An unexpected server error occurred while calling remote catalog API (HTTP {response.status_code}): {response.text}"
|
|
119
|
+
)
|
localstack/utils/collections.py
CHANGED
|
@@ -5,7 +5,7 @@ and manipulate python collection (dicts, list, sets).
|
|
|
5
5
|
|
|
6
6
|
import logging
|
|
7
7
|
import re
|
|
8
|
-
from collections.abc import Callable, Iterable, Iterator, Mapping, Sized
|
|
8
|
+
from collections.abc import Callable, Generator, Iterable, Iterator, Mapping, Sized
|
|
9
9
|
from typing import (
|
|
10
10
|
Any,
|
|
11
11
|
Optional,
|
|
@@ -24,6 +24,9 @@ LOG = logging.getLogger(__name__)
|
|
|
24
24
|
# default regex to match an item in a comma-separated list string
|
|
25
25
|
DEFAULT_REGEX_LIST_ITEM = r"[\w-]+"
|
|
26
26
|
|
|
27
|
+
_E = TypeVar("_E")
|
|
28
|
+
"""TypeVar var used internally for container type parameters."""
|
|
29
|
+
|
|
27
30
|
|
|
28
31
|
class AccessTrackingDict(dict):
|
|
29
32
|
"""
|
|
@@ -101,21 +104,18 @@ class HashableJsonDict(ImmutableDict):
|
|
|
101
104
|
return hash(canonical_json(self._dict))
|
|
102
105
|
|
|
103
106
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
class PaginatedList(list[_ListType]):
|
|
107
|
+
class PaginatedList(list[_E]):
|
|
108
108
|
"""List which can be paginated and filtered. For usage in AWS APIs with paginated responses"""
|
|
109
109
|
|
|
110
110
|
DEFAULT_PAGE_SIZE = 50
|
|
111
111
|
|
|
112
112
|
def get_page(
|
|
113
113
|
self,
|
|
114
|
-
token_generator: Callable[[
|
|
114
|
+
token_generator: Callable[[_E], str],
|
|
115
115
|
next_token: str = None,
|
|
116
116
|
page_size: int = None,
|
|
117
|
-
filter_function: Callable[[
|
|
118
|
-
) -> tuple[list[
|
|
117
|
+
filter_function: Callable[[_E], bool] = None,
|
|
118
|
+
) -> tuple[list[_E], str | None]:
|
|
119
119
|
if filter_function is not None:
|
|
120
120
|
result_list = list(filter(filter_function, self))
|
|
121
121
|
else:
|
|
@@ -528,9 +528,6 @@ def is_comma_delimited_list(string: str, item_regex: str | None = None) -> bool:
|
|
|
528
528
|
return True
|
|
529
529
|
|
|
530
530
|
|
|
531
|
-
_E = TypeVar("_E")
|
|
532
|
-
|
|
533
|
-
|
|
534
531
|
def optional_list(condition: bool, items: Iterable[_E]) -> list[_E]:
|
|
535
532
|
"""
|
|
536
533
|
Given an iterable, either create a list out of the entire iterable (if `condition` is `True`), or return the empty list.
|
|
@@ -540,3 +537,18 @@ def optional_list(condition: bool, items: Iterable[_E]) -> list[_E]:
|
|
|
540
537
|
[]
|
|
541
538
|
"""
|
|
542
539
|
return list(filter(lambda _: condition, items))
|
|
540
|
+
|
|
541
|
+
|
|
542
|
+
def iter_chunks(items: list[_E], chunk_size: int) -> Generator[list[_E], None, None]:
|
|
543
|
+
"""
|
|
544
|
+
Split a list into smaller chunks of a specified size and iterate over them.
|
|
545
|
+
|
|
546
|
+
It is implemented as a generator and yields each chunk as needed, making it memory-efficient for large lists.
|
|
547
|
+
|
|
548
|
+
:param items: A list of elements to be divided into chunks.
|
|
549
|
+
:param chunk_size: The maximum number of elements that a single chunk can contain.
|
|
550
|
+
:return: A generator that yields chunks (sublists) of the original list. Each chunk contains up to `chunk_size`
|
|
551
|
+
elements.
|
|
552
|
+
"""
|
|
553
|
+
for i in range(0, len(items), chunk_size):
|
|
554
|
+
yield items[i : i + chunk_size]
|
localstack/utils/crypto.py
CHANGED
|
@@ -4,7 +4,13 @@ import os
|
|
|
4
4
|
import re
|
|
5
5
|
import threading
|
|
6
6
|
|
|
7
|
+
from asn1crypto import algos, cms, core
|
|
8
|
+
from asn1crypto import x509 as asn1_x509
|
|
7
9
|
from cryptography.hazmat.backends import default_backend
|
|
10
|
+
from cryptography.hazmat.primitives import hashes
|
|
11
|
+
from cryptography.hazmat.primitives import padding as sym_padding
|
|
12
|
+
from cryptography.hazmat.primitives.asymmetric import padding
|
|
13
|
+
from cryptography.hazmat.primitives.asymmetric.rsa import RSAPublicKey
|
|
8
14
|
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
|
|
9
15
|
|
|
10
16
|
from .files import TMP_FILES, file_exists_not_empty, load_file, new_tmp_file, save_file
|
|
@@ -26,6 +32,11 @@ PEM_CERT_END = "-----END CERTIFICATE-----"
|
|
|
26
32
|
PEM_KEY_START_REGEX = r"-----BEGIN(.*)PRIVATE KEY-----"
|
|
27
33
|
PEM_KEY_END_REGEX = r"-----END(.*)PRIVATE KEY-----"
|
|
28
34
|
|
|
35
|
+
OID_AES256_CBC = "2.16.840.1.101.3.4.1.42"
|
|
36
|
+
OID_MGF1 = "1.2.840.113549.1.1.8"
|
|
37
|
+
OID_RSAES_OAEP = "1.2.840.113549.1.1.7"
|
|
38
|
+
OID_SHA256 = "2.16.840.1.101.3.4.2.1"
|
|
39
|
+
|
|
29
40
|
|
|
30
41
|
@synchronized(lock=SSL_CERT_LOCK)
|
|
31
42
|
def generate_ssl_cert(
|
|
@@ -183,3 +194,101 @@ def decrypt(
|
|
|
183
194
|
decrypted = decryptor.update(encrypted) + decryptor.finalize()
|
|
184
195
|
decrypted = unpad(decrypted)
|
|
185
196
|
return decrypted
|
|
197
|
+
|
|
198
|
+
|
|
199
|
+
def pkcs7_envelope_encrypt(plaintext: bytes, recipient_pubkey: RSAPublicKey) -> bytes:
|
|
200
|
+
"""
|
|
201
|
+
Create a PKCS7 wrapper of some plaintext decryptable by recipient_pubkey. Uses RSA-OAEP with SHA-256
|
|
202
|
+
to encrypt the AES-256-CBC content key. Hazmat's PKCS7EnvelopeBuilder doesn't support RSA-OAEP with SHA-256,
|
|
203
|
+
so we need to build the pieces manually and then put them together in an envelope with asn1crypto.
|
|
204
|
+
"""
|
|
205
|
+
|
|
206
|
+
# Encrypt the plaintext with an AES session key, then encrypt the session key to the recipient_pubkey
|
|
207
|
+
session_key = os.urandom(32)
|
|
208
|
+
iv = os.urandom(16)
|
|
209
|
+
encrypted_session_key = recipient_pubkey.encrypt(
|
|
210
|
+
session_key,
|
|
211
|
+
padding.OAEP(
|
|
212
|
+
mgf=padding.MGF1(algorithm=hashes.SHA256()), algorithm=hashes.SHA256(), label=None
|
|
213
|
+
),
|
|
214
|
+
)
|
|
215
|
+
cipher = Cipher(algorithms.AES(session_key), modes.CBC(iv), backend=default_backend())
|
|
216
|
+
encryptor = cipher.encryptor()
|
|
217
|
+
padder = sym_padding.PKCS7(algorithms.AES.block_size).padder()
|
|
218
|
+
padded_plaintext = padder.update(plaintext) + padder.finalize()
|
|
219
|
+
encrypted_content = encryptor.update(padded_plaintext) + encryptor.finalize()
|
|
220
|
+
|
|
221
|
+
# Now put together the envelope.
|
|
222
|
+
# Add the recipient with their copy of the session key
|
|
223
|
+
recipient_identifier = cms.RecipientIdentifier(
|
|
224
|
+
name="issuer_and_serial_number",
|
|
225
|
+
value=cms.IssuerAndSerialNumber(
|
|
226
|
+
{
|
|
227
|
+
"issuer": asn1_x509.Name.build({"common_name": "recipient"}),
|
|
228
|
+
"serial_number": 1,
|
|
229
|
+
}
|
|
230
|
+
),
|
|
231
|
+
)
|
|
232
|
+
key_enc_algorithm = cms.KeyEncryptionAlgorithm(
|
|
233
|
+
{
|
|
234
|
+
"algorithm": OID_RSAES_OAEP,
|
|
235
|
+
"parameters": algos.RSAESOAEPParams(
|
|
236
|
+
{
|
|
237
|
+
"hash_algorithm": algos.DigestAlgorithm(
|
|
238
|
+
{
|
|
239
|
+
"algorithm": OID_SHA256,
|
|
240
|
+
}
|
|
241
|
+
),
|
|
242
|
+
"mask_gen_algorithm": algos.MaskGenAlgorithm(
|
|
243
|
+
{
|
|
244
|
+
"algorithm": OID_MGF1,
|
|
245
|
+
"parameters": algos.DigestAlgorithm(
|
|
246
|
+
{
|
|
247
|
+
"algorithm": OID_SHA256,
|
|
248
|
+
}
|
|
249
|
+
),
|
|
250
|
+
}
|
|
251
|
+
),
|
|
252
|
+
}
|
|
253
|
+
),
|
|
254
|
+
}
|
|
255
|
+
)
|
|
256
|
+
recipient_info = cms.KeyTransRecipientInfo(
|
|
257
|
+
{
|
|
258
|
+
"version": "v0",
|
|
259
|
+
"rid": recipient_identifier,
|
|
260
|
+
"key_encryption_algorithm": key_enc_algorithm,
|
|
261
|
+
"encrypted_key": encrypted_session_key,
|
|
262
|
+
}
|
|
263
|
+
)
|
|
264
|
+
|
|
265
|
+
# Add the encrypted content
|
|
266
|
+
content_enc_algorithm = cms.EncryptionAlgorithm(
|
|
267
|
+
{
|
|
268
|
+
"algorithm": OID_AES256_CBC,
|
|
269
|
+
"parameters": core.OctetString(iv),
|
|
270
|
+
}
|
|
271
|
+
)
|
|
272
|
+
encrypted_content_info = cms.EncryptedContentInfo(
|
|
273
|
+
{
|
|
274
|
+
"content_type": "data",
|
|
275
|
+
"content_encryption_algorithm": content_enc_algorithm,
|
|
276
|
+
"encrypted_content": encrypted_content,
|
|
277
|
+
}
|
|
278
|
+
)
|
|
279
|
+
enveloped_data = cms.EnvelopedData(
|
|
280
|
+
{
|
|
281
|
+
"version": "v0",
|
|
282
|
+
"recipient_infos": [recipient_info],
|
|
283
|
+
"encrypted_content_info": encrypted_content_info,
|
|
284
|
+
}
|
|
285
|
+
)
|
|
286
|
+
|
|
287
|
+
# Finally add a wrapper and return its bytes
|
|
288
|
+
content_info = cms.ContentInfo(
|
|
289
|
+
{
|
|
290
|
+
"content_type": "enveloped_data",
|
|
291
|
+
"content": enveloped_data,
|
|
292
|
+
}
|
|
293
|
+
)
|
|
294
|
+
return content_info.dump()
|
localstack/version.py
CHANGED
|
@@ -28,7 +28,7 @@ version_tuple: VERSION_TUPLE
|
|
|
28
28
|
commit_id: COMMIT_ID
|
|
29
29
|
__commit_id__: COMMIT_ID
|
|
30
30
|
|
|
31
|
-
__version__ = version = '4.
|
|
32
|
-
__version_tuple__ = version_tuple = (4,
|
|
31
|
+
__version__ = version = '4.11.2.dev14'
|
|
32
|
+
__version_tuple__ = version_tuple = (4, 11, 2, 'dev14')
|
|
33
33
|
|
|
34
34
|
__commit_id__ = commit_id = None
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: localstack-core
|
|
3
|
-
Version: 4.
|
|
3
|
+
Version: 4.11.2.dev14
|
|
4
4
|
Summary: The core library and runtime of LocalStack
|
|
5
5
|
Author-email: LocalStack Contributors <info@localstack.cloud>
|
|
6
6
|
License-Expression: Apache-2.0
|
|
@@ -15,7 +15,8 @@ Classifier: Topic :: Software Development :: Testing
|
|
|
15
15
|
Classifier: Topic :: System :: Emulators
|
|
16
16
|
Requires-Python: >=3.10
|
|
17
17
|
License-File: LICENSE.txt
|
|
18
|
-
Requires-Dist:
|
|
18
|
+
Requires-Dist: asn1crypto>=1.5.1
|
|
19
|
+
Requires-Dist: click>=8.2.0
|
|
19
20
|
Requires-Dist: cachetools>=5.0
|
|
20
21
|
Requires-Dist: cryptography
|
|
21
22
|
Requires-Dist: dill==0.3.6
|
|
@@ -29,8 +30,8 @@ Requires-Dist: rich>=12.3.0
|
|
|
29
30
|
Requires-Dist: requests>=2.20.0
|
|
30
31
|
Requires-Dist: semver>=2.10
|
|
31
32
|
Provides-Extra: base-runtime
|
|
32
|
-
Requires-Dist: boto3==1.
|
|
33
|
-
Requires-Dist: botocore==1.
|
|
33
|
+
Requires-Dist: boto3==1.42.0; extra == "base-runtime"
|
|
34
|
+
Requires-Dist: botocore==1.41.6; extra == "base-runtime"
|
|
34
35
|
Requires-Dist: awscrt!=0.27.1,>=0.13.14; extra == "base-runtime"
|
|
35
36
|
Requires-Dist: cbor2>=5.5.0; extra == "base-runtime"
|
|
36
37
|
Requires-Dist: dnspython>=1.16.0; extra == "base-runtime"
|
|
@@ -52,7 +53,7 @@ Requires-Dist: xmltodict>=0.13.0; extra == "base-runtime"
|
|
|
52
53
|
Requires-Dist: rolo>=0.7; extra == "base-runtime"
|
|
53
54
|
Provides-Extra: runtime
|
|
54
55
|
Requires-Dist: localstack-core[base-runtime]; extra == "runtime"
|
|
55
|
-
Requires-Dist: awscli==1.
|
|
56
|
+
Requires-Dist: awscli==1.43.6; extra == "runtime"
|
|
56
57
|
Requires-Dist: airspeed-ext>=0.6.3; extra == "runtime"
|
|
57
58
|
Requires-Dist: antlr4-python3-runtime==4.13.2; extra == "runtime"
|
|
58
59
|
Requires-Dist: apispec>=5.1.1; extra == "runtime"
|
|
@@ -99,5 +100,5 @@ Requires-Dist: rstr>=3.2.0; extra == "dev"
|
|
|
99
100
|
Requires-Dist: mypy; extra == "dev"
|
|
100
101
|
Provides-Extra: typehint
|
|
101
102
|
Requires-Dist: localstack-core[dev]; extra == "typehint"
|
|
102
|
-
Requires-Dist: boto3-stubs[acm,acm-pca,amplify,apigateway,apigatewayv2,appconfig,appconfigdata,application-autoscaling,appsync,athena,autoscaling,backup,batch,ce,cloudcontrol,cloudformation,cloudfront,cloudtrail,cloudwatch,codebuild,codecommit,codeconnections,codedeploy,codepipeline,codestar-connections,cognito-identity,cognito-idp,dms,docdb,dynamodb,dynamodbstreams,ec2,ecr,ecs,efs,eks,elasticache,elasticbeanstalk,elbv2,emr,emr-serverless,es,events,firehose,fis,glacier,glue,iam,identitystore,iot,iot-data,iotanalytics,iotwireless,kafka,kinesis,
|
|
103
|
+
Requires-Dist: boto3-stubs[acm,acm-pca,amplify,apigateway,apigatewayv2,appconfig,appconfigdata,application-autoscaling,appsync,athena,autoscaling,backup,batch,ce,cloudcontrol,cloudformation,cloudfront,cloudtrail,cloudwatch,codebuild,codecommit,codeconnections,codedeploy,codepipeline,codestar-connections,cognito-identity,cognito-idp,dms,docdb,dynamodb,dynamodbstreams,ec2,ecr,ecs,efs,eks,elasticache,elasticbeanstalk,elbv2,emr,emr-serverless,es,events,firehose,fis,glacier,glue,iam,identitystore,iot,iot-data,iotanalytics,iotwireless,kafka,kinesis,kinesisanalyticsv2,kms,lakeformation,lambda,logs,managedblockchain,mediaconvert,mediastore,mq,mwaa,neptune,opensearch,organizations,pi,pinpoint,pipes,rds,rds-data,redshift,redshift-data,resource-groups,resourcegroupstaggingapi,route53,route53resolver,s3,s3control,sagemaker,sagemaker-runtime,secretsmanager,serverlessrepo,servicediscovery,ses,sesv2,sns,sqs,ssm,sso-admin,stepfunctions,sts,timestream-query,timestream-write,transcribe,verifiedpermissions,wafv2,xray]; extra == "typehint"
|
|
103
104
|
Dynamic: license-file
|