diff --git a/.changes/1.28.3.json b/.changes/1.28.3.json new file mode 100644 index 0000000000..b205a47c88 --- /dev/null +++ b/.changes/1.28.3.json @@ -0,0 +1,32 @@ +[ + { + "category": "``ec2``", + "description": "Feature supports the replacement of instance root volume using an updated AMI without requiring customers to stop their instance.", + "type": "api-change" + }, + { + "category": "``fms``", + "description": "Add support NetworkFirewall Managed Rule Group Override flag in GetViolationDetails API", + "type": "api-change" + }, + { + "category": "``glue``", + "description": "Added support for custom datatypes when using custom csv classifier.", + "type": "api-change" + }, + { + "category": "``redshift``", + "description": "This release clarifies use for the ElasticIp parameter of the CreateCluster and RestoreFromClusterSnapshot APIs.", + "type": "api-change" + }, + { + "category": "``sagemaker``", + "description": "This change allows customers to provide a custom entrypoint script for the docker container to be run while executing training jobs, and provide custom arguments to the entrypoint script.", + "type": "api-change" + }, + { + "category": "``wafv2``", + "description": "This release adds the following: Challenge rule action, to silently verify client browsers; rule group rule action override to any valid rule action, not just Count; token sharing between protected applications for challenge/CAPTCHA token; targeted rules option for Bot Control managed rule group.", + "type": "api-change" + } +] \ No newline at end of file diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 7a51c1e97a..e598743254 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -2,6 +2,17 @@ CHANGELOG ========= +1.28.3 +====== + +* api-change:``ec2``: Feature supports the replacement of instance root volume using an updated AMI without requiring customers to stop their instance. +* api-change:``fms``: Add support NetworkFirewall Managed Rule Group Override flag in GetViolationDetails API +* api-change:``glue``: Added support for custom datatypes when using custom csv classifier. +* api-change:``redshift``: This release clarifies use for the ElasticIp parameter of the CreateCluster and RestoreFromClusterSnapshot APIs. +* api-change:``sagemaker``: This change allows customers to provide a custom entrypoint script for the docker container to be run while executing training jobs, and provide custom arguments to the entrypoint script. +* api-change:``wafv2``: This release adds the following: Challenge rule action, to silently verify client browsers; rule group rule action override to any valid rule action, not just Count; token sharing between protected applications for challenge/CAPTCHA token; targeted rules option for Bot Control managed rule group. + + 1.28.2 ====== diff --git a/botocore/__init__.py b/botocore/__init__.py index 1448e83573..fe0cfad23f 100644 --- a/botocore/__init__.py +++ b/botocore/__init__.py @@ -16,7 +16,7 @@ import os import re -__version__ = '1.28.2' +__version__ = '1.28.3' class NullHandler(logging.Handler): diff --git a/botocore/args.py b/botocore/args.py index c9338cd9b3..9ae10b52cd 100644 --- a/botocore/args.py +++ b/botocore/args.py @@ -239,7 +239,7 @@ def compute_client_args( self._compute_connect_timeout(config_kwargs) s3_config = self.compute_s3_config(client_config) - is_s3_service = service_name in ['s3', 's3-control'] + is_s3_service = self._is_s3_service(service_name) if is_s3_service and 'dualstack' in endpoint_variant_tags: if s3_config is None: @@ -278,6 +278,16 @@ def compute_s3_config(self, client_config): return s3_configuration + def _is_s3_service(self, service_name): + """Whether the service is S3 or S3 Control. + + Note that throughout this class, service_name refers to the endpoint + prefix, not the folder name of the service in botocore/data. For + S3 Control, the folder name is 's3control' but the endpoint prefix is + 's3-control'. + """ + return service_name in ['s3', 's3-control'] + def _compute_endpoint_config( self, service_name, @@ -532,9 +542,11 @@ def _build_endpoint_resolver( # botocore does not support client context parameters generically # for every service. Instead, the s3 config section entries are # available as client context parameters. In the future, endpoint - # rulesets of services other than S3 may require client context - # parameters. - client_context = s3_config_raw if service_name_raw == 's3' else {} + # rulesets of services other than s3/s3control may require client + # context parameters. + client_context = ( + s3_config_raw if self._is_s3_service(service_name_raw) else {} + ) sig_version = ( client_config.signature_version if client_config is not None diff --git a/botocore/client.py b/botocore/client.py index b05cf7c829..1f54d52739 100644 --- a/botocore/client.py +++ b/botocore/client.py @@ -823,7 +823,7 @@ def __init__( client_config, partition, exceptions_factory, - endpoint_ruleset_resolver, + endpoint_ruleset_resolver=None, ): self._serializer = serializer self._endpoint = endpoint diff --git a/botocore/data/ec2/2016-11-15/service-2.json b/botocore/data/ec2/2016-11-15/service-2.json index b7fd6f09f1..335da510e8 100644 --- a/botocore/data/ec2/2016-11-15/service-2.json +++ b/botocore/data/ec2/2016-11-15/service-2.json @@ -885,7 +885,7 @@ }, "input":{"shape":"CreateReplaceRootVolumeTaskRequest"}, "output":{"shape":"CreateReplaceRootVolumeTaskResult"}, - "documentation":"

Creates a root volume replacement task for an Amazon EC2 instance. The root volume can either be restored to its initial launch state, or it can be restored using a specific snapshot.

For more information, see Replace a root volume in the Amazon Elastic Compute Cloud User Guide.

" + "documentation":"

Replaces the EBS-backed root volume for a running instance with a new volume that is restored to the original root volume's launch state, that is restored to a specific snapshot taken from the original root volume, or that is restored from an AMI that has the same key characteristics as that of the instance.

For more information, see Replace a root volume in the Amazon Elastic Compute Cloud User Guide.

" }, "CreateReservedInstancesListing":{ "name":"CreateReservedInstancesListing", @@ -12538,7 +12538,7 @@ }, "SnapshotId":{ "shape":"SnapshotId", - "documentation":"

The ID of the snapshot from which to restore the replacement root volume. If you want to restore the volume to the initial launch state, omit this parameter.

" + "documentation":"

The ID of the snapshot from which to restore the replacement root volume. The specified snapshot must be a snapshot that you previously created from the original root volume.

If you want to restore the replacement root volume to the initial launch state, or if you want to restore the replacement root volume from an AMI, omit this parameter.

" }, "ClientToken":{ "shape":"String", @@ -12553,6 +12553,14 @@ "shape":"TagSpecificationList", "documentation":"

The tags to apply to the root volume replacement task.

", "locationName":"TagSpecification" + }, + "ImageId":{ + "shape":"ImageId", + "documentation":"

The ID of the AMI to use to restore the root volume. The specified AMI must have the same product code, billing information, architecture type, and virtualization type as that of the instance.

If you want to restore the replacement volume from a specific snapshot, or if you want to restore it to its launch state, omit this parameter.

" + }, + "DeleteReplacedRootVolume":{ + "shape":"Boolean", + "documentation":"

Indicates whether to automatically delete the original root volume after the root volume replacement task completes. To delete the original root volume, specify true. If you choose to keep the original root volume after the replacement task completes, you must manually delete it when you no longer need it.

" } } }, @@ -42262,6 +42270,21 @@ "shape":"TagList", "documentation":"

The tags assigned to the task.

", "locationName":"tagSet" + }, + "ImageId":{ + "shape":"ImageId", + "documentation":"

The ID of the AMI used to create the replacement root volume.

", + "locationName":"imageId" + }, + "SnapshotId":{ + "shape":"SnapshotId", + "documentation":"

The ID of the snapshot used to create the replacement root volume.

", + "locationName":"snapshotId" + }, + "DeleteReplacedRootVolume":{ + "shape":"Boolean", + "documentation":"

Indicates whether the original root volume is to be deleted after the root volume replacement task completes.

", + "locationName":"deleteReplacedRootVolume" } }, "documentation":"

Information about a root volume replacement task.

" diff --git a/botocore/data/endpoints.json b/botocore/data/endpoints.json index cf3994c1ff..2ec5e756f3 100644 --- a/botocore/data/endpoints.json +++ b/botocore/data/endpoints.json @@ -2190,6 +2190,7 @@ "deprecated" : true, "hostname" : "cloudcontrolapi-fips.us-west-2.amazonaws.com" }, + "me-central-1" : { }, "me-south-1" : { }, "sa-east-1" : { }, "us-east-1" : { @@ -20372,7 +20373,8 @@ }, "ds" : { "endpoints" : { - "us-iso-east-1" : { } + "us-iso-east-1" : { }, + "us-iso-west-1" : { } } }, "dynamodb" : { diff --git a/botocore/data/fms/2018-01-01/service-2.json b/botocore/data/fms/2018-01-01/service-2.json index d28cf0fc18..e7aa84bfee 100644 --- a/botocore/data/fms/2018-01-01/service-2.json +++ b/botocore/data/fms/2018-01-01/service-2.json @@ -2000,6 +2000,10 @@ }, "documentation":"

Violation detail for Network Firewall for an Availability Zone that's missing the expected Firewall Manager managed subnet.

" }, + "NetworkFirewallOverrideAction":{ + "type":"string", + "enum":["DROP_TO_ALERT"] + }, "NetworkFirewallPolicy":{ "type":"structure", "members":{ @@ -2068,6 +2072,16 @@ "min":1, "pattern":"^[a-zA-Z0-9-]+$" }, + "NetworkFirewallStatefulRuleGroupOverride":{ + "type":"structure", + "members":{ + "Action":{ + "shape":"NetworkFirewallOverrideAction", + "documentation":"

The action that changes the rule group from DROP to ALERT. This only applies to managed rule groups.

" + } + }, + "documentation":"

The setting that allows the policy owner to change the behavior of the rule group within a policy.

" + }, "NetworkFirewallUnexpectedFirewallRoutesViolation":{ "type":"structure", "members":{ @@ -2978,7 +2992,7 @@ }, "ManagedServiceData":{ "shape":"ManagedServiceData", - "documentation":"

Details about the service that are specific to the service type, in JSON format.

" + "documentation":"

Details about the service that are specific to the service type, in JSON format.

" }, "PolicyOption":{ "shape":"PolicyOption", @@ -3025,6 +3039,10 @@ "Priority":{ "shape":"PriorityNumber", "documentation":"

An integer setting that indicates the order in which to run the stateful rule groups in a single Network Firewall firewall policy. This setting only applies to firewall policies that specify the STRICT_ORDER rule order in the stateful engine options settings.

Network Firewall evalutes each stateful rule group against a packet starting with the group that has the lowest priority setting. You must ensure that the priority settings are unique within each policy. For information about

You can change the priority settings of your rule groups at any time. To make it easier to insert rule groups later, number them so there's a wide range in between, for example use 100, 200, and so on.

" + }, + "Override":{ + "shape":"NetworkFirewallStatefulRuleGroupOverride", + "documentation":"

The action that allows the policy owner to override the behavior of the rule group within a policy.

" } }, "documentation":"

Network Firewall stateful rule group, used in a NetworkFirewallPolicyDescription.

" diff --git a/botocore/data/glue/2017-03-31/service-2.json b/botocore/data/glue/2017-03-31/service-2.json index 74bc684c9b..9dc7e98f9b 100644 --- a/botocore/data/glue/2017-03-31/service-2.json +++ b/botocore/data/glue/2017-03-31/service-2.json @@ -5890,6 +5890,14 @@ "AllowSingleColumn":{ "shape":"NullableBoolean", "documentation":"

Enables the processing of files that contain only one column.

" + }, + "CustomDatatypeConfigured":{ + "shape":"NullableBoolean", + "documentation":"

Enables the configuration of custom datatypes.

" + }, + "CustomDatatypes":{ + "shape":"CustomDatatypes", + "documentation":"

Creates a list of supported custom datatypes.

" } }, "documentation":"

Specifies a custom CSV classifier for CreateClassifier to create.

" @@ -6883,6 +6891,14 @@ "AllowSingleColumn":{ "shape":"NullableBoolean", "documentation":"

Enables the processing of files that contain only one column.

" + }, + "CustomDatatypeConfigured":{ + "shape":"NullableBoolean", + "documentation":"

Enables the custom datatype to be configured.

" + }, + "CustomDatatypes":{ + "shape":"CustomDatatypes", + "documentation":"

A list of custom datatypes including \"BINARY\", \"BOOLEAN\", \"DATE\", \"DECIMAL\", \"DOUBLE\", \"FLOAT\", \"INT\", \"LONG\", \"SHORT\", \"STRING\", \"TIMESTAMP\".

" } }, "documentation":"

A classifier for custom CSV content.

" @@ -6943,6 +6959,10 @@ }, "documentation":"

Specifies a transform that uses custom code you provide to perform the data transformation. The output is a collection of DynamicFrames.

" }, + "CustomDatatypes":{ + "type":"list", + "member":{"shape":"NameString"} + }, "CustomEntityType":{ "type":"structure", "required":[ @@ -17293,6 +17313,14 @@ "AllowSingleColumn":{ "shape":"NullableBoolean", "documentation":"

Enables the processing of files that contain only one column.

" + }, + "CustomDatatypeConfigured":{ + "shape":"NullableBoolean", + "documentation":"

Specifies the configuration of custom datatypes.

" + }, + "CustomDatatypes":{ + "shape":"CustomDatatypes", + "documentation":"

Specifies a list of supported custom datatypes.

" } }, "documentation":"

Specifies a custom CSV classifier to be updated.

" diff --git a/botocore/data/redshift/2012-12-01/service-2.json b/botocore/data/redshift/2012-12-01/service-2.json index 9c3fd37abc..59720248ce 100644 --- a/botocore/data/redshift/2012-12-01/service-2.json +++ b/botocore/data/redshift/2012-12-01/service-2.json @@ -3764,7 +3764,7 @@ }, "ElasticIp":{ "shape":"String", - "documentation":"

The Elastic IP (EIP) address for the cluster.

Constraints: The cluster must be provisioned in EC2-VPC and publicly-accessible through an Internet gateway. For more information about provisioning clusters in EC2-VPC, go to Supported Platforms to Launch Your Cluster in the Amazon Redshift Cluster Management Guide.

" + "documentation":"

The Elastic IP (EIP) address for the cluster.

Constraints: The cluster must be provisioned in EC2-VPC and publicly-accessible through an Internet gateway. Don't specify the Elastic IP address for a publicly accessible cluster with availability zone relocation turned on. For more information about provisioning clusters in EC2-VPC, go to Supported Platforms to Launch Your Cluster in the Amazon Redshift Cluster Management Guide.

" }, "Tags":{ "shape":"TagList", @@ -8611,7 +8611,7 @@ }, "ElasticIp":{ "shape":"String", - "documentation":"

The elastic IP (EIP) address for the cluster.

" + "documentation":"

The Elastic IP (EIP) address for the cluster. Don't specify the Elastic IP address for a publicly accessible cluster with availability zone relocation turned on.

" }, "ClusterParameterGroupName":{ "shape":"String", diff --git a/botocore/data/sagemaker/2017-07-24/service-2.json b/botocore/data/sagemaker/2017-07-24/service-2.json index 7986625539..6fe2f7a1f8 100644 --- a/botocore/data/sagemaker/2017-07-24/service-2.json +++ b/botocore/data/sagemaker/2017-07-24/service-2.json @@ -619,7 +619,7 @@ {"shape":"ResourceLimitExceeded"}, {"shape":"ResourceNotFound"} ], - "documentation":"

Starts a model training job. After training completes, SageMaker saves the resulting model artifacts to an Amazon S3 location that you specify.

If you choose to host your model using SageMaker hosting services, you can use the resulting model artifacts as part of the model. You can also use the artifacts in a machine learning service other than SageMaker, provided that you know how to use them for inference.

In the request body, you provide the following:

For more information about SageMaker, see How It Works.

" + "documentation":"

Starts a model training job. After training completes, SageMaker saves the resulting model artifacts to an Amazon S3 location that you specify.

If you choose to host your model using SageMaker hosting services, you can use the resulting model artifacts as part of the model. You can also use the artifacts in a machine learning service other than SageMaker, provided that you know how to use them for inference.

In the request body, you provide the following:

For more information about SageMaker, see How It Works.

" }, "CreateTransformJob":{ "name":"CreateTransformJob", @@ -3453,6 +3453,14 @@ "EnableSageMakerMetricsTimeSeries":{ "shape":"Boolean", "documentation":"

To generate and save time-series metrics during training, set to true. The default is false and time-series metrics aren't generated except in the following cases:

" + }, + "ContainerEntrypoint":{ + "shape":"TrainingContainerEntrypoint", + "documentation":"

The entrypoint script for a Docker container used to run a training job. This script takes precedence over the default train processing instructions. See How Amazon SageMaker Runs Your Training Image for more information.

" + }, + "ContainerArguments":{ + "shape":"TrainingContainerArguments", + "documentation":"

The arguments for a container used to run a training job. See How Amazon SageMaker Runs Your Training Image for additional information.

" } }, "documentation":"

Specifies the training algorithm to use in a CreateTrainingJob request.

For more information about algorithms provided by SageMaker, see Algorithms. For information about using your own algorithms, see Using Your Own Algorithms with Amazon SageMaker.

" @@ -26758,6 +26766,28 @@ "type":"string", "enum":["PHASES"] }, + "TrainingContainerArgument":{ + "type":"string", + "max":256, + "pattern":".*" + }, + "TrainingContainerArguments":{ + "type":"list", + "member":{"shape":"TrainingContainerArgument"}, + "max":100, + "min":1 + }, + "TrainingContainerEntrypoint":{ + "type":"list", + "member":{"shape":"TrainingContainerEntrypointString"}, + "max":10, + "min":1 + }, + "TrainingContainerEntrypointString":{ + "type":"string", + "max":256, + "pattern":".*" + }, "TrainingEnvironmentKey":{ "type":"string", "max":512, diff --git a/botocore/data/wafv2/2019-07-29/service-2.json b/botocore/data/wafv2/2019-07-29/service-2.json index 28a16eb701..6b35e35bdc 100644 --- a/botocore/data/wafv2/2019-07-29/service-2.json +++ b/botocore/data/wafv2/2019-07-29/service-2.json @@ -135,7 +135,8 @@ {"shape":"WAFTagOperationInternalErrorException"}, {"shape":"WAFSubscriptionNotFoundException"}, {"shape":"WAFInvalidOperationException"}, - {"shape":"WAFConfigurationWarningException"} + {"shape":"WAFConfigurationWarningException"}, + {"shape":"WAFExpiredManagedRuleGroupVersionException"} ], "documentation":"

Creates a WebACL per the specifications provided.

A web ACL defines a collection of rules to use to inspect and control web requests. Each rule has an action defined (allow, block, or count) for requests that match the statement of the rule. In the web ACL, you assign a default action to take (allow, block) for any request that does not match any of the rules. The rules in a web ACL can be a combination of the types Rule, RuleGroup, and managed rule group. You can associate a web ACL with one or more Amazon Web Services resources to protect. The resources can be an Amazon CloudFront distribution, an Amazon API Gateway REST API, an Application Load Balancer, an AppSync GraphQL API, or an Amazon Cognito user pool.

" }, @@ -316,7 +317,7 @@ {"shape":"WAFInvalidParameterException"}, {"shape":"WAFInvalidOperationException"} ], - "documentation":"

Generates a presigned download URL for the specified release of the mobile SDK.

The mobile SDK is not generally available. Customers who have access to the mobile SDK can use it to establish and manage Security Token Service (STS) security tokens for use in HTTP(S) requests from a mobile device to WAF. For more information, see WAF client application integration in the WAF Developer Guide.

" + "documentation":"

Generates a presigned download URL for the specified release of the mobile SDK.

The mobile SDK is not generally available. Customers who have access to the mobile SDK can use it to establish and manage WAF tokens for use in HTTP(S) requests from a mobile device to WAF. For more information, see WAF client application integration in the WAF Developer Guide.

" }, "GetIPSet":{ "name":"GetIPSet", @@ -380,7 +381,7 @@ {"shape":"WAFInvalidParameterException"}, {"shape":"WAFInvalidOperationException"} ], - "documentation":"

Retrieves information for the specified mobile SDK release, including release notes and tags.

The mobile SDK is not generally available. Customers who have access to the mobile SDK can use it to establish and manage Security Token Service (STS) security tokens for use in HTTP(S) requests from a mobile device to WAF. For more information, see WAF client application integration in the WAF Developer Guide.

" + "documentation":"

Retrieves information for the specified mobile SDK release, including release notes and tags.

The mobile SDK is not generally available. Customers who have access to the mobile SDK can use it to establish and manage WAF tokens for use in HTTP(S) requests from a mobile device to WAF. For more information, see WAF client application integration in the WAF Developer Guide.

" }, "GetPermissionPolicy":{ "name":"GetPermissionPolicy", @@ -582,7 +583,7 @@ {"shape":"WAFInvalidParameterException"}, {"shape":"WAFInvalidOperationException"} ], - "documentation":"

Retrieves a list of the available releases for the mobile SDK and the specified device platform.

The mobile SDK is not generally available. Customers who have access to the mobile SDK can use it to establish and manage Security Token Service (STS) security tokens for use in HTTP(S) requests from a mobile device to WAF. For more information, see WAF client application integration in the WAF Developer Guide.

" + "documentation":"

Retrieves a list of the available releases for the mobile SDK and the specified device platform.

The mobile SDK is not generally available. Customers who have access to the mobile SDK can use it to establish and manage WAF tokens for use in HTTP(S) requests from a mobile device to WAF. For more information, see WAF client application integration in the WAF Developer Guide.

" }, "ListRegexPatternSets":{ "name":"ListRegexPatternSets", @@ -856,6 +857,17 @@ } }, "shapes":{ + "AWSManagedRulesBotControlRuleSet":{ + "type":"structure", + "required":["InspectionLevel"], + "members":{ + "InspectionLevel":{ + "shape":"InspectionLevel", + "documentation":"

The inspection level to use for the Bot Control rule group. The common level is the least expensive. The targeted level includes all common level rules and adds rules with more advanced inspection criteria. For details, see WAF Bot Control rule group.

" + } + }, + "documentation":"

Details for your use of the Bot Control managed rule group, used in ManagedRuleGroupConfig.

" + }, "Action":{"type":"string"}, "ActionCondition":{ "type":"structure", @@ -863,7 +875,7 @@ "members":{ "Action":{ "shape":"ActionValue", - "documentation":"

The action setting that a log record must contain in order to meet the condition.

" + "documentation":"

The action setting that a log record must contain in order to meet the condition. This is the action that WAF applied to the web request.

For rule groups, this is either the configured rule action setting, or if you've applied a rule action override to the rule, it's the override action. The value EXCLUDED_AS_COUNT matches on excluded rules and also on rules that have a rule action override of Count.

" } }, "documentation":"

A single action condition for a Condition in a logging filter.

" @@ -875,6 +887,7 @@ "BLOCK", "COUNT", "CAPTCHA", + "CHALLENGE", "EXCLUDED_AS_COUNT" ] }, @@ -999,17 +1012,17 @@ "members":{ "CustomRequestHandling":{ "shape":"CustomRequestHandling", - "documentation":"

Defines custom handling for the web request.

For information about customizing web requests and responses, see Customizing web requests and responses in WAF in the WAF Developer Guide.

" + "documentation":"

Defines custom handling for the web request, used when the CAPTCHA inspection determines that the request's token is valid and unexpired.

For information about customizing web requests and responses, see Customizing web requests and responses in WAF in the WAF Developer Guide.

" } }, - "documentation":"

Specifies that WAF should run a CAPTCHA check against the request:

You can configure the expiration time in the CaptchaConfig ImmunityTimeProperty setting at the rule and web ACL level. The rule setting overrides the web ACL setting.

This action option is available for rules. It isn't available for web ACL default actions.

" + "documentation":"

Specifies that WAF should run a CAPTCHA check against the request:

You can configure the expiration time in the CaptchaConfig ImmunityTimeProperty setting at the rule and web ACL level. The rule setting overrides the web ACL setting.

This action option is available for rules. It isn't available for web ACL default actions.

" }, "CaptchaConfig":{ "type":"structure", "members":{ "ImmunityTimeProperty":{ "shape":"ImmunityTimeProperty", - "documentation":"

Determines how long a CAPTCHA token remains valid after the client successfully solves a CAPTCHA puzzle.

" + "documentation":"

Determines how long a CAPTCHA timestamp in the token remains valid after the client successfully solves a CAPTCHA puzzle.

" } }, "documentation":"

Specifies how WAF should handle CAPTCHA evaluations. This is available at the web ACL level and in each rule.

" @@ -1023,7 +1036,7 @@ }, "SolveTimestamp":{ "shape":"SolveTimestamp", - "documentation":"

The time that the CAPTCHA puzzle was solved for the supplied token.

" + "documentation":"

The time that the CAPTCHA was last solved for the supplied token.

" }, "FailureReason":{ "shape":"FailureReason", @@ -1032,6 +1045,44 @@ }, "documentation":"

The result from the inspection of the web request for a valid CAPTCHA token.

" }, + "ChallengeAction":{ + "type":"structure", + "members":{ + "CustomRequestHandling":{ + "shape":"CustomRequestHandling", + "documentation":"

Defines custom handling for the web request, used when the challenge inspection determines that the request's token is valid and unexpired.

For information about customizing web requests and responses, see Customizing web requests and responses in WAF in the WAF Developer Guide.

" + } + }, + "documentation":"

Specifies that WAF should run a Challenge check against the request to verify that the request is coming from a legitimate client session:

You can configure the expiration time in the ChallengeConfig ImmunityTimeProperty setting at the rule and web ACL level. The rule setting overrides the web ACL setting.

This action option is available for rules. It isn't available for web ACL default actions.

" + }, + "ChallengeConfig":{ + "type":"structure", + "members":{ + "ImmunityTimeProperty":{ + "shape":"ImmunityTimeProperty", + "documentation":"

Determines how long a challenge timestamp in the token remains valid after the client successfully responds to a challenge.

" + } + }, + "documentation":"

Specifies how WAF should handle Challenge evaluations. This is available at the web ACL level and in each rule.

" + }, + "ChallengeResponse":{ + "type":"structure", + "members":{ + "ResponseCode":{ + "shape":"ResponseCode", + "documentation":"

The HTTP response code indicating the status of the challenge token in the web request. If the token is missing, invalid, or expired, this code is 202 Request Accepted.

" + }, + "SolveTimestamp":{ + "shape":"SolveTimestamp", + "documentation":"

The time that the challenge was last solved for the supplied token.

" + }, + "FailureReason":{ + "shape":"FailureReason", + "documentation":"

The reason for failure, populated when the evaluation of the token fails.

" + } + }, + "documentation":"

The result from the inspection of the web request for a valid challenge token.

" + }, "CheckCapacityRequest":{ "type":"structure", "required":[ @@ -1589,6 +1640,14 @@ "CaptchaConfig":{ "shape":"CaptchaConfig", "documentation":"

Specifies how WAF should handle CAPTCHA evaluations for rules that don't have their own CaptchaConfig settings. If you don't specify this, WAF uses its default settings for CaptchaConfig.

" + }, + "ChallengeConfig":{ + "shape":"ChallengeConfig", + "documentation":"

Specifies how WAF should handle challenge evaluations for rules that don't have their own ChallengeConfig settings. If you don't specify this, WAF uses its default settings for ChallengeConfig.

" + }, + "TokenDomains":{ + "shape":"TokenDomains", + "documentation":"

Specifies the domains that WAF should accept in a web request token. This enables the use of tokens across multiple protected websites. When WAF provides a token, it uses the domain of the Amazon Web Services resource that the web ACL is protecting. If you don't specify a list of token domains, WAF accepts tokens only for the domain of the protected resource. With a token domain list, WAF accepts the resource's host domain plus all domains in the token domain list, including their prefixed subdomains.

Example JSON: \"TokenDomains\": { \"mywebsite.com\", \"myotherwebsite.com\" }

" } } }, @@ -1645,7 +1704,7 @@ "documentation":"

The HTTP headers to insert into the request. Duplicate header names are not allowed.

For information about the limits on count and size for custom request and response settings, see WAF quotas in the WAF Developer Guide.

" } }, - "documentation":"

Custom request handling behavior that inserts custom headers into a web request. You can add custom request handling for the rule actions allow and count.

For information about customizing web requests and responses, see Customizing web requests and responses in WAF in the WAF Developer Guide.

" + "documentation":"

Custom request handling behavior that inserts custom headers into a web request. You can add custom request handling for WAF to use when the rule action doesn't block the request. For example, CaptchaAction for requests with valid t okens, and AllowAction.

For information about customizing web requests and responses, see Customizing web requests and responses in WAF in the WAF Developer Guide.

" }, "CustomResponse":{ "type":"structure", @@ -1992,7 +2051,7 @@ "documentation":"

The name of the rule whose action you want to override to Count.

" } }, - "documentation":"

Specifies a single rule in a rule group whose action you want to override to Count. When you exclude a rule, WAF evaluates it exactly as it would if the rule action setting were Count. This is a useful option for testing the rules in a rule group without modifying how they handle your web traffic.

" + "documentation":"

Specifies a single rule in a rule group whose action you want to override to Count.

Instead of this option, use RuleActionOverrides. It accepts any valid action setting, including Count.

" }, "ExcludedRules":{ "type":"list", @@ -2003,7 +2062,9 @@ "type":"string", "enum":[ "TOKEN_MISSING", - "TOKEN_EXPIRED" + "TOKEN_EXPIRED", + "TOKEN_INVALID", + "TOKEN_DOMAIN_MISMATCH" ] }, "FallbackBehavior":{ @@ -2137,7 +2198,7 @@ }, "OverrideAction":{ "shape":"OverrideAction", - "documentation":"

The action to use in the place of the action that results from the rule group evaluation. Set the override action to none to leave the result of the rule group alone. Set it to count to override the result to count only.

You can only use this for rule statements that reference a rule group, like RuleGroupReferenceStatement and ManagedRuleGroupStatement.

This option is usually set to none. It does not affect how the rules in the rule group are evaluated. If you want the rules in the rule group to only count matches, do not use this and instead exclude those rules in your rule group reference statement settings.

" + "documentation":"

The action to use in the place of the action that results from the rule group evaluation. Set the override action to none to leave the result of the rule group alone. Set it to count to override the result to count only.

You can only use this for rule statements that reference a rule group, like RuleGroupReferenceStatement and ManagedRuleGroupStatement.

This option is usually set to none. It does not affect how the rules in the rule group are evaluated. If you want the rules in the rule group to only count matches, do not use this and instead use the rule action override option, with Count action, in your rule group reference statement settings.

" }, "VisibilityConfig":{ "shape":"VisibilityConfig", @@ -2818,10 +2879,17 @@ "members":{ "ImmunityTime":{ "shape":"TimeWindowSecond", - "documentation":"

The amount of time, in seconds, that a CAPTCHA token is valid. The default setting is 300.

" + "documentation":"

The amount of time, in seconds, that a CAPTCHA or challenge timestamp is considered valid by WAF. The default setting is 300.

For the Challenge action, the minimum setting is 300.

" } }, - "documentation":"

Determines how long a CAPTCHA token remains valid after the client successfully solves a CAPTCHA puzzle.

" + "documentation":"

Used for CAPTCHA and challenge token settings. Determines how long a CAPTCHA or challenge timestamp remains valid after WAF updates it for a successful CAPTCHA or challenge response.

" + }, + "InspectionLevel":{ + "type":"string", + "enum":[ + "COMMON", + "TARGETED" + ] }, "JsonBody":{ "type":"structure", @@ -3401,9 +3469,13 @@ "PasswordField":{ "shape":"PasswordField", "documentation":"

Details about your login page password field.

" + }, + "AWSManagedRulesBotControlRuleSet":{ + "shape":"AWSManagedRulesBotControlRuleSet", + "documentation":"

Additional configuration for using the Bot Control managed rule group. Use this to specify the inspection level that you want to use. For information about using the Bot Control managed rule group, see WAF Bot Control rule group and WAF Bot Control in the WAF Developer Guide.

" } }, - "documentation":"

Additional information that's used by a managed rule group. Most managed rule groups don't require this.

Use this for the account takeover prevention managed rule group AWSManagedRulesATPRuleSet, to provide information about the sign-in page of your application.

You can provide multiple individual ManagedRuleGroupConfig objects for any rule group configuration, for example UsernameField and PasswordField. The configuration that you provide depends on the needs of the managed rule group. For the ATP managed rule group, you provide the following individual configuration objects: LoginPath, PasswordField, PayloadType and UsernameField.

For example specifications, see the examples section of CreateWebACL.

" + "documentation":"

Additional information that's used by a managed rule group. Many managed rule groups don't require this.

Use the AWSManagedRulesBotControlRuleSet configuration object to configure the protection level that you want the Bot Control rule group to use.

For example specifications, see the examples section of CreateWebACL.

" }, "ManagedRuleGroupConfigs":{ "type":"list", @@ -3431,7 +3503,7 @@ }, "ExcludedRules":{ "shape":"ExcludedRules", - "documentation":"

The rules in the referenced rule group whose actions are set to Count. When you exclude a rule, WAF evaluates it exactly as it would if the rule action setting were Count. This is a useful option for testing the rules in a rule group without modifying how they handle your web traffic.

" + "documentation":"

Rules in the referenced rule group whose actions are set to Count.

Instead of this option, use RuleActionOverrides. It accepts any valid action setting, including Count.

" }, "ScopeDownStatement":{ "shape":"Statement", @@ -3439,7 +3511,11 @@ }, "ManagedRuleGroupConfigs":{ "shape":"ManagedRuleGroupConfigs", - "documentation":"

Additional information that's used by a managed rule group. Most managed rule groups don't require this.

Use this for the account takeover prevention managed rule group AWSManagedRulesATPRuleSet, to provide information about the sign-in page of your application.

You can provide multiple individual ManagedRuleGroupConfig objects for any rule group configuration, for example UsernameField and PasswordField. The configuration that you provide depends on the needs of the managed rule group. For the ATP managed rule group, you provide the following individual configuration objects: LoginPath, PasswordField, PayloadType and UsernameField.

" + "documentation":"

Additional information that's used by a managed rule group. Many managed rule groups don't require this.

Use the AWSManagedRulesBotControlRuleSet configuration object to configure the protection level that you want the Bot Control rule group to use.

" + }, + "RuleActionOverrides":{ + "shape":"RuleActionOverrides", + "documentation":"

Action settings to use in the place of the rule actions that are configured inside the rule group. You specify one override for each rule whose action you want to change.

You can use overrides for testing, for example you can override all of rule actions to Count and then monitor the resulting count metrics to understand how the rule group would handle your web traffic. You can also permanently override some or all actions, to modify how the rule group manages your web traffic.

" } }, "documentation":"

A rule statement used to run the rules that are defined in a managed rule group. To use this, provide the vendor name and the name of the rule group in this statement. You can retrieve the required names by calling ListAvailableManagedRuleGroups.

You cannot nest a ManagedRuleGroupStatement, for example for use inside a NotStatement or OrStatement. It can only be referenced as a top-level statement within a rule.

You are charged additional fees when you use the WAF Bot Control managed rule group AWSManagedRulesBotControlRuleSet or the WAF Fraud Control account takeover prevention (ATP) managed rule group AWSManagedRulesATPRuleSet. For more information, see WAF Pricing.

" @@ -3631,7 +3707,7 @@ "documentation":"

Tags that are associated with the release.

" } }, - "documentation":"

Information for a release of the mobile SDK, including release notes and tags.

The mobile SDK is not generally available. Customers who have access to the mobile SDK can use it to establish and manage Security Token Service (STS) security tokens for use in HTTP(S) requests from a mobile device to WAF. For more information, see WAF client application integration in the WAF Developer Guide.

" + "documentation":"

Information for a release of the mobile SDK, including release notes and tags.

The mobile SDK is not generally available. Customers who have access to the mobile SDK can use it to establish and manage WAF tokens for use in HTTP(S) requests from a mobile device to WAF. For more information, see WAF client application integration in the WAF Developer Guide.

" }, "NextMarker":{ "type":"string", @@ -3673,14 +3749,14 @@ "members":{ "Count":{ "shape":"CountAction", - "documentation":"

Override the rule group evaluation result to count only.

This option is usually set to none. It does not affect how the rules in the rule group are evaluated. If you want the rules in the rule group to only count matches, do not use this and instead exclude those rules in your rule group reference statement settings.

" + "documentation":"

Override the rule group evaluation result to count only.

This option is usually set to none. It does not affect how the rules in the rule group are evaluated. If you want the rules in the rule group to only count matches, do not use this and instead use the rule action override option, with Count action, in your rule group reference statement settings.

" }, "None":{ "shape":"NoneAction", "documentation":"

Don't override the rule group evaluation result. This is the most common setting.

" } }, - "documentation":"

The action to use in the place of the action that results from the rule group evaluation. Set the override action to none to leave the result of the rule group alone. Set it to count to override the result to count only.

You can only use this for rule statements that reference a rule group, like RuleGroupReferenceStatement and ManagedRuleGroupStatement.

This option is usually set to none. It does not affect how the rules in the rule group are evaluated. If you want the rules in the rule group to only count matches, do not use this and instead exclude those rules in your rule group reference statement settings.

" + "documentation":"

The action to use in the place of the action that results from the rule group evaluation. Set the override action to none to leave the result of the rule group alone. Set it to count to override the result to count only.

You can only use this for rule statements that reference a rule group, like RuleGroupReferenceStatement and ManagedRuleGroupStatement.

This option is usually set to none. It does not affect how the rules in the rule group are evaluated. If you want the rules in the rule group to only count matches, do not use this and instead use the rule action override option, with Count action, in your rule group reference statement settings.

" }, "OversizeHandling":{ "type":"string", @@ -3760,7 +3836,9 @@ "HEADER_MATCH_PATTERN", "COOKIE_MATCH_PATTERN", "MAP_MATCH_SCOPE", - "OVERSIZE_HANDLING" + "OVERSIZE_HANDLING", + "CHALLENGE_CONFIG", + "TOKEN_DOMAIN" ] }, "ParameterExceptionParameter":{ @@ -4169,7 +4247,7 @@ }, "OverrideAction":{ "shape":"OverrideAction", - "documentation":"

The action to use in the place of the action that results from the rule group evaluation. Set the override action to none to leave the result of the rule group alone. Set it to count to override the result to count only.

You can only use this for rule statements that reference a rule group, like RuleGroupReferenceStatement and ManagedRuleGroupStatement.

This option is usually set to none. It does not affect how the rules in the rule group are evaluated. If you want the rules in the rule group to only count matches, do not use this and instead exclude those rules in your rule group reference statement settings.

" + "documentation":"

The action to use in the place of the action that results from the rule group evaluation. Set the override action to none to leave the result of the rule group alone. Set it to count to override the result to count only.

You can only use this for rule statements that reference a rule group, like RuleGroupReferenceStatement and ManagedRuleGroupStatement.

This option is usually set to none. It does not affect how the rules in the rule group are evaluated. If you want the rules in the rule group to only count matches, do not use this and instead use the rule action override option, with Count action, in your rule group reference statement settings.

" }, "RuleLabels":{ "shape":"Labels", @@ -4182,6 +4260,10 @@ "CaptchaConfig":{ "shape":"CaptchaConfig", "documentation":"

Specifies how WAF should handle CAPTCHA evaluations. If you don't specify this, WAF uses the CAPTCHA configuration that's defined for the web ACL.

" + }, + "ChallengeConfig":{ + "shape":"ChallengeConfig", + "documentation":"

Specifies how WAF should handle Challenge evaluations. If you don't specify this, WAF uses the challenge configuration that's defined for the web ACL.

" } }, "documentation":"

A single rule, which you can use in a WebACL or RuleGroup to identify web requests that you want to allow, block, or count. Each rule includes one top-level Statement that WAF uses to identify matching web requests, and parameters that govern how WAF handles them.

" @@ -4204,10 +4286,38 @@ "Captcha":{ "shape":"CaptchaAction", "documentation":"

Instructs WAF to run a CAPTCHA check against the web request.

" + }, + "Challenge":{ + "shape":"ChallengeAction", + "documentation":"

Instructs WAF to run a Challenge check against the web request.

" } }, "documentation":"

The action that WAF should take on a web request when it matches a rule's statement. Settings at the web ACL level can override the rule action setting.

" }, + "RuleActionOverride":{ + "type":"structure", + "required":[ + "Name", + "ActionToUse" + ], + "members":{ + "Name":{ + "shape":"EntityName", + "documentation":"

The name of the rule to override.

" + }, + "ActionToUse":{ + "shape":"RuleAction", + "documentation":"

The override action to use, in place of the configured action of the rule in the rule group.

" + } + }, + "documentation":"

Action setting to use in the place of a rule action that is configured inside the rule group. You specify one override for each rule whose action you want to change.

You can use overrides for testing, for example you can override all of rule actions to Count and then monitor the resulting count metrics to understand how the rule group would handle your web traffic. You can also permanently override some or all actions, to modify how the rule group manages your web traffic.

" + }, + "RuleActionOverrides":{ + "type":"list", + "member":{"shape":"RuleActionOverride"}, + "max":100, + "min":1 + }, "RuleGroup":{ "type":"structure", "required":[ @@ -4275,7 +4385,11 @@ }, "ExcludedRules":{ "shape":"ExcludedRules", - "documentation":"

The rules in the referenced rule group whose actions are set to Count. When you exclude a rule, WAF evaluates it exactly as it would if the rule action setting were Count. This is a useful option for testing the rules in a rule group without modifying how they handle your web traffic.

" + "documentation":"

Rules in the referenced rule group whose actions are set to Count.

Instead of this option, use RuleActionOverrides. It accepts any valid action setting, including Count.

" + }, + "RuleActionOverrides":{ + "shape":"RuleActionOverrides", + "documentation":"

Action settings to use in the place of the rule actions that are configured inside the rule group. You specify one override for each rule whose action you want to change.

You can use overrides for testing, for example you can override all of rule actions to Count and then monitor the resulting count metrics to understand how the rule group would handle your web traffic. You can also permanently override some or all actions, to modify how the rule group manages your web traffic.

" } }, "documentation":"

A rule statement used to run the rules that are defined in a RuleGroup. To use this, create a rule group with your rules, then provide the ARN of the rule group in this statement.

You cannot nest a RuleGroupReferenceStatement, for example for use inside a NotStatement or OrStatement. You can only use a rule group reference statement at the top level inside a web ACL.

" @@ -4361,7 +4475,7 @@ }, "Action":{ "shape":"Action", - "documentation":"

The action for the Rule that the request matched: Allow, Block, or Count.

" + "documentation":"

The action that WAF applied to the request.

" }, "RuleNameWithinRuleGroup":{ "shape":"EntityName", @@ -4382,6 +4496,14 @@ "CaptchaResponse":{ "shape":"CaptchaResponse", "documentation":"

The CAPTCHA response for the request.

" + }, + "ChallengeResponse":{ + "shape":"ChallengeResponse", + "documentation":"

The Challenge response for the request.

" + }, + "OverriddenAction":{ + "shape":"Action", + "documentation":"

Used only for rule group rules that have a rule action override in place in the web ACL. This is the action that the rule group rule is configured for, and not the action that was applied to the request. The action that WAF applied is the Action value.

" } }, "documentation":"

Represents a single sampled web request. The response from GetSampledRequests includes a SampledHTTPRequests complex type that appears as SampledRequests in the response syntax. SampledHTTPRequests contains an array of SampledHTTPRequest objects.

" @@ -4716,6 +4838,17 @@ "min":60 }, "Timestamp":{"type":"timestamp"}, + "TokenDomain":{ + "type":"string", + "max":253, + "min":1, + "pattern":"^[\\w\\.\\-/]+$" + }, + "TokenDomains":{ + "type":"list", + "member":{"shape":"TokenDomain"}, + "min":1 + }, "URIString":{"type":"string"}, "UntagResourceRequest":{ "type":"structure", @@ -4986,6 +5119,14 @@ "CaptchaConfig":{ "shape":"CaptchaConfig", "documentation":"

Specifies how WAF should handle CAPTCHA evaluations for rules that don't have their own CaptchaConfig settings. If you don't specify this, WAF uses its default settings for CaptchaConfig.

" + }, + "ChallengeConfig":{ + "shape":"ChallengeConfig", + "documentation":"

Specifies how WAF should handle challenge evaluations for rules that don't have their own ChallengeConfig settings. If you don't specify this, WAF uses its default settings for ChallengeConfig.

" + }, + "TokenDomains":{ + "shape":"TokenDomains", + "documentation":"

Specifies the domains that WAF should accept in a web request token. This enables the use of tokens across multiple protected websites. When WAF provides a token, it uses the domain of the Amazon Web Services resource that the web ACL is protecting. If you don't specify a list of token domains, WAF accepts tokens only for the domain of the protected resource. With a token domain list, WAF accepts the resource's host domain plus all domains in the token domain list, including their prefixed subdomains.

Example JSON: \"TokenDomains\": { \"mywebsite.com\", \"myotherwebsite.com\" }

" } } }, @@ -5292,6 +5433,14 @@ "CaptchaConfig":{ "shape":"CaptchaConfig", "documentation":"

Specifies how WAF should handle CAPTCHA evaluations for rules that don't have their own CaptchaConfig settings. If you don't specify this, WAF uses its default settings for CaptchaConfig.

" + }, + "ChallengeConfig":{ + "shape":"ChallengeConfig", + "documentation":"

Specifies how WAF should handle challenge evaluations for rules that don't have their own ChallengeConfig settings. If you don't specify this, WAF uses its default settings for ChallengeConfig.

" + }, + "TokenDomains":{ + "shape":"TokenDomains", + "documentation":"

Specifies the domains that WAF should accept in a web request token. This enables the use of tokens across multiple protected websites. When WAF provides a token, it uses the domain of the Amazon Web Services resource that the web ACL is protecting. If you don't specify a list of token domains, WAF accepts tokens only for the domain of the protected resource. With a token domain list, WAF accepts the resource's host domain plus all domains in the token domain list, including their prefixed subdomains.

" } }, "documentation":"

A web ACL defines a collection of rules to use to inspect and control web requests. Each rule has an action defined (allow, block, or count) for requests that match the statement of the rule. In the web ACL, you assign a default action to take (allow, block) for any request that does not match any of the rules. The rules in a web ACL can be a combination of the types Rule, RuleGroup, and managed rule group. You can associate a web ACL with one or more Amazon Web Services resources to protect. The resources can be an Amazon CloudFront distribution, an Amazon API Gateway REST API, an Application Load Balancer, an AppSync GraphQL API, or an Amazon Cognito user pool.

" diff --git a/docs/source/conf.py b/docs/source/conf.py index 34cd1ac641..d60a4d29fa 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -54,7 +54,7 @@ # The short X.Y version. version = '1.28' # The full version, including alpha/beta/rc tags. -release = '1.28.2' +release = '1.28.3' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. diff --git a/tests/functional/test_context_params.py b/tests/functional/test_context_params.py new file mode 100644 index 0000000000..f83327d24b --- /dev/null +++ b/tests/functional/test_context_params.py @@ -0,0 +1,502 @@ +# Copyright 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"). You +# may not use this file except in compliance with the License. A copy of +# the License is located at +# +# http://aws.amazon.com/apache2.0/ +# +# or in the "license" file accompanying this file. This file is +# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF +# ANY KIND, either express or implied. See the License for the specific +# language governing permissions and limitations under the License. + +import pytest + +from botocore.config import Config +from tests import ClientHTTPStubber, mock + + +# Some tests in this file require ruleset based endpoint resolution to be +# enabled for all services (including the mock service "otherservice"). This +# temporary fixutre should be removed once ruleset based endpoint resolution +# is no longer limited to a subset of services. +@pytest.fixture(autouse=True) +def enable_endpoint_resolution_v2_for_all_services(): + with mock.patch('botocore.client.FORCE_ENDPOINT_RESOLUTION_V2', True): + yield + + +# fake rulesets compatible with all fake service models below + +FAKE_RULESET_TEMPLATE = { + "version": "1.0", + "parameters": {}, + "rules": [ + { + "conditions": [], + "type": "endpoint", + "endpoint": { + "url": "https://foo.bar", + "properties": {}, + "headers": {}, + }, + } + ], +} + +# The region param is unrelated to context parameters and used as control in +# all test cases to ascertain that ANY EndpointProvider paramaters get +# populated. +REGION_PARAM = { + "builtIn": "AWS::Region", + "required": False, + "documentation": "", + "type": "String", +} + +FAKE_RULESET_WITHOUT_ANY_CONTEXT_PARAMS = { + **FAKE_RULESET_TEMPLATE, + "parameters": { + "Region": REGION_PARAM, + }, +} + +FAKE_RULESET_WITH_CLIENT_CONTEXT_PARAM = { + **FAKE_RULESET_TEMPLATE, + "parameters": { + "Region": REGION_PARAM, + "FooClientContextParamName": { + "required": False, + "documentation": "", + "type": "String", + }, + }, +} + +FAKE_RULESET_WITH_STATIC_CONTEXT_PARAM = { + **FAKE_RULESET_TEMPLATE, + "parameters": { + "Region": REGION_PARAM, + "FooStaticContextParamName": { + "required": False, + "documentation": "", + "type": "String", + }, + }, +} + +FAKE_RULESET_WITH_DYNAMIC_CONTEXT_PARAM = { + **FAKE_RULESET_TEMPLATE, + "parameters": { + "Region": REGION_PARAM, + "FooDynamicContextParamName": { + "required": False, + "documentation": "", + "type": "String", + }, + }, +} + +# fake models for "otherservice" + +FAKE_MODEL_WITHOUT_ANY_CONTEXT_PARAMS = { + "version": "2.0", + "documentation": "", + "metadata": { + "apiVersion": "2020-02-02", + "endpointPrefix": "otherservice", + "protocol": "rest-xml", + "serviceFullName": "Other Service", + "serviceId": "Other Service", + "signatureVersion": "v4", + "signingName": "otherservice", + "uid": "otherservice-2020-02-02", + }, + "operations": { + "MockOperation": { + "name": "MockOperation", + "http": {"method": "GET", "requestUri": "/"}, + "input": {"shape": "MockOperationRequest"}, + "documentation": "", + }, + }, + "shapes": { + "MockOpParam": { + "type": "string", + }, + "MockOperationRequest": { + "type": "structure", + "required": ["MockOpParam"], + "members": { + "MockOpParam": { + "shape": "MockOpParam", + "documentation": "", + "location": "uri", + "locationName": "param", + }, + }, + }, + }, +} + +FAKE_MODEL_WITH_CLIENT_CONTEXT_PARAM = { + **FAKE_MODEL_WITHOUT_ANY_CONTEXT_PARAMS, + "clientContextParams": { + "FooClientContextParamName": { + "documentation": "My mock client context parameter", + "type": "string", + } + }, +} + +FAKE_MODEL_WITH_STATIC_CONTEXT_PARAM = { + **FAKE_MODEL_WITHOUT_ANY_CONTEXT_PARAMS, + "operations": { + "MockOperation": { + "name": "MockOperation", + "http": {"method": "GET", "requestUri": "/"}, + "input": {"shape": "MockOperationRequest"}, + "documentation": "", + "staticContextParams": { + "FooStaticContextParamName": { + "value": "foo-static-context-param-value" + } + }, + }, + }, +} + +FAKE_MODEL_WITH_DYNAMIC_CONTEXT_PARAM = { + **FAKE_MODEL_WITHOUT_ANY_CONTEXT_PARAMS, + "shapes": { + "MockOpParam": { + "type": "string", + }, + "MockOperationRequest": { + "type": "structure", + "required": ["MockOpParam"], + "members": { + "MockOpParam": { + "shape": "MockOpParam", + "documentation": "", + "location": "uri", + "locationName": "param", + "contextParam": {"name": "FooDynamicContextParamName"}, + }, + }, + }, + }, + # +} + +# fake models for s3 and s3control, the only services botocore currently +# supports client context parameters for + +S3_METADATA = { + "apiVersion": "2006-03-01", + "checksumFormat": "md5", + "endpointPrefix": "s3", + "globalEndpoint": "s3.amazonaws.com", + "protocol": "rest-xml", + "serviceAbbreviation": "Amazon S3", + "serviceFullName": "Amazon Simple Storage Service", + "serviceId": "S3", + "signatureVersion": "s3", + "uid": "s3-2006-03-01", +} + +FAKE_S3_MODEL_WITHOUT_ANY_CONTEXT_PARAMS = { + **FAKE_MODEL_WITHOUT_ANY_CONTEXT_PARAMS, + "metadata": S3_METADATA, +} + +FAKE_S3_MODEL_WITH_CLIENT_CONTEXT_PARAM = { + **FAKE_MODEL_WITH_CLIENT_CONTEXT_PARAM, + "metadata": S3_METADATA, +} + +S3CONTROL_METADATA = { + "apiVersion": "2018-08-20", + "endpointPrefix": "s3-control", + "protocol": "rest-xml", + "serviceFullName": "AWS S3 Control", + "serviceId": "S3 Control", + "signatureVersion": "s3v4", + "signingName": "s3", + "uid": "s3control-2018-08-20", +} + +FAKE_S3CONTROL_MODEL_WITHOUT_ANY_CONTEXT_PARAMS = { + **FAKE_MODEL_WITHOUT_ANY_CONTEXT_PARAMS, + "metadata": S3CONTROL_METADATA, +} + +FAKE_S3CONTROL_MODEL_WITH_CLIENT_CONTEXT_PARAM = { + **FAKE_MODEL_WITH_CLIENT_CONTEXT_PARAM, + "metadata": S3CONTROL_METADATA, +} + + +def patch_load_service_model( + session, monkeypatch, service_model_json, ruleset_json +): + def mock_load_service_model(service_name, type_name, api_version=None): + if type_name == 'service-2': + return service_model_json + if type_name == 'endpoint-rule-set-1': + return ruleset_json + + loader = session.get_component('data_loader') + monkeypatch.setattr(loader, 'load_service_model', mock_load_service_model) + + +@pytest.mark.parametrize( + 'service_name,service_model,ruleset,call_should_include_ctx_param', + [ + # s3 + ( + 's3', + FAKE_S3_MODEL_WITH_CLIENT_CONTEXT_PARAM, + FAKE_RULESET_WITH_CLIENT_CONTEXT_PARAM, + True, + ), + ( + 's3', + FAKE_S3_MODEL_WITH_CLIENT_CONTEXT_PARAM, + FAKE_RULESET_WITHOUT_ANY_CONTEXT_PARAMS, + False, + ), + ( + 's3', + FAKE_S3_MODEL_WITHOUT_ANY_CONTEXT_PARAMS, + FAKE_RULESET_WITH_CLIENT_CONTEXT_PARAM, + False, + ), + ( + 's3', + FAKE_S3_MODEL_WITHOUT_ANY_CONTEXT_PARAMS, + FAKE_RULESET_WITHOUT_ANY_CONTEXT_PARAMS, + False, + ), + # s3control + ( + 's3control', + FAKE_S3CONTROL_MODEL_WITH_CLIENT_CONTEXT_PARAM, + FAKE_RULESET_WITH_CLIENT_CONTEXT_PARAM, + True, + ), + ( + 's3control', + FAKE_S3CONTROL_MODEL_WITH_CLIENT_CONTEXT_PARAM, + FAKE_RULESET_WITHOUT_ANY_CONTEXT_PARAMS, + False, + ), + ( + 's3control', + FAKE_S3CONTROL_MODEL_WITHOUT_ANY_CONTEXT_PARAMS, + FAKE_RULESET_WITH_CLIENT_CONTEXT_PARAM, + False, + ), + ( + 's3control', + FAKE_S3CONTROL_MODEL_WITHOUT_ANY_CONTEXT_PARAMS, + FAKE_RULESET_WITHOUT_ANY_CONTEXT_PARAMS, + False, + ), + # botocore does not currently support client context params for + # services other than s3 and s3-control. + ( + 'otherservice', + FAKE_MODEL_WITH_CLIENT_CONTEXT_PARAM, + FAKE_RULESET_WITH_CLIENT_CONTEXT_PARAM, + False, # would be True for s3 and s3control + ), + ( + 'otherservice', + FAKE_MODEL_WITH_CLIENT_CONTEXT_PARAM, + FAKE_RULESET_WITHOUT_ANY_CONTEXT_PARAMS, + False, # same as for s3 and s3control + ), + ( + 'otherservice', + FAKE_MODEL_WITHOUT_ANY_CONTEXT_PARAMS, + FAKE_RULESET_WITH_CLIENT_CONTEXT_PARAM, + False, # same as for s3 and s3control + ), + ( + 'otherservice', + FAKE_MODEL_WITHOUT_ANY_CONTEXT_PARAMS, + FAKE_RULESET_WITHOUT_ANY_CONTEXT_PARAMS, + False, # same as for s3 and s3control + ), + ], +) +def test_client_context_param_sent_to_endpoint_resolver( + monkeypatch, + patched_session, + service_name, + service_model, + ruleset, + call_should_include_ctx_param, +): + # patch loader to return fake service model and fake endpoint ruleset + patch_load_service_model( + patched_session, monkeypatch, service_model, ruleset + ) + + # construct client using patched loader and a config object with an s3 + # section that sets the foo_context_param to a value + client = patched_session.create_client( + service_name, + region_name='us-east-1', + config=Config( + s3={'foo_client_context_param_name': 'foo_context_param_value'} + ), + ) + + # Stub client to prevent a request from getting sent and asceertain that + # only a single request would get sent. Wrap the EndpointProvider's + # resolve_endpoint method for inspecting the arguments it gets called with. + with ClientHTTPStubber(client, strict=True) as http_stubber: + http_stubber.add_response(status=200) + with mock.patch.object( + client._ruleset_resolver._provider, + 'resolve_endpoint', + wraps=client._ruleset_resolver._provider.resolve_endpoint, + ) as mock_resolve_endpoint: + client.mock_operation(MockOpParam='mock-op-param-value') + + if call_should_include_ctx_param: + mock_resolve_endpoint.assert_called_once_with( + Region='us-east-1', + FooClientContextParamName='foo_context_param_value', + ) + else: + mock_resolve_endpoint.assert_called_once_with(Region='us-east-1') + + +@pytest.mark.parametrize( + 'service_name,service_model,ruleset,call_should_include_ctx_param', + [ + ( + 'otherservice', + FAKE_MODEL_WITH_STATIC_CONTEXT_PARAM, + FAKE_RULESET_WITH_STATIC_CONTEXT_PARAM, + True, + ), + ( + 'otherservice', + FAKE_MODEL_WITH_STATIC_CONTEXT_PARAM, + FAKE_RULESET_WITHOUT_ANY_CONTEXT_PARAMS, + False, + ), + ( + 'otherservice', + FAKE_MODEL_WITHOUT_ANY_CONTEXT_PARAMS, + FAKE_RULESET_WITH_STATIC_CONTEXT_PARAM, + False, + ), + ( + 'otherservice', + FAKE_MODEL_WITHOUT_ANY_CONTEXT_PARAMS, + FAKE_RULESET_WITHOUT_ANY_CONTEXT_PARAMS, + False, + ), + ], +) +def test_static_context_param_sent_to_endpoint_resolver( + monkeypatch, + patched_session, + service_name, + service_model, + ruleset, + call_should_include_ctx_param, +): + # patch loader to return fake service model and fake endpoint ruleset + patch_load_service_model( + patched_session, monkeypatch, service_model, ruleset + ) + + # construct client using patched loader, but no special config is required + # for static context param to take effect + client = patched_session.create_client( + service_name, region_name='us-east-1' + ) + + with ClientHTTPStubber(client, strict=True) as http_stubber: + http_stubber.add_response(status=200) + with mock.patch.object( + client._ruleset_resolver._provider, + 'resolve_endpoint', + wraps=client._ruleset_resolver._provider.resolve_endpoint, + ) as mock_resolve_endpoint: + client.mock_operation(MockOpParam='mock-op-param-value') + + if call_should_include_ctx_param: + mock_resolve_endpoint.assert_called_once_with( + Region='us-east-1', + FooStaticContextParamName='foo-static-context-param-value', + ) + else: + mock_resolve_endpoint.assert_called_once_with(Region='us-east-1') + + +@pytest.mark.parametrize( + 'service_name,service_model,ruleset,call_should_include_ctx_param', + [ + ( + 'otherservice', + FAKE_MODEL_WITH_DYNAMIC_CONTEXT_PARAM, + FAKE_RULESET_WITH_DYNAMIC_CONTEXT_PARAM, + True, + ), + ( + 'otherservice', + FAKE_MODEL_WITH_DYNAMIC_CONTEXT_PARAM, + FAKE_RULESET_WITHOUT_ANY_CONTEXT_PARAMS, + False, + ), + ( + 'otherservice', + FAKE_MODEL_WITHOUT_ANY_CONTEXT_PARAMS, + FAKE_RULESET_WITH_DYNAMIC_CONTEXT_PARAM, + False, + ), + ], +) +def test_dynamic_context_param_sent_to_endpoint_resolver( + monkeypatch, + patched_session, + service_name, + service_model, + ruleset, + call_should_include_ctx_param, +): + # patch loader to return fake service model and fake endpoint ruleset + patch_load_service_model( + patched_session, monkeypatch, service_model, ruleset + ) + + # construct client using patched loader, but no special config is required + # for static context param to take effect + client = patched_session.create_client( + service_name, region_name='us-east-1' + ) + + with ClientHTTPStubber(client, strict=True) as http_stubber: + http_stubber.add_response(status=200) + with mock.patch.object( + client._ruleset_resolver._provider, + 'resolve_endpoint', + wraps=client._ruleset_resolver._provider.resolve_endpoint, + ) as mock_resolve_endpoint: + client.mock_operation(MockOpParam='mock-op-param-value') + + if call_should_include_ctx_param: + mock_resolve_endpoint.assert_called_once_with( + Region='us-east-1', + FooDynamicContextParamName='mock-op-param-value', + ) + else: + mock_resolve_endpoint.assert_called_once_with(Region='us-east-1')