aws-cdk-lib 2.136.0__py3-none-any.whl → 2.137.0__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.
Potentially problematic release.
This version of aws-cdk-lib might be problematic. Click here for more details.
- aws_cdk/_jsii/__init__.py +1 -1
- aws_cdk/_jsii/{aws-cdk-lib@2.136.0.jsii.tgz → aws-cdk-lib@2.137.0.jsii.tgz} +0 -0
- aws_cdk/assertions/__init__.py +152 -5
- aws_cdk/aws_cloudfront/__init__.py +196 -15
- aws_cdk/aws_ec2/__init__.py +367 -2788
- aws_cdk/aws_ecr_assets/__init__.py +3 -4
- aws_cdk/aws_elasticloadbalancingv2/__init__.py +223 -3
- aws_cdk/aws_iam/__init__.py +23 -38
- aws_cdk/aws_kms/__init__.py +8 -13
- aws_cdk/aws_route53/__init__.py +4 -4
- aws_cdk/aws_s3_deployment/__init__.py +84 -7
- aws_cdk/aws_sns/__init__.py +122 -0
- {aws_cdk_lib-2.136.0.dist-info → aws_cdk_lib-2.137.0.dist-info}/METADATA +1 -1
- {aws_cdk_lib-2.136.0.dist-info → aws_cdk_lib-2.137.0.dist-info}/RECORD +18 -18
- {aws_cdk_lib-2.136.0.dist-info → aws_cdk_lib-2.137.0.dist-info}/LICENSE +0 -0
- {aws_cdk_lib-2.136.0.dist-info → aws_cdk_lib-2.137.0.dist-info}/NOTICE +0 -0
- {aws_cdk_lib-2.136.0.dist-info → aws_cdk_lib-2.137.0.dist-info}/WHEEL +0 -0
- {aws_cdk_lib-2.136.0.dist-info → aws_cdk_lib-2.137.0.dist-info}/top_level.txt +0 -0
|
@@ -214,10 +214,9 @@ method. This will modify the IAM policy of the principal to allow it to
|
|
|
214
214
|
pull images from this repository.
|
|
215
215
|
|
|
216
216
|
If the pulling principal is not in the same account or is an AWS service that
|
|
217
|
-
doesn't assume a role in your account (e.g. AWS CodeBuild),
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
grant the desired principal the following permissions: "ecr:GetDownloadUrlForLayer",
|
|
217
|
+
doesn't assume a role in your account (e.g. AWS CodeBuild), you must either copy the image to a new repository, or
|
|
218
|
+
grant pull permissions on the resource policy of the repository. Since the repository is managed by the CDK bootstrap stack,
|
|
219
|
+
the following permissions must be granted there, or granted manually on the repository: "ecr:GetDownloadUrlForLayer",
|
|
221
220
|
"ecr:BatchGetImage" and "ecr:BatchCheckLayerAvailability".
|
|
222
221
|
'''
|
|
223
222
|
from pkgutil import extend_path
|
|
@@ -234,7 +234,22 @@ lb = elbv2.ApplicationLoadBalancer(self, "LB",
|
|
|
234
234
|
cross_zone_enabled=True,
|
|
235
235
|
|
|
236
236
|
# Whether the load balancer blocks traffic through the Internet Gateway (IGW).
|
|
237
|
-
deny_all_igw_traffic=False
|
|
237
|
+
deny_all_igw_traffic=False,
|
|
238
|
+
|
|
239
|
+
# Whether to preserve host header in the request to the target
|
|
240
|
+
preserve_host_header=True,
|
|
241
|
+
|
|
242
|
+
# Whether to add the TLS information header to the request
|
|
243
|
+
x_amzn_tls_version_and_cipher_suite_headers=True,
|
|
244
|
+
|
|
245
|
+
# Whether the X-Forwarded-For header should preserve the source port
|
|
246
|
+
preserve_xff_client_port=True,
|
|
247
|
+
|
|
248
|
+
# The processing mode for X-Forwarded-For headers
|
|
249
|
+
xff_header_processing_mode=elbv2.XffHeaderProcessingMode.APPEND,
|
|
250
|
+
|
|
251
|
+
# Whether to allow a load balancer to route requests to targets if it is unable to forward the request to AWS WAF.
|
|
252
|
+
waf_fail_open=True
|
|
238
253
|
)
|
|
239
254
|
```
|
|
240
255
|
|
|
@@ -10597,7 +10612,22 @@ class DesyncMitigationMode(enum.Enum):
|
|
|
10597
10612
|
cross_zone_enabled=True,
|
|
10598
10613
|
|
|
10599
10614
|
# Whether the load balancer blocks traffic through the Internet Gateway (IGW).
|
|
10600
|
-
deny_all_igw_traffic=False
|
|
10615
|
+
deny_all_igw_traffic=False,
|
|
10616
|
+
|
|
10617
|
+
# Whether to preserve host header in the request to the target
|
|
10618
|
+
preserve_host_header=True,
|
|
10619
|
+
|
|
10620
|
+
# Whether to add the TLS information header to the request
|
|
10621
|
+
x_amzn_tls_version_and_cipher_suite_headers=True,
|
|
10622
|
+
|
|
10623
|
+
# Whether the X-Forwarded-For header should preserve the source port
|
|
10624
|
+
preserve_xff_client_port=True,
|
|
10625
|
+
|
|
10626
|
+
# The processing mode for X-Forwarded-For headers
|
|
10627
|
+
xff_header_processing_mode=elbv2.XffHeaderProcessingMode.APPEND,
|
|
10628
|
+
|
|
10629
|
+
# Whether to allow a load balancer to route requests to targets if it is unable to forward the request to AWS WAF.
|
|
10630
|
+
waf_fail_open=True
|
|
10601
10631
|
)
|
|
10602
10632
|
'''
|
|
10603
10633
|
|
|
@@ -14730,7 +14760,22 @@ class IpAddressType(enum.Enum):
|
|
|
14730
14760
|
cross_zone_enabled=True,
|
|
14731
14761
|
|
|
14732
14762
|
# Whether the load balancer blocks traffic through the Internet Gateway (IGW).
|
|
14733
|
-
deny_all_igw_traffic=False
|
|
14763
|
+
deny_all_igw_traffic=False,
|
|
14764
|
+
|
|
14765
|
+
# Whether to preserve host header in the request to the target
|
|
14766
|
+
preserve_host_header=True,
|
|
14767
|
+
|
|
14768
|
+
# Whether to add the TLS information header to the request
|
|
14769
|
+
x_amzn_tls_version_and_cipher_suite_headers=True,
|
|
14770
|
+
|
|
14771
|
+
# Whether the X-Forwarded-For header should preserve the source port
|
|
14772
|
+
preserve_xff_client_port=True,
|
|
14773
|
+
|
|
14774
|
+
# The processing mode for X-Forwarded-For headers
|
|
14775
|
+
xff_header_processing_mode=elbv2.XffHeaderProcessingMode.APPEND,
|
|
14776
|
+
|
|
14777
|
+
# Whether to allow a load balancer to route requests to targets if it is unable to forward the request to AWS WAF.
|
|
14778
|
+
waf_fail_open=True
|
|
14734
14779
|
)
|
|
14735
14780
|
'''
|
|
14736
14781
|
|
|
@@ -18095,6 +18140,72 @@ class WeightedTargetGroup:
|
|
|
18095
18140
|
)
|
|
18096
18141
|
|
|
18097
18142
|
|
|
18143
|
+
@jsii.enum(jsii_type="aws-cdk-lib.aws_elasticloadbalancingv2.XffHeaderProcessingMode")
|
|
18144
|
+
class XffHeaderProcessingMode(enum.Enum):
|
|
18145
|
+
'''Processing mode of the X-Forwarded-For header in the HTTP request before the Application Load Balancer sends the request to the target.
|
|
18146
|
+
|
|
18147
|
+
:exampleMetadata: infused
|
|
18148
|
+
|
|
18149
|
+
Example::
|
|
18150
|
+
|
|
18151
|
+
# vpc: ec2.Vpc
|
|
18152
|
+
|
|
18153
|
+
|
|
18154
|
+
lb = elbv2.ApplicationLoadBalancer(self, "LB",
|
|
18155
|
+
vpc=vpc,
|
|
18156
|
+
internet_facing=True,
|
|
18157
|
+
|
|
18158
|
+
# Whether HTTP/2 is enabled
|
|
18159
|
+
http2_enabled=False,
|
|
18160
|
+
|
|
18161
|
+
# The idle timeout value, in seconds
|
|
18162
|
+
idle_timeout=Duration.seconds(1000),
|
|
18163
|
+
|
|
18164
|
+
# Whether HTTP headers with header fields thatare not valid
|
|
18165
|
+
# are removed by the load balancer (true), or routed to targets
|
|
18166
|
+
drop_invalid_header_fields=True,
|
|
18167
|
+
|
|
18168
|
+
# How the load balancer handles requests that might
|
|
18169
|
+
# pose a security risk to your application
|
|
18170
|
+
desync_mitigation_mode=elbv2.DesyncMitigationMode.DEFENSIVE,
|
|
18171
|
+
|
|
18172
|
+
# The type of IP addresses to use.
|
|
18173
|
+
ip_address_type=elbv2.IpAddressType.IPV4,
|
|
18174
|
+
|
|
18175
|
+
# The duration of client keep-alive connections
|
|
18176
|
+
client_keep_alive=Duration.seconds(500),
|
|
18177
|
+
|
|
18178
|
+
# Whether cross-zone load balancing is enabled.
|
|
18179
|
+
cross_zone_enabled=True,
|
|
18180
|
+
|
|
18181
|
+
# Whether the load balancer blocks traffic through the Internet Gateway (IGW).
|
|
18182
|
+
deny_all_igw_traffic=False,
|
|
18183
|
+
|
|
18184
|
+
# Whether to preserve host header in the request to the target
|
|
18185
|
+
preserve_host_header=True,
|
|
18186
|
+
|
|
18187
|
+
# Whether to add the TLS information header to the request
|
|
18188
|
+
x_amzn_tls_version_and_cipher_suite_headers=True,
|
|
18189
|
+
|
|
18190
|
+
# Whether the X-Forwarded-For header should preserve the source port
|
|
18191
|
+
preserve_xff_client_port=True,
|
|
18192
|
+
|
|
18193
|
+
# The processing mode for X-Forwarded-For headers
|
|
18194
|
+
xff_header_processing_mode=elbv2.XffHeaderProcessingMode.APPEND,
|
|
18195
|
+
|
|
18196
|
+
# Whether to allow a load balancer to route requests to targets if it is unable to forward the request to AWS WAF.
|
|
18197
|
+
waf_fail_open=True
|
|
18198
|
+
)
|
|
18199
|
+
'''
|
|
18200
|
+
|
|
18201
|
+
APPEND = "APPEND"
|
|
18202
|
+
'''Application Load Balancer adds the client IP address (of the last hop) to the X-Forwarded-For header in the HTTP request before it sends it to targets.'''
|
|
18203
|
+
PRESERVE = "PRESERVE"
|
|
18204
|
+
'''Application Load Balancer preserves the X-Forwarded-For header in the HTTP request, and sends it to targets without any change.'''
|
|
18205
|
+
REMOVE = "REMOVE"
|
|
18206
|
+
'''Application Load Balancer removes the X-Forwarded-For header in the HTTP request before it sends it to targets.'''
|
|
18207
|
+
|
|
18208
|
+
|
|
18098
18209
|
@jsii.data_type(
|
|
18099
18210
|
jsii_type="aws-cdk-lib.aws_elasticloadbalancingv2.AddApplicationActionProps",
|
|
18100
18211
|
jsii_struct_bases=[AddRuleProps],
|
|
@@ -19128,7 +19239,12 @@ class ApplicationLoadBalancerLookupOptions(BaseLoadBalancerLookupOptions):
|
|
|
19128
19239
|
"http2_enabled": "http2Enabled",
|
|
19129
19240
|
"idle_timeout": "idleTimeout",
|
|
19130
19241
|
"ip_address_type": "ipAddressType",
|
|
19242
|
+
"preserve_host_header": "preserveHostHeader",
|
|
19243
|
+
"preserve_xff_client_port": "preserveXffClientPort",
|
|
19131
19244
|
"security_group": "securityGroup",
|
|
19245
|
+
"waf_fail_open": "wafFailOpen",
|
|
19246
|
+
"x_amzn_tls_version_and_cipher_suite_headers": "xAmznTlsVersionAndCipherSuiteHeaders",
|
|
19247
|
+
"xff_header_processing_mode": "xffHeaderProcessingMode",
|
|
19132
19248
|
},
|
|
19133
19249
|
)
|
|
19134
19250
|
class ApplicationLoadBalancerProps(BaseLoadBalancerProps):
|
|
@@ -19148,7 +19264,12 @@ class ApplicationLoadBalancerProps(BaseLoadBalancerProps):
|
|
|
19148
19264
|
http2_enabled: typing.Optional[builtins.bool] = None,
|
|
19149
19265
|
idle_timeout: typing.Optional[_Duration_4839e8c3] = None,
|
|
19150
19266
|
ip_address_type: typing.Optional[IpAddressType] = None,
|
|
19267
|
+
preserve_host_header: typing.Optional[builtins.bool] = None,
|
|
19268
|
+
preserve_xff_client_port: typing.Optional[builtins.bool] = None,
|
|
19151
19269
|
security_group: typing.Optional[_ISecurityGroup_acf8a799] = None,
|
|
19270
|
+
waf_fail_open: typing.Optional[builtins.bool] = None,
|
|
19271
|
+
x_amzn_tls_version_and_cipher_suite_headers: typing.Optional[builtins.bool] = None,
|
|
19272
|
+
xff_header_processing_mode: typing.Optional[XffHeaderProcessingMode] = None,
|
|
19152
19273
|
) -> None:
|
|
19153
19274
|
'''Properties for defining an Application Load Balancer.
|
|
19154
19275
|
|
|
@@ -19165,8 +19286,14 @@ class ApplicationLoadBalancerProps(BaseLoadBalancerProps):
|
|
|
19165
19286
|
:param http2_enabled: Indicates whether HTTP/2 is enabled. Default: true
|
|
19166
19287
|
:param idle_timeout: The load balancer idle timeout, in seconds. Default: 60
|
|
19167
19288
|
:param ip_address_type: The type of IP addresses to use. Default: IpAddressType.IPV4
|
|
19289
|
+
:param preserve_host_header: Indicates whether the Application Load Balancer should preserve the host header in the HTTP request and send it to the target without any change. Default: false
|
|
19290
|
+
:param preserve_xff_client_port: Indicates whether the X-Forwarded-For header should preserve the source port that the client used to connect to the load balancer. Default: false
|
|
19168
19291
|
:param security_group: Security group to associate with this load balancer. Default: A security group is created
|
|
19292
|
+
:param waf_fail_open: Indicates whether to allow a WAF-enabled load balancer to route requests to targets if it is unable to forward the request to AWS WAF. Default: false
|
|
19293
|
+
:param x_amzn_tls_version_and_cipher_suite_headers: Indicates whether the two headers (x-amzn-tls-version and x-amzn-tls-cipher-suite), which contain information about the negotiated TLS version and cipher suite, are added to the client request before sending it to the target. The x-amzn-tls-version header has information about the TLS protocol version negotiated with the client, and the x-amzn-tls-cipher-suite header has information about the cipher suite negotiated with the client. Both headers are in OpenSSL format. Default: false
|
|
19294
|
+
:param xff_header_processing_mode: Enables you to modify, preserve, or remove the X-Forwarded-For header in the HTTP request before the Application Load Balancer sends the request to the target. Default: XffHeaderProcessingMode.APPEND
|
|
19169
19295
|
|
|
19296
|
+
:see: https://docs.aws.amazon.com/elasticloadbalancing/latest/application/application-load-balancers.html#load-balancer-attributes
|
|
19170
19297
|
:exampleMetadata: infused
|
|
19171
19298
|
|
|
19172
19299
|
Example::
|
|
@@ -19218,7 +19345,12 @@ class ApplicationLoadBalancerProps(BaseLoadBalancerProps):
|
|
|
19218
19345
|
check_type(argname="argument http2_enabled", value=http2_enabled, expected_type=type_hints["http2_enabled"])
|
|
19219
19346
|
check_type(argname="argument idle_timeout", value=idle_timeout, expected_type=type_hints["idle_timeout"])
|
|
19220
19347
|
check_type(argname="argument ip_address_type", value=ip_address_type, expected_type=type_hints["ip_address_type"])
|
|
19348
|
+
check_type(argname="argument preserve_host_header", value=preserve_host_header, expected_type=type_hints["preserve_host_header"])
|
|
19349
|
+
check_type(argname="argument preserve_xff_client_port", value=preserve_xff_client_port, expected_type=type_hints["preserve_xff_client_port"])
|
|
19221
19350
|
check_type(argname="argument security_group", value=security_group, expected_type=type_hints["security_group"])
|
|
19351
|
+
check_type(argname="argument waf_fail_open", value=waf_fail_open, expected_type=type_hints["waf_fail_open"])
|
|
19352
|
+
check_type(argname="argument x_amzn_tls_version_and_cipher_suite_headers", value=x_amzn_tls_version_and_cipher_suite_headers, expected_type=type_hints["x_amzn_tls_version_and_cipher_suite_headers"])
|
|
19353
|
+
check_type(argname="argument xff_header_processing_mode", value=xff_header_processing_mode, expected_type=type_hints["xff_header_processing_mode"])
|
|
19222
19354
|
self._values: typing.Dict[builtins.str, typing.Any] = {
|
|
19223
19355
|
"vpc": vpc,
|
|
19224
19356
|
}
|
|
@@ -19246,8 +19378,18 @@ class ApplicationLoadBalancerProps(BaseLoadBalancerProps):
|
|
|
19246
19378
|
self._values["idle_timeout"] = idle_timeout
|
|
19247
19379
|
if ip_address_type is not None:
|
|
19248
19380
|
self._values["ip_address_type"] = ip_address_type
|
|
19381
|
+
if preserve_host_header is not None:
|
|
19382
|
+
self._values["preserve_host_header"] = preserve_host_header
|
|
19383
|
+
if preserve_xff_client_port is not None:
|
|
19384
|
+
self._values["preserve_xff_client_port"] = preserve_xff_client_port
|
|
19249
19385
|
if security_group is not None:
|
|
19250
19386
|
self._values["security_group"] = security_group
|
|
19387
|
+
if waf_fail_open is not None:
|
|
19388
|
+
self._values["waf_fail_open"] = waf_fail_open
|
|
19389
|
+
if x_amzn_tls_version_and_cipher_suite_headers is not None:
|
|
19390
|
+
self._values["x_amzn_tls_version_and_cipher_suite_headers"] = x_amzn_tls_version_and_cipher_suite_headers
|
|
19391
|
+
if xff_header_processing_mode is not None:
|
|
19392
|
+
self._values["xff_header_processing_mode"] = xff_header_processing_mode
|
|
19251
19393
|
|
|
19252
19394
|
@builtins.property
|
|
19253
19395
|
def vpc(self) -> _IVpc_f30d5663:
|
|
@@ -19366,6 +19508,24 @@ class ApplicationLoadBalancerProps(BaseLoadBalancerProps):
|
|
|
19366
19508
|
result = self._values.get("ip_address_type")
|
|
19367
19509
|
return typing.cast(typing.Optional[IpAddressType], result)
|
|
19368
19510
|
|
|
19511
|
+
@builtins.property
|
|
19512
|
+
def preserve_host_header(self) -> typing.Optional[builtins.bool]:
|
|
19513
|
+
'''Indicates whether the Application Load Balancer should preserve the host header in the HTTP request and send it to the target without any change.
|
|
19514
|
+
|
|
19515
|
+
:default: false
|
|
19516
|
+
'''
|
|
19517
|
+
result = self._values.get("preserve_host_header")
|
|
19518
|
+
return typing.cast(typing.Optional[builtins.bool], result)
|
|
19519
|
+
|
|
19520
|
+
@builtins.property
|
|
19521
|
+
def preserve_xff_client_port(self) -> typing.Optional[builtins.bool]:
|
|
19522
|
+
'''Indicates whether the X-Forwarded-For header should preserve the source port that the client used to connect to the load balancer.
|
|
19523
|
+
|
|
19524
|
+
:default: false
|
|
19525
|
+
'''
|
|
19526
|
+
result = self._values.get("preserve_xff_client_port")
|
|
19527
|
+
return typing.cast(typing.Optional[builtins.bool], result)
|
|
19528
|
+
|
|
19369
19529
|
@builtins.property
|
|
19370
19530
|
def security_group(self) -> typing.Optional[_ISecurityGroup_acf8a799]:
|
|
19371
19531
|
'''Security group to associate with this load balancer.
|
|
@@ -19375,6 +19535,40 @@ class ApplicationLoadBalancerProps(BaseLoadBalancerProps):
|
|
|
19375
19535
|
result = self._values.get("security_group")
|
|
19376
19536
|
return typing.cast(typing.Optional[_ISecurityGroup_acf8a799], result)
|
|
19377
19537
|
|
|
19538
|
+
@builtins.property
|
|
19539
|
+
def waf_fail_open(self) -> typing.Optional[builtins.bool]:
|
|
19540
|
+
'''Indicates whether to allow a WAF-enabled load balancer to route requests to targets if it is unable to forward the request to AWS WAF.
|
|
19541
|
+
|
|
19542
|
+
:default: false
|
|
19543
|
+
'''
|
|
19544
|
+
result = self._values.get("waf_fail_open")
|
|
19545
|
+
return typing.cast(typing.Optional[builtins.bool], result)
|
|
19546
|
+
|
|
19547
|
+
@builtins.property
|
|
19548
|
+
def x_amzn_tls_version_and_cipher_suite_headers(
|
|
19549
|
+
self,
|
|
19550
|
+
) -> typing.Optional[builtins.bool]:
|
|
19551
|
+
'''Indicates whether the two headers (x-amzn-tls-version and x-amzn-tls-cipher-suite), which contain information about the negotiated TLS version and cipher suite, are added to the client request before sending it to the target.
|
|
19552
|
+
|
|
19553
|
+
The x-amzn-tls-version header has information about the TLS protocol version negotiated with the client,
|
|
19554
|
+
and the x-amzn-tls-cipher-suite header has information about the cipher suite negotiated with the client.
|
|
19555
|
+
|
|
19556
|
+
Both headers are in OpenSSL format.
|
|
19557
|
+
|
|
19558
|
+
:default: false
|
|
19559
|
+
'''
|
|
19560
|
+
result = self._values.get("x_amzn_tls_version_and_cipher_suite_headers")
|
|
19561
|
+
return typing.cast(typing.Optional[builtins.bool], result)
|
|
19562
|
+
|
|
19563
|
+
@builtins.property
|
|
19564
|
+
def xff_header_processing_mode(self) -> typing.Optional[XffHeaderProcessingMode]:
|
|
19565
|
+
'''Enables you to modify, preserve, or remove the X-Forwarded-For header in the HTTP request before the Application Load Balancer sends the request to the target.
|
|
19566
|
+
|
|
19567
|
+
:default: XffHeaderProcessingMode.APPEND
|
|
19568
|
+
'''
|
|
19569
|
+
result = self._values.get("xff_header_processing_mode")
|
|
19570
|
+
return typing.cast(typing.Optional[XffHeaderProcessingMode], result)
|
|
19571
|
+
|
|
19378
19572
|
def __eq__(self, rhs: typing.Any) -> builtins.bool:
|
|
19379
19573
|
return isinstance(rhs, self.__class__) and rhs._values == self._values
|
|
19380
19574
|
|
|
@@ -21287,7 +21481,12 @@ class ApplicationLoadBalancer(
|
|
|
21287
21481
|
http2_enabled: typing.Optional[builtins.bool] = None,
|
|
21288
21482
|
idle_timeout: typing.Optional[_Duration_4839e8c3] = None,
|
|
21289
21483
|
ip_address_type: typing.Optional[IpAddressType] = None,
|
|
21484
|
+
preserve_host_header: typing.Optional[builtins.bool] = None,
|
|
21485
|
+
preserve_xff_client_port: typing.Optional[builtins.bool] = None,
|
|
21290
21486
|
security_group: typing.Optional[_ISecurityGroup_acf8a799] = None,
|
|
21487
|
+
waf_fail_open: typing.Optional[builtins.bool] = None,
|
|
21488
|
+
x_amzn_tls_version_and_cipher_suite_headers: typing.Optional[builtins.bool] = None,
|
|
21489
|
+
xff_header_processing_mode: typing.Optional[XffHeaderProcessingMode] = None,
|
|
21291
21490
|
vpc: _IVpc_f30d5663,
|
|
21292
21491
|
cross_zone_enabled: typing.Optional[builtins.bool] = None,
|
|
21293
21492
|
deletion_protection: typing.Optional[builtins.bool] = None,
|
|
@@ -21305,7 +21504,12 @@ class ApplicationLoadBalancer(
|
|
|
21305
21504
|
:param http2_enabled: Indicates whether HTTP/2 is enabled. Default: true
|
|
21306
21505
|
:param idle_timeout: The load balancer idle timeout, in seconds. Default: 60
|
|
21307
21506
|
:param ip_address_type: The type of IP addresses to use. Default: IpAddressType.IPV4
|
|
21507
|
+
:param preserve_host_header: Indicates whether the Application Load Balancer should preserve the host header in the HTTP request and send it to the target without any change. Default: false
|
|
21508
|
+
:param preserve_xff_client_port: Indicates whether the X-Forwarded-For header should preserve the source port that the client used to connect to the load balancer. Default: false
|
|
21308
21509
|
:param security_group: Security group to associate with this load balancer. Default: A security group is created
|
|
21510
|
+
:param waf_fail_open: Indicates whether to allow a WAF-enabled load balancer to route requests to targets if it is unable to forward the request to AWS WAF. Default: false
|
|
21511
|
+
:param x_amzn_tls_version_and_cipher_suite_headers: Indicates whether the two headers (x-amzn-tls-version and x-amzn-tls-cipher-suite), which contain information about the negotiated TLS version and cipher suite, are added to the client request before sending it to the target. The x-amzn-tls-version header has information about the TLS protocol version negotiated with the client, and the x-amzn-tls-cipher-suite header has information about the cipher suite negotiated with the client. Both headers are in OpenSSL format. Default: false
|
|
21512
|
+
:param xff_header_processing_mode: Enables you to modify, preserve, or remove the X-Forwarded-For header in the HTTP request before the Application Load Balancer sends the request to the target. Default: XffHeaderProcessingMode.APPEND
|
|
21309
21513
|
:param vpc: The VPC network to place the load balancer in.
|
|
21310
21514
|
:param cross_zone_enabled: Indicates whether cross-zone load balancing is enabled. Default: - false for Network Load Balancers and true for Application Load Balancers.
|
|
21311
21515
|
:param deletion_protection: Indicates whether deletion protection is enabled. Default: false
|
|
@@ -21325,7 +21529,12 @@ class ApplicationLoadBalancer(
|
|
|
21325
21529
|
http2_enabled=http2_enabled,
|
|
21326
21530
|
idle_timeout=idle_timeout,
|
|
21327
21531
|
ip_address_type=ip_address_type,
|
|
21532
|
+
preserve_host_header=preserve_host_header,
|
|
21533
|
+
preserve_xff_client_port=preserve_xff_client_port,
|
|
21328
21534
|
security_group=security_group,
|
|
21535
|
+
waf_fail_open=waf_fail_open,
|
|
21536
|
+
x_amzn_tls_version_and_cipher_suite_headers=x_amzn_tls_version_and_cipher_suite_headers,
|
|
21537
|
+
xff_header_processing_mode=xff_header_processing_mode,
|
|
21329
21538
|
vpc=vpc,
|
|
21330
21539
|
cross_zone_enabled=cross_zone_enabled,
|
|
21331
21540
|
deletion_protection=deletion_protection,
|
|
@@ -23298,6 +23507,7 @@ __all__ = [
|
|
|
23298
23507
|
"TargetType",
|
|
23299
23508
|
"UnauthenticatedAction",
|
|
23300
23509
|
"WeightedTargetGroup",
|
|
23510
|
+
"XffHeaderProcessingMode",
|
|
23301
23511
|
]
|
|
23302
23512
|
|
|
23303
23513
|
publication.publish()
|
|
@@ -25082,7 +25292,12 @@ def _typecheckingstub__e43cf75024913d9be0d5d621a5f2c2c7be60a57898a54967cd54179b2
|
|
|
25082
25292
|
http2_enabled: typing.Optional[builtins.bool] = None,
|
|
25083
25293
|
idle_timeout: typing.Optional[_Duration_4839e8c3] = None,
|
|
25084
25294
|
ip_address_type: typing.Optional[IpAddressType] = None,
|
|
25295
|
+
preserve_host_header: typing.Optional[builtins.bool] = None,
|
|
25296
|
+
preserve_xff_client_port: typing.Optional[builtins.bool] = None,
|
|
25085
25297
|
security_group: typing.Optional[_ISecurityGroup_acf8a799] = None,
|
|
25298
|
+
waf_fail_open: typing.Optional[builtins.bool] = None,
|
|
25299
|
+
x_amzn_tls_version_and_cipher_suite_headers: typing.Optional[builtins.bool] = None,
|
|
25300
|
+
xff_header_processing_mode: typing.Optional[XffHeaderProcessingMode] = None,
|
|
25086
25301
|
) -> None:
|
|
25087
25302
|
"""Type checking stubs"""
|
|
25088
25303
|
pass
|
|
@@ -25432,7 +25647,12 @@ def _typecheckingstub__22d249b6cdbe3ce0dfc1a873ef276c65fe89ce6a5dba0603fae0a5755
|
|
|
25432
25647
|
http2_enabled: typing.Optional[builtins.bool] = None,
|
|
25433
25648
|
idle_timeout: typing.Optional[_Duration_4839e8c3] = None,
|
|
25434
25649
|
ip_address_type: typing.Optional[IpAddressType] = None,
|
|
25650
|
+
preserve_host_header: typing.Optional[builtins.bool] = None,
|
|
25651
|
+
preserve_xff_client_port: typing.Optional[builtins.bool] = None,
|
|
25435
25652
|
security_group: typing.Optional[_ISecurityGroup_acf8a799] = None,
|
|
25653
|
+
waf_fail_open: typing.Optional[builtins.bool] = None,
|
|
25654
|
+
x_amzn_tls_version_and_cipher_suite_headers: typing.Optional[builtins.bool] = None,
|
|
25655
|
+
xff_header_processing_mode: typing.Optional[XffHeaderProcessingMode] = None,
|
|
25436
25656
|
vpc: _IVpc_f30d5663,
|
|
25437
25657
|
cross_zone_enabled: typing.Optional[builtins.bool] = None,
|
|
25438
25658
|
deletion_protection: typing.Optional[builtins.bool] = None,
|
aws_cdk/aws_iam/__init__.py
CHANGED
|
@@ -9907,24 +9907,20 @@ class PolicyStatement(
|
|
|
9907
9907
|
|
|
9908
9908
|
Example::
|
|
9909
9909
|
|
|
9910
|
-
|
|
9910
|
+
# destination_bucket: s3.Bucket
|
|
9911
9911
|
|
|
9912
|
-
call_region = "us-west-1" # sdk call to be made in specified region (optional)
|
|
9913
9912
|
|
|
9914
|
-
|
|
9915
|
-
|
|
9916
|
-
|
|
9917
|
-
region=call_region, # optional
|
|
9918
|
-
service="sts",
|
|
9919
|
-
action="GetCallerIdentity",
|
|
9920
|
-
physical_resource_id=cr.PhysicalResourceId.of("id")
|
|
9921
|
-
),
|
|
9922
|
-
policy=cr.AwsCustomResourcePolicy.from_statements([iam.PolicyStatement.from_json({
|
|
9923
|
-
"Effect": "Allow",
|
|
9924
|
-
"Action": "sts:AssumeRole",
|
|
9925
|
-
"Resource": cross_account_role_arn
|
|
9926
|
-
})])
|
|
9913
|
+
deployment = s3deploy.BucketDeployment(self, "DeployFiles",
|
|
9914
|
+
sources=[s3deploy.Source.asset(path.join(__dirname, "source-files"))],
|
|
9915
|
+
destination_bucket=destination_bucket
|
|
9927
9916
|
)
|
|
9917
|
+
|
|
9918
|
+
deployment.handler_role.add_to_policy(
|
|
9919
|
+
iam.PolicyStatement(
|
|
9920
|
+
actions=["kms:Decrypt", "kms:DescribeKey"],
|
|
9921
|
+
effect=iam.Effect.ALLOW,
|
|
9922
|
+
resources=["<encryption key ARN>"]
|
|
9923
|
+
))
|
|
9928
9924
|
'''
|
|
9929
9925
|
|
|
9930
9926
|
def __init__(
|
|
@@ -10468,35 +10464,24 @@ class PolicyStatementProps:
|
|
|
10468
10464
|
:param resources: Resource ARNs to add to the statement. Default: - no resources
|
|
10469
10465
|
:param sid: The Sid (statement ID) is an optional identifier that you provide for the policy statement. You can assign a Sid value to each statement in a statement array. In services that let you specify an ID element, such as SQS and SNS, the Sid value is just a sub-ID of the policy document's ID. In IAM, the Sid value must be unique within a JSON policy. Default: - no sid
|
|
10470
10466
|
|
|
10471
|
-
:exampleMetadata:
|
|
10467
|
+
:exampleMetadata: infused
|
|
10472
10468
|
|
|
10473
10469
|
Example::
|
|
10474
10470
|
|
|
10475
|
-
#
|
|
10476
|
-
vpc = ec2.Vpc(self, "MyVpc",
|
|
10477
|
-
gateway_endpoints={
|
|
10478
|
-
"S3": cdk.aws_ec2.GatewayVpcEndpointOptions(
|
|
10479
|
-
service=ec2.GatewayVpcEndpointAwsService.S3
|
|
10480
|
-
)
|
|
10481
|
-
}
|
|
10482
|
-
)
|
|
10483
|
-
|
|
10484
|
-
# Alternatively gateway endpoints can be added on the VPC
|
|
10485
|
-
dynamo_db_endpoint = vpc.add_gateway_endpoint("DynamoDbEndpoint",
|
|
10486
|
-
service=ec2.GatewayVpcEndpointAwsService.DYNAMODB
|
|
10487
|
-
)
|
|
10471
|
+
# destination_bucket: s3.Bucket
|
|
10488
10472
|
|
|
10489
|
-
# This allows to customize the endpoint policy
|
|
10490
|
-
dynamo_db_endpoint.add_to_policy(
|
|
10491
|
-
iam.PolicyStatement( # Restrict to listing and describing tables
|
|
10492
|
-
principals=[iam.AnyPrincipal()],
|
|
10493
|
-
actions=["dynamodb:DescribeTable", "dynamodb:ListTables"],
|
|
10494
|
-
resources=["*"]))
|
|
10495
10473
|
|
|
10496
|
-
|
|
10497
|
-
|
|
10498
|
-
|
|
10474
|
+
deployment = s3deploy.BucketDeployment(self, "DeployFiles",
|
|
10475
|
+
sources=[s3deploy.Source.asset(path.join(__dirname, "source-files"))],
|
|
10476
|
+
destination_bucket=destination_bucket
|
|
10499
10477
|
)
|
|
10478
|
+
|
|
10479
|
+
deployment.handler_role.add_to_policy(
|
|
10480
|
+
iam.PolicyStatement(
|
|
10481
|
+
actions=["kms:Decrypt", "kms:DescribeKey"],
|
|
10482
|
+
effect=iam.Effect.ALLOW,
|
|
10483
|
+
resources=["<encryption key ARN>"]
|
|
10484
|
+
))
|
|
10500
10485
|
'''
|
|
10501
10486
|
if __debug__:
|
|
10502
10487
|
type_hints = typing.get_type_hints(_typecheckingstub__b1307ab5f5dd84b7184f36603f7af026efb2798812c35c96dbe60552fff14c3b)
|
aws_cdk/aws_kms/__init__.py
CHANGED
|
@@ -2034,20 +2034,15 @@ class Key(
|
|
|
2034
2034
|
|
|
2035
2035
|
Example::
|
|
2036
2036
|
|
|
2037
|
-
#
|
|
2037
|
+
# destination_bucket: s3.Bucket
|
|
2038
2038
|
|
|
2039
|
-
|
|
2040
|
-
|
|
2041
|
-
|
|
2042
|
-
|
|
2043
|
-
|
|
2044
|
-
|
|
2045
|
-
|
|
2046
|
-
secret_name="my-cool-name",
|
|
2047
|
-
encryption_key=my_key,
|
|
2048
|
-
exclude_characters="!&*^#@()",
|
|
2049
|
-
replica_regions=[secretsmanager.ReplicaRegion(region="eu-west-1"), secretsmanager.ReplicaRegion(region="eu-west-2")]
|
|
2050
|
-
)
|
|
2039
|
+
source_bucket = s3.Bucket.from_bucket_attributes(self, "SourceBucket",
|
|
2040
|
+
bucket_arn="arn:aws:s3:::my-source-bucket-name",
|
|
2041
|
+
encryption_key=kms.Key.from_key_arn(self, "SourceBucketEncryptionKey", "arn:aws:kms:us-east-1:123456789012:key/<key-id>")
|
|
2042
|
+
)
|
|
2043
|
+
deployment = s3deploy.BucketDeployment(self, "DeployFiles",
|
|
2044
|
+
sources=[s3deploy.Source.bucket(source_bucket, "source.zip")],
|
|
2045
|
+
destination_bucket=destination_bucket
|
|
2051
2046
|
)
|
|
2052
2047
|
'''
|
|
2053
2048
|
|
aws_cdk/aws_route53/__init__.py
CHANGED
|
@@ -267,9 +267,9 @@ cross_account_role = iam.Role(self, "CrossAccountRole",
|
|
|
267
267
|
resources=["*"]
|
|
268
268
|
),
|
|
269
269
|
iam.PolicyStatement(
|
|
270
|
-
sid="
|
|
270
|
+
sid="GetHostedZoneAndChangeResourceRecordSets",
|
|
271
271
|
effect=iam.Effect.ALLOW,
|
|
272
|
-
actions=["route53:GetHostedZone", "route53:
|
|
272
|
+
actions=["route53:GetHostedZone", "route53:ChangeResourceRecordSets"],
|
|
273
273
|
# This example assumes the RecordSet subdomain.somexample.com
|
|
274
274
|
# is contained in the HostedZone
|
|
275
275
|
resources=["arn:aws:route53:::hostedzone/HZID00000000000000000"],
|
|
@@ -7282,9 +7282,9 @@ class PublicHostedZoneProps(CommonHostedZoneProps):
|
|
|
7282
7282
|
resources=["*"]
|
|
7283
7283
|
),
|
|
7284
7284
|
iam.PolicyStatement(
|
|
7285
|
-
sid="
|
|
7285
|
+
sid="GetHostedZoneAndChangeResourceRecordSets",
|
|
7286
7286
|
effect=iam.Effect.ALLOW,
|
|
7287
|
-
actions=["route53:GetHostedZone", "route53:
|
|
7287
|
+
actions=["route53:GetHostedZone", "route53:ChangeResourceRecordSets"],
|
|
7288
7288
|
# This example assumes the RecordSet subdomain.somexample.com
|
|
7289
7289
|
# is contained in the HostedZone
|
|
7290
7290
|
resources=["arn:aws:route53:::hostedzone/HZID00000000000000000"],
|
|
@@ -24,12 +24,13 @@ This is what happens under the hood:
|
|
|
24
24
|
|
|
25
25
|
1. When this stack is deployed (either via `cdk deploy` or via CI/CD), the
|
|
26
26
|
contents of the local `website-dist` directory will be archived and uploaded
|
|
27
|
-
to an intermediary assets bucket
|
|
28
|
-
be individually uploaded.
|
|
29
|
-
2. The `BucketDeployment` construct synthesizes a custom CloudFormation resource
|
|
27
|
+
to an intermediary assets bucket (the `StagingBucket` of the CDK bootstrap stack).
|
|
28
|
+
If there is more than one source, they will be individually uploaded.
|
|
29
|
+
2. The `BucketDeployment` construct synthesizes a Lambda-backed custom CloudFormation resource
|
|
30
30
|
of type `Custom::CDKBucketDeployment` into the template. The source bucket/key
|
|
31
31
|
is set to point to the assets bucket.
|
|
32
|
-
3. The custom resource
|
|
32
|
+
3. The custom resource invokes its associated Lambda function, which downloads the .zip archive,
|
|
33
|
+
extracts it and issues `aws s3 sync --delete` against the destination bucket (in this case
|
|
33
34
|
`websiteBucket`). If there is more than one source, the sources will be
|
|
34
35
|
downloaded and merged pre-deployment at this step.
|
|
35
36
|
|
|
@@ -68,6 +69,56 @@ deployment = s3deploy.BucketDeployment(self, "DeployWebsite",
|
|
|
68
69
|
deployment.add_source(s3deploy.Source.asset("./another-asset"))
|
|
69
70
|
```
|
|
70
71
|
|
|
72
|
+
For the Lambda function to download object(s) from the source bucket, besides the obvious
|
|
73
|
+
`s3:GetObject*` permissions, the Lambda's execution role needs the `kms:Decrypt` and `kms:DescribeKey`
|
|
74
|
+
permissions on the KMS key that is used to encrypt the bucket. By default, when the source bucket is
|
|
75
|
+
encrypted with the S3 managed key of the account, these permissions are granted by the key's
|
|
76
|
+
resource-based policy, so they do not need to be on the Lambda's execution role policy explicitly.
|
|
77
|
+
However, if the encryption key is not the s3 managed one, its resource-based policy is quite likely
|
|
78
|
+
to NOT grant such KMS permissions. In this situation, the Lambda execution will fail with an error
|
|
79
|
+
message like below:
|
|
80
|
+
|
|
81
|
+
```txt
|
|
82
|
+
download failed: ...
|
|
83
|
+
An error occurred (AccessDenied) when calling the GetObject operation:
|
|
84
|
+
User: *** is not authorized to perform: kms:Decrypt on the resource associated with this ciphertext
|
|
85
|
+
because no identity-based policy allows the kms:Decrypt action
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
When this happens, users can use the public `handlerRole` property of `BucketDeployment` to manually
|
|
89
|
+
add the KMS permissions:
|
|
90
|
+
|
|
91
|
+
```python
|
|
92
|
+
# destination_bucket: s3.Bucket
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
deployment = s3deploy.BucketDeployment(self, "DeployFiles",
|
|
96
|
+
sources=[s3deploy.Source.asset(path.join(__dirname, "source-files"))],
|
|
97
|
+
destination_bucket=destination_bucket
|
|
98
|
+
)
|
|
99
|
+
|
|
100
|
+
deployment.handler_role.add_to_policy(
|
|
101
|
+
iam.PolicyStatement(
|
|
102
|
+
actions=["kms:Decrypt", "kms:DescribeKey"],
|
|
103
|
+
effect=iam.Effect.ALLOW,
|
|
104
|
+
resources=["<encryption key ARN>"]
|
|
105
|
+
))
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
The situation above could arise from the following scenarios:
|
|
109
|
+
|
|
110
|
+
* User created a customer managed KMS key and passed its ID to the `cdk bootstrap` command via
|
|
111
|
+
the `--bootstrap-kms-key-id` CLI option.
|
|
112
|
+
The [default key policy](https://docs.aws.amazon.com/kms/latest/developerguide/key-policy-default.html#key-policy-default-allow-root-enable-iam)
|
|
113
|
+
alone is not sufficient to grant the Lambda KMS permissions.
|
|
114
|
+
* A corporation uses its own custom CDK bootstrap process, which encrypts the CDK `StagingBucket`
|
|
115
|
+
by a KMS key from a management account of the corporation's AWS Organization. In this cross-account
|
|
116
|
+
access scenario, the KMS permissions must be explicitly present in the Lambda's execution role policy.
|
|
117
|
+
* One of the sources for the `BucketDeployment` comes from the `Source.bucket` static method, which
|
|
118
|
+
points to a bucket whose encryption key is not the S3 managed one, and the resource-based policy
|
|
119
|
+
of the encryption key is not sufficient to grant the Lambda `kms:Decrypt` and `kms:DescribeKey`
|
|
120
|
+
permissions.
|
|
121
|
+
|
|
71
122
|
## Supported sources
|
|
72
123
|
|
|
73
124
|
The following source types are supported for bucket deployments:
|
|
@@ -378,7 +429,6 @@ The syntax for template variables is `{{ variableName }}` in your local file. Th
|
|
|
378
429
|
specify the substitutions in CDK like this:
|
|
379
430
|
|
|
380
431
|
```python
|
|
381
|
-
import aws_cdk.aws_iam as iam
|
|
382
432
|
import aws_cdk.aws_lambda as lambda_
|
|
383
433
|
|
|
384
434
|
# my_lambda_function: lambda.Function
|
|
@@ -678,6 +728,12 @@ class BucketDeployment(
|
|
|
678
728
|
'''
|
|
679
729
|
return typing.cast(_IBucket_42e086fd, jsii.get(self, "deployedBucket"))
|
|
680
730
|
|
|
731
|
+
@builtins.property
|
|
732
|
+
@jsii.member(jsii_name="handlerRole")
|
|
733
|
+
def handler_role(self) -> _IRole_235f5d8e:
|
|
734
|
+
'''Execution role of the Lambda function behind the custom CloudFormation resource of type ``Custom::CDKBucketDeployment``.'''
|
|
735
|
+
return typing.cast(_IRole_235f5d8e, jsii.get(self, "handlerRole"))
|
|
736
|
+
|
|
681
737
|
@builtins.property
|
|
682
738
|
@jsii.member(jsii_name="objectKeys")
|
|
683
739
|
def object_keys(self) -> typing.List[builtins.str]:
|
|
@@ -1457,7 +1513,6 @@ class DeployTimeSubstitutedFile(
|
|
|
1457
1513
|
|
|
1458
1514
|
Example::
|
|
1459
1515
|
|
|
1460
|
-
import aws_cdk.aws_iam as iam
|
|
1461
1516
|
import aws_cdk.aws_lambda as lambda_
|
|
1462
1517
|
|
|
1463
1518
|
# my_lambda_function: lambda.Function
|
|
@@ -1555,7 +1610,6 @@ class DeployTimeSubstitutedFileProps:
|
|
|
1555
1610
|
|
|
1556
1611
|
Example::
|
|
1557
1612
|
|
|
1558
|
-
import aws_cdk.aws_iam as iam
|
|
1559
1613
|
import aws_cdk.aws_lambda as lambda_
|
|
1560
1614
|
|
|
1561
1615
|
# my_lambda_function: lambda.Function
|
|
@@ -1870,8 +1924,31 @@ class Source(metaclass=jsii.JSIIMeta, jsii_type="aws-cdk-lib.aws_s3_deployment.S
|
|
|
1870
1924
|
|
|
1871
1925
|
Make sure you trust the producer of the archive.
|
|
1872
1926
|
|
|
1927
|
+
If the ``bucket`` parameter is an "out-of-app" reference "imported" via static methods such
|
|
1928
|
+
as ``s3.Bucket.fromBucketName``, be cautious about the bucket's encryption key. In general,
|
|
1929
|
+
CDK does not query for additional properties of imported constructs at synthesis time.
|
|
1930
|
+
For example, for a bucket created from ``s3.Bucket.fromBucketName``, CDK does not know
|
|
1931
|
+
its ``IBucket.encryptionKey`` property, and therefore will NOT give KMS permissions to the
|
|
1932
|
+
Lambda execution role of the ``BucketDeployment`` construct. If you want the
|
|
1933
|
+
``kms:Decrypt`` and ``kms:DescribeKey`` permissions on the bucket's encryption key
|
|
1934
|
+
to be added automatically, reference the imported bucket via ``s3.Bucket.fromBucketAttributes``
|
|
1935
|
+
and pass in the ``encryptionKey`` attribute explicitly.
|
|
1936
|
+
|
|
1873
1937
|
:param bucket: The S3 Bucket.
|
|
1874
1938
|
:param zip_object_key: The S3 object key of the zip file with contents.
|
|
1939
|
+
|
|
1940
|
+
Example::
|
|
1941
|
+
|
|
1942
|
+
# destination_bucket: s3.Bucket
|
|
1943
|
+
|
|
1944
|
+
source_bucket = s3.Bucket.from_bucket_attributes(self, "SourceBucket",
|
|
1945
|
+
bucket_arn="arn:aws:s3:::my-source-bucket-name",
|
|
1946
|
+
encryption_key=kms.Key.from_key_arn(self, "SourceBucketEncryptionKey", "arn:aws:kms:us-east-1:123456789012:key/<key-id>")
|
|
1947
|
+
)
|
|
1948
|
+
deployment = s3deploy.BucketDeployment(self, "DeployFiles",
|
|
1949
|
+
sources=[s3deploy.Source.bucket(source_bucket, "source.zip")],
|
|
1950
|
+
destination_bucket=destination_bucket
|
|
1951
|
+
)
|
|
1875
1952
|
'''
|
|
1876
1953
|
if __debug__:
|
|
1877
1954
|
type_hints = typing.get_type_hints(_typecheckingstub__bcaba123a95f1aa9d99f9f5af319da23dd5f345454e757ba9257364325b3efb5)
|