Repository: boto/botocore
Pull request #2973 (2023-06-20 16:08:01)

Configured endpoint URL resolution
This PR implements the proposal for configuring endpoints per service:

https://github.com/aws/aws-sdk/pull/230

Adds a config provider to resolve the endpoint URL provided in an environment variable or shared configuration file. It resolves the endpoint in the following manner:

1. The value provided through the `endpoint_url` parameter provided to the client constructor.
2. The value provided by a service-specific environment variable.
3. The value provided by the global endpoint environment variable (`AWS_ENDPOINT_URL`).
4. The value provided by a service-specific parameter from a services definition section in the shared configuration file.
5. The value provided by the global parameter from a services definition section in the shared configuration file.
6. The value resolved when no configured endpoint URL is provided.

The endpoint config provider uses the client name (name used to instantiate a client object) for construction and add to the config value store. This uses multiple client/service name lookups to handle service name changes for backwards compatibility.

codecov-commenter: ## [Codecov](https://app.codecov.io/gh/boto/botocore/pull/2973?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=boto) Report
Patch coverage: **`96.00`**% and project coverage change: **`+0.02`** :tada:
> Comparison is base [(`97ba590`)](https://app.codecov.io/gh/boto/botocore/commit/97ba59024bdc313df6d18865f9ef233d24d60f95?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=boto) 93.29% compared to head [(`e43091c`)](https://app.codecov.io/gh/boto/botocore/pull/2973?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=boto) 93.31%.

:exclamation: Your organization is not using the GitHub App Integration. As a result you may experience degraded service beginning May 15th. Please [install the Github App Integration](https://github.com/apps/codecov) for your organization. [Read more](https://about.codecov.io/blog/codecov-is-updating-its-github-integration/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=boto).

<details><summary>Additional details and impacted files</summary>


```diff
@@             Coverage Diff             @@
##           develop    #2973      +/-   ##
===========================================
+ Coverage    93.29%   93.31%   +0.02%     
===========================================
  Files           64       64              
  Lines        13588    13665      +77     
===========================================
+ Hits         12677    12752      +75     
- Misses         911      913       +2     
```


| [Impacted Files](https://app.codecov.io/gh/boto/botocore/pull/2973?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=boto) | Coverage Δ | |
|---|---|---|
| [botocore/config.py](https://app.codecov.io/gh/boto/botocore/pull/2973?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=boto#diff-Ym90b2NvcmUvY29uZmlnLnB5) | `100.00% <ø> (ø)` | |
| [botocore/args.py](https://app.codecov.io/gh/boto/botocore/pull/2973?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=boto#diff-Ym90b2NvcmUvYXJncy5weQ==) | `99.56% <92.30%> (-0.44%)` | :arrow_down: |
| [botocore/configprovider.py](https://app.codecov.io/gh/boto/botocore/pull/2973?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=boto#diff-Ym90b2NvcmUvY29uZmlncHJvdmlkZXIucHk=) | `94.49% <95.31%> (+0.39%)` | :arrow_up: |
| [botocore/configloader.py](https://app.codecov.io/gh/boto/botocore/pull/2973?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=boto#diff-Ym90b2NvcmUvY29uZmlnbG9hZGVyLnB5) | `100.00% <100.00%> (+2.08%)` | :arrow_up: |
| [botocore/handlers.py](https://app.codecov.io/gh/boto/botocore/pull/2973?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=boto#diff-Ym90b2NvcmUvaGFuZGxlcnMucHk=) | `95.18% <100.00%> (ø)` | |
| [botocore/session.py](https://app.codecov.io/gh/boto/botocore/pull/2973?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=boto#diff-Ym90b2NvcmUvc2Vzc2lvbi5weQ==) | `96.91% <100.00%> (+0.02%)` | :arrow_up: |
| [botocore/utils.py](https://app.codecov.io/gh/boto/botocore/pull/2973?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=boto#diff-Ym90b2NvcmUvdXRpbHMucHk=) | `79.31% <100.00%> (-0.04%)` | :arrow_down: |


</details>

[:umbrella: View full report in Codecov by Sentry](https://app.codecov.io/gh/boto/botocore/pull/2973?src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=boto).   
:loudspeaker: Do you have feedback about the report comment? [Let us know in this issue](https://about.codecov.io/codecov-pr-comment-feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=boto).

larroy: Will this work for setting the S3 endpoint url?
A-Levin: when will you merge it?

Patch:
diff --git a/.changes/1.30.1.json b/.changes/1.30.1.json
deleted file mode 100644
index 454809135..000000000
--- a/.changes/1.30.1.json
+++ /dev/null
@@ -1,27 +0,0 @@
-[
-  {
-    "category": "``comprehendmedical``",
-    "description": "Update to Amazon Comprehend Medical documentation.",
-    "type": "api-change"
-  },
-  {
-    "category": "``connect``",
-    "description": "GetMetricDataV2 API: Channels filters do not count towards overall limitation of 100 filter values.",
-    "type": "api-change"
-  },
-  {
-    "category": "``kms``",
-    "description": "Added Dry Run Feature to cryptographic and cross-account mutating KMS APIs (14 in all). This feature allows users to test their permissions and parameters before making the actual API call.",
-    "type": "api-change"
-  },
-  {
-    "category": "``mgn``",
-    "description": "This release introduces the Global view feature and new Replication state APIs.",
-    "type": "api-change"
-  },
-  {
-    "category": "``securityhub``",
-    "description": "Documentation updates for AWS Security Hub",
-    "type": "api-change"
-  }
-]
\ No newline at end of file
diff --git a/.changes/next-release/bugfix-configprovider-46546.json b/.changes/next-release/bugfix-configprovider-46546.json
new file mode 100644
index 000000000..c4627e329
--- /dev/null
+++ b/.changes/next-release/bugfix-configprovider-46546.json
@@ -0,0 +1,5 @@
+{
+  "type": "bugfix",
+  "category": "configprovider",
+  "description": "Fix bug when deep copying config value store where overrides were not preserved"
+}
diff --git a/.changes/next-release/enhancement-configprovider-27540.json b/.changes/next-release/enhancement-configprovider-27540.json
new file mode 100644
index 000000000..b22279103
--- /dev/null
+++ b/.changes/next-release/enhancement-configprovider-27540.json
@@ -0,0 +1,5 @@
+{
+  "type": "enhancement",
+  "category": "configprovider",
+  "description": "Always use shallow copy of session config value store for clients"
+}
diff --git a/.changes/next-release/feature-configuration-3829.json b/.changes/next-release/feature-configuration-3829.json
new file mode 100644
index 000000000..ee690b9d2
--- /dev/null
+++ b/.changes/next-release/feature-configuration-3829.json
@@ -0,0 +1,5 @@
+{
+  "type": "feature",
+  "category": "configuration",
+  "description": "Configure the endpoint URL in the shared configuration file or via an environment variable for a specific AWS service or all AWS services."
+}
diff --git a/CHANGELOG.rst b/CHANGELOG.rst
index efe51b572..7b6256c18 100644
--- a/CHANGELOG.rst
+++ b/CHANGELOG.rst
@@ -2,16 +2,6 @@
 CHANGELOG
 =========
 
-1.30.1
-======
-
-* api-change:``comprehendmedical``: Update to Amazon Comprehend Medical documentation.
-* api-change:``connect``: GetMetricDataV2 API: Channels filters do not count towards overall limitation of 100 filter values.
-* api-change:``kms``: Added Dry Run Feature to cryptographic and cross-account mutating KMS APIs (14 in all). This feature allows users to test their permissions and parameters before making the actual API call.
-* api-change:``mgn``: This release introduces the Global view feature and new Replication state APIs.
-* api-change:``securityhub``: Documentation updates for AWS Security Hub
-
-
 1.30.0
 ======
 
diff --git a/botocore/__init__.py b/botocore/__init__.py
index aa346e87f..7e843c0bc 100644
--- a/botocore/__init__.py
+++ b/botocore/__init__.py
@@ -16,7 +16,7 @@ import logging
 import os
 import re
 
-__version__ = '1.30.1'
+__version__ = '1.30.0'
 
 
 class NullHandler(logging.Handler):
diff --git a/botocore/args.py b/botocore/args.py
index 7f4766bf7..73c8ab45e 100644
--- a/botocore/args.py
+++ b/botocore/args.py
@@ -115,7 +115,7 @@ class ClientArgsCreator:
         s3_config = final_args['s3_config']
         partition = endpoint_config['metadata'].get('partition', None)
         socket_options = final_args['socket_options']
-
+        configured_endpoint_url = final_args['configured_endpoint_url']
         signing_region = endpoint_config['signing_region']
         endpoint_region_name = endpoint_config['region_name']
 
@@ -160,7 +160,7 @@ class ClientArgsCreator:
             service_model,
             endpoint_region_name,
             region_name,
-            endpoint_url,
+            configured_endpoint_url,
             endpoint,
             is_secure,
             endpoint_bridge,
@@ -210,10 +210,16 @@ class ClientArgsCreator:
                 parameter_validation = ensure_boolean(raw_value)
 
         s3_config = self.compute_s3_config(client_config)
+
+        configured_endpoint_url = self._compute_configured_endpoint_url(
+            client_config=client_config,
+            endpoint_url=endpoint_url,
+        )
+
         endpoint_config = self._compute_endpoint_config(
             service_name=service_name,
             region_name=region_name,
-            endpoint_url=endpoint_url,
+            endpoint_url=configured_endpoint_url,
             is_secure=is_secure,
             endpoint_bridge=endpoint_bridge,
             s3_config=s3_config,
@@ -270,6 +276,7 @@ class ClientArgsCreator:
         return {
             'service_name': service_name,
             'parameter_validation': parameter_validation,
+            'configured_endpoint_url': configured_endpoint_url,
             'endpoint_config': endpoint_config,
             'protocol': protocol,
             'config_kwargs': config_kwargs,
@@ -279,6 +286,27 @@ class ClientArgsCreator:
             ),
         }
 
+    def _compute_configured_endpoint_url(self, client_config, endpoint_url):
+        if endpoint_url is not None:
+            return endpoint_url
+
+        if self._ignore_configured_endpoint_urls(client_config):
+            logger.debug("Ignoring configured endpoint URLs.")
+            return endpoint_url
+
+        return self._config_store.get_config_variable('endpoint_url')
+
+    def _ignore_configured_endpoint_urls(self, client_config):
+        if (
+            client_config
+            and client_config.ignore_configured_endpoint_urls is not None
+        ):
+            return client_config.ignore_configured_endpoint_urls
+
+        return self._config_store.get_config_variable(
+            'ignore_configured_endpoint_urls'
+        )
+
     def compute_s3_config(self, client_config):
         s3_configuration = self._config_store.get_config_variable('s3')
 
diff --git a/botocore/config.py b/botocore/config.py
index 6ce25f8b6..be3a475fa 100644
--- a/botocore/config.py
+++ b/botocore/config.py
@@ -194,6 +194,13 @@ class Config:
 
         Defaults to None.
 
+    :type ignore_configured_endpoint_urls: bool
+    :param ignore_configured_endpoint_urls: Setting to True disables use
+        of endpoint URLs provided via environment variables and
+        the shared configuration file.
+
+        Defaults to None.
+
     :type tcp_keepalive: bool
     :param tcp_keepalive: Enables the TCP Keep-Alive socket option used when
         creating new connections if set to True.
@@ -221,6 +228,7 @@ class Config:
             ('endpoint_discovery_enabled', None),
             ('use_dualstack_endpoint', None),
             ('use_fips_endpoint', None),
+            ('ignore_configured_endpoint_urls', None),
             ('defaults_mode', None),
             ('tcp_keepalive', None),
         ]
diff --git a/botocore/configloader.py b/botocore/configloader.py
index 245d9d8eb..0b6c82bca 100644
--- a/botocore/configloader.py
+++ b/botocore/configloader.py
@@ -200,6 +200,17 @@ def _parse_nested(config_value):
     return parsed
 
 
+def _parse_section(key, values):
+    result = {}
+    try:
+        parts = shlex.split(key)
+    except ValueError:
+        return result
+    if len(parts) == 2:
+        result[parts[1]] = values
+    return result
+
+
 def build_profile_map(parsed_ini_config):
     """Convert the parsed INI config into a profile map.
 
@@ -254,22 +265,15 @@ def build_profile_map(parsed_ini_config):
     parsed_config = copy.deepcopy(parsed_ini_config)
     profiles = {}
     sso_sessions = {}
+    services = {}
     final_config = {}
     for key, values in parsed_config.items():
         if key.startswith("profile"):
-            try:
-                parts = shlex.split(key)
-            except ValueError:
-                continue
-            if len(parts) == 2:
-                profiles[parts[1]] = values
+            profiles.update(_parse_section(key, values))
         elif key.startswith("sso-session"):
-            try:
-                parts = shlex.split(key)
-            except ValueError:
-                continue
-            if len(parts) == 2:
-                sso_sessions[parts[1]] = values
+            sso_sessions.update(_parse_section(key, values))
+        elif key.startswith("services"):
+            services.update(_parse_section(key, values))
         elif key == 'default':
             # default section is special and is considered a profile
             # name but we don't require you use 'profile "default"'
@@ -279,4 +283,5 @@ def build_profile_map(parsed_ini_config):
             final_config[key] = values
     final_config['profiles'] = profiles
     final_config['sso_sessions'] = sso_sessions
+    final_config['services'] = services
     return final_config
diff --git a/botocore/configprovider.py b/botocore/configprovider.py
index e2ebd5efe..d7b2e19de 100644
--- a/botocore/configprovider.py
+++ b/botocore/configprovider.py
@@ -18,6 +18,7 @@ import logging
 import os
 
 from botocore import utils
+from botocore.exceptions import InvalidConfigError
 
 logger = logging.getLogger(__name__)
 
@@ -108,6 +109,12 @@ BOTOCORE_DEFAUT_SESSION_VARIABLES = {
         None,
         utils.ensure_boolean,
     ),
+    'ignore_configured_endpoint_urls': (
+        'ignore_configured_endpoint_urls',
+        'AWS_IGNORE_CONFIGURED_ENDPOINT_URLS',
+        None,
+        utils.ensure_boolean,
+    ),
     'parameter_validation': ('parameter_validation', None, True, None),
     # Client side monitoring configurations.
     # Note: These configurations are considered internal to botocore.
@@ -403,7 +410,18 @@ class ConfigValueStore:
                 self.set_config_provider(logical_name, provider)
 
     def __deepcopy__(self, memo):
-        return ConfigValueStore(copy.deepcopy(self._mapping, memo))
+        config_store = ConfigValueStore(copy.deepcopy(self._mapping, memo))
+        for logical_name, override_value in self._overrides.items():
+            config_store.set_config_variable(logical_name, override_value)
+
+        return config_store
+
+    def __copy__(self):
+        config_store = ConfigValueStore(copy.copy(self._mapping))
+        for logical_name, override_value in self._overrides.items():
+            config_store.set_config_variable(logical_name, override_value)
+
+        return config_store
 
     def get_config_variable(self, logical_name):
         """
@@ -543,24 +561,28 @@ class SmartDefaultsConfigStoreFactory:
         return 'standard'
 
     def _update_provider(self, config_store, variable, value):
-        provider = config_store.get_config_provider(variable)
+        original_provider = config_store.get_config_provider(variable)
         default_provider = ConstantProvider(value)
-        if isinstance(provider, ChainProvider):
-            provider.set_default_provider(default_provider)
-            return
-        elif isinstance(provider, BaseProvider):
+        if isinstance(original_provider, ChainProvider):
+            chain_provider_copy = copy.deepcopy(original_provider)
+            chain_provider_copy.set_default_provider(default_provider)
+            default_provider = chain_provider_copy
+        elif isinstance(original_provider, BaseProvider):
             default_provider = ChainProvider(
-                providers=[provider, default_provider]
+                providers=[original_provider, default_provider]
             )
         config_store.set_config_provider(variable, default_provider)
 
     def _update_section_provider(
         self, config_store, section_name, variable, value
     ):
-        section_provider = config_store.get_config_provider(section_name)
-        section_provider.set_default_provider(
+        section_provider_copy = copy.deepcopy(
+            config_store.get_config_provider(section_name)
+        )
+        section_provider_copy.set_default_provider(
             variable, ConstantProvider(value)
         )
+        config_store.set_config_provider(section_name, section_provider_copy)
 
     def _set_retryMode(self, config_store, value):
         self._update_provider(config_store, 'retry_mode', value)
@@ -837,3 +859,142 @@ class ConstantProvider(BaseProvider):
 
     def __repr__(self):
         return 'ConstantProvider(value=%s)' % self._value
+
+
+class ConfiguredEndpointProvider(BaseProvider):
+    """Lookup an endpoint URL from environment variable or shared config file.
+
+    NOTE: This class is considered private and is subject to abrupt breaking
+    changes or removal without prior announcement. Please do not use it
+    directly.
+    """
+
+    _ENDPOINT_URL_LOOKUP_ORDER = [
+        'environment_service',
+        'environment_global',
+        'config_service',
+        'config_global',
+    ]
+
+    def __init__(
+        self,
+        full_config,
+        scoped_config,
+        client_name,
+        environ=None,
+    ):
+        """Initialize a ConfiguredEndpointProviderChain.
+
+        :type full_config: dict
+        :param full_config: This is the dict representing the full
+            configuration file.
+
+        :type scoped_config: dict
+        :param scoped_config: This is the dict representing the configuration
+            for the current profile for the session.
+
+        :type client_name: str
+        :param client_name: The name used to instantiate a client using
+            botocore.session.Session.create_client.
+
+        :type environ: dict
+        :param environ: A mapping to use for environment variables. If this
+            is not provided it will default to use os.environ.
+        """
+        self._full_config = full_config
+        self._scoped_config = scoped_config
+        self._client_name = client_name
+        self._transformed_service_id = self._get_snake_case_service_id(
+            self._client_name
+        )
+        if environ is None:
+            environ = os.environ
+        self._environ = environ
+
+    def provide(self):
+        """Lookup the configured endpoint URL.
+
+        The order is:
+
+        1. The value provided by a service-specific environment variable.
+        2. The value provided by the global endpoint environment variable
+           (AWS_ENDPOINT_URL).
+        3. The value provided by a service-specific parameter from a services
+           definition section in the shared configuration file.
+        4. The value provided by the global parameter from a services
+           definition section in the shared configuration file.
+        """
+        for location in self._ENDPOINT_URL_LOOKUP_ORDER:
+            logger.debug(
+                'Looking for endpoint for %s via: %s',
+                self._client_name,
+                location,
+            )
+
+            endpoint_url = getattr(self, f'_get_endpoint_url_{location}')()
+
+            if endpoint_url:
+                logger.info(
+                    'Found endpoint for %s via: %s.',
+                    self._client_name,
+                    location,
+                )
+                return endpoint_url
+
+        logger.debug('No configured endpoint found.')
+        return None
+
+    def _get_snake_case_service_id(self, client_name):
+        # Get the service ID without loading the service data file, accounting
+        # for any aliases and standardizing the names with hyphens.
+        client_name = utils.SERVICE_NAME_ALIASES.get(client_name, client_name)
+        hyphenized_service_id = (
+            utils.CLIENT_NAME_TO_HYPHENIZED_SERVICE_ID_OVERRIDES.get(
+                client_name, client_name
+            )
+        )
+        return hyphenized_service_id.replace('-', '_')
+
+    def _get_service_env_var_name(self):
+        transformed_service_id_env = self._transformed_service_id.upper()
+        return f'AWS_ENDPOINT_URL_{transformed_service_id_env}'
+
+    def _get_services_config(self):
+        if 'services' not in self._scoped_config:
+            return {}
+
+        section_name = self._scoped_config['services']
+        services_section = self._full_config.get('services', {}).get(
+            section_name
+        )
+
+        if not services_section:
+            error_msg = (
+                f'The profile is configured to use the services '
+                f'section but the "{section_name}" services '
+                f'configuration does not exist.'
+            )
+            raise InvalidConfigError(error_msg=error_msg)
+
+        return services_section
+
+    def _get_endpoint_url_config_service(self):
+        snakecase_service_id = self._transformed_service_id.lower()
+        return (
+            self._get_services_config()
+            .get(snakecase_service_id, {})
+            .get('endpoint_url')
+        )
+
+    def _get_endpoint_url_config_global(self):
+        return self._scoped_config.get('endpoint_url')
+
+    def _get_endpoint_url_environment_service(self):
+        return EnvironmentProvider(
+            name=self._get_service_env_var_name(), env=self._environ
+        ).provide()
+
+    def _get_endpoint_url_environment_global(self):
+        return EnvironmentProvider(
+            name='AWS_ENDPOINT_URL', env=self._environ
+        ).provide()
diff --git a/botocore/data/comprehendmedical/2018-10-30/service-2.json b/botocore/data/comprehendmedical/2018-10-30/service-2.json
index 1f23ff490..8ed7cac3c 100644
--- a/botocore/data/comprehendmedical/2018-10-30/service-2.json
+++ b/botocore/data/comprehendmedical/2018-10-30/service-2.json
@@ -110,7 +110,7 @@
         {"shape":"InvalidEncodingException"},
         {"shape":"TextSizeLimitExceededException"}
       ],
-      "documentation":"<p>The <code>DetectEntities</code> operation is deprecated. You should use the <a>DetectEntitiesV2</a> operation instead.</p> <p>Inspects the clinical text for a variety of medical entities and returns specific information about them such as entity category, location, and confidence score on that information.</p>",
+      "documentation":"<p>The <code>DetectEntities</code> operation is deprecated. You should use the <a>DetectEntitiesV2</a> operation instead.</p> <p> Inspects the clinical text for a variety of medical entities and returns specific information about them such as entity category, location, and confidence score on that information .</p>",
       "deprecated":true,
       "deprecatedMessage":"This operation is deprecated, use DetectEntitiesV2 instead."
     },
@@ -148,7 +148,7 @@
         {"shape":"InvalidEncodingException"},
         {"shape":"TextSizeLimitExceededException"}
       ],
-      "documentation":"<p>Inspects the clinical text for protected health information (PHI) entities and returns the entity category, location, and confidence score for each entity. Amazon Comprehend Medical only detects entities in English language texts.</p>"
+      "documentation":"<p> Inspects the clinical text for protected health information (PHI) entities and returns the entity category, location, and confidence score for each entity. Amazon Comprehend Medical only detects entities in English language texts.</p>"
     },
     "InferICD10CM":{
       "name":"InferICD10CM",
@@ -250,7 +250,7 @@
         {"shape":"TooManyRequestsException"},
         {"shape":"InternalServerException"}
       ],
-      "documentation":"<p>Gets a list of protected health information (PHI) detection jobs you have submitted.</p>"
+      "documentation":"<p>Gets a list of protected health information (PHI) detection jobs that you have submitted.</p>"
     },
     "ListRxNormInferenceJobs":{
       "name":"ListRxNormInferenceJobs",
@@ -452,11 +452,11 @@
         },
         "Score":{
           "shape":"Float",
-          "documentation":"<p> The level of confidence that Amazon Comprehend Medical has that the segment of text is correctly recognized as an attribute. </p>"
+          "documentation":"<p> The level of confidence that Comprehend Medical; has that the segment of text is correctly recognized as an attribute. </p>"
         },
         "RelationshipScore":{
           "shape":"Float",
-          "documentation":"<p> The level of confidence that Amazon Comprehend Medical has that this attribute is correctly related to this entity. </p>"
+          "documentation":"<p> The level of confidence that Comprehend Medical; has that this attribute is correctly related to this entity. </p>"
         },
         "RelationshipType":{
           "shape":"RelationshipType",
@@ -517,7 +517,7 @@
       "members":{
         "OriginalTextCharacters":{
           "shape":"Integer",
-          "documentation":"<p> The number of characters present in the input text document as processed by Amazon Comprehend Medical. </p>"
+          "documentation":"<p> The number of characters present in the input text document as processed by Comprehend Medical. </p>"
         }
       },
       "documentation":"<p> The number of characters in the input text to be analyzed. </p>"
@@ -595,7 +595,7 @@
         },
         "DataAccessRoleArn":{
           "shape":"IamRoleArn",
-          "documentation":"<p>The Amazon Resource Name (ARN) that gives Amazon Comprehend Medical read access to your input data.</p>"
+          "documentation":"<p>The Amazon Resource Name (ARN) that gives Comprehend Medical; read access to your input data.</p>"
         },
         "ManifestFilePath":{
           "shape":"ManifestFilePath",
@@ -622,7 +622,7 @@
       "members":{
         "JobId":{
           "shape":"JobId",
-          "documentation":"<p>The identifier that Amazon Comprehend Medical generated for the job. The <code>StartEntitiesDetectionV2Job</code> operation returns this identifier in its response.</p>"
+          "documentation":"<p>The identifier that Comprehend Medical; generated for the job. The <code>StartEntitiesDetectionV2Job</code> operation returns this identifier in its response.</p>"
         }
       }
     },
@@ -660,7 +660,7 @@
       "members":{
         "JobId":{
           "shape":"JobId",
-          "documentation":"<p>The identifier that Amazon Comprehend Medical generated for the job. The <code>StartPHIDetectionJob</code> operation returns this identifier in its response.</p>"
+          "documentation":"<p>The identifier that Comprehend Medical; generated for the job. The <code>StartPHIDetectionJob</code> operation returns this identifier in its response.</p>"
         }
       }
     },
@@ -714,7 +714,7 @@
       "members":{
         "Text":{
           "shape":"BoundedLengthString",
-          "documentation":"<p> A UTF-8 text string containing the clinical content being examined for entities.</p>"
+          "documentation":"<p> A UTF-8 text string containing the clinical content being examined for entities. Each string must contain fewer than 20,000 bytes of characters.</p>"
         }
       }
     },
@@ -727,15 +727,15 @@
       "members":{
         "Entities":{
           "shape":"EntityList",
-          "documentation":"<p>The collection of medical entities extracted from the input text and their associated information. For each entity, the response provides the entity text, the entity category, where the entity text begins and ends, and the level of confidence that Amazon Comprehend Medical has in the detection and analysis. Attributes and traits of the entity are also returned.</p>"
+          "documentation":"<p> The collection of medical entities extracted from the input text and their associated information. For each entity, the response provides the entity text, the entity category, where the entity text begins and ends, and the level of confidence that Comprehend Medical; has in the detection and analysis. Attributes and traits of the entity are also returned.</p>"
         },
         "UnmappedAttributes":{
           "shape":"UnmappedAttributeList",
-          "documentation":"<p>Attributes extracted from the input text that we were unable to relate to an entity.</p>"
+          "documentation":"<p> Attributes extracted from the input text that we were unable to relate to an entity.</p>"
         },
         "PaginationToken":{
           "shape":"String",
-          "documentation":"<p>If the result of the previous request to <code>DetectEntities</code> was truncated, include the <code>PaginationToken</code> to fetch the next page of entities.</p>"
+          "documentation":"<p> If the result of the previous request to <code>DetectEntities</code> was truncated, include the <code>PaginationToken</code> to fetch the next page of entities.</p>"
         },
         "ModelVersion":{
           "shape":"String",
@@ -749,7 +749,7 @@
       "members":{
         "Text":{
           "shape":"BoundedLengthString",
-          "documentation":"<p>A UTF-8 string containing the clinical content being examined for entities.</p>"
+          "documentation":"<p>A UTF-8 string containing the clinical content being examined for entities. Each string must contain fewer than 20,000 bytes of characters.</p>"
         }
       }
     },
@@ -784,7 +784,7 @@
       "members":{
         "Text":{
           "shape":"BoundedLengthString",
-          "documentation":"<p>A UTF-8 text string containing the clinical content being examined for PHI entities.</p>"
+          "documentation":"<p> A UTF-8 text string containing the clinical content being examined for PHI entities. Each string must contain fewer than 20,000 bytes of characters.</p>"
         }
       }
     },
@@ -797,11 +797,11 @@
       "members":{
         "Entities":{
           "shape":"EntityList",
-          "documentation":"<p>The collection of PHI entities extracted from the input text and their associated information. For each entity, the response provides the entity text, the entity category, where the entity text begins and ends, and the level of confidence that Amazon Comprehend Medical has in its detection.</p>"
+          "documentation":"<p> The collection of PHI entities extracted from the input text and their associated information. For each entity, the response provides the entity text, the entity category, where the entity text begins and ends, and the level of confidence that Comprehend Medical; has in its detection. </p>"
         },
         "PaginationToken":{
           "shape":"String",
-          "documentation":"<p>If the result of the previous request to <code>DetectPHI</code> was truncated, include the <code>PaginationToken</code> to fetch the next page of PHI entities. </p>"
+          "documentation":"<p> If the result of the previous request to <code>DetectPHI</code> was truncated, include the <code>PaginationToken</code> to fetch the next page of PHI entities. </p>"
         },
         "ModelVersion":{
           "shape":"String",
@@ -826,7 +826,7 @@
         },
         "Score":{
           "shape":"Float",
-          "documentation":"<p>The level of confidence that Amazon Comprehend Medical has in the accuracy of the detection.</p>"
+          "documentation":"<p>The level of confidence that Comprehend Medical; has in the accuracy of the detection.</p>"
         },
         "Text":{
           "shape":"String",
@@ -1080,7 +1080,7 @@
         },
         "Score":{
           "shape":"Float",
-          "documentation":"<p>The level of confidence that Amazon Comprehend Medical has that the segment of text is correctly recognized as a trait.</p>"
+          "documentation":"<p>The level of confidence that Comprehend Medical; has that the segment of text is correctly recognized as a trait.</p>"
         }
       },
       "documentation":"<p>Contextual information for the entity. The traits recognized by InferICD10CM are <code>DIAGNOSIS</code>, <code>SIGN</code>, <code>SYMPTOM</code>, and <code>NEGATION</code>.</p>"
@@ -1113,7 +1113,7 @@
       "members":{
         "Text":{
           "shape":"OntologyLinkingBoundedLengthString",
-          "documentation":"<p>The input text used for analysis.</p>"
+          "documentation":"<p>The input text used for analysis. The input for InferICD10CM is a string from 1 to 10000 characters.</p>"
         }
       }
     },
@@ -1141,7 +1141,7 @@
       "members":{
         "Text":{
           "shape":"OntologyLinkingBoundedLengthString",
-          "documentation":"<p>The input text used for analysis.</p>"
+          "documentation":"<p>The input text used for analysis. The input for InferRxNorm is a string from 1 to 10000 characters.</p>"
         }
       }
     },
@@ -1169,7 +1169,7 @@
       "members":{
         "Text":{
           "shape":"OntologyLinkingBoundedLengthString",
-          "documentation":"<p>The input text to be analyzed using InferSNOMEDCT.</p>"
+          "documentation":"<p> The input text to be analyzed using InferSNOMEDCT. The text should be a string with 1 to 10000 characters. </p>"
         }
       }
     },
@@ -1179,7 +1179,7 @@
       "members":{
         "Entities":{
           "shape":"SNOMEDCTEntityList",
-          "documentation":"<p> The collection of medical concept entities extracted from the input text and their associated information. For each entity, the response provides the entity text, the entity category, where the entity text begins and ends, and the level of confidence that Amazon Comprehend Medical has in the detection and analysis. Attributes and traits of the entity are also returned. </p>"
+          "documentation":"<p> The collection of medical concept entities extracted from the input text and their associated information. For each entity, the response provides the entity text, the entity category, where the entity text begins and ends, and the level of confidence that Comprehend Medical has in the detection and analysis. Attributes and traits of the entity are also returned. </p>"
         },
         "PaginationToken":{
           "shape":"String",
@@ -1205,7 +1205,7 @@
       "members":{
         "S3Bucket":{
           "shape":"S3Bucket",
-          "documentation":"<p>The URI of the S3 bucket that contains the input data. The bucket must be in the same region as the API endpoint that you are calling.</p>"
+          "documentation":"<p>The URI of the S3 bucket that contains the input data. The bucket must be in the same region as the API endpoint that you are calling.</p> <p>Each file in the document collection must be less than 40 KB. You can store a maximum of 30 GB in the bucket.</p>"
         },
         "S3Key":{
           "shape":"S3Key",
@@ -1447,7 +1447,7 @@
         },
         "S3Key":{
           "shape":"S3Key",
-          "documentation":"<p>The path to the output data files in the S3 bucket. Amazon Comprehend Medical creates an output directory using the job ID so that the output from one job does not overwrite the output of another.</p>"
+          "documentation":"<p>The path to the output data files in the S3 bucket. Comprehend Medical; creates an output directory using the job ID so that the output from one job does not overwrite the output of another.</p>"
         }
       },
       "documentation":"<p>The output properties for a detection job.</p>"
@@ -1496,7 +1496,7 @@
         },
         "Score":{
           "shape":"Float",
-          "documentation":"<p>The level of confidence that Amazon Comprehend Medical has that the segment of text is correctly recognized as an attribute.</p>"
+          "documentation":"<p>The level of confidence that Comprehend Medical has that the segment of text is correctly recognized as an attribute.</p>"
         },
         "RelationshipScore":{
           "shape":"Float",
@@ -1600,11 +1600,11 @@
         },
         "Traits":{
           "shape":"RxNormTraitList",
-          "documentation":"<p>Contextual information for the entity.</p>"
+          "documentation":"<p> Contextual information for the entity.</p>"
         },
         "RxNormConcepts":{
           "shape":"RxNormConceptList",
-          "documentation":"<p>The RxNorm concepts that the entity could refer to, along with a score indicating the likelihood of the match.</p>"
+          "documentation":"<p> The RxNorm concepts that the entity could refer to, along with a score indicating the likelihood of the match.</p>"
         }
       },
       "documentation":"<p>The collection of medical entities extracted from the input text and their associated information. For each entity, the response provides the entity text, the entity category, where the entity text begins and ends, and the level of confidence that Amazon Comprehend Medical has in the detection and analysis. Attributes and traits of the entity are also returned. </p>"
@@ -1673,11 +1673,11 @@
         },
         "Score":{
           "shape":"Float",
-          "documentation":"<p> The level of confidence that Amazon Comprehend Medical has that the segment of text is correctly recognized as an attribute. </p>"
+          "documentation":"<p> The level of confidence that Comprehend Medical has that the segment of text is correctly recognized as an attribute. </p>"
         },
         "RelationshipScore":{
           "shape":"Float",
-          "documentation":"<p> The level of confidence that Amazon Comprehend Medical has that this attribute is correctly related to this entity. </p>"
+          "documentation":"<p> The level of confidence that Comprehend Medical has that this attribute is correctly related to this entity. </p>"
         },
         "RelationshipType":{
           "shape":"SNOMEDCTRelationshipType",
@@ -1738,7 +1738,7 @@
         },
         "Score":{
           "shape":"Float",
-          "documentation":"<p> The level of confidence Amazon Comprehend Medical has that the entity should be linked to the identified SNOMED-CT concept. </p>"
+          "documentation":"<p> The level of confidence Comprehend Medical has that the entity should be linked to the identified SNOMED-CT concept. </p>"
         }
       },
       "documentation":"<p> The SNOMED-CT concepts that the entity could refer to, along with a score indicating the likelihood of the match. </p>"
@@ -1786,7 +1786,7 @@
         },
         "Score":{
           "shape":"Float",
-          "documentation":"<p> The level of confidence that Amazon Comprehend Medical has in the accuracy of the detected entity. </p>"
+          "documentation":"<p> The level of confidence that Comprehend Medical has in the accuracy of the detected entity. </p>"
         },
         "BeginOffset":{
           "shape":"Integer",
@@ -1809,7 +1809,7 @@
           "documentation":"<p> The SNOMED concepts that the entity could refer to, along with a score indicating the likelihood of the match. </p>"
         }
       },
-      "documentation":"<p> The collection of medical entities extracted from the input text and their associated information. For each entity, the response provides the entity text, the entity category, where the entity text begins and ends, and the level of confidence that Amazon Comprehend Medical has in the detection and analysis. Attributes and traits of the entity are also returned. </p>"
+      "documentation":"<p> The collection of medical entities extracted from the input text and their associated information. For each entity, the response provides the entity text, the entity category, where the entity text begins and ends, and the level of confidence that Comprehend Medical has in the detection and analysis. Attributes and traits of the entity are also returned. </p>"
     },
     "SNOMEDCTEntityCategory":{
       "type":"string",
@@ -1853,7 +1853,7 @@
         },
         "Score":{
           "shape":"Float",
-          "documentation":"<p> The level of confidence that Amazon Comprehend Medical has in the accuracy of a detected trait. </p>"
+          "documentation":"<p> The level of confidence that Comprehend Medical has in the accuracy of a detected trait. </p>"
         }
       },
       "documentation":"<p> Contextual information for an entity. </p>"
@@ -1881,7 +1881,7 @@
       "members":{
         "Message":{"shape":"String"}
       },
-      "documentation":"<p> The Amazon Comprehend Medical service is temporarily unavailable. Please wait and then retry your request. </p>",
+      "documentation":"<p> The Comprehend Medical; service is temporarily unavailable. Please wait and then retry your request. </p>",
       "exception":true
     },
     "StartEntitiesDetectionV2JobRequest":{
@@ -1903,7 +1903,7 @@
         },
         "DataAccessRoleArn":{
           "shape":"IamRoleArn",
-          "documentation":"<p>The Amazon Resource Name (ARN) of the AWS Identity and Access Management (IAM) role that grants Amazon Comprehend Medical read access to your input data. For more information, see <a href=\"https://docs.aws.amazon.com/comprehend/latest/dg/access-control-managing-permissions-med.html#auth-role-permissions-med\">Role-Based Permissions Required for Asynchronous Operations</a>.</p>"
+          "documentation":"<p>The Amazon Resource Name (ARN) of the AWS Identity and Access Management (IAM) role that grants Comprehend Medical; read access to your input data. For more information, see <a href=\"https://docs.aws.amazon.com/comprehend/latest/dg/access-control-managing-permissions-med.html#auth-role-permissions-med\"> Role-Based Permissions Required for Asynchronous Operations</a>.</p>"
         },
         "JobName":{
           "shape":"JobName",
@@ -1911,7 +1911,7 @@
         },
         "ClientRequestToken":{
           "shape":"ClientRequestTokenString",
-          "documentation":"<p>A unique identifier for the request. If you don't set the client request token, Amazon Comprehend Medical generates one for you.</p>",
+          "documentation":"<p>A unique identifier for the request. If you don't set the client request token, Comprehend Medical; generates one for you.</p>",
           "idempotencyToken":true
         },
         "KMSKey":{
@@ -1920,7 +1920,7 @@
         },
         "LanguageCode":{
           "shape":"LanguageCode",
-          "documentation":"<p>The language of the input documents. All documents must be in the same language. Amazon Comprehend Medical processes files in US English (en).</p>"
+          "documentation":"<p>The language of the input documents. All documents must be in the same language. Comprehend Medical; processes files in US English (en).</p>"
         }
       }
     },
@@ -1952,7 +1952,7 @@
         },
         "DataAccessRoleArn":{
           "shape":"IamRoleArn",
-          "documentation":"<p>The Amazon Resource Name (ARN) of the AWS Identity and Access Management (IAM) role that grants Amazon Comprehend Medical read access to your input data. For more information, see <a href=\"https://docs.aws.amazon.com/comprehend/latest/dg/access-control-managing-permissions-med.html#auth-role-permissions-med\"> Role-Based Permissions Required for Asynchronous Operations</a>.</p>"
+          "documentation":"<p>The Amazon Resource Name (ARN) of the AWS Identity and Access Management (IAM) role that grants Comprehend Medical; read access to your input data. For more information, see <a href=\"https://docs.aws.amazon.com/comprehend/latest/dg/access-control-managing-permissions-med.html#auth-role-permissions-med\"> Role-Based Permissions Required for Asynchronous Operations</a>.</p>"
         },
         "JobName":{
           "shape":"JobName",
@@ -1960,7 +1960,7 @@
         },
         "ClientRequestToken":{
           "shape":"ClientRequestTokenString",
-          "documentation":"<p>A unique identifier for the request. If you don't set the client request token, Amazon Comprehend Medical generates one.</p>",
+          "documentation":"<p>A unique identifier for the request. If you don't set the client request token, Comprehend Medical; generates one.</p>",
           "idempotencyToken":true
         },
         "KMSKey":{
@@ -2001,7 +2001,7 @@
         },
         "DataAccessRoleArn":{
           "shape":"IamRoleArn",
-          "documentation":"<p>The Amazon Resource Name (ARN) of the AWS Identity and Access Management (IAM) role that grants Amazon Comprehend Medical read access to your input data. For more information, see <a href=\"https://docs.aws.amazon.com/comprehend/latest/dg/access-control-managing-permissions-med.html#auth-role-permissions-med\"> Role-Based Permissions Required for Asynchronous Operations</a>.</p>"
+          "documentation":"<p>The Amazon Resource Name (ARN) of the AWS Identity and Access Management (IAM) role that grants Comprehend Medical; read access to your input data. For more information, see <a href=\"https://docs.aws.amazon.com/comprehend/latest/dg/access-control-managing-permissions-med.html#auth-role-permissions-med\"> Role-Based Permissions Required for Asynchronous Operations</a>.</p>"
         },
         "JobName":{
           "shape":"JobName",
@@ -2009,7 +2009,7 @@
         },
         "ClientRequestToken":{
           "shape":"ClientRequestTokenString",
-          "documentation":"<p>A unique identifier for the request. If you don't set the client request token, Amazon Comprehend Medical generates one.</p>",
+          "documentation":"<p>A unique identifier for the request. If you don't set the client request token, Comprehend Medical; generates one.</p>",
           "idempotencyToken":true
         },
         "KMSKey":{
@@ -2050,7 +2050,7 @@
         },
         "DataAccessRoleArn":{
           "shape":"IamRoleArn",
-          "documentation":"<p>The Amazon Resource Name (ARN) of the AWS Identity and Access Management (IAM) role that grants Amazon Comprehend Medical read access to your input data. For more information, see <a href=\"https://docs.aws.amazon.com/comprehend/latest/dg/access-control-managing-permissions-med.html#auth-role-permissions-med\"> Role-Based Permissions Required for Asynchronous Operations</a>.</p>"
+          "documentation":"<p>The Amazon Resource Name (ARN) of the AWS Identity and Access Management (IAM) role that grants Comprehend Medical; read access to your input data. For more information, see <a href=\"https://docs.aws.amazon.com/comprehend/latest/dg/access-control-managing-permissions-med.html#auth-role-permissions-med\"> Role-Based Permissions Required for Asynchronous Operations</a>.</p>"
         },
         "JobName":{
           "shape":"JobName",
@@ -2058,7 +2058,7 @@
         },
         "ClientRequestToken":{
           "shape":"ClientRequestTokenString",
-          "documentation":"<p>A unique identifier for the request. If you don't set the client request token, Amazon Comprehend Medical generates one.</p>",
+          "documentation":"<p>A unique identifier for the request. If you don't set the client request token, Comprehend Medical; generates one.</p>",
           "idempotencyToken":true
         },
         "KMSKey":{
@@ -2248,7 +2248,7 @@
         },
         "Score":{
           "shape":"Float",
-          "documentation":"<p> The level of confidence that Amazon Comprehend Medical has in the accuracy of this trait.</p>"
+          "documentation":"<p> The level of confidence that Comprehend Medical; has in the accuracy of this trait.</p>"
         }
       },
       "documentation":"<p> Provides contextual information about the extracted entity. </p>"
@@ -2269,7 +2269,7 @@
           "documentation":"<p> The specific attribute that has been extracted but not mapped to an entity. </p>"
         }
       },
-      "documentation":"<p>An attribute that was extracted, but Amazon Comprehend Medical was unable to relate to an entity. </p>"
+      "documentation":"<p> An attribute that was extracted, but Comprehend Medical; was unable to relate to an entity. </p>"
     },
     "UnmappedAttributeList":{
       "type":"list",
@@ -2284,5 +2284,5 @@
       "exception":true
     }
   },
-  "documentation":"<p>Amazon Comprehend Medical extracts structured information from unstructured clinical text. Use these actions to gain insight in your documents. Amazon Comprehend Medical only detects entities in English language texts. Amazon Comprehend Medical places limits on the sizes of files allowed for different API operations. To learn more, see <a href=\"https://docs.aws.amazon.com/comprehend-medical/latest/dev/comprehendmedical-quotas.html\">Guidelines and quotas</a> in the <i>Amazon Comprehend Medical Developer Guide</i>.</p>"
+  "documentation":"<p> Comprehend Medical; extracts structured information from unstructured clinical text. Use these actions to gain insight in your documents. </p>"
 }
diff --git a/botocore/data/connect/2017-08-08/service-2.json b/botocore/data/connect/2017-08-08/service-2.json
index 37cc6a6c0..effb497b0 100644
--- a/botocore/data/connect/2017-08-08/service-2.json
+++ b/botocore/data/connect/2017-08-08/service-2.json
@@ -408,7 +408,7 @@
         {"shape":"ThrottlingException"},
         {"shape":"InternalServiceException"}
       ],
-      "documentation":"<p>This API is in preview release for Amazon Connect and is subject to change.</p> <p>Creates a new queue for the specified Amazon Connect instance.</p> <important> <p>If the number being used in the input is claimed to a traffic distribution group, and you are calling this API using an instance in the Amazon Web Services Region where the traffic distribution group was created, you can use either a full phone number ARN or UUID value for the <code>OutboundCallerIdNumberId</code> value of the <a href=\"https://docs.aws.amazon.com/connect/latest/APIReference/API_OutboundCallerConfig\">OutboundCallerConfig</a> request body parameter. However, if the number is claimed to a traffic distribution group and you are calling this API using an instance in the alternate Amazon Web Services Region associated with the traffic distribution group, you must provide a full phone number ARN. If a UUID is provided in this scenario, you will receive a <code>ResourceNotFoundException</code>.</p> <p>Only use the phone number ARN format that doesn't contain <code>instance</code> in the path, for example, <code>arn:aws:connect:us-east-1:1234567890:phone-number/uuid</code>. This is the same ARN format that is returned when you call the <a href=\"https://docs.aws.amazon.com/connect/latest/APIReference/API_ListPhoneNumbersV2.html\">ListPhoneNumbersV2</a> API.</p> </important>"
+      "documentation":"<p>This API is in preview release for Amazon Connect and is subject to change.</p> <p>Creates a new queue for the specified Amazon Connect instance.</p> <important> <p>If the number being used in the input is claimed to a traffic distribution group, and you are calling this API using an instance in the Amazon Web Services Region where the traffic distribution group was created, you can use either a full phone number ARN or UUID value for the <code>OutboundCallerIdNumberId</code> value of the <a href=\"https://docs.aws.amazon.com/connect/latest/APIReference/API_OutboundCallerConfig\">OutboundCallerConfig</a> request body parameter. However, if the number is claimed to a traffic distribution group and you are calling this API using an instance in the alternate Amazon Web Services Region associated with the traffic distribution group, you must provide a full phone number ARN. If a UUID is provided in this scenario, you will receive a <code>ResourceNotFoundException</code>.</p> </important>"
     },
     "CreateQuickConnect":{
       "name":"CreateQuickConnect",
@@ -2321,7 +2321,7 @@
         {"shape":"ThrottlingException"},
         {"shape":"InternalServiceException"}
       ],
-      "documentation":"<p>Searches queues in an Amazon Connect instance, with optional filtering.</p>"
+      "documentation":"<p>This API is in preview release for Amazon Connect and is subject to change.</p> <p>Searches queues in an Amazon Connect instance, with optional filtering.</p>"
     },
     "SearchQuickConnects":{
       "name":"SearchQuickConnects",
@@ -2373,7 +2373,7 @@
         {"shape":"ThrottlingException"},
         {"shape":"InternalServiceException"}
       ],
-      "documentation":"<p>Searches routing profiles in an Amazon Connect instance, with optional filtering.</p>"
+      "documentation":"<p>This API is in preview release for Amazon Connect and is subject to change.</p> <p>Searches routing profiles in an Amazon Connect instance, with optional filtering.</p>"
     },
     "SearchSecurityProfiles":{
       "name":"SearchSecurityProfiles",
@@ -2390,7 +2390,7 @@
         {"shape":"ThrottlingException"},
         {"shape":"InternalServiceException"}
       ],
-      "documentation":"<p>Searches security profiles in an Amazon Connect instance, with optional filtering.</p>"
+      "documentation":"<p>This API is in preview release for Amazon Connect and is subject to change.</p> <p>Searches security profiles in an Amazon Connect instance, with optional filtering.</p>"
     },
     "SearchUsers":{
       "name":"SearchUsers",
@@ -3024,7 +3024,7 @@
         {"shape":"ThrottlingException"},
         {"shape":"InternalServiceException"}
       ],
-      "documentation":"<p>This API is in preview release for Amazon Connect and is subject to change.</p> <p>Updates the outbound caller ID name, number, and outbound whisper flow for a specified queue.</p> <important> <p>If the number being used in the input is claimed to a traffic distribution group, and you are calling this API using an instance in the Amazon Web Services Region where the traffic distribution group was created, you can use either a full phone number ARN or UUID value for the <code>OutboundCallerIdNumberId</code> value of the <a href=\"https://docs.aws.amazon.com/connect/latest/APIReference/API_OutboundCallerConfig\">OutboundCallerConfig</a> request body parameter. However, if the number is claimed to a traffic distribution group and you are calling this API using an instance in the alternate Amazon Web Services Region associated with the traffic distribution group, you must provide a full phone number ARN. If a UUID is provided in this scenario, you will receive a <code>ResourceNotFoundException</code>.</p> <p>Only use the phone number ARN format that doesn't contain <code>instance</code> in the path, for example, <code>arn:aws:connect:us-east-1:1234567890:phone-number/uuid</code>. This is the same ARN format that is returned when you call the <a href=\"https://docs.aws.amazon.com/connect/latest/APIReference/API_ListPhoneNumbersV2.html\">ListPhoneNumbersV2</a> API.</p> </important>"
+      "documentation":"<p>This API is in preview release for Amazon Connect and is subject to change.</p> <p>Updates the outbound caller ID name, number, and outbound whisper flow for a specified queue.</p> <important> <p>If the number being used in the input is claimed to a traffic distribution group, and you are calling this API using an instance in the Amazon Web Services Region where the traffic distribution group was created, you can use either a full phone number ARN or UUID value for the <code>OutboundCallerIdNumberId</code> value of the <a href=\"https://docs.aws.amazon.com/connect/latest/APIReference/API_OutboundCallerConfig\">OutboundCallerConfig</a> request body parameter. However, if the number is claimed to a traffic distribution group and you are calling this API using an instance in the alternate Amazon Web Services Region associated with the traffic distribution group, you must provide a full phone number ARN. If a UUID is provided in this scenario, you will receive a <code>ResourceNotFoundException</code>.</p> </important>"
     },
     "UpdateQueueStatus":{
       "name":"UpdateQueueStatus",
@@ -8405,7 +8405,7 @@
         },
         "Filters":{
           "shape":"FiltersV2List",
-          "documentation":"<p>The filters to apply to returned metrics. You can filter on the following resources:</p> <ul> <li> <p>Queues</p> </li> <li> <p>Routing profiles</p> </li> <li> <p>Agents</p> </li> <li> <p>Channels</p> </li> <li> <p>User hierarchy groups</p> </li> </ul> <p>At least one filter must be passed from queues, routing profiles, agents, or user hierarchy groups.</p> <p>To filter by phone number, see <a href=\"https://docs.aws.amazon.com/connect/latest/adminguide/create-historical-metrics-report.html\">Create a historical metrics report</a> in the <i>Amazon Connect Administrator's Guide</i>.</p> <p>Note the following limits:</p> <ul> <li> <p> <b>Filter keys</b>: A maximum of 5 filter keys are supported in a single request. Valid filter keys: <code>QUEUE</code> | <code>ROUTING_PROFILE</code> | <code>AGENT</code> | <code>CHANNEL</code> | <code>AGENT_HIERARCHY_LEVEL_ONE</code> | <code>AGENT_HIERARCHY_LEVEL_TWO</code> | <code>AGENT_HIERARCHY_LEVEL_THREE</code> | <code>AGENT_HIERARCHY_LEVEL_FOUR</code> | <code>AGENT_HIERARCHY_LEVEL_FIVE</code> </p> </li> <li> <p> <b>Filter values</b>: A maximum of 100 filter values are supported in a single request. VOICE, CHAT, and TASK are valid <code>filterValue</code> for the CHANNEL filter key. They do not count towards limitation of 100 filter values. For example, a GetMetricDataV2 request can filter by 50 queues, 35 agents, and 15 routing profiles for a total of 100 filter values, along with 3 channel filters.</p> </li> </ul>"
+          "documentation":"<p>The filters to apply to returned metrics. You can filter on the following resources:</p> <ul> <li> <p>Queues</p> </li> <li> <p>Routing profiles</p> </li> <li> <p>Agents</p> </li> <li> <p>Channels</p> </li> <li> <p>User hierarchy groups</p> </li> </ul> <p>At least one filter must be passed from queues, routing profiles, agents, or user hierarchy groups.</p> <p>To filter by phone number, see <a href=\"https://docs.aws.amazon.com/connect/latest/adminguide/create-historical-metrics-report.html\">Create a historical metrics report</a> in the <i>Amazon Connect Administrator's Guide</i>.</p> <p>Note the following limits:</p> <ul> <li> <p> <b>Filter keys</b>: A maximum of 5 filter keys are supported in a single request. Valid filter keys: <code>QUEUE</code> | <code>ROUTING_PROFILE</code> | <code>AGENT</code> | <code>CHANNEL</code> | <code>AGENT_HIERARCHY_LEVEL_ONE</code> | <code>AGENT_HIERARCHY_LEVEL_TWO</code> | <code>AGENT_HIERARCHY_LEVEL_THREE</code> | <code>AGENT_HIERARCHY_LEVEL_FOUR</code> | <code>AGENT_HIERARCHY_LEVEL_FIVE</code> </p> </li> <li> <p> <b>Filter values</b>: A maximum of 100 filter values are supported in a single request. For example, a <code>GetMetricDataV2</code> request can filter by 50 queues, 35 agents, and 15 routing profiles for a total of 100 filter values. <code>VOICE</code>, <code>CHAT</code>, and <code>TASK</code> are valid <code>filterValue</code> for the <code>CHANNEL</code> filter key.</p> </li> </ul>"
         },
         "Groupings":{
           "shape":"GroupingsV2",
diff --git a/botocore/data/kms/2014-11-01/service-2.json b/botocore/data/kms/2014-11-01/service-2.json
index 215a358af..c096e0a6e 100644
--- a/botocore/data/kms/2014-11-01/service-2.json
+++ b/botocore/data/kms/2014-11-01/service-2.json
@@ -110,8 +110,7 @@
         {"shape":"KMSInternalException"},
         {"shape":"InvalidGrantTokenException"},
         {"shape":"LimitExceededException"},
-        {"shape":"KMSInvalidStateException"},
-        {"shape":"DryRunOperationException"}
+        {"shape":"KMSInvalidStateException"}
       ],
       "documentation":"<p>Adds a grant to a KMS key. </p> <p>A <i>grant</i> is a policy instrument that allows Amazon Web Services principals to use KMS keys in cryptographic operations. It also can allow them to view a KMS key (<a>DescribeKey</a>) and create and manage grants. When authorizing access to a KMS key, grants are considered along with key policies and IAM policies. Grants are often used for temporary permissions because you can create one, use its permissions, and delete it without changing your key policies or IAM policies. </p> <p>For detailed information about grants, including grant terminology, see <a href=\"https://docs.aws.amazon.com/kms/latest/developerguide/grants.html\">Grants in KMS</a> in the <i> <i>Key Management Service Developer Guide</i> </i>. For examples of working with grants in several programming languages, see <a href=\"https://docs.aws.amazon.com/kms/latest/developerguide/programming-grants.html\">Programming grants</a>. </p> <p>The <code>CreateGrant</code> operation returns a <code>GrantToken</code> and a <code>GrantId</code>.</p> <ul> <li> <p>When you create, retire, or revoke a grant, there might be a brief delay, usually less than five minutes, until the grant is available throughout KMS. This state is known as <i>eventual consistency</i>. Once the grant has achieved eventual consistency, the grantee principal can use the permissions in the grant without identifying the grant. </p> <p>However, to use the permissions in the grant immediately, use the <code>GrantToken</code> that <code>CreateGrant</code> returns. For details, see <a href=\"https://docs.aws.amazon.com/kms/latest/developerguide/grant-manage.html#using-grant-token\">Using a grant token</a> in the <i> <i>Key Management Service Developer Guide</i> </i>.</p> </li> <li> <p>The <code>CreateGrant</code> operation also returns a <code>GrantId</code>. You can use the <code>GrantId</code> and a key identifier to identify the grant in the <a>RetireGrant</a> and <a>RevokeGrant</a> operations. To find the grant ID, use the <a>ListGrants</a> or <a>ListRetirableGrants</a> operations.</p> </li> </ul> <p>The KMS key that you use for this operation must be in a compatible key state. For details, see <a href=\"https://docs.aws.amazon.com/kms/latest/developerguide/key-state.html\">Key states of KMS keys</a> in the <i>Key Management Service Developer Guide</i>.</p> <p> <b>Cross-account use</b>: Yes. To perform this operation on a KMS key in a different Amazon Web Services account, specify the key ARN in the value of the <code>KeyId</code> parameter. </p> <p> <b>Required permissions</b>: <a href=\"https://docs.aws.amazon.com/kms/latest/developerguide/kms-api-permissions-reference.html\">kms:CreateGrant</a> (key policy)</p> <p> <b>Related operations:</b> </p> <ul> <li> <p> <a>ListGrants</a> </p> </li> <li> <p> <a>ListRetirableGrants</a> </p> </li> <li> <p> <a>RetireGrant</a> </p> </li> <li> <p> <a>RevokeGrant</a> </p> </li> </ul>"
     },
@@ -158,8 +157,7 @@
         {"shape":"DependencyTimeoutException"},
         {"shape":"InvalidGrantTokenException"},
         {"shape":"KMSInternalException"},
-        {"shape":"KMSInvalidStateException"},
-        {"shape":"DryRunOperationException"}
+        {"shape":"KMSInvalidStateException"}
       ],
       "documentation":"<p>Decrypts ciphertext that was encrypted by a KMS key using any of the following operations:</p> <ul> <li> <p> <a>Encrypt</a> </p> </li> <li> <p> <a>GenerateDataKey</a> </p> </li> <li> <p> <a>GenerateDataKeyPair</a> </p> </li> <li> <p> <a>GenerateDataKeyWithoutPlaintext</a> </p> </li> <li> <p> <a>GenerateDataKeyPairWithoutPlaintext</a> </p> </li> </ul> <p>You can use this operation to decrypt ciphertext that was encrypted under a symmetric encryption KMS key or an asymmetric encryption KMS key. When the KMS key is asymmetric, you must specify the KMS key and the encryption algorithm that was used to encrypt the ciphertext. For information about asymmetric KMS keys, see <a href=\"https://docs.aws.amazon.com/kms/latest/developerguide/symmetric-asymmetric.html\">Asymmetric KMS keys</a> in the <i>Key Management Service Developer Guide</i>.</p> <p>The <code>Decrypt</code> operation also decrypts ciphertext that was encrypted outside of KMS by the public key in an KMS asymmetric KMS key. However, it cannot decrypt symmetric ciphertext produced by other libraries, such as the <a href=\"https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/\">Amazon Web Services Encryption SDK</a> or <a href=\"https://docs.aws.amazon.com/AmazonS3/latest/dev/UsingClientSideEncryption.html\">Amazon S3 client-side encryption</a>. These libraries return a ciphertext format that is incompatible with KMS.</p> <p>If the ciphertext was encrypted under a symmetric encryption KMS key, the <code>KeyId</code> parameter is optional. KMS can get this information from metadata that it adds to the symmetric ciphertext blob. This feature adds durability to your implementation by ensuring that authorized users can decrypt ciphertext decades after it was encrypted, even if they've lost track of the key ID. However, specifying the KMS key is always recommended as a best practice. When you use the <code>KeyId</code> parameter to specify a KMS key, KMS only uses the KMS key you specify. If the ciphertext was encrypted under a different KMS key, the <code>Decrypt</code> operation fails. This practice ensures that you use the KMS key that you intend.</p> <p>Whenever possible, use key policies to give users permission to call the <code>Decrypt</code> operation on a particular KMS key, instead of using &amp;IAM; policies. Otherwise, you might create an &amp;IAM; policy that gives the user <code>Decrypt</code> permission on all KMS keys. This user could decrypt ciphertext that was encrypted by KMS keys in other accounts if the key policy for the cross-account KMS key permits it. If you must use an IAM policy for <code>Decrypt</code> permissions, limit the user to particular KMS keys or particular trusted accounts. For details, see <a href=\"https://docs.aws.amazon.com/kms/latest/developerguide/iam-policies.html#iam-policies-best-practices\">Best practices for IAM policies</a> in the <i>Key Management Service Developer Guide</i>.</p> <p> <code>Decrypt</code> also supports <a href=\"https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/nitro-enclave.html\">Amazon Web Services Nitro Enclaves</a>, which provide an isolated compute environment in Amazon EC2. To call <code>Decrypt</code> for a Nitro enclave, use the <a href=\"https://docs.aws.amazon.com/enclaves/latest/user/developing-applications.html#sdk\">Amazon Web Services Nitro Enclaves SDK</a> or any Amazon Web Services SDK. Use the <code>Recipient</code> parameter to provide the attestation document for the enclave. Instead of the plaintext data, the response includes the plaintext data encrypted with the public key from the attestation document (<code>CiphertextForRecipient</code>).For information about the interaction between KMS and Amazon Web Services Nitro Enclaves, see <a href=\"https://docs.aws.amazon.com/kms/latest/developerguide/services-nitro-enclaves.html\">How Amazon Web Services Nitro Enclaves uses KMS</a> in the <i>Key Management Service Developer Guide</i>..</p> <p>The KMS key that you use for this operation must be in a compatible key state. For details, see <a href=\"https://docs.aws.amazon.com/kms/latest/developerguide/key-state.html\">Key states of KMS keys</a> in the <i>Key Management Service Developer Guide</i>.</p> <p> <b>Cross-account use</b>: Yes. If you use the <code>KeyId</code> parameter to identify a KMS key in a different Amazon Web Services account, specify the key ARN or the alias ARN of the KMS key.</p> <p> <b>Required permissions</b>: <a href=\"https://docs.aws.amazon.com/kms/latest/developerguide/kms-api-permissions-reference.html\">kms:Decrypt</a> (key policy)</p> <p> <b>Related operations:</b> </p> <ul> <li> <p> <a>Encrypt</a> </p> </li> <li> <p> <a>GenerateDataKey</a> </p> </li> <li> <p> <a>GenerateDataKeyPair</a> </p> </li> <li> <p> <a>ReEncrypt</a> </p> </li> </ul>"
     },
@@ -342,8 +340,7 @@
         {"shape":"InvalidKeyUsageException"},
         {"shape":"InvalidGrantTokenException"},
         {"shape":"KMSInternalException"},
-        {"shape":"KMSInvalidStateException"},
-        {"shape":"DryRunOperationException"}
+        {"shape":"KMSInvalidStateException"}
       ],
       "documentation":"<p>Encrypts plaintext of up to 4,096 bytes using a KMS key. You can use a symmetric or asymmetric KMS key with a <code>KeyUsage</code> of <code>ENCRYPT_DECRYPT</code>.</p> <p>You can use this operation to encrypt small amounts of arbitrary data, such as a personal identifier or database password, or other sensitive information. You don't need to use the <code>Encrypt</code> operation to encrypt a data key. The <a>GenerateDataKey</a> and <a>GenerateDataKeyPair</a> operations return a plaintext data key and an encrypted copy of that data key.</p> <p>If you use a symmetric encryption KMS key, you can use an encryption context to add additional security to your encryption operation. If you specify an <code>EncryptionContext</code> when encrypting data, you must specify the same encryption context (a case-sensitive exact match) when decrypting the data. Otherwise, the request to decrypt fails with an <code>InvalidCiphertextException</code>. For more information, see <a href=\"https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#encrypt_context\">Encryption Context</a> in the <i>Key Management Service Developer Guide</i>.</p> <p>If you specify an asymmetric KMS key, you must also specify the encryption algorithm. The algorithm must be compatible with the KMS key spec.</p> <important> <p>When you use an asymmetric KMS key to encrypt or reencrypt data, be sure to record the KMS key and encryption algorithm that you choose. You will be required to provide the same KMS key and encryption algorithm when you decrypt the data. If the KMS key and algorithm do not match the values used to encrypt the data, the decrypt operation fails.</p> <p>You are not required to supply the key ID and encryption algorithm when you decrypt with symmetric encryption KMS keys because KMS stores this information in the ciphertext blob. KMS cannot store metadata in ciphertext generated with asymmetric keys. The standard format for asymmetric key ciphertext does not include configurable fields.</p> </important> <p>The maximum size of the data that you can encrypt varies with the type of KMS key and the encryption algorithm that you choose.</p> <ul> <li> <p>Symmetric encryption KMS keys</p> <ul> <li> <p> <code>SYMMETRIC_DEFAULT</code>: 4096 bytes</p> </li> </ul> </li> <li> <p> <code>RSA_2048</code> </p> <ul> <li> <p> <code>RSAES_OAEP_SHA_1</code>: 214 bytes</p> </li> <li> <p> <code>RSAES_OAEP_SHA_256</code>: 190 bytes</p> </li> </ul> </li> <li> <p> <code>RSA_3072</code> </p> <ul> <li> <p> <code>RSAES_OAEP_SHA_1</code>: 342 bytes</p> </li> <li> <p> <code>RSAES_OAEP_SHA_256</code>: 318 bytes</p> </li> </ul> </li> <li> <p> <code>RSA_4096</code> </p> <ul> <li> <p> <code>RSAES_OAEP_SHA_1</code>: 470 bytes</p> </li> <li> <p> <code>RSAES_OAEP_SHA_256</code>: 446 bytes</p> </li> </ul> </li> <li> <p> <code>SM2PKE</code>: 1024 bytes (China Regions only)</p> </li> </ul> <p>The KMS key that you use for this operation must be in a compatible key state. For details, see <a href=\"https://docs.aws.amazon.com/kms/latest/developerguide/key-state.html\">Key states of KMS keys</a> in the <i>Key Management Service Developer Guide</i>.</p> <p> <b>Cross-account use</b>: Yes. To perform this operation with a KMS key in a different Amazon Web Services account, specify the key ARN or alias ARN in the value of the <code>KeyId</code> parameter.</p> <p> <b>Required permissions</b>: <a href=\"https://docs.aws.amazon.com/kms/latest/developerguide/kms-api-permissions-reference.html\">kms:Encrypt</a> (key policy)</p> <p> <b>Related operations:</b> </p> <ul> <li> <p> <a>Decrypt</a> </p> </li> <li> <p> <a>GenerateDataKey</a> </p> </li> <li> <p> <a>GenerateDataKeyPair</a> </p> </li> </ul>"
     },
@@ -363,8 +360,7 @@
         {"shape":"InvalidKeyUsageException"},
         {"shape":"InvalidGrantTokenException"},
         {"shape":"KMSInternalException"},
-        {"shape":"KMSInvalidStateException"},
-        {"shape":"DryRunOperationException"}
+        {"shape":"KMSInvalidStateException"}
       ],
       "documentation":"<p>Returns a unique symmetric data key for use outside of KMS. This operation returns a plaintext copy of the data key and a copy that is encrypted under a symmetric encryption KMS key that you specify. The bytes in the plaintext key are random; they are not related to the caller or the KMS key. You can use the plaintext key to encrypt your data outside of KMS and store the encrypted data key with the encrypted data.</p> <p>To generate a data key, specify the symmetric encryption KMS key that will be used to encrypt the data key. You cannot use an asymmetric KMS key to encrypt data keys. To get the type of your KMS key, use the <a>DescribeKey</a> operation.</p> <p>You must also specify the length of the data key. Use either the <code>KeySpec</code> or <code>NumberOfBytes</code> parameters (but not both). For 128-bit and 256-bit data keys, use the <code>KeySpec</code> parameter.</p> <p>To generate a 128-bit SM4 data key (China Regions only), specify a <code>KeySpec</code> value of <code>AES_128</code> or a <code>NumberOfBytes</code> value of <code>16</code>. The symmetric encryption key used in China Regions to encrypt your data key is an SM4 encryption key.</p> <p>To get only an encrypted copy of the data key, use <a>GenerateDataKeyWithoutPlaintext</a>. To generate an asymmetric data key pair, use the <a>GenerateDataKeyPair</a> or <a>GenerateDataKeyPairWithoutPlaintext</a> operation. To get a cryptographically secure random byte string, use <a>GenerateRandom</a>.</p> <p>You can use an optional encryption context to add additional security to the encryption operation. If you specify an <code>EncryptionContext</code>, you must specify the same encryption context (a case-sensitive exact match) when decrypting the encrypted data key. Otherwise, the request to decrypt fails with an <code>InvalidCiphertextException</code>. For more information, see <a href=\"https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#encrypt_context\">Encryption Context</a> in the <i>Key Management Service Developer Guide</i>.</p> <p> <code>GenerateDataKey</code> also supports <a href=\"https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/nitro-enclave.html\">Amazon Web Services Nitro Enclaves</a>, which provide an isolated compute environment in Amazon EC2. To call <code>GenerateDataKey</code> for an Amazon Web Services Nitro enclave, use the <a href=\"https://docs.aws.amazon.com/enclaves/latest/user/developing-applications.html#sdk\">Amazon Web Services Nitro Enclaves SDK</a> or any Amazon Web Services SDK. Use the <code>Recipient</code> parameter to provide the attestation document for the enclave. <code>GenerateDataKey</code> returns a copy of the data key encrypted under the specified KMS key, as usual. But instead of a plaintext copy of the data key, the response includes a copy of the data key encrypted under the public key from the attestation document (<code>CiphertextForRecipient</code>). For information about the interaction between KMS and Amazon Web Services Nitro Enclaves, see <a href=\"https://docs.aws.amazon.com/kms/latest/developerguide/services-nitro-enclaves.html\">How Amazon Web Services Nitro Enclaves uses KMS</a> in the <i>Key Management Service Developer Guide</i>..</p> <p>The KMS key that you use for this operation must be in a compatible key state. For details, see <a href=\"https://docs.aws.amazon.com/kms/latest/developerguide/key-state.html\">Key states of KMS keys</a> in the <i>Key Management Service Developer Guide</i>.</p> <p> <b>How to use your data key</b> </p> <p>We recommend that you use the following pattern to encrypt data locally in your application. You can write your own code or use a client-side encryption library, such as the <a href=\"https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/\">Amazon Web Services Encryption SDK</a>, the <a href=\"https://docs.aws.amazon.com/dynamodb-encryption-client/latest/devguide/\">Amazon DynamoDB Encryption Client</a>, or <a href=\"https://docs.aws.amazon.com/AmazonS3/latest/dev/UsingClientSideEncryption.html\">Amazon S3 client-side encryption</a> to do these tasks for you.</p> <p>To encrypt data outside of KMS:</p> <ol> <li> <p>Use the <code>GenerateDataKey</code> operation to get a data key.</p> </li> <li> <p>Use the plaintext data key (in the <code>Plaintext</code> field of the response) to encrypt your data outside of KMS. Then erase the plaintext data key from memory.</p> </li> <li> <p>Store the encrypted data key (in the <code>CiphertextBlob</code> field of the response) with the encrypted data.</p> </li> </ol> <p>To decrypt data outside of KMS:</p> <ol> <li> <p>Use the <a>Decrypt</a> operation to decrypt the encrypted data key. The operation returns a plaintext copy of the data key.</p> </li> <li> <p>Use the plaintext data key to decrypt data outside of KMS, then erase the plaintext data key from memory.</p> </li> </ol> <p> <b>Cross-account use</b>: Yes. To perform this operation with a KMS key in a different Amazon Web Services account, specify the key ARN or alias ARN in the value of the <code>KeyId</code> parameter.</p> <p> <b>Required permissions</b>: <a href=\"https://docs.aws.amazon.com/kms/latest/developerguide/kms-api-permissions-reference.html\">kms:GenerateDataKey</a> (key policy)</p> <p> <b>Related operations:</b> </p> <ul> <li> <p> <a>Decrypt</a> </p> </li> <li> <p> <a>Encrypt</a> </p> </li> <li> <p> <a>GenerateDataKeyPair</a> </p> </li> <li> <p> <a>GenerateDataKeyPairWithoutPlaintext</a> </p> </li> <li> <p> <a>GenerateDataKeyWithoutPlaintext</a> </p> </li> </ul>"
     },
@@ -385,8 +381,7 @@
         {"shape":"InvalidGrantTokenException"},
         {"shape":"KMSInternalException"},
         {"shape":"KMSInvalidStateException"},
-        {"shape":"UnsupportedOperationException"},
-        {"shape":"DryRunOperationException"}
+        {"shape":"UnsupportedOperationException"}
       ],
       "documentation":"<p>Returns a unique asymmetric data key pair for use outside of KMS. This operation returns a plaintext public key, a plaintext private key, and a copy of the private key that is encrypted under the symmetric encryption KMS key you specify. You can use the data key pair to perform asymmetric cryptography and implement digital signatures outside of KMS. The bytes in the keys are random; they not related to the caller or to the KMS key that is used to encrypt the private key. </p> <p>You can use the public key that <code>GenerateDataKeyPair</code> returns to encrypt data or verify a signature outside of KMS. Then, store the encrypted private key with the data. When you are ready to decrypt data or sign a message, you can use the <a>Decrypt</a> operation to decrypt the encrypted private key.</p> <p>To generate a data key pair, you must specify a symmetric encryption KMS key to encrypt the private key in a data key pair. You cannot use an asymmetric KMS key or a KMS key in a custom key store. To get the type and origin of your KMS key, use the <a>DescribeKey</a> operation. </p> <p>Use the <code>KeyPairSpec</code> parameter to choose an RSA or Elliptic Curve (ECC) data key pair. In China Regions, you can also choose an SM2 data key pair. KMS recommends that you use ECC key pairs for signing, and use RSA and SM2 key pairs for either encryption or signing, but not both. However, KMS cannot enforce any restrictions on the use of data key pairs outside of KMS.</p> <p>If you are using the data key pair to encrypt data, or for any operation where you don't immediately need a private key, consider using the <a>GenerateDataKeyPairWithoutPlaintext</a> operation. <code>GenerateDataKeyPairWithoutPlaintext</code> returns a plaintext public key and an encrypted private key, but omits the plaintext private key that you need only to decrypt ciphertext or sign a message. Later, when you need to decrypt the data or sign a message, use the <a>Decrypt</a> operation to decrypt the encrypted private key in the data key pair.</p> <p> <code>GenerateDataKeyPair</code> returns a unique data key pair for each request. The bytes in the keys are random; they are not related to the caller or the KMS key that is used to encrypt the private key. The public key is a DER-encoded X.509 SubjectPublicKeyInfo, as specified in <a href=\"https://tools.ietf.org/html/rfc5280\">RFC 5280</a>. The private key is a DER-encoded PKCS8 PrivateKeyInfo, as specified in <a href=\"https://tools.ietf.org/html/rfc5958\">RFC 5958</a>.</p> <p> <code>GenerateDataKeyPair</code> also supports <a href=\"https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/nitro-enclave.html\">Amazon Web Services Nitro Enclaves</a>, which provide an isolated compute environment in Amazon EC2. To call <code>GenerateDataKeyPair</code> for an Amazon Web Services Nitro enclave, use the <a href=\"https://docs.aws.amazon.com/enclaves/latest/user/developing-applications.html#sdk\">Amazon Web Services Nitro Enclaves SDK</a> or any Amazon Web Services SDK. Use the <code>Recipient</code> parameter to provide the attestation document for the enclave. <code>GenerateDataKeyPair</code> returns the public data key and a copy of the private data key encrypted under the specified KMS key, as usual. But instead of a plaintext copy of the private data key (<code>PrivateKeyPlaintext</code>), the response includes a copy of the private data key encrypted under the public key from the attestation document (<code>CiphertextForRecipient</code>). For information about the interaction between KMS and Amazon Web Services Nitro Enclaves, see <a href=\"https://docs.aws.amazon.com/kms/latest/developerguide/services-nitro-enclaves.html\">How Amazon Web Services Nitro Enclaves uses KMS</a> in the <i>Key Management Service Developer Guide</i>..</p> <p>You can use an optional encryption context to add additional security to the encryption operation. If you specify an <code>EncryptionContext</code>, you must specify the same encryption context (a case-sensitive exact match) when decrypting the encrypted data key. Otherwise, the request to decrypt fails with an <code>InvalidCiphertextException</code>. For more information, see <a href=\"https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#encrypt_context\">Encryption Context</a> in the <i>Key Management Service Developer Guide</i>.</p> <p>The KMS key that you use for this operation must be in a compatible key state. For details, see <a href=\"https://docs.aws.amazon.com/kms/latest/developerguide/key-state.html\">Key states of KMS keys</a> in the <i>Key Management Service Developer Guide</i>.</p> <p> <b>Cross-account use</b>: Yes. To perform this operation with a KMS key in a different Amazon Web Services account, specify the key ARN or alias ARN in the value of the <code>KeyId</code> parameter.</p> <p> <b>Required permissions</b>: <a href=\"https://docs.aws.amazon.com/kms/latest/developerguide/kms-api-permissions-reference.html\">kms:GenerateDataKeyPair</a> (key policy)</p> <p> <b>Related operations:</b> </p> <ul> <li> <p> <a>Decrypt</a> </p> </li> <li> <p> <a>Encrypt</a> </p> </li> <li> <p> <a>GenerateDataKey</a> </p> </li> <li> <p> <a>GenerateDataKeyPairWithoutPlaintext</a> </p> </li> <li> <p> <a>GenerateDataKeyWithoutPlaintext</a> </p> </li> </ul>"
     },
@@ -407,8 +402,7 @@
         {"shape":"InvalidGrantTokenException"},
         {"shape":"KMSInternalException"},
         {"shape":"KMSInvalidStateException"},
-        {"shape":"UnsupportedOperationException"},
-        {"shape":"DryRunOperationException"}
+        {"shape":"UnsupportedOperationException"}
       ],
       "documentation":"<p>Returns a unique asymmetric data key pair for use outside of KMS. This operation returns a plaintext public key and a copy of the private key that is encrypted under the symmetric encryption KMS key you specify. Unlike <a>GenerateDataKeyPair</a>, this operation does not return a plaintext private key. The bytes in the keys are random; they are not related to the caller or to the KMS key that is used to encrypt the private key. </p> <p>You can use the public key that <code>GenerateDataKeyPairWithoutPlaintext</code> returns to encrypt data or verify a signature outside of KMS. Then, store the encrypted private key with the data. When you are ready to decrypt data or sign a message, you can use the <a>Decrypt</a> operation to decrypt the encrypted private key.</p> <p>To generate a data key pair, you must specify a symmetric encryption KMS key to encrypt the private key in a data key pair. You cannot use an asymmetric KMS key or a KMS key in a custom key store. To get the type and origin of your KMS key, use the <a>DescribeKey</a> operation. </p> <p>Use the <code>KeyPairSpec</code> parameter to choose an RSA or Elliptic Curve (ECC) data key pair. In China Regions, you can also choose an SM2 data key pair. KMS recommends that you use ECC key pairs for signing, and use RSA and SM2 key pairs for either encryption or signing, but not both. However, KMS cannot enforce any restrictions on the use of data key pairs outside of KMS.</p> <p> <code>GenerateDataKeyPairWithoutPlaintext</code> returns a unique data key pair for each request. The bytes in the key are not related to the caller or KMS key that is used to encrypt the private key. The public key is a DER-encoded X.509 SubjectPublicKeyInfo, as specified in <a href=\"https://tools.ietf.org/html/rfc5280\">RFC 5280</a>.</p> <p>You can use an optional encryption context to add additional security to the encryption operation. If you specify an <code>EncryptionContext</code>, you must specify the same encryption context (a case-sensitive exact match) when decrypting the encrypted data key. Otherwise, the request to decrypt fails with an <code>InvalidCiphertextException</code>. For more information, see <a href=\"https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#encrypt_context\">Encryption Context</a> in the <i>Key Management Service Developer Guide</i>.</p> <p>The KMS key that you use for this operation must be in a compatible key state. For details, see <a href=\"https://docs.aws.amazon.com/kms/latest/developerguide/key-state.html\">Key states of KMS keys</a> in the <i>Key Management Service Developer Guide</i>.</p> <p> <b>Cross-account use</b>: Yes. To perform this operation with a KMS key in a different Amazon Web Services account, specify the key ARN or alias ARN in the value of the <code>KeyId</code> parameter.</p> <p> <b>Required permissions</b>: <a href=\"https://docs.aws.amazon.com/kms/latest/developerguide/kms-api-permissions-reference.html\">kms:GenerateDataKeyPairWithoutPlaintext</a> (key policy)</p> <p> <b>Related operations:</b> </p> <ul> <li> <p> <a>Decrypt</a> </p> </li> <li> <p> <a>Encrypt</a> </p> </li> <li> <p> <a>GenerateDataKey</a> </p> </li> <li> <p> <a>GenerateDataKeyPair</a> </p> </li> <li> <p> <a>GenerateDataKeyWithoutPlaintext</a> </p> </li> </ul>"
     },
@@ -428,8 +422,7 @@
         {"shape":"InvalidKeyUsageException"},
         {"shape":"InvalidGrantTokenException"},
         {"shape":"KMSInternalException"},
-        {"shape":"KMSInvalidStateException"},
-        {"shape":"DryRunOperationException"}
+        {"shape":"KMSInvalidStateException"}
       ],
       "documentation":"<p>Returns a unique symmetric data key for use outside of KMS. This operation returns a data key that is encrypted under a symmetric encryption KMS key that you specify. The bytes in the key are random; they are not related to the caller or to the KMS key.</p> <p> <code>GenerateDataKeyWithoutPlaintext</code> is identical to the <a>GenerateDataKey</a> operation except that it does not return a plaintext copy of the data key. </p> <p>This operation is useful for systems that need to encrypt data at some point, but not immediately. When you need to encrypt the data, you call the <a>Decrypt</a> operation on the encrypted copy of the key.</p> <p>It's also useful in distributed systems with different levels of trust. For example, you might store encrypted data in containers. One component of your system creates new containers and stores an encrypted data key with each container. Then, a different component puts the data into the containers. That component first decrypts the data key, uses the plaintext data key to encrypt data, puts the encrypted data into the container, and then destroys the plaintext data key. In this system, the component that creates the containers never sees the plaintext data key.</p> <p>To request an asymmetric data key pair, use the <a>GenerateDataKeyPair</a> or <a>GenerateDataKeyPairWithoutPlaintext</a> operations.</p> <p>To generate a data key, you must specify the symmetric encryption KMS key that is used to encrypt the data key. You cannot use an asymmetric KMS key or a key in a custom key store to generate a data key. To get the type of your KMS key, use the <a>DescribeKey</a> operation.</p> <p>You must also specify the length of the data key. Use either the <code>KeySpec</code> or <code>NumberOfBytes</code> parameters (but not both). For 128-bit and 256-bit data keys, use the <code>KeySpec</code> parameter.</p> <p>To generate an SM4 data key (China Regions only), specify a <code>KeySpec</code> value of <code>AES_128</code> or <code>NumberOfBytes</code> value of <code>16</code>. The symmetric encryption key used in China Regions to encrypt your data key is an SM4 encryption key.</p> <p>If the operation succeeds, you will find the encrypted copy of the data key in the <code>CiphertextBlob</code> field.</p> <p>You can use an optional encryption context to add additional security to the encryption operation. If you specify an <code>EncryptionContext</code>, you must specify the same encryption context (a case-sensitive exact match) when decrypting the encrypted data key. Otherwise, the request to decrypt fails with an <code>InvalidCiphertextException</code>. For more information, see <a href=\"https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#encrypt_context\">Encryption Context</a> in the <i>Key Management Service Developer Guide</i>.</p> <p>The KMS key that you use for this operation must be in a compatible key state. For details, see <a href=\"https://docs.aws.amazon.com/kms/latest/developerguide/key-state.html\">Key states of KMS keys</a> in the <i>Key Management Service Developer Guide</i>.</p> <p> <b>Cross-account use</b>: Yes. To perform this operation with a KMS key in a different Amazon Web Services account, specify the key ARN or alias ARN in the value of the <code>KeyId</code> parameter.</p> <p> <b>Required permissions</b>: <a href=\"https://docs.aws.amazon.com/kms/latest/developerguide/kms-api-permissions-reference.html\">kms:GenerateDataKeyWithoutPlaintext</a> (key policy)</p> <p> <b>Related operations:</b> </p> <ul> <li> <p> <a>Decrypt</a> </p> </li> <li> <p> <a>Encrypt</a> </p> </li> <li> <p> <a>GenerateDataKey</a> </p> </li> <li> <p> <a>GenerateDataKeyPair</a> </p> </li> <li> <p> <a>GenerateDataKeyPairWithoutPlaintext</a> </p> </li> </ul>"
     },
@@ -448,8 +441,7 @@
         {"shape":"InvalidKeyUsageException"},
         {"shape":"InvalidGrantTokenException"},
         {"shape":"KMSInternalException"},
-        {"shape":"KMSInvalidStateException"},
-        {"shape":"DryRunOperationException"}
+        {"shape":"KMSInvalidStateException"}
       ],
       "documentation":"<p>Generates a hash-based message authentication code (HMAC) for a message using an HMAC KMS key and a MAC algorithm that the key supports. HMAC KMS keys and the HMAC algorithms that KMS uses conform to industry standards defined in <a href=\"https://datatracker.ietf.org/doc/html/rfc2104\">RFC 2104</a>.</p> <p>You can use value that GenerateMac returns in the <a>VerifyMac</a> operation to demonstrate that the original message has not changed. Also, because a secret key is used to create the hash, you can verify that the party that generated the hash has the required secret key. You can also use the raw result to implement HMAC-based algorithms such as key derivation functions. This operation is part of KMS support for HMAC KMS keys. For details, see <a href=\"https://docs.aws.amazon.com/kms/latest/developerguide/hmac.html\">HMAC keys in KMS</a> in the <i> <i>Key Management Service Developer Guide</i> </i>.</p> <note> <p>Best practices recommend that you limit the time during which any signing mechanism, including an HMAC, is effective. This deters an attack where the actor uses a signed message to establish validity repeatedly or long after the message is superseded. HMAC tags do not include a timestamp, but you can include a timestamp in the token or message to help you detect when its time to refresh the HMAC. </p> </note> <p>The KMS key that you use for this operation must be in a compatible key state. For details, see <a href=\"https://docs.aws.amazon.com/kms/latest/developerguide/key-state.html\">Key states of KMS keys</a> in the <i>Key Management Service Developer Guide</i>.</p> <p> <b>Cross-account use</b>: Yes. To perform this operation with a KMS key in a different Amazon Web Services account, specify the key ARN or alias ARN in the value of the <code>KeyId</code> parameter. </p> <p> <b>Required permissions</b>: <a href=\"https://docs.aws.amazon.com/kms/latest/developerguide/kms-api-permissions-reference.html\">kms:GenerateMac</a> (key policy)</p> <p> <b>Related operations</b>: <a>VerifyMac</a> </p>"
     },
@@ -705,8 +697,7 @@
         {"shape":"InvalidKeyUsageException"},
         {"shape":"InvalidGrantTokenException"},
         {"shape":"KMSInternalException"},
-        {"shape":"KMSInvalidStateException"},
-        {"shape":"DryRunOperationException"}
+        {"shape":"KMSInvalidStateException"}
       ],
       "documentation":"<p>Decrypts ciphertext and then reencrypts it entirely within KMS. You can use this operation to change the KMS key under which data is encrypted, such as when you <a href=\"https://docs.aws.amazon.com/kms/latest/developerguide/rotate-keys.html#rotate-keys-manually\">manually rotate</a> a KMS key or change the KMS key that protects a ciphertext. You can also use it to reencrypt ciphertext under the same KMS key, such as to change the <a href=\"https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#encrypt_context\">encryption context</a> of a ciphertext.</p> <p>The <code>ReEncrypt</code> operation can decrypt ciphertext that was encrypted by using a KMS key in an KMS operation, such as <a>Encrypt</a> or <a>GenerateDataKey</a>. It can also decrypt ciphertext that was encrypted by using the public key of an <a href=\"https://docs.aws.amazon.com/kms/latest/developerguide/symm-asymm-concepts.html#asymmetric-cmks\">asymmetric KMS key</a> outside of KMS. However, it cannot decrypt ciphertext produced by other libraries, such as the <a href=\"https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/\">Amazon Web Services Encryption SDK</a> or <a href=\"https://docs.aws.amazon.com/AmazonS3/latest/dev/UsingClientSideEncryption.html\">Amazon S3 client-side encryption</a>. These libraries return a ciphertext format that is incompatible with KMS.</p> <p>When you use the <code>ReEncrypt</code> operation, you need to provide information for the decrypt operation and the subsequent encrypt operation.</p> <ul> <li> <p>If your ciphertext was encrypted under an asymmetric KMS key, you must use the <code>SourceKeyId</code> parameter to identify the KMS key that encrypted the ciphertext. You must also supply the encryption algorithm that was used. This information is required to decrypt the data.</p> </li> <li> <p>If your ciphertext was encrypted under a symmetric encryption KMS key, the <code>SourceKeyId</code> parameter is optional. KMS can get this information from metadata that it adds to the symmetric ciphertext blob. This feature adds durability to your implementation by ensuring that authorized users can decrypt ciphertext decades after it was encrypted, even if they've lost track of the key ID. However, specifying the source KMS key is always recommended as a best practice. When you use the <code>SourceKeyId</code> parameter to specify a KMS key, KMS uses only the KMS key you specify. If the ciphertext was encrypted under a different KMS key, the <code>ReEncrypt</code> operation fails. This practice ensures that you use the KMS key that you intend.</p> </li> <li> <p>To reencrypt the data, you must use the <code>DestinationKeyId</code> parameter to specify the KMS key that re-encrypts the data after it is decrypted. If the destination KMS key is an asymmetric KMS key, you must also provide the encryption algorithm. The algorithm that you choose must be compatible with the KMS key.</p> <important> <p>When you use an asymmetric KMS key to encrypt or reencrypt data, be sure to record the KMS key and encryption algorithm that you choose. You will be required to provide the same KMS key and encryption algorithm when you decrypt the data. If the KMS key and algorithm do not match the values used to encrypt the data, the decrypt operation fails.</p> <p>You are not required to supply the key ID and encryption algorithm when you decrypt with symmetric encryption KMS keys because KMS stores this information in the ciphertext blob. KMS cannot store metadata in ciphertext generated with asymmetric keys. The standard format for asymmetric key ciphertext does not include configurable fields.</p> </important> </li> </ul> <p>The KMS key that you use for this operation must be in a compatible key state. For details, see <a href=\"https://docs.aws.amazon.com/kms/latest/developerguide/key-state.html\">Key states of KMS keys</a> in the <i>Key Management Service Developer Guide</i>.</p> <p> <b>Cross-account use</b>: Yes. The source KMS key and destination KMS key can be in different Amazon Web Services accounts. Either or both KMS keys can be in a different account than the caller. To specify a KMS key in a different account, you must use its key ARN or alias ARN.</p> <p> <b>Required permissions</b>:</p> <ul> <li> <p> <a href=\"https://docs.aws.amazon.com/kms/latest/developerguide/kms-api-permissions-reference.html\">kms:ReEncryptFrom</a> permission on the source KMS key (key policy)</p> </li> <li> <p> <a href=\"https://docs.aws.amazon.com/kms/latest/developerguide/kms-api-permissions-reference.html\">kms:ReEncryptTo</a> permission on the destination KMS key (key policy)</p> </li> </ul> <p>To permit reencryption from or to a KMS key, include the <code>\"kms:ReEncrypt*\"</code> permission in your <a href=\"https://docs.aws.amazon.com/kms/latest/developerguide/key-policies.html\">key policy</a>. This permission is automatically included in the key policy when you use the console to create a KMS key. But you must include it manually when you create a KMS key programmatically or when you use the <a>PutKeyPolicy</a> operation to set a key policy.</p> <p> <b>Related operations:</b> </p> <ul> <li> <p> <a>Decrypt</a> </p> </li> <li> <p> <a>Encrypt</a> </p> </li> <li> <p> <a>GenerateDataKey</a> </p> </li> <li> <p> <a>GenerateDataKeyPair</a> </p> </li> </ul>"
     },
@@ -746,8 +737,7 @@
         {"shape":"NotFoundException"},
         {"shape":"DependencyTimeoutException"},
         {"shape":"KMSInternalException"},
-        {"shape":"KMSInvalidStateException"},
-        {"shape":"DryRunOperationException"}
+        {"shape":"KMSInvalidStateException"}
       ],
       "documentation":"<p>Deletes a grant. Typically, you retire a grant when you no longer need its permissions. To identify the grant to retire, use a <a href=\"https://docs.aws.amazon.com/kms/latest/developerguide/grants.html#grant_token\">grant token</a>, or both the grant ID and a key identifier (key ID or key ARN) of the KMS key. The <a>CreateGrant</a> operation returns both values.</p> <p>This operation can be called by the <i>retiring principal</i> for a grant, by the <i>grantee principal</i> if the grant allows the <code>RetireGrant</code> operation, and by the Amazon Web Services account in which the grant is created. It can also be called by principals to whom permission for retiring a grant is delegated. For details, see <a href=\"https://docs.aws.amazon.com/kms/latest/developerguide/grant-manage.html#grant-delete\">Retiring and revoking grants</a> in the <i>Key Management Service Developer Guide</i>.</p> <p>For detailed information about grants, including grant terminology, see <a href=\"https://docs.aws.amazon.com/kms/latest/developerguide/grants.html\">Grants in KMS</a> in the <i> <i>Key Management Service Developer Guide</i> </i>. For examples of working with grants in several programming languages, see <a href=\"https://docs.aws.amazon.com/kms/latest/developerguide/programming-grants.html\">Programming grants</a>. </p> <p> <b>Cross-account use</b>: Yes. You can retire a grant on a KMS key in a different Amazon Web Services account.</p> <p> <b>Required permissions:</b>:Permission to retire a grant is determined primarily by the grant. For details, see <a href=\"https://docs.aws.amazon.com/kms/latest/developerguide/grant-manage.html#grant-delete\">Retiring and revoking grants</a> in the <i>Key Management Service Developer Guide</i>.</p> <p> <b>Related operations:</b> </p> <ul> <li> <p> <a>CreateGrant</a> </p> </li> <li> <p> <a>ListGrants</a> </p> </li> <li> <p> <a>ListRetirableGrants</a> </p> </li> <li> <p> <a>RevokeGrant</a> </p> </li> </ul>"
     },
@@ -764,8 +754,7 @@
         {"shape":"InvalidArnException"},
         {"shape":"InvalidGrantIdException"},
         {"shape":"KMSInternalException"},
-        {"shape":"KMSInvalidStateException"},
-        {"shape":"DryRunOperationException"}
+        {"shape":"KMSInvalidStateException"}
       ],
       "documentation":"<p>Deletes the specified grant. You revoke a grant to terminate the permissions that the grant allows. For more information, see <a href=\"https://docs.aws.amazon.com/kms/latest/developerguide/managing-grants.html#grant-delete\">Retiring and revoking grants</a> in the <i> <i>Key Management Service Developer Guide</i> </i>.</p> <p>When you create, retire, or revoke a grant, there might be a brief delay, usually less than five minutes, until the grant is available throughout KMS. This state is known as <i>eventual consistency</i>. For details, see <a href=\"https://docs.aws.amazon.com/kms/latest/developerguide/grants.html#terms-eventual-consistency\">Eventual consistency</a> in the <i> <i>Key Management Service Developer Guide</i> </i>. </p> <p>For detailed information about grants, including grant terminology, see <a href=\"https://docs.aws.amazon.com/kms/latest/developerguide/grants.html\">Grants in KMS</a> in the <i> <i>Key Management Service Developer Guide</i> </i>. For examples of working with grants in several programming languages, see <a href=\"https://docs.aws.amazon.com/kms/latest/developerguide/programming-grants.html\">Programming grants</a>. </p> <p> <b>Cross-account use</b>: Yes. To perform this operation on a KMS key in a different Amazon Web Services account, specify the key ARN in the value of the <code>KeyId</code> parameter.</p> <p> <b>Required permissions</b>: <a href=\"https://docs.aws.amazon.com/kms/latest/developerguide/kms-api-permissions-reference.html\">kms:RevokeGrant</a> (key policy).</p> <p> <b>Related operations:</b> </p> <ul> <li> <p> <a>CreateGrant</a> </p> </li> <li> <p> <a>ListGrants</a> </p> </li> <li> <p> <a>ListRetirableGrants</a> </p> </li> <li> <p> <a>RetireGrant</a> </p> </li> </ul>"
     },
@@ -784,7 +773,7 @@
         {"shape":"KMSInternalException"},
         {"shape":"KMSInvalidStateException"}
       ],
-      "documentation":"<p>Schedules the deletion of a KMS key. By default, KMS applies a waiting period of 30 days, but you can specify a waiting period of 7-30 days. When this operation is successful, the key state of the KMS key changes to <code>PendingDeletion</code> and the key can't be used in any cryptographic operations. It remains in this state for the duration of the waiting period. Before the waiting period ends, you can use <a>CancelKeyDeletion</a> to cancel the deletion of the KMS key. After the waiting period ends, KMS deletes the KMS key, its key material, and all KMS data associated with it, including all aliases that refer to it.</p> <important> <p>Deleting a KMS key is a destructive and potentially dangerous operation. When a KMS key is deleted, all data that was encrypted under the KMS key is unrecoverable. (The only exception is a <a href=\"kms/latest/developerguide/multi-region-keys-delete.html\">multi-Region replica key</a>, or an <a href=\"kms/latest/developerguide/importing-keys-managing.html#import-delete-key\">asymmetric or HMAC KMS key with imported key material</a>.) To prevent the use of a KMS key without deleting it, use <a>DisableKey</a>. </p> </important> <p>You can schedule the deletion of a multi-Region primary key and its replica keys at any time. However, KMS will not delete a multi-Region primary key with existing replica keys. If you schedule the deletion of a primary key with replicas, its key state changes to <code>PendingReplicaDeletion</code> and it cannot be replicated or used in cryptographic operations. This status can continue indefinitely. When the last of its replicas keys is deleted (not just scheduled), the key state of the primary key changes to <code>PendingDeletion</code> and its waiting period (<code>PendingWindowInDays</code>) begins. For details, see <a href=\"https://docs.aws.amazon.com/kms/latest/developerguide/multi-region-keys-delete.html\">Deleting multi-Region keys</a> in the <i>Key Management Service Developer Guide</i>.</p> <p>When KMS <a href=\"https://docs.aws.amazon.com/kms/latest/developerguide/delete-cmk-keystore.html\">deletes a KMS key from an CloudHSM key store</a>, it makes a best effort to delete the associated key material from the associated CloudHSM cluster. However, you might need to manually <a href=\"https://docs.aws.amazon.com/kms/latest/developerguide/fix-keystore.html#fix-keystore-orphaned-key\">delete the orphaned key material</a> from the cluster and its backups. <a href=\"https://docs.aws.amazon.com/kms/latest/developerguide/delete-xks-key.html\">Deleting a KMS key from an external key store</a> has no effect on the associated external key. However, for both types of custom key stores, deleting a KMS key is destructive and irreversible. You cannot decrypt ciphertext encrypted under the KMS key by using only its associated external key or CloudHSM key. Also, you cannot recreate a KMS key in an external key store by creating a new KMS key with the same key material.</p> <p>For more information about scheduling a KMS key for deletion, see <a href=\"https://docs.aws.amazon.com/kms/latest/developerguide/deleting-keys.html\">Deleting KMS keys</a> in the <i>Key Management Service Developer Guide</i>.</p> <p>The KMS key that you use for this operation must be in a compatible key state. For details, see <a href=\"https://docs.aws.amazon.com/kms/latest/developerguide/key-state.html\">Key states of KMS keys</a> in the <i>Key Management Service Developer Guide</i>.</p> <p> <b>Cross-account use</b>: No. You cannot perform this operation on a KMS key in a different Amazon Web Services account.</p> <p> <b>Required permissions</b>: kms:ScheduleKeyDeletion (key policy)</p> <p> <b>Related operations</b> </p> <ul> <li> <p> <a>CancelKeyDeletion</a> </p> </li> <li> <p> <a>DisableKey</a> </p> </li> </ul>"
+      "documentation":"<p>Schedules the deletion of a KMS key. By default, KMS applies a waiting period of 30 days, but you can specify a waiting period of 7-30 days. When this operation is successful, the key state of the KMS key changes to <code>PendingDeletion</code> and the key can't be used in any cryptographic operations. It remains in this state for the duration of the waiting period. Before the waiting period ends, you can use <a>CancelKeyDeletion</a> to cancel the deletion of the KMS key. After the waiting period ends, KMS deletes the KMS key, its key material, and all KMS data associated with it, including all aliases that refer to it.</p> <important> <p>Deleting a KMS key is a destructive and potentially dangerous operation. When a KMS key is deleted, all data that was encrypted under the KMS key is unrecoverable. (The only exception is a <a href=\"kms/latest/developerguide/multi-region-keys-delete.html\">multi-Region replica key</a>, or an asymmetric or HMAC KMS key with imported key material[BUGBUG-link to importing-keys-managing.html#import-delete-key.) To prevent the use of a KMS key without deleting it, use <a>DisableKey</a>. </p> </important> <p>You can schedule the deletion of a multi-Region primary key and its replica keys at any time. However, KMS will not delete a multi-Region primary key with existing replica keys. If you schedule the deletion of a primary key with replicas, its key state changes to <code>PendingReplicaDeletion</code> and it cannot be replicated or used in cryptographic operations. This status can continue indefinitely. When the last of its replicas keys is deleted (not just scheduled), the key state of the primary key changes to <code>PendingDeletion</code> and its waiting period (<code>PendingWindowInDays</code>) begins. For details, see <a href=\"https://docs.aws.amazon.com/kms/latest/developerguide/multi-region-keys-delete.html\">Deleting multi-Region keys</a> in the <i>Key Management Service Developer Guide</i>.</p> <p>When KMS <a href=\"https://docs.aws.amazon.com/kms/latest/developerguide/delete-cmk-keystore.html\">deletes a KMS key from an CloudHSM key store</a>, it makes a best effort to delete the associated key material from the associated CloudHSM cluster. However, you might need to manually <a href=\"https://docs.aws.amazon.com/kms/latest/developerguide/fix-keystore.html#fix-keystore-orphaned-key\">delete the orphaned key material</a> from the cluster and its backups. <a href=\"https://docs.aws.amazon.com/kms/latest/developerguide/delete-xks-key.html\">Deleting a KMS key from an external key store</a> has no effect on the associated external key. However, for both types of custom key stores, deleting a KMS key is destructive and irreversible. You cannot decrypt ciphertext encrypted under the KMS key by using only its associated external key or CloudHSM key. Also, you cannot recreate a KMS key in an external key store by creating a new KMS key with the same key material.</p> <p>For more information about scheduling a KMS key for deletion, see <a href=\"https://docs.aws.amazon.com/kms/latest/developerguide/deleting-keys.html\">Deleting KMS keys</a> in the <i>Key Management Service Developer Guide</i>.</p> <p>The KMS key that you use for this operation must be in a compatible key state. For details, see <a href=\"https://docs.aws.amazon.com/kms/latest/developerguide/key-state.html\">Key states of KMS keys</a> in the <i>Key Management Service Developer Guide</i>.</p> <p> <b>Cross-account use</b>: No. You cannot perform this operation on a KMS key in a different Amazon Web Services account.</p> <p> <b>Required permissions</b>: kms:ScheduleKeyDeletion (key policy)</p> <p> <b>Related operations</b> </p> <ul> <li> <p> <a>CancelKeyDeletion</a> </p> </li> <li> <p> <a>DisableKey</a> </p> </li> </ul>"
     },
     "Sign":{
       "name":"Sign",
@@ -802,8 +791,7 @@
         {"shape":"InvalidKeyUsageException"},
         {"shape":"InvalidGrantTokenException"},
         {"shape":"KMSInternalException"},
-        {"shape":"KMSInvalidStateException"},
-        {"shape":"DryRunOperationException"}
+        {"shape":"KMSInvalidStateException"}
       ],
       "documentation":"<p>Creates a <a href=\"https://en.wikipedia.org/wiki/Digital_signature\">digital signature</a> for a message or message digest by using the private key in an asymmetric signing KMS key. To verify the signature, use the <a>Verify</a> operation, or use the public key in the same asymmetric KMS key outside of KMS. For information about asymmetric KMS keys, see <a href=\"https://docs.aws.amazon.com/kms/latest/developerguide/symmetric-asymmetric.html\">Asymmetric KMS keys</a> in the <i>Key Management Service Developer Guide</i>.</p> <p>Digital signatures are generated and verified by using asymmetric key pair, such as an RSA or ECC pair that is represented by an asymmetric KMS key. The key owner (or an authorized user) uses their private key to sign a message. Anyone with the public key can verify that the message was signed with that particular private key and that the message hasn't changed since it was signed. </p> <p>To use the <code>Sign</code> operation, provide the following information:</p> <ul> <li> <p>Use the <code>KeyId</code> parameter to identify an asymmetric KMS key with a <code>KeyUsage</code> value of <code>SIGN_VERIFY</code>. To get the <code>KeyUsage</code> value of a KMS key, use the <a>DescribeKey</a> operation. The caller must have <code>kms:Sign</code> permission on the KMS key.</p> </li> <li> <p>Use the <code>Message</code> parameter to specify the message or message digest to sign. You can submit messages of up to 4096 bytes. To sign a larger message, generate a hash digest of the message, and then provide the hash digest in the <code>Message</code> parameter. To indicate whether the message is a full message or a digest, use the <code>MessageType</code> parameter.</p> </li> <li> <p>Choose a signing algorithm that is compatible with the KMS key. </p> </li> </ul> <important> <p>When signing a message, be sure to record the KMS key and the signing algorithm. This information is required to verify the signature.</p> </important> <note> <p>Best practices recommend that you limit the time during which any signature is effective. This deters an attack where the actor uses a signed message to establish validity repeatedly or long after the message is superseded. Signatures do not include a timestamp, but you can include a timestamp in the signed message to help you detect when its time to refresh the signature. </p> </note> <p>To verify the signature that this operation generates, use the <a>Verify</a> operation. Or use the <a>GetPublicKey</a> operation to download the public key and then use the public key to verify the signature outside of KMS. </p> <p>The KMS key that you use for this operation must be in a compatible key state. For details, see <a href=\"https://docs.aws.amazon.com/kms/latest/developerguide/key-state.html\">Key states of KMS keys</a> in the <i>Key Management Service Developer Guide</i>.</p> <p> <b>Cross-account use</b>: Yes. To perform this operation with a KMS key in a different Amazon Web Services account, specify the key ARN or alias ARN in the value of the <code>KeyId</code> parameter.</p> <p> <b>Required permissions</b>: <a href=\"https://docs.aws.amazon.com/kms/latest/developerguide/kms-api-permissions-reference.html\">kms:Sign</a> (key policy)</p> <p> <b>Related operations</b>: <a>Verify</a> </p>"
     },
@@ -935,8 +923,7 @@
         {"shape":"InvalidGrantTokenException"},
         {"shape":"KMSInternalException"},
         {"shape":"KMSInvalidStateException"},
-        {"shape":"KMSInvalidSignatureException"},
-        {"shape":"DryRunOperationException"}
+        {"shape":"KMSInvalidSignatureException"}
       ],
       "documentation":"<p>Verifies a digital signature that was generated by the <a>Sign</a> operation. </p> <p/> <p>Verification confirms that an authorized user signed the message with the specified KMS key and signing algorithm, and the message hasn't changed since it was signed. If the signature is verified, the value of the <code>SignatureValid</code> field in the response is <code>True</code>. If the signature verification fails, the <code>Verify</code> operation fails with an <code>KMSInvalidSignatureException</code> exception.</p> <p>A digital signature is generated by using the private key in an asymmetric KMS key. The signature is verified by using the public key in the same asymmetric KMS key. For information about asymmetric KMS keys, see <a href=\"https://docs.aws.amazon.com/kms/latest/developerguide/symmetric-asymmetric.html\">Asymmetric KMS keys</a> in the <i>Key Management Service Developer Guide</i>.</p> <p>To use the <code>Verify</code> operation, specify the same asymmetric KMS key, message, and signing algorithm that were used to produce the signature. The message type does not need to be the same as the one used for signing, but it must indicate whether the value of the <code>Message</code> parameter should be hashed as part of the verification process.</p> <p>You can also verify the digital signature by using the public key of the KMS key outside of KMS. Use the <a>GetPublicKey</a> operation to download the public key in the asymmetric KMS key and then use the public key to verify the signature outside of KMS. The advantage of using the <code>Verify</code> operation is that it is performed within KMS. As a result, it's easy to call, the operation is performed within the FIPS boundary, it is logged in CloudTrail, and you can use key policy and IAM policy to determine who is authorized to use the KMS key to verify signatures.</p> <p>To verify a signature outside of KMS with an SM2 public key (China Regions only), you must specify the distinguishing ID. By default, KMS uses <code>1234567812345678</code> as the distinguishing ID. For more information, see <a href=\"https://docs.aws.amazon.com/kms/latest/developerguide/asymmetric-key-specs.html#key-spec-sm-offline-verification\">Offline verification with SM2 key pairs</a>.</p> <p>The KMS key that you use for this operation must be in a compatible key state. For details, see <a href=\"https://docs.aws.amazon.com/kms/latest/developerguide/key-state.html\">Key states of KMS keys</a> in the <i>Key Management Service Developer Guide</i>.</p> <p> <b>Cross-account use</b>: Yes. To perform this operation with a KMS key in a different Amazon Web Services account, specify the key ARN or alias ARN in the value of the <code>KeyId</code> parameter. </p> <p> <b>Required permissions</b>: <a href=\"https://docs.aws.amazon.com/kms/latest/developerguide/kms-api-permissions-reference.html\">kms:Verify</a> (key policy)</p> <p> <b>Related operations</b>: <a>Sign</a> </p>"
     },
@@ -956,8 +943,7 @@
         {"shape":"InvalidGrantTokenException"},
         {"shape":"KMSInternalException"},
         {"shape":"KMSInvalidMacException"},
-        {"shape":"KMSInvalidStateException"},
-        {"shape":"DryRunOperationException"}
+        {"shape":"KMSInvalidStateException"}
       ],
       "documentation":"<p>Verifies the hash-based message authentication code (HMAC) for a specified message, HMAC KMS key, and MAC algorithm. To verify the HMAC, <code>VerifyMac</code> computes an HMAC using the message, HMAC KMS key, and MAC algorithm that you specify, and compares the computed HMAC to the HMAC that you specify. If the HMACs are identical, the verification succeeds; otherwise, it fails. Verification indicates that the message hasn't changed since the HMAC was calculated, and the specified key was used to generate and verify the HMAC.</p> <p>HMAC KMS keys and the HMAC algorithms that KMS uses conform to industry standards defined in <a href=\"https://datatracker.ietf.org/doc/html/rfc2104\">RFC 2104</a>.</p> <p>This operation is part of KMS support for HMAC KMS keys. For details, see <a href=\"https://docs.aws.amazon.com/kms/latest/developerguide/hmac.html\">HMAC keys in KMS</a> in the <i>Key Management Service Developer Guide</i>.</p> <p>The KMS key that you use for this operation must be in a compatible key state. For details, see <a href=\"https://docs.aws.amazon.com/kms/latest/developerguide/key-state.html\">Key states of KMS keys</a> in the <i>Key Management Service Developer Guide</i>.</p> <p> <b>Cross-account use</b>: Yes. To perform this operation with a KMS key in a different Amazon Web Services account, specify the key ARN or alias ARN in the value of the <code>KeyId</code> parameter. </p> <p> <b>Required permissions</b>: <a href=\"https://docs.aws.amazon.com/kms/latest/developerguide/kms-api-permissions-reference.html\">kms:VerifyMac</a> (key policy)</p> <p> <b>Related operations</b>: <a>GenerateMac</a> </p>"
     }
@@ -1254,10 +1240,6 @@
         "Name":{
           "shape":"GrantNameType",
           "documentation":"<p>A friendly name for the grant. Use this value to prevent the unintended creation of duplicate grants when retrying this request.</p> <important> <p>Do not include confidential or sensitive information in this field. This field may be displayed in plaintext in CloudTrail logs and other output.</p> </important> <p>When this value is absent, all <code>CreateGrant</code> requests result in a new grant with a unique <code>GrantId</code> even if all the supplied parameters are identical. This can result in unintended duplicates when you retry the <code>CreateGrant</code> request.</p> <p>When this value is present, you can retry a <code>CreateGrant</code> request with identical parameters; if the grant already exists, the original <code>GrantId</code> is returned without creating a new grant. Note that the returned grant token is unique with every <code>CreateGrant</code> request, even when a duplicate <code>GrantId</code> is returned. All grant tokens for the same grant ID can be used interchangeably.</p>"
-        },
-        "DryRun":{
-          "shape":"NullableBooleanType",
-          "documentation":"<p>Checks if your request will succeed. <code>DryRun</code> is an optional parameter. </p> <p>To learn more about how to use this parameter, see <a href=\"https://docs.aws.amazon.com/kms/latest/developerguide/programming-dryrun.html\">Testing your KMS API calls</a> in the <i>Key Management Service Developer Guide</i>.</p>"
         }
       }
     },
@@ -1497,10 +1479,6 @@
         "Recipient":{
           "shape":"RecipientInfo",
           "documentation":"<p>A signed <a href=\"https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/nitro-enclave-how.html#term-attestdoc\">attestation document</a> from an Amazon Web Services Nitro enclave and the encryption algorithm to use with the enclave's public key. The only valid encryption algorithm is <code>RSAES_OAEP_SHA_256</code>. </p> <p>This parameter only supports attestation documents for Amazon Web Services Nitro Enclaves. To include this parameter, use the <a href=\"https://docs.aws.amazon.com/enclaves/latest/user/developing-applications.html#sdk\">Amazon Web Services Nitro Enclaves SDK</a> or any Amazon Web Services SDK.</p> <p>When you use this parameter, instead of returning the plaintext data, KMS encrypts the plaintext data with the public key in the attestation document, and returns the resulting ciphertext in the <code>CiphertextForRecipient</code> field in the response. This ciphertext can be decrypted only with the private key in the enclave. The <code>Plaintext</code> field in the response is null or empty.</p> <p>For information about the interaction between KMS and Amazon Web Services Nitro Enclaves, see <a href=\"https://docs.aws.amazon.com/kms/latest/developerguide/services-nitro-enclaves.html\">How Amazon Web Services Nitro Enclaves uses KMS</a> in the <i>Key Management Service Developer Guide</i>.</p>"
-        },
-        "DryRun":{
-          "shape":"NullableBooleanType",
-          "documentation":"<p>Checks if your request will succeed. <code>DryRun</code> is an optional parameter. </p> <p>To learn more about how to use this parameter, see <a href=\"https://docs.aws.amazon.com/kms/latest/developerguide/programming-dryrun.html\">Testing your KMS API calls</a> in the <i>Key Management Service Developer Guide</i>.</p>"
         }
       }
     },
@@ -1678,14 +1656,6 @@
       "members":{
       }
     },
-    "DryRunOperationException":{
-      "type":"structure",
-      "members":{
-        "message":{"shape":"ErrorMessageType"}
-      },
-      "documentation":"<p> The request was rejected because the DryRun parameter was specified. </p>",
-      "exception":true
-    },
     "EnableKeyRequest":{
       "type":"structure",
       "required":["KeyId"],
@@ -1732,10 +1702,6 @@
         "EncryptionAlgorithm":{
           "shape":"EncryptionAlgorithmSpec",
           "documentation":"<p>Specifies the encryption algorithm that KMS will use to encrypt the plaintext message. The algorithm must be compatible with the KMS key that you specify.</p> <p>This parameter is required only for asymmetric KMS keys. The default value, <code>SYMMETRIC_DEFAULT</code>, is the algorithm used for symmetric encryption KMS keys. If you are using an asymmetric KMS key, we recommend RSAES_OAEP_SHA_256.</p> <p>The SM2PKE algorithm is only available in China Regions.</p>"
-        },
-        "DryRun":{
-          "shape":"NullableBooleanType",
-          "documentation":"<p>Checks if your request will succeed. <code>DryRun</code> is an optional parameter. </p> <p>To learn more about how to use this parameter, see <a href=\"https://docs.aws.amazon.com/kms/latest/developerguide/programming-dryrun.html\">Testing your KMS API calls</a> in the <i>Key Management Service Developer Guide</i>.</p>"
         }
       }
     },
@@ -1818,10 +1784,6 @@
         "Recipient":{
           "shape":"RecipientInfo",
           "documentation":"<p>A signed <a href=\"https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/nitro-enclave-how.html#term-attestdoc\">attestation document</a> from an Amazon Web Services Nitro enclave and the encryption algorithm to use with the enclave's public key. The only valid encryption algorithm is <code>RSAES_OAEP_SHA_256</code>. </p> <p>This parameter only supports attestation documents for Amazon Web Services Nitro Enclaves. To include this parameter, use the <a href=\"https://docs.aws.amazon.com/enclaves/latest/user/developing-applications.html#sdk\">Amazon Web Services Nitro Enclaves SDK</a> or any Amazon Web Services SDK.</p> <p>When you use this parameter, instead of returning a plaintext copy of the private data key, KMS encrypts the plaintext private data key under the public key in the attestation document, and returns the resulting ciphertext in the <code>CiphertextForRecipient</code> field in the response. This ciphertext can be decrypted only with the private key in the enclave. The <code>CiphertextBlob</code> field in the response contains a copy of the private data key encrypted under the KMS key specified by the <code>KeyId</code> parameter. The <code>PrivateKeyPlaintext</code> field in the response is null or empty.</p> <p>For information about the interaction between KMS and Amazon Web Services Nitro Enclaves, see <a href=\"https://docs.aws.amazon.com/kms/latest/developerguide/services-nitro-enclaves.html\">How Amazon Web Services Nitro Enclaves uses KMS</a> in the <i>Key Management Service Developer Guide</i>.</p>"
-        },
-        "DryRun":{
-          "shape":"NullableBooleanType",
-          "documentation":"<p>Checks if your request will succeed. <code>DryRun</code> is an optional parameter. </p> <p>To learn more about how to use this parameter, see <a href=\"https://docs.aws.amazon.com/kms/latest/developerguide/programming-dryrun.html\">Testing your KMS API calls</a> in the <i>Key Management Service Developer Guide</i>.</p>"
         }
       }
     },
@@ -1876,10 +1838,6 @@
         "GrantTokens":{
           "shape":"GrantTokenList",
           "documentation":"<p>A list of grant tokens.</p> <p>Use a grant token when your permission to call this operation comes from a new grant that has not yet achieved <i>eventual consistency</i>. For more information, see <a href=\"https://docs.aws.amazon.com/kms/latest/developerguide/grants.html#grant_token\">Grant token</a> and <a href=\"https://docs.aws.amazon.com/kms/latest/developerguide/grant-manage.html#using-grant-token\">Using a grant token</a> in the <i>Key Management Service Developer Guide</i>.</p>"
-        },
-        "DryRun":{
-          "shape":"NullableBooleanType",
-          "documentation":"<p>Checks if your request will succeed. <code>DryRun</code> is an optional parameter. </p> <p>To learn more about how to use this parameter, see <a href=\"https://docs.aws.amazon.com/kms/latest/developerguide/programming-dryrun.html\">Testing your KMS API calls</a> in the <i>Key Management Service Developer Guide</i>.</p>"
         }
       }
     },
@@ -1931,10 +1889,6 @@
         "Recipient":{
           "shape":"RecipientInfo",
           "documentation":"<p>A signed <a href=\"https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/nitro-enclave-how.html#term-attestdoc\">attestation document</a> from an Amazon Web Services Nitro enclave and the encryption algorithm to use with the enclave's public key. The only valid encryption algorithm is <code>RSAES_OAEP_SHA_256</code>. </p> <p>This parameter only supports attestation documents for Amazon Web Services Nitro Enclaves. To include this parameter, use the <a href=\"https://docs.aws.amazon.com/enclaves/latest/user/developing-applications.html#sdk\">Amazon Web Services Nitro Enclaves SDK</a> or any Amazon Web Services SDK.</p> <p>When you use this parameter, instead of returning the plaintext data key, KMS encrypts the plaintext data key under the public key in the attestation document, and returns the resulting ciphertext in the <code>CiphertextForRecipient</code> field in the response. This ciphertext can be decrypted only with the private key in the enclave. The <code>CiphertextBlob</code> field in the response contains a copy of the data key encrypted under the KMS key specified by the <code>KeyId</code> parameter. The <code>Plaintext</code> field in the response is null or empty.</p> <p>For information about the interaction between KMS and Amazon Web Services Nitro Enclaves, see <a href=\"https://docs.aws.amazon.com/kms/latest/developerguide/services-nitro-enclaves.html\">How Amazon Web Services Nitro Enclaves uses KMS</a> in the <i>Key Management Service Developer Guide</i>.</p>"
-        },
-        "DryRun":{
-          "shape":"NullableBooleanType",
-          "documentation":"<p>Checks if your request will succeed. <code>DryRun</code> is an optional parameter. </p> <p>To learn more about how to use this parameter, see <a href=\"https://docs.aws.amazon.com/kms/latest/developerguide/programming-dryrun.html\">Testing your KMS API calls</a> in the <i>Key Management Service Developer Guide</i>.</p>"
         }
       }
     },
@@ -1982,10 +1936,6 @@
         "GrantTokens":{
           "shape":"GrantTokenList",
           "documentation":"<p>A list of grant tokens.</p> <p>Use a grant token when your permission to call this operation comes from a new grant that has not yet achieved <i>eventual consistency</i>. For more information, see <a href=\"https://docs.aws.amazon.com/kms/latest/developerguide/grants.html#grant_token\">Grant token</a> and <a href=\"https://docs.aws.amazon.com/kms/latest/developerguide/grant-manage.html#using-grant-token\">Using a grant token</a> in the <i>Key Management Service Developer Guide</i>.</p>"
-        },
-        "DryRun":{
-          "shape":"NullableBooleanType",
-          "documentation":"<p>Checks if your request will succeed. <code>DryRun</code> is an optional parameter. </p> <p>To learn more about how to use this parameter, see <a href=\"https://docs.aws.amazon.com/kms/latest/developerguide/programming-dryrun.html\">Testing your KMS API calls</a> in the <i>Key Management Service Developer Guide</i>.</p>"
         }
       }
     },
@@ -2025,10 +1975,6 @@
         "GrantTokens":{
           "shape":"GrantTokenList",
           "documentation":"<p>A list of grant tokens.</p> <p>Use a grant token when your permission to call this operation comes from a new grant that has not yet achieved <i>eventual consistency</i>. For more information, see <a href=\"https://docs.aws.amazon.com/kms/latest/developerguide/grants.html#grant_token\">Grant token</a> and <a href=\"https://docs.aws.amazon.com/kms/latest/developerguide/grant-manage.html#using-grant-token\">Using a grant token</a> in the <i>Key Management Service Developer Guide</i>.</p>"
-        },
-        "DryRun":{
-          "shape":"NullableBooleanType",
-          "documentation":"<p>Checks if your request will succeed. <code>DryRun</code> is an optional parameter. </p> <p>To learn more about how to use this parameter, see <a href=\"https://docs.aws.amazon.com/kms/latest/developerguide/programming-dryrun.html\">Testing your KMS API calls</a> in the <i>Key Management Service Developer Guide</i>.</p>"
         }
       }
     },
@@ -3082,10 +3028,6 @@
         "GrantTokens":{
           "shape":"GrantTokenList",
           "documentation":"<p>A list of grant tokens.</p> <p>Use a grant token when your permission to call this operation comes from a new grant that has not yet achieved <i>eventual consistency</i>. For more information, see <a href=\"https://docs.aws.amazon.com/kms/latest/developerguide/grants.html#grant_token\">Grant token</a> and <a href=\"https://docs.aws.amazon.com/kms/latest/developerguide/grant-manage.html#using-grant-token\">Using a grant token</a> in the <i>Key Management Service Developer Guide</i>.</p>"
-        },
-        "DryRun":{
-          "shape":"NullableBooleanType",
-          "documentation":"<p>Checks if your request will succeed. <code>DryRun</code> is an optional parameter. </p> <p>To learn more about how to use this parameter, see <a href=\"https://docs.aws.amazon.com/kms/latest/developerguide/programming-dryrun.html\">Testing your KMS API calls</a> in the <i>Key Management Service Developer Guide</i>.</p>"
         }
       }
     },
@@ -3198,10 +3140,6 @@
         "GrantId":{
           "shape":"GrantIdType",
           "documentation":"<p>Identifies the grant to retire. To get the grant ID, use <a>CreateGrant</a>, <a>ListGrants</a>, or <a>ListRetirableGrants</a>.</p> <ul> <li> <p>Grant ID Example - 0123456789012345678901234567890123456789012345678901234567890123</p> </li> </ul>"
-        },
-        "DryRun":{
-          "shape":"NullableBooleanType",
-          "documentation":"<p>Checks if your request will succeed. <code>DryRun</code> is an optional parameter. </p> <p>To learn more about how to use this parameter, see <a href=\"https://docs.aws.amazon.com/kms/latest/developerguide/programming-dryrun.html\">Testing your KMS API calls</a> in the <i>Key Management Service Developer Guide</i>.</p>"
         }
       }
     },
@@ -3219,10 +3157,6 @@
         "GrantId":{
           "shape":"GrantIdType",
           "documentation":"<p>Identifies the grant to revoke. To get the grant ID, use <a>CreateGrant</a>, <a>ListGrants</a>, or <a>ListRetirableGrants</a>.</p>"
-        },
-        "DryRun":{
-          "shape":"NullableBooleanType",
-          "documentation":"<p>Checks if your request will succeed. <code>DryRun</code> is an optional parameter. </p> <p>To learn more about how to use this parameter, see <a href=\"https://docs.aws.amazon.com/kms/latest/developerguide/programming-dryrun.html\">Testing your KMS API calls</a> in the <i>Key Management Service Developer Guide</i>.</p>"
         }
       }
     },
@@ -3236,7 +3170,7 @@
         },
         "PendingWindowInDays":{
           "shape":"PendingWindowInDaysType",
-          "documentation":"<p>The waiting period, specified in number of days. After the waiting period ends, KMS deletes the KMS key.</p> <p>If the KMS key is a multi-Region primary key with replica keys, the waiting period begins when the last of its replica keys is deleted. Otherwise, the waiting period begins immediately.</p> <p>This value is optional. If you include a value, it must be between 7 and 30, inclusive. If you do not include a value, it defaults to 30. You can use the <a href=\"https://docs.aws.amazon.com/kms/latest/developerguide/conditions-kms.html#conditions-kms-schedule-key-deletion-pending-window-in-days\"> <code>kms:ScheduleKeyDeletionPendingWindowInDays</code> </a> condition key to further constrain the values that principals can specify in the <code>PendingWindowInDays</code> parameter.</p>"
+          "documentation":"<p>The waiting period, specified in number of days. After the waiting period ends, KMS deletes the KMS key.</p> <p>If the KMS key is a multi-Region primary key with replica keys, the waiting period begins when the last of its replica keys is deleted. Otherwise, the waiting period begins immediately.</p> <p>This value is optional. If you include a value, it must be between 7 and 30, inclusive. If you do not include a value, it defaults to 30. You can use the <a href=\"https://docs.aws.amazon.com/kms/latest/developerguide/conditions-kms.html#conditions-pending-deletion-window\"> <code>kms:ScheduleKeyDeletionPendingWindowInDays</code> </a> condition key to further constrain the values that principals can specify in the <code>PendingWindowInDays</code> parameter.</p>"
         }
       }
     },
@@ -3288,10 +3222,6 @@
         "SigningAlgorithm":{
           "shape":"SigningAlgorithmSpec",
           "documentation":"<p>Specifies the signing algorithm to use when signing the message. </p> <p>Choose an algorithm that is compatible with the type and size of the specified asymmetric KMS key. When signing with RSA key pairs, RSASSA-PSS algorithms are preferred. We include RSASSA-PKCS1-v1_5 algorithms for compatibility with existing applications.</p>"
-        },
-        "DryRun":{
-          "shape":"NullableBooleanType",
-          "documentation":"<p>Checks if your request will succeed. <code>DryRun</code> is an optional parameter. </p> <p>To learn more about how to use this parameter, see <a href=\"https://docs.aws.amazon.com/kms/latest/developerguide/programming-dryrun.html\">Testing your KMS API calls</a> in the <i>Key Management Service Developer Guide</i>.</p>"
         }
       }
     },
@@ -3548,10 +3478,6 @@
         "GrantTokens":{
           "shape":"GrantTokenList",
           "documentation":"<p>A list of grant tokens.</p> <p>Use a grant token when your permission to call this operation comes from a new grant that has not yet achieved <i>eventual consistency</i>. For more information, see <a href=\"https://docs.aws.amazon.com/kms/latest/developerguide/grants.html#grant_token\">Grant token</a> and <a href=\"https://docs.aws.amazon.com/kms/latest/developerguide/grant-manage.html#using-grant-token\">Using a grant token</a> in the <i>Key Management Service Developer Guide</i>.</p>"
-        },
-        "DryRun":{
-          "shape":"NullableBooleanType",
-          "documentation":"<p>Checks if your request will succeed. <code>DryRun</code> is an optional parameter. </p> <p>To learn more about how to use this parameter, see <a href=\"https://docs.aws.amazon.com/kms/latest/developerguide/programming-dryrun.html\">Testing your KMS API calls</a> in the <i>Key Management Service Developer Guide</i>.</p>"
         }
       }
     },
@@ -3604,10 +3530,6 @@
         "GrantTokens":{
           "shape":"GrantTokenList",
           "documentation":"<p>A list of grant tokens.</p> <p>Use a grant token when your permission to call this operation comes from a new grant that has not yet achieved <i>eventual consistency</i>. For more information, see <a href=\"https://docs.aws.amazon.com/kms/latest/developerguide/grants.html#grant_token\">Grant token</a> and <a href=\"https://docs.aws.amazon.com/kms/latest/developerguide/grant-manage.html#using-grant-token\">Using a grant token</a> in the <i>Key Management Service Developer Guide</i>.</p>"
-        },
-        "DryRun":{
-          "shape":"NullableBooleanType",
-          "documentation":"<p>Checks if your request will succeed. <code>DryRun</code> is an optional parameter. </p> <p>To learn more about how to use this parameter, see <a href=\"https://docs.aws.amazon.com/kms/latest/developerguide/programming-dryrun.html\">Testing your KMS API calls</a> in the <i>Key Management Service Developer Guide</i>.</p>"
         }
       }
     },
diff --git a/botocore/data/mgn/2020-02-26/paginators-1.json b/botocore/data/mgn/2020-02-26/paginators-1.json
index 7500df2e9..44640baf5 100644
--- a/botocore/data/mgn/2020-02-26/paginators-1.json
+++ b/botocore/data/mgn/2020-02-26/paginators-1.json
@@ -83,12 +83,6 @@
       "output_token": "nextToken",
       "limit_key": "maxResults",
       "result_key": "items"
-    },
-    "ListManagedAccounts": {
-      "input_token": "nextToken",
-      "output_token": "nextToken",
-      "limit_key": "maxResults",
-      "result_key": "items"
     }
   }
 }
diff --git a/botocore/data/mgn/2020-02-26/service-2.json b/botocore/data/mgn/2020-02-26/service-2.json
index c5b77936d..bb8325c55 100644
--- a/botocore/data/mgn/2020-02-26/service-2.json
+++ b/botocore/data/mgn/2020-02-26/service-2.json
@@ -562,21 +562,6 @@
       ],
       "documentation":"<p>List imports.</p>"
     },
-    "ListManagedAccounts":{
-      "name":"ListManagedAccounts",
-      "http":{
-        "method":"POST",
-        "requestUri":"/ListManagedAccounts",
-        "responseCode":200
-      },
-      "input":{"shape":"ListManagedAccountsRequest"},
-      "output":{"shape":"ListManagedAccountsResponse"},
-      "errors":[
-        {"shape":"UninitializedAccountException"},
-        {"shape":"ValidationException"}
-      ],
-      "documentation":"<p>List Managed Accounts.</p>"
-    },
     "ListSourceServerActions":{
       "name":"ListSourceServerActions",
       "http":{
@@ -655,24 +640,6 @@
       ],
       "documentation":"<p>Archives specific Source Servers by setting the SourceServer.isArchived property to true for specified SourceServers by ID. This command only works for SourceServers with a lifecycle. state which equals DISCONNECTED or CUTOVER.</p>"
     },
-    "PauseReplication":{
-      "name":"PauseReplication",
-      "http":{
-        "method":"POST",
-        "requestUri":"/PauseReplication",
-        "responseCode":200
-      },
-      "input":{"shape":"PauseReplicationRequest"},
-      "output":{"shape":"SourceServer"},
-      "errors":[
-        {"shape":"UninitializedAccountException"},
-        {"shape":"ResourceNotFoundException"},
-        {"shape":"ValidationException"},
-        {"shape":"ServiceQuotaExceededException"},
-        {"shape":"ConflictException"}
-      ],
-      "documentation":"<p>Pause Replication.</p>"
-    },
     "PutSourceServerAction":{
       "name":"PutSourceServerAction",
       "http":{
@@ -739,24 +706,6 @@
       ],
       "documentation":"<p>Remove template post migration custom action.</p>"
     },
-    "ResumeReplication":{
-      "name":"ResumeReplication",
-      "http":{
-        "method":"POST",
-        "requestUri":"/ResumeReplication",
-        "responseCode":200
-      },
-      "input":{"shape":"ResumeReplicationRequest"},
-      "output":{"shape":"SourceServer"},
-      "errors":[
-        {"shape":"UninitializedAccountException"},
-        {"shape":"ResourceNotFoundException"},
-        {"shape":"ValidationException"},
-        {"shape":"ServiceQuotaExceededException"},
-        {"shape":"ConflictException"}
-      ],
-      "documentation":"<p>Resume Replication.</p>"
-    },
     "RetryDataReplication":{
       "name":"RetryDataReplication",
       "http":{
@@ -857,24 +806,6 @@
       ],
       "documentation":"<p>Launches a Test Instance for specific Source Servers. This command starts a LAUNCH job whose initiatedBy property is StartTest and changes the SourceServer.lifeCycle.state property to TESTING.</p>"
     },
-    "StopReplication":{
-      "name":"StopReplication",
-      "http":{
-        "method":"POST",
-        "requestUri":"/StopReplication",
-        "responseCode":200
-      },
-      "input":{"shape":"StopReplicationRequest"},
-      "output":{"shape":"SourceServer"},
-      "errors":[
-        {"shape":"UninitializedAccountException"},
-        {"shape":"ResourceNotFoundException"},
-        {"shape":"ValidationException"},
-        {"shape":"ServiceQuotaExceededException"},
-        {"shape":"ConflictException"}
-      ],
-      "documentation":"<p>Stop Replication.</p>"
-    },
     "TagResource":{
       "name":"TagResource",
       "http":{
@@ -1267,10 +1198,6 @@
       "type":"structure",
       "required":["applicationID"],
       "members":{
-        "accountID":{
-          "shape":"AccountID",
-          "documentation":"<p>Account ID.</p>"
-        },
         "applicationID":{
           "shape":"ApplicationID",
           "documentation":"<p>Application ID.</p>"
@@ -1281,10 +1208,6 @@
       "type":"structure",
       "required":["waveID"],
       "members":{
-        "accountID":{
-          "shape":"AccountID",
-          "documentation":"<p>Account ID.</p>"
-        },
         "waveID":{
           "shape":"WaveID",
           "documentation":"<p>Wave ID.</p>"
@@ -1298,10 +1221,6 @@
         "waveID"
       ],
       "members":{
-        "accountID":{
-          "shape":"AccountID",
-          "documentation":"<p>Account ID.</p>"
-        },
         "applicationIDs":{
           "shape":"ApplicationIDs",
           "documentation":"<p>Application IDs list.</p>"
@@ -1324,10 +1243,6 @@
         "sourceServerIDs"
       ],
       "members":{
-        "accountID":{
-          "shape":"AccountID",
-          "documentation":"<p>Account ID.</p>"
-        },
         "applicationID":{
           "shape":"ApplicationID",
           "documentation":"<p>Application ID.</p>"
@@ -1349,11 +1264,6 @@
       "members":{
       }
     },
-    "BandwidthThrottling":{
-      "type":"long",
-      "max":10000,
-      "min":0
-    },
     "Boolean":{
       "type":"boolean",
       "box":true
@@ -1391,10 +1301,6 @@
         "sourceServerID"
       ],
       "members":{
-        "accountID":{
-          "shape":"AccountID",
-          "documentation":"<p>The request to change the source server migration account ID.</p>"
-        },
         "lifeCycle":{
           "shape":"ChangeServerLifeCycleStateSourceServerLifecycle",
           "documentation":"<p>The request to change the source server migration lifecycle state.</p>"
@@ -1474,10 +1380,6 @@
       "type":"structure",
       "required":["name"],
       "members":{
-        "accountID":{
-          "shape":"AccountID",
-          "documentation":"<p>Account ID.</p>"
-        },
         "description":{
           "shape":"ApplicationDescription",
           "documentation":"<p>Application description.</p>"
@@ -1571,7 +1473,7 @@
           "documentation":"<p>Request to associate the default Application Migration Service Security group with the Replication Settings template.</p>"
         },
         "bandwidthThrottling":{
-          "shape":"BandwidthThrottling",
+          "shape":"PositiveInteger",
           "documentation":"<p>Request to configure bandwidth throttling during Replication Settings template creation.</p>"
         },
         "createPublicIP":{
@@ -1617,10 +1519,6 @@
         "useDedicatedReplicationServer":{
           "shape":"Boolean",
           "documentation":"<p>Request to use Dedicated Replication Servers during Replication Settings template creation.</p>"
-        },
-        "useFipsEndpoint":{
-          "shape":"Boolean",
-          "documentation":"<p>Request to use Fips Endpoint during Replication Settings template creation.</p>"
         }
       }
     },
@@ -1628,10 +1526,6 @@
       "type":"structure",
       "required":["name"],
       "members":{
-        "accountID":{
-          "shape":"AccountID",
-          "documentation":"<p>Account ID.</p>"
-        },
         "description":{
           "shape":"WaveDescription",
           "documentation":"<p>Wave description.</p>"
@@ -1830,10 +1724,6 @@
       "type":"structure",
       "required":["applicationID"],
       "members":{
-        "accountID":{
-          "shape":"AccountID",
-          "documentation":"<p>Account ID.</p>"
-        },
         "applicationID":{
           "shape":"ApplicationID",
           "documentation":"<p>Application ID.</p>"
@@ -1849,10 +1739,6 @@
       "type":"structure",
       "required":["jobID"],
       "members":{
-        "accountID":{
-          "shape":"AccountID",
-          "documentation":"<p>Request to delete Job from service by Account ID.</p>"
-        },
         "jobID":{
           "shape":"JobID",
           "documentation":"<p>Request to delete Job from service by Job ID.</p>"
@@ -1898,10 +1784,6 @@
       "type":"structure",
       "required":["sourceServerID"],
       "members":{
-        "accountID":{
-          "shape":"AccountID",
-          "documentation":"<p>Request to delete Source Server from service by Account ID.</p>"
-        },
         "sourceServerID":{
           "shape":"SourceServerID",
           "documentation":"<p>Request to delete Source Server from service by Server ID.</p>"
@@ -1927,10 +1809,6 @@
       "type":"structure",
       "required":["waveID"],
       "members":{
-        "accountID":{
-          "shape":"AccountID",
-          "documentation":"<p>Account ID.</p>"
-        },
         "waveID":{
           "shape":"WaveID",
           "documentation":"<p>Wave ID.</p>"
@@ -1946,10 +1824,6 @@
       "type":"structure",
       "required":["jobID"],
       "members":{
-        "accountID":{
-          "shape":"AccountID",
-          "documentation":"<p>Request to describe Job log Account ID.</p>"
-        },
         "jobID":{
           "shape":"JobID",
           "documentation":"<p>Request to describe Job log job ID.</p>"
@@ -1980,10 +1854,6 @@
     "DescribeJobsRequest":{
       "type":"structure",
       "members":{
-        "accountID":{
-          "shape":"AccountID",
-          "documentation":"<p>Request to describe job log items by Account ID.</p>"
-        },
         "filters":{
           "shape":"DescribeJobsRequestFilters",
           "documentation":"<p>Request to describe Job log filters.</p>"
@@ -2098,10 +1968,6 @@
     "DescribeSourceServersRequest":{
       "type":"structure",
       "members":{
-        "accountID":{
-          "shape":"AccountID",
-          "documentation":"<p>Request to filter Source Servers list by Accoun ID.</p>"
-        },
         "filters":{
           "shape":"DescribeSourceServersRequestFilters",
           "documentation":"<p>Request to filter Source Servers list.</p>"
@@ -2204,10 +2070,6 @@
         "waveID"
       ],
       "members":{
-        "accountID":{
-          "shape":"AccountID",
-          "documentation":"<p>Account ID.</p>"
-        },
         "applicationIDs":{
           "shape":"ApplicationIDs",
           "documentation":"<p>Application IDs list.</p>"
@@ -2230,10 +2092,6 @@
         "sourceServerIDs"
       ],
       "members":{
-        "accountID":{
-          "shape":"AccountID",
-          "documentation":"<p>Account ID.</p>"
-        },
         "applicationID":{
           "shape":"ApplicationID",
           "documentation":"<p>Application ID.</p>"
@@ -2259,10 +2117,6 @@
       "type":"structure",
       "required":["sourceServerID"],
       "members":{
-        "accountID":{
-          "shape":"AccountID",
-          "documentation":"<p>Request to disconnect Source Server from service by Account ID.</p>"
-        },
         "sourceServerID":{
           "shape":"SourceServerID",
           "documentation":"<p>Request to disconnect Source Server from service by Server ID.</p>"
@@ -2443,10 +2297,6 @@
       "type":"structure",
       "required":["sourceServerID"],
       "members":{
-        "accountID":{
-          "shape":"AccountID",
-          "documentation":"<p>Request to finalize Cutover by Source Account ID.</p>"
-        },
         "sourceServerID":{
           "shape":"SourceServerID",
           "documentation":"<p>Request to finalize Cutover by Source Server ID.</p>"
@@ -2470,10 +2320,6 @@
       "type":"structure",
       "required":["sourceServerID"],
       "members":{
-        "accountID":{
-          "shape":"AccountID",
-          "documentation":"<p>Request to get Launch Configuration information by Account ID.</p>"
-        },
         "sourceServerID":{
           "shape":"SourceServerID",
           "documentation":"<p>Request to get Launch Configuration information by Source Server ID.</p>"
@@ -2484,10 +2330,6 @@
       "type":"structure",
       "required":["sourceServerID"],
       "members":{
-        "accountID":{
-          "shape":"AccountID",
-          "documentation":"<p>Request to get Replication Configuration by Account ID.</p>"
-        },
         "sourceServerID":{
           "shape":"SourceServerID",
           "documentation":"<p>Request to get Replication Configuration by Source Server ID.</p>"
@@ -2538,10 +2380,6 @@
     "ImportErrorData":{
       "type":"structure",
       "members":{
-        "accountID":{
-          "shape":"AccountID",
-          "documentation":"<p>Import error data source account ID.</p>"
-        },
         "applicationID":{
           "shape":"ApplicationID",
           "documentation":"<p>Import error data application ID.</p>"
@@ -2753,11 +2591,6 @@
       "exception":true,
       "fault":true
     },
-    "Iops":{
-      "type":"long",
-      "max":64000,
-      "min":100
-    },
     "JmesPathString":{
       "type":"string",
       "max":1011,
@@ -3088,11 +2921,11 @@
       "type":"structure",
       "members":{
         "iops":{
-          "shape":"Iops",
+          "shape":"PositiveInteger",
           "documentation":"<p>Launch template disk iops configuration.</p>"
         },
         "throughput":{
-          "shape":"Throughput",
+          "shape":"PositiveInteger",
           "documentation":"<p>Launch template disk throughput configuration.</p>"
         },
         "volumeType":{
@@ -3292,10 +3125,6 @@
     "ListApplicationsRequest":{
       "type":"structure",
       "members":{
-        "accountID":{
-          "shape":"AccountID",
-          "documentation":"<p>Applications list Account ID.</p>"
-        },
         "filters":{
           "shape":"ListApplicationsRequestFilters",
           "documentation":"<p>Applications list filters.</p>"
@@ -3494,43 +3323,10 @@
       },
       "documentation":"<p>List import response.</p>"
     },
-    "ListManagedAccountsRequest":{
-      "type":"structure",
-      "members":{
-        "maxResults":{
-          "shape":"MaxResultsType",
-          "documentation":"<p>List managed accounts request max results.</p>"
-        },
-        "nextToken":{
-          "shape":"PaginationToken",
-          "documentation":"<p>List managed accounts request next token.</p>"
-        }
-      },
-      "documentation":"<p>List managed accounts request.</p>"
-    },
-    "ListManagedAccountsResponse":{
-      "type":"structure",
-      "required":["items"],
-      "members":{
-        "items":{
-          "shape":"ManagedAccounts",
-          "documentation":"<p>List managed accounts response items.</p>"
-        },
-        "nextToken":{
-          "shape":"PaginationToken",
-          "documentation":"<p>List managed accounts response next token.</p>"
-        }
-      },
-      "documentation":"<p>List managed accounts response.</p>"
-    },
     "ListSourceServerActionsRequest":{
       "type":"structure",
       "required":["sourceServerID"],
       "members":{
-        "accountID":{
-          "shape":"AccountID",
-          "documentation":"<p>Account ID to return when listing source server post migration custom actions.</p>"
-        },
         "filters":{
           "shape":"SourceServerActionsRequestFilters",
           "documentation":"<p>Filters to apply when listing source server post migration custom actions.</p>"
@@ -3621,10 +3417,6 @@
     "ListWavesRequest":{
       "type":"structure",
       "members":{
-        "accountID":{
-          "shape":"AccountID",
-          "documentation":"<p>Request account ID.</p>"
-        },
         "filters":{
           "shape":"ListWavesRequestFilters",
           "documentation":"<p>Waves list filters.</p>"
@@ -3666,30 +3458,10 @@
         }
       }
     },
-    "ManagedAccount":{
-      "type":"structure",
-      "members":{
-        "accountId":{
-          "shape":"AccountID",
-          "documentation":"<p>Managed account, account ID.</p>"
-        }
-      },
-      "documentation":"<p>Managed account.</p>"
-    },
-    "ManagedAccounts":{
-      "type":"list",
-      "member":{"shape":"ManagedAccount"},
-      "max":1000,
-      "min":0
-    },
     "MarkAsArchivedRequest":{
       "type":"structure",
       "required":["sourceServerID"],
       "members":{
-        "accountID":{
-          "shape":"AccountID",
-          "documentation":"<p>Mark as archived by Account ID.</p>"
-        },
         "sourceServerID":{
           "shape":"SourceServerID",
           "documentation":"<p>Mark as archived by Source Server ID.</p>"
@@ -3776,20 +3548,6 @@
       "type":"list",
       "member":{"shape":"ParticipatingServer"}
     },
-    "PauseReplicationRequest":{
-      "type":"structure",
-      "required":["sourceServerID"],
-      "members":{
-        "accountID":{
-          "shape":"AccountID",
-          "documentation":"<p>Pause Replication Request account ID.</p>"
-        },
-        "sourceServerID":{
-          "shape":"SourceServerID",
-          "documentation":"<p>Pause Replication Request source server ID.</p>"
-        }
-      }
-    },
     "PositiveInteger":{
       "type":"long",
       "min":0
@@ -3864,10 +3622,6 @@
         "sourceServerID"
       ],
       "members":{
-        "accountID":{
-          "shape":"AccountID",
-          "documentation":"<p>Source server post migration custom account ID.</p>"
-        },
         "actionID":{
           "shape":"ActionID",
           "documentation":"<p>Source server post migration custom action ID.</p>"
@@ -3997,10 +3751,6 @@
         "sourceServerID"
       ],
       "members":{
-        "accountID":{
-          "shape":"AccountID",
-          "documentation":"<p>Source server post migration account ID.</p>"
-        },
         "actionID":{
           "shape":"ActionID",
           "documentation":"<p>Source server post migration custom action ID to remove.</p>"
@@ -4046,7 +3796,7 @@
           "documentation":"<p>Replication Configuration associate default Application Migration Service Security Group.</p>"
         },
         "bandwidthThrottling":{
-          "shape":"BandwidthThrottling",
+          "shape":"PositiveInteger",
           "documentation":"<p>Replication Configuration set bandwidth throttling.</p>"
         },
         "createPublicIP":{
@@ -4100,10 +3850,6 @@
         "useDedicatedReplicationServer":{
           "shape":"Boolean",
           "documentation":"<p>Replication Configuration use Dedicated Replication Server.</p>"
-        },
-        "useFipsEndpoint":{
-          "shape":"Boolean",
-          "documentation":"<p>Replication Configuration use Fips Endpoint.</p>"
         }
       }
     },
@@ -4187,7 +3933,7 @@
           "documentation":"<p>Replication Configuration template associate default Application Migration Service Security group.</p>"
         },
         "bandwidthThrottling":{
-          "shape":"BandwidthThrottling",
+          "shape":"PositiveInteger",
           "documentation":"<p>Replication Configuration template bandwidth throttling.</p>"
         },
         "createPublicIP":{
@@ -4237,10 +3983,6 @@
         "useDedicatedReplicationServer":{
           "shape":"Boolean",
           "documentation":"<p>Replication Configuration template use Dedicated Replication Server.</p>"
-        },
-        "useFipsEndpoint":{
-          "shape":"Boolean",
-          "documentation":"<p>Replication Configuration template use Fips Endpoint.</p>"
         }
       }
     },
@@ -4300,28 +4042,10 @@
       },
       "exception":true
     },
-    "ResumeReplicationRequest":{
-      "type":"structure",
-      "required":["sourceServerID"],
-      "members":{
-        "accountID":{
-          "shape":"AccountID",
-          "documentation":"<p>Resume Replication Request account ID.</p>"
-        },
-        "sourceServerID":{
-          "shape":"SourceServerID",
-          "documentation":"<p>Resume Replication Request source server ID.</p>"
-        }
-      }
-    },
     "RetryDataReplicationRequest":{
       "type":"structure",
       "required":["sourceServerID"],
       "members":{
-        "accountID":{
-          "shape":"AccountID",
-          "documentation":"<p>Retry data replication for Account ID.</p>"
-        },
         "sourceServerID":{
           "shape":"SourceServerID",
           "documentation":"<p>Retry data replication for Source Server ID.</p>"
@@ -4703,10 +4427,6 @@
       "type":"structure",
       "required":["sourceServerIDs"],
       "members":{
-        "accountID":{
-          "shape":"AccountID",
-          "documentation":"<p>Start Cutover by Account IDs</p>"
-        },
         "sourceServerIDs":{
           "shape":"StartCutoverRequestSourceServerIDs",
           "documentation":"<p>Start Cutover by Source Server IDs.</p>"
@@ -4794,10 +4514,6 @@
       "type":"structure",
       "required":["sourceServerID"],
       "members":{
-        "accountID":{
-          "shape":"AccountID",
-          "documentation":"<p>Account ID on which to start replication.</p>"
-        },
         "sourceServerID":{
           "shape":"SourceServerID",
           "documentation":"<p>ID of source server on which to start replication.</p>"
@@ -4808,10 +4524,6 @@
       "type":"structure",
       "required":["sourceServerIDs"],
       "members":{
-        "accountID":{
-          "shape":"AccountID",
-          "documentation":"<p>Start Test for Account ID.</p>"
-        },
         "sourceServerIDs":{
           "shape":"StartTestRequestSourceServerIDs",
           "documentation":"<p>Start Test for Source Server IDs.</p>"
@@ -4837,20 +4549,6 @@
         }
       }
     },
-    "StopReplicationRequest":{
-      "type":"structure",
-      "required":["sourceServerID"],
-      "members":{
-        "accountID":{
-          "shape":"AccountID",
-          "documentation":"<p>Stop Replication Request account ID.</p>"
-        },
-        "sourceServerID":{
-          "shape":"SourceServerID",
-          "documentation":"<p>Stop Replication Request source server ID.</p>"
-        }
-      }
-    },
     "StrictlyPositiveInteger":{
       "type":"integer",
       "min":1
@@ -4899,8 +4597,6 @@
       "type":"map",
       "key":{"shape":"TagKey"},
       "value":{"shape":"TagValue"},
-      "max":50,
-      "min":0,
       "sensitive":true
     },
     "TargetInstanceTypeRightSizingMethod":{
@@ -4987,10 +4683,6 @@
       "type":"structure",
       "required":["sourceServerIDs"],
       "members":{
-        "accountID":{
-          "shape":"AccountID",
-          "documentation":"<p>Terminate Target instance by Account ID</p>"
-        },
         "sourceServerIDs":{
           "shape":"TerminateTargetInstancesRequestSourceServerIDs",
           "documentation":"<p>Terminate Target instance by Source Server IDs.</p>"
@@ -5043,19 +4735,10 @@
       },
       "exception":true
     },
-    "Throughput":{
-      "type":"long",
-      "max":1000,
-      "min":125
-    },
     "UnarchiveApplicationRequest":{
       "type":"structure",
       "required":["applicationID"],
       "members":{
-        "accountID":{
-          "shape":"AccountID",
-          "documentation":"<p>Account ID.</p>"
-        },
         "applicationID":{
           "shape":"ApplicationID",
           "documentation":"<p>Application ID.</p>"
@@ -5066,10 +4749,6 @@
       "type":"structure",
       "required":["waveID"],
       "members":{
-        "accountID":{
-          "shape":"AccountID",
-          "documentation":"<p>Account ID.</p>"
-        },
         "waveID":{
           "shape":"WaveID",
           "documentation":"<p>Wave ID.</p>"
@@ -5114,10 +4793,6 @@
       "type":"structure",
       "required":["applicationID"],
       "members":{
-        "accountID":{
-          "shape":"AccountID",
-          "documentation":"<p>Account ID.</p>"
-        },
         "applicationID":{
           "shape":"ApplicationID",
           "documentation":"<p>Application ID.</p>"
@@ -5136,10 +4811,6 @@
       "type":"structure",
       "required":["sourceServerID"],
       "members":{
-        "accountID":{
-          "shape":"AccountID",
-          "documentation":"<p>Update Launch configuration Account ID.</p>"
-        },
         "bootMode":{
           "shape":"BootMode",
           "documentation":"<p>Update Launch configuration boot mode request.</p>"
@@ -5246,16 +4917,12 @@
       "type":"structure",
       "required":["sourceServerID"],
       "members":{
-        "accountID":{
-          "shape":"AccountID",
-          "documentation":"<p>Update replication configuration Account ID request.</p>"
-        },
         "associateDefaultSecurityGroup":{
           "shape":"Boolean",
           "documentation":"<p>Update replication configuration associate default Application Migration Service Security group request.</p>"
         },
         "bandwidthThrottling":{
-          "shape":"BandwidthThrottling",
+          "shape":"PositiveInteger",
           "documentation":"<p>Update replication configuration bandwidth throttling request.</p>"
         },
         "createPublicIP":{
@@ -5309,10 +4976,6 @@
         "useDedicatedReplicationServer":{
           "shape":"Boolean",
           "documentation":"<p>Update replication configuration use dedicated Replication Server request.</p>"
-        },
-        "useFipsEndpoint":{
-          "shape":"Boolean",
-          "documentation":"<p>Update replication configuration use Fips Endpoint.</p>"
         }
       }
     },
@@ -5329,7 +4992,7 @@
           "documentation":"<p>Update replication configuration template associate default Application Migration Service Security group request.</p>"
         },
         "bandwidthThrottling":{
-          "shape":"BandwidthThrottling",
+          "shape":"PositiveInteger",
           "documentation":"<p>Update replication configuration template bandwidth throttling request.</p>"
         },
         "createPublicIP":{
@@ -5375,10 +5038,6 @@
         "useDedicatedReplicationServer":{
           "shape":"Boolean",
           "documentation":"<p>Update replication configuration template use dedicated Replication Server request.</p>"
-        },
-        "useFipsEndpoint":{
-          "shape":"Boolean",
-          "documentation":"<p>Update replication configuration template use Fips Endpoint request.</p>"
         }
       }
     },
@@ -5389,10 +5048,6 @@
         "sourceServerID"
       ],
       "members":{
-        "accountID":{
-          "shape":"AccountID",
-          "documentation":"<p>Account ID on which to update replication type.</p>"
-        },
         "replicationType":{
           "shape":"ReplicationType",
           "documentation":"<p>Replication type to which to update source server.</p>"
@@ -5407,10 +5062,6 @@
       "type":"structure",
       "required":["waveID"],
       "members":{
-        "accountID":{
-          "shape":"AccountID",
-          "documentation":"<p>Account ID.</p>"
-        },
         "description":{
           "shape":"WaveDescription",
           "documentation":"<p>Wave description.</p>"
diff --git a/botocore/data/securityhub/2018-10-26/service-2.json b/botocore/data/securityhub/2018-10-26/service-2.json
index b6f2a5044..f2adc9ddd 100644
--- a/botocore/data/securityhub/2018-10-26/service-2.json
+++ b/botocore/data/securityhub/2018-10-26/service-2.json
@@ -1460,7 +1460,7 @@
       "members":{
         "Type":{
           "shape":"AutomationRulesActionType",
-          "documentation":"<p> Specifies that the rule action should update the <code>Types</code> finding field. The <code>Types</code> finding field classifies findings in the format of namespace/category/classifier. For more information, see <a href=\"https://docs.aws.amazon.com/securityhub/latest/userguide/securityhub-findings-format-type-taxonomy.html\">Types taxonomy for ASFF</a> in the <i>Security Hub User Guide</i>. </p>"
+          "documentation":"<p> Specifies that the rule action should update the <code>Types</code> finding field. The <code>Types</code> finding field provides one or more finding types in the format of namespace/category/classifier that classify a finding. For more information, see <a href=\"https://docs.aws.amazon.com/securityhub/latest/userguide/securityhub-findings-format-type-taxonomy.html\">Types taxonomy for ASFF</a> in the <i>Security Hub User Guide</i>. </p>"
         },
         "FindingFieldsUpdate":{
           "shape":"AutomationRulesFindingFieldsUpdate",
@@ -1488,7 +1488,7 @@
         },
         "RuleStatus":{
           "shape":"RuleStatus",
-          "documentation":"<p> Whether the rule is active after it is created. If this parameter is equal to <code>ENABLED</code>, Security Hub starts applying the rule to findings and finding updates after the rule is created. </p>"
+          "documentation":"<p> Whether the rule is active after it is created. If this parameter is equal to <code>&gt;ENABLED</code>, Security Hub will apply the rule to findings and finding updates after the rule is created. </p>"
         },
         "RuleOrder":{
           "shape":"RuleOrderValue",
@@ -1504,11 +1504,11 @@
         },
         "IsTerminal":{
           "shape":"Boolean",
-          "documentation":"<p>Specifies whether a rule is the last to be applied with respect to a finding that matches the rule criteria. This is useful when a finding matches the criteria for multiple rules, and each rule has different actions. If the value of this field is set to <code>true</code> for a rule, Security Hub applies the rule action to a finding that matches the rule criteria and doesn't evaluate other rules for the finding.&#x2028; The default value of this field is <code>false</code>. </p>"
+          "documentation":"<p>Specifies whether a rule is the last to be applied with respect to a finding that matches the rule criteria. This is useful when a finding matches the criteria for multiple rules, and each rule has different actions. If the value of this field is set to <code>true</code> for a rule, Security Hub applies the rule action to a finding that matches the rule criteria and won't evaluate other rules for the finding.&#x2028; The default value of this field is <code>false</code>. </p>"
         },
         "Criteria":{
           "shape":"AutomationRulesFindingFilters",
-          "documentation":"<p> A set of <a href=\"https://docs.aws.amazon.com/securityhub/latest/userguide/securityhub-findings-format.html\">Amazon Web Services Security Finding Format</a> finding field attributes and corresponding expected values that Security Hub uses to filter findings. If a rule is enabled and a finding matches the conditions specified in this parameter, Security Hub applies the rule action to the finding. </p>"
+          "documentation":"<p> A set of <a href=\"https://docs.aws.amazon.com/securityhub/latest/userguide/securityhub-findings-format.html\">Amazon Web Services Security Finding Format</a> finding field attributes and corresponding expected values that Security Hub uses to filter findings. If a finding matches the conditions specified in this parameter, Security Hub applies the rule action to the finding. </p>"
         },
         "Actions":{
           "shape":"ActionList",
@@ -1540,31 +1540,31 @@
         "Severity":{"shape":"SeverityUpdate"},
         "VerificationState":{
           "shape":"VerificationState",
-          "documentation":"<p> The rule action updates the <code>VerificationState</code> field of a finding. </p>"
+          "documentation":"<p> The rule action will update the <code>VerificationState</code> field of a finding. </p>"
         },
         "Confidence":{
           "shape":"RatioScale",
-          "documentation":"<p> The rule action updates the <code>Confidence</code> field of a finding. </p>"
+          "documentation":"<p> The rule action will update the <code>Confidence</code> field of a finding. </p>"
         },
         "Criticality":{
           "shape":"RatioScale",
-          "documentation":"<p> The rule action updates the <code>Criticality</code> field of a finding. </p>"
+          "documentation":"<p> The rule action will update the <code>Criticality</code> field of a finding. </p>"
         },
         "Types":{
           "shape":"TypeList",
-          "documentation":"<p> The rule action updates the <code>Types</code> field of a finding. </p>"
+          "documentation":"<p> The rule action will update the <code>Types</code> field of a finding. </p>"
         },
         "UserDefinedFields":{
           "shape":"FieldMap",
-          "documentation":"<p> The rule action updates the <code>UserDefinedFields</code> field of a finding. </p>"
+          "documentation":"<p> The rule action will update the <code>UserDefinedFields</code> field of a finding. </p>"
         },
         "Workflow":{"shape":"WorkflowUpdate"},
         "RelatedFindings":{
           "shape":"RelatedFindingList",
-          "documentation":"<p> The rule action updates the <code>RelatedFindings</code> field of a finding. </p>"
+          "documentation":"<p> A list of findings that are related to a finding. </p>"
         }
       },
-      "documentation":"<p> Identifies the finding fields that the automation rule action updates when a finding matches the defined criteria. </p>"
+      "documentation":"<p> Identifies the finding fields that the automation rule action will update when a finding matches the defined criteria. </p>"
     },
     "AutomationRulesFindingFilters":{
       "type":"structure",
@@ -1721,7 +1721,7 @@
         },
         "RuleStatus":{
           "shape":"RuleStatus",
-          "documentation":"<p> Whether the rule is active after it is created. If this parameter is equal to <code>ENABLED</code>, Security Hub starts applying the rule to findings and finding updates after the rule is created. To change the value of this parameter after creating a rule, use <a href=\"https://docs.aws.amazon.com/securityhub/1.0/APIReference/API_BatchUpdateAutomationRules.html\"> <code>BatchUpdateAutomationRules</code> </a>. </p>"
+          "documentation":"<p> Whether the rule is active after it is created. If this parameter is equal to <code>ENABLED</code>, Security Hub will apply the rule to findings and finding updates after the rule is created. To change the value of this parameter after creating a rule, use <code>BatchUpdateAutomationRules</code>. </p>"
         },
         "RuleOrder":{
           "shape":"RuleOrderValue",
@@ -1737,7 +1737,7 @@
         },
         "IsTerminal":{
           "shape":"Boolean",
-          "documentation":"<p> Specifies whether a rule is the last to be applied with respect to a finding that matches the rule criteria. This is useful when a finding matches the criteria for multiple rules, and each rule has different actions. If the value of this field is set to <code>true</code> for a rule, Security Hub applies the rule action to a finding that matches the rule criteria and doesn't evaluate other rules for the finding.&#x2028; The default value of this field is <code>false</code>. </p>"
+          "documentation":"<p> Specifies whether a rule is the last to be applied with respect to a finding that matches the rule criteria. This is useful when a finding matches the criteria for multiple rules, and each rule has different actions. If the value of this field is set to <code>true</code> for a rule, Security Hub applies the rule action to a finding that matches the rule criteria and won't evaluate other rules for the finding.&#x2028; The default value of this field is <code>false</code>. </p>"
         },
         "CreatedAt":{
           "shape":"Timestamp",
@@ -14696,7 +14696,7 @@
         },
         "RuleStatus":{
           "shape":"RuleStatus",
-          "documentation":"<p> Whether the rule is active after it is created. If this parameter is equal to <code>ENABLED</code>, Security Hub starts applying the rule to findings and finding updates after the rule is created. To change the value of this parameter after creating a rule, use <a href=\"https://docs.aws.amazon.com/securityhub/1.0/APIReference/API_BatchUpdateAutomationRules.html\"> <code>BatchUpdateAutomationRules</code> </a>. </p>"
+          "documentation":"<p> Whether the rule is active after it is created. If this parameter is equal to <code>Enabled</code>, Security Hub will apply the rule to findings and finding updates after the rule is created. To change the value of this parameter after creating a rule, use <code>BatchUpdateAutomationRules</code>. </p>"
         },
         "RuleOrder":{
           "shape":"RuleOrderValue",
@@ -14712,11 +14712,11 @@
         },
         "IsTerminal":{
           "shape":"Boolean",
-          "documentation":"<p>Specifies whether a rule is the last to be applied with respect to a finding that matches the rule criteria. This is useful when a finding matches the criteria for multiple rules, and each rule has different actions. If the value of this field is set to <code>true</code> for a rule, Security Hub applies the rule action to a finding that matches the rule criteria and doesn't evaluate other rules for the finding. The default value of this field is <code>false</code>. </p>"
+          "documentation":"<p>Specifies whether a rule is the last to be applied with respect to a finding that matches the rule criteria. This is useful when a finding matches the criteria for multiple rules, and each rule has different actions. If the value of this field is set to <code>true</code> for a rule, Security Hub applies the rule action to a finding that matches the rule criteria and won't evaluate other rules for the finding. The default value of this field is <code>false</code>. </p>"
         },
         "Criteria":{
           "shape":"AutomationRulesFindingFilters",
-          "documentation":"<p> A set of ASFF finding field attributes and corresponding expected values that Security Hub uses to filter findings. If a rule is enabled and a finding matches the conditions specified in this parameter, Security Hub applies the rule action to the finding. </p>"
+          "documentation":"<p> A set of ASFF finding field attributes and corresponding expected values that Security Hub uses to filter findings. If a finding matches the conditions specified in this parameter, Security Hub applies the rule action to the finding. </p>"
         },
         "Actions":{
           "shape":"ActionList",
@@ -18127,7 +18127,7 @@
         },
         "SecurityControlStatus":{
           "shape":"ControlStatus",
-          "documentation":"<p> The enablement status of a security control in a specific standard. </p>"
+          "documentation":"<p> The status of a security control based on the compliance status of its findings. For more information about how control status is determined, see <a href=\"https://docs.aws.amazon.com/securityhub/latest/userguide/controls-overall-status.html\">Determining the overall status of a control from its findings</a> in the <i>Security Hub User Guide</i>. </p>"
         }
       },
       "documentation":"<p> A security control in Security Hub describes a security best practice related to a specific resource. </p>"
@@ -19116,7 +19116,7 @@
         },
         "RuleStatus":{
           "shape":"RuleStatus",
-          "documentation":"<p> Whether the rule is active after it is created. If this parameter is equal to <code>ENABLED</code>, Security Hub starts applying the rule to findings and finding updates after the rule is created. To change the value of this parameter after creating a rule, use <a href=\"https://docs.aws.amazon.com/securityhub/1.0/APIReference/API_BatchUpdateAutomationRules.html\"> <code>BatchUpdateAutomationRules</code> </a>. </p>"
+          "documentation":"<p> Whether the rule is active after it is created. If this parameter is equal to <code>ENABLED</code>, Security Hub will apply the rule to findings and finding updates after the rule is created. To change the value of this parameter after creating a rule, use <code>BatchUpdateAutomationRules</code>. </p>"
         },
         "RuleOrder":{
           "shape":"RuleOrderValue",
@@ -19132,11 +19132,11 @@
         },
         "IsTerminal":{
           "shape":"Boolean",
-          "documentation":"<p>Specifies whether a rule is the last to be applied with respect to a finding that matches the rule criteria. This is useful when a finding matches the criteria for multiple rules, and each rule has different actions. If the value of this field is set to <code>true</code> for a rule, Security Hub applies the rule action to a finding that matches the rule criteria and doesn't evaluate other rules for the finding.&#x2028; The default value of this field is <code>false</code>. </p>"
+          "documentation":"<p>Specifies whether a rule is the last to be applied with respect to a finding that matches the rule criteria. This is useful when a finding matches the criteria for multiple rules, and each rule has different actions. If the value of this field is set to <code>true</code> for a rule, Security Hub applies the rule action to a finding that matches the rule criteria and won't evaluate other rules for the finding.&#x2028; The default value of this field is <code>false</code>. </p>"
         },
         "Criteria":{
           "shape":"AutomationRulesFindingFilters",
-          "documentation":"<p> A set of ASFF finding field attributes and corresponding expected values that Security Hub uses to filter findings. If a rule is enabled and a finding matches the conditions specified in this parameter, Security Hub applies the rule action to the finding. </p>"
+          "documentation":"<p> A set of ASFF finding field attributes and corresponding expected values that Security Hub uses to filter findings. If a finding matches the conditions specified in this parameter, Security Hub applies the rule action to the finding. </p>"
         },
         "Actions":{
           "shape":"ActionList",
diff --git a/botocore/handlers.py b/botocore/handlers.py
index 9546c6112..55087f674 100644
--- a/botocore/handlers.py
+++ b/botocore/handlers.py
@@ -73,6 +73,7 @@ from botocore.compat import MD5_AVAILABLE  # noqa
 from botocore.exceptions import MissingServiceIdError  # noqa
 from botocore.utils import hyphenize_service_id  # noqa
 from botocore.utils import is_global_accesspoint  # noqa
+from botocore.utils import SERVICE_NAME_ALIASES  # noqa
 
 
 logger = logging.getLogger(__name__)
@@ -99,8 +100,6 @@ VALID_S3_ARN = re.compile('|'.join([_ACCESSPOINT_ARN, _OUTPOST_ARN]))
 S3_SIGNING_NAMES = ('s3', 's3-outposts', 's3-object-lambda')
 VERSION_ID_SUFFIX = re.compile(r'\?versionId=[^\s]+$')
 
-SERVICE_NAME_ALIASES = {'runtime.sagemaker': 'sagemaker-runtime'}
-
 
 def handle_service_name_alias(service_name, **kwargs):
     return SERVICE_NAME_ALIASES.get(service_name, service_name)
diff --git a/botocore/session.py b/botocore/session.py
index 9aa596bdd..b260d76cd 100644
--- a/botocore/session.py
+++ b/botocore/session.py
@@ -42,6 +42,7 @@ from botocore.compat import HAS_CRT, MutableMapping
 from botocore.configprovider import (
     BOTOCORE_DEFAUT_SESSION_VARIABLES,
     ConfigChainFactory,
+    ConfiguredEndpointProvider,
     ConfigValueStore,
     DefaultConfigResolver,
     SmartDefaultsConfigStoreFactory,
@@ -957,7 +958,7 @@ class Session:
         auth_token = self.get_auth_token()
         endpoint_resolver = self._get_internal_component('endpoint_resolver')
         exceptions_factory = self._get_internal_component('exceptions_factory')
-        config_store = self.get_component('config_store')
+        config_store = copy.copy(self.get_component('config_store'))
         user_agent_creator = self.get_component('user_agent_creator')
         # Session configuration values for the user agent string are applied
         # just before each client creation because they may have been modified
@@ -972,10 +973,15 @@ class Session:
             smart_defaults_factory = self._get_internal_component(
                 'smart_defaults_factory'
             )
-            config_store = copy.deepcopy(config_store)
             smart_defaults_factory.merge_smart_defaults(
                 config_store, defaults_mode, region_name
             )
+
+        self._add_configured_endpoint_provider(
+            client_name=service_name,
+            config_store=config_store,
+        )
+
         client_creator = botocore.client.ClientCreator(
             loader,
             endpoint_resolver,
@@ -1045,6 +1051,17 @@ class Session:
 
         return lmode
 
+    def _add_configured_endpoint_provider(self, client_name, config_store):
+        chain = ConfiguredEndpointProvider(
+            full_config=self.full_config,
+            scoped_config=self.get_scoped_config(),
+            client_name=client_name,
+        )
+        config_store.set_config_provider(
+            logical_name='endpoint_url',
+            provider=chain,
+        )
+
     def _missing_cred_vars(self, access_key, secret_key):
         if access_key is not None and secret_key is None:
             return 'aws_secret_access_key'
diff --git a/botocore/utils.py b/botocore/utils.py
index 67755968d..266d20462 100644
--- a/botocore/utils.py
+++ b/botocore/utils.py
@@ -3353,3 +3353,79 @@ class JSONFileCache:
                 return value.isoformat()
             return value.strftime('%Y-%m-%dT%H:%M:%S%Z')
         return value
+
+
+# This parameter is not part of the public interface and is subject to abrupt
+# breaking changes or removal without prior announcement.
+# Mapping of services that have been renamed for backwards compatibility reasons.
+# Keys are the previous name that should be allowed, values are the documented
+# and preferred client name.
+SERVICE_NAME_ALIASES = {'runtime.sagemaker': 'sagemaker-runtime'}
+
+
+# This parameter is not part of the public interface and is subject to abrupt
+# breaking changes or removal without prior announcement.
+# Mapping to determine the service ID for services that do not use it as the
+# model data directory name. The keys are the data directory name and the
+# values are the transformed service IDs (lower case and hyphenated).
+CLIENT_NAME_TO_HYPHENIZED_SERVICE_ID_OVERRIDES = {
+    # Actual service name we use -> Allowed computed service name.
+    'alexaforbusiness': 'alexa-for-business',
+    'apigateway': 'api-gateway',
+    'application-autoscaling': 'application-auto-scaling',
+    'appmesh': 'app-mesh',
+    'autoscaling': 'auto-scaling',
+    'autoscaling-plans': 'auto-scaling-plans',
+    'ce': 'cost-explorer',
+    'cloudhsmv2': 'cloudhsm-v2',
+    'cloudsearchdomain': 'cloudsearch-domain',
+    'cognito-idp': 'cognito-identity-provider',
+    'config': 'config-service',
+    'cur': 'cost-and-usage-report-service',
+    'datapipeline': 'data-pipeline',
+    'directconnect': 'direct-connect',
+    'devicefarm': 'device-farm',
+    'discovery': 'application-discovery-service',
+    'dms': 'database-migration-service',
+    'ds': 'directory-service',
+    'dynamodbstreams': 'dynamodb-streams',
+    'elasticbeanstalk': 'elastic-beanstalk',
+    'elastictranscoder': 'elastic-transcoder',
+    'elb': 'elastic-load-balancing',
+    'elbv2': 'elastic-load-balancing-v2',
+    'es': 'elasticsearch-service',
+    'events': 'eventbridge',
+    'globalaccelerator': 'global-accelerator',
+    'iot-data': 'iot-data-plane',
+    'iot-jobs-data': 'iot-jobs-data-plane',
+    'iot1click-devices': 'iot-1click-devices-service',
+    'iot1click-projects': 'iot-1click-projects',
+    'iotevents-data': 'iot-events-data',
+    'iotevents': 'iot-events',
+    'iotwireless': 'iot-wireless',
+    'kinesisanalytics': 'kinesis-analytics',
+    'kinesisanalyticsv2': 'kinesis-analytics-v2',
+    'kinesisvideo': 'kinesis-video',
+    'lex-models': 'lex-model-building-service',
+    'lexv2-models': 'lex-models-v2',
+    'lex-runtime': 'lex-runtime-service',
+    'lexv2-runtime': 'lex-runtime-v2',
+    'logs': 'cloudwatch-logs',
+    'machinelearning': 'machine-learning',
+    'marketplacecommerceanalytics': 'marketplace-commerce-analytics',
+    'marketplace-entitlement': 'marketplace-entitlement-service',
+    'meteringmarketplace': 'marketplace-metering',
+    'mgh': 'migration-hub',
+    'sms-voice': 'pinpoint-sms-voice',
+    'resourcegroupstaggingapi': 'resource-groups-tagging-api',
+    'route53': 'route-53',
+    'route53domains': 'route-53-domains',
+    's3control': 's3-control',
+    'sdb': 'simpledb',
+    'secretsmanager': 'secrets-manager',
+    'serverlessrepo': 'serverlessapplicationrepository',
+    'servicecatalog': 'service-catalog',
+    'servicecatalog-appregistry': 'service-catalog-appregistry',
+    'stepfunctions': 'sfn',
+    'storagegateway': 'storage-gateway',
+}
diff --git a/docs/source/conf.py b/docs/source/conf.py
index d5863917e..f3f65c0d4 100644
--- a/docs/source/conf.py
+++ b/docs/source/conf.py
@@ -59,7 +59,7 @@ copyright = f'{current_year}, Amazon Web Services, Inc'
 # The short X.Y version.
 version = '1.30'
 # The full version, including alpha/beta/rc tags.
-release = '1.30.1'
+release = '1.30.0'
 
 # The language for content autogenerated by Sphinx. Refer to documentation
 # for a list of supported languages.


Test patch:
diff --git a/tests/functional/configured_endpoint_urls/__init__.py b/tests/functional/configured_endpoint_urls/__init__.py
new file mode 100644
index 000000000..c5c740907
--- /dev/null
+++ b/tests/functional/configured_endpoint_urls/__init__.py
@@ -0,0 +1,12 @@
+# Copyright 2023 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.
diff --git a/tests/functional/configured_endpoint_urls/profile-tests.json b/tests/functional/configured_endpoint_urls/profile-tests.json
new file mode 100644
index 000000000..5681edc1f
--- /dev/null
+++ b/tests/functional/configured_endpoint_urls/profile-tests.json
@@ -0,0 +1,505 @@
+{
+  "description": [
+    "These are test descriptions that describe how specific data should be loaded from a profile file based on a ",
+    "profile name."
+  ],
+
+  "testSuites": [
+    {
+      "profiles": {
+        "default": {
+          "aws_access_key_id": "123",
+          "aws_secret_access_key": "456",
+          "region": "fake-region-10"
+        },
+        "service_localhost_global_only": {
+          "aws_access_key_id": "123",
+          "aws_secret_access_key": "456",
+          "region": "fake-region-10",
+          "endpoint_url": "http://localhost:1234"
+        },
+        "service_global_only": {
+          "aws_access_key_id": "123",
+          "aws_secret_access_key": "456",
+          "region": "fake-region-10",
+          "endpoint_url": "https://global.endpoint.aws"
+        },
+        "service_specific_s3": {
+          "aws_access_key_id": "123",
+          "aws_secret_access_key": "456",
+          "services": "service_specific_s3",
+          "region": "fake-region-10"
+        },
+        "global_and_service_specific_s3": {
+          "aws_access_key_id": "123",
+          "aws_secret_access_key": "456",
+          "endpoint_url": "https://global.endpoint.aws",
+          "services": "service_specific_s3",
+          "region": "fake-region-10"
+        },
+        "ignore_global_and_service_specific_s3": {
+          "aws_access_key_id": "123",
+          "aws_secret_access_key": "456",
+          "endpoint_url": "https://global.endpoint.aws",
+          "services": "service_specific_s3",
+          "region": "fake-region-10",
+          "ignore_configured_endpoint_urls": "true"
+        },
+        "service_specific_dynamodb_and_s3": {
+          "aws_access_key_id": "123",
+          "aws_secret_access_key": "456",
+          "services": "service_specific_dynamodb_and_s3",
+          "region": "fake-region-10"
+        }
+      },
+
+      "services": {
+        "service_specific_s3": {
+          "s3": {
+            "endpoint_url": "https://s3.endpoint.aws"
+          }
+        },
+        "service_specific_dynamodb_and_s3": {
+          "dynamodb": {
+            "endpoint_url": "https://dynamodb.endpoint.aws"
+          },
+          "s3": {
+            "endpoint_url": "https://s3.endpoint.aws"
+          }
+        }
+      },
+
+      "client_configs": {
+        "default": {},
+        "endpoint_url_provided":{
+          "endpoint_url": "https://client-config.endpoint.aws"
+        },
+        "ignore_configured_endpoint_urls": {
+          "ignore_configured_endpoint_urls": true
+        },
+        "provide_and_ignore_configured_endpoint_urls": {
+          "ignore_configured_endpoint_urls": true,
+          "endpoint_url": "https://client-config.endpoint.aws"
+        }
+      },
+
+      "environments": {
+        "default": {},
+        "global_only": {
+          "AWS_ENDPOINT_URL": "https://global-from-envvar.endpoint.aws"
+        },
+        "service_specific_s3": {
+          "AWS_ENDPOINT_URL_S3": "https://s3-from-envvar.endpoint.aws"
+        },
+        "global_and_service_specific_s3": {
+          "AWS_ENDPOINT_URL": "https://global-from-envvar.endpoint.aws",
+          "AWS_ENDPOINT_URL_S3": "https://s3-from-envvar.endpoint.aws"
+
+        },
+        "ignore_global_and_service_specific_s3": {
+          "AWS_ENDPOINT_URL": "https://global-from-envvar.endpoint.aws",
+          "AWS_ENDPOINT_URL_S3": "https://s3-from-envvar.endpoint.aws",
+          "AWS_IGNORE_CONFIGURED_ENDPOINT_URLS": "true"
+        },
+        "service_specific_dynamodb_and_s3": {
+          "AWS_ENDPOINT_URL_DYNAMODB": "https://dynamodb-from-envvar.endpoint.aws",
+          "AWS_ENDPOINT_URL_S3": "https://s3-from-envvar.endpoint.aws"
+        }
+      },
+
+    "endpointUrlTests": [
+      {
+        "name": "Global endpoint url is read from services section and used for an S3 client.",
+        "profile": "service_global_only",
+        "client_config": "default",
+        "environment": "default",
+        "service": "s3",
+        "output": {
+          "endpointUrl": "https://global.endpoint.aws"
+        }
+      },
+      {
+        "name": "Service specific endpoint url is read from services section and used for an S3 client.",
+        "profile": "service_specific_s3",
+        "client_config": "default",
+        "environment": "default",
+        "service": "s3",
+        "output": {
+          "endpointUrl": "https://s3.endpoint.aws"
+        }
+      },
+      {
+        "name": "S3 Service-specific endpoint URL from configuration file takes precedence over global endpoint URL from configuration file.",
+        "profile": "global_and_service_specific_s3",
+        "client_config": "default",
+        "environment": "default",
+        "service": "s3",
+        "output": {
+          "endpointUrl": "https://s3.endpoint.aws"
+        }
+      },
+      {
+        "name": "Global endpoint url environment variable takes precedence over the value resolved by the SDK.",
+        "profile": "default",
+        "client_config": "default",
+        "environment": "global_only",
+        "service": "s3",
+        "output": {
+          "endpointUrl": "https://global-from-envvar.endpoint.aws"
+        }
+      },
+      {
+        "name": "Global endpoint url environment variable takes precendence over global endpoint configuration option.",
+        "profile": "service_global_only",
+        "client_config": "default",
+        "environment": "global_only",
+        "service": "s3",
+        "output": {
+          "endpointUrl": "https://global-from-envvar.endpoint.aws"
+        }
+      },
+      {
+        "name": "Global endpoint url environment variable takes precendence over service-specific endpoint configuration option.",
+        "profile": "service_specific_s3",
+        "client_config": "default",
+        "environment": "global_only",
+        "service": "s3",
+        "output": {
+          "endpointUrl": "https://global-from-envvar.endpoint.aws"
+        }
+      },
+      {
+        "name": "Global endpoint url environment variable takes precendence over global endpoint configuration option and service-specific endpoint configuration option.",
+        "profile": "global_and_service_specific_s3",
+        "client_config": "default",
+        "environment": "global_only",
+        "service": "s3",
+        "output": {
+          "endpointUrl": "https://global-from-envvar.endpoint.aws"
+        }
+      },
+      {
+        "name": "Service-specific endpoint url environment variable takes precedence over the value resolved by the SDK.",
+        "profile": "default",
+        "client_config": "default",
+        "environment": "service_specific_s3",
+        "service": "s3",
+        "output": {
+          "endpointUrl": "https://s3-from-envvar.endpoint.aws"
+        }
+      },
+      {
+        "name": "Service-specific endpoint url environment variable takes precedence over the global endpoint url configuration option.",
+        "profile": "service_global_only",
+        "client_config": "default",
+        "environment": "service_specific_s3",
+        "service": "s3",
+        "output": {
+          "endpointUrl": "https://s3-from-envvar.endpoint.aws"
+        }
+      },
+      {
+        "name": "Service-specific endpoint url environment variable takes precedence over the service-specific endpoint url configuration option.",
+        "profile": "service_specific_s3",
+        "client_config": "default",
+        "environment": "service_specific_s3",
+        "service": "s3",
+        "output": {
+          "endpointUrl": "https://s3-from-envvar.endpoint.aws"
+        }
+      },
+      {
+        "name": "Service-specific endpoint url environment variable takes precedence over the services-specific endpoint url configuration option and the global endpoint url configuration option.",
+        "profile": "global_and_service_specific_s3",
+        "client_config": "default",
+        "environment": "service_specific_s3",
+        "service": "s3",
+        "output": {
+          "endpointUrl": "https://s3-from-envvar.endpoint.aws"
+        }
+      },
+      {
+        "name": "Service-specific endpoint url environment variable takes precedence over the global endpoint url environment variable.",
+        "profile": "default",
+        "client_config": "default",
+        "environment": "global_and_service_specific_s3",
+        "service": "s3",
+        "output": {
+          "endpointUrl": "https://s3-from-envvar.endpoint.aws"
+        }
+      },
+      {
+        "name": "Service-specific endpoint url environment variable takes precedence over the global endpoint url environment variable and the global endpoint url configuration option.",
+        "profile": "service_global_only",
+        "client_config": "default",
+        "environment": "global_and_service_specific_s3",
+        "service": "s3",
+        "output": {
+          "endpointUrl": "https://s3-from-envvar.endpoint.aws"
+        }
+      },
+      {
+        "name": "Service-specific endpoint url environment variable takes precedence over the global endpoint url environment variable and the the service-specific endpoint url configuration option.",
+        "profile": "service_specific_s3",
+        "client_config": "default",
+        "environment": "global_and_service_specific_s3",
+        "service": "s3",
+        "output": {
+          "endpointUrl": "https://s3-from-envvar.endpoint.aws"
+        }
+      },
+      {
+        "name": "Service-specific endpoint url environment variable takes precedence over the global endpoint url environment variable, the service-specific endpoint URL configuration option, and the global endpoint URL configuration option.",
+        "profile": "global_and_service_specific_s3",
+        "client_config": "default",
+        "environment": "global_and_service_specific_s3",
+        "service": "s3",
+        "output": {
+          "endpointUrl": "https://s3-from-envvar.endpoint.aws"
+        }
+      },
+      {
+        "name": "Client configuration takes precedence over value provided by the SDK.",
+        "profile": "default",
+        "client_config": "endpoint_url_provided",
+        "environment": "default",
+        "service": "s3",
+        "output": {
+          "endpointUrl": "https://client-config.endpoint.aws"
+        }
+      },
+      {
+        "name": "Client configuration takes precedence over global endpoint url from services section and used for an S3 client.",
+        "profile": "service_global_only",
+        "client_config": "endpoint_url_provided",
+        "environment": "default",
+        "service": "s3",
+        "output": {
+          "endpointUrl": "https://client-config.endpoint.aws"
+        }
+      },
+      {
+        "name": "Client configuration takes precedence over service specific endpoint url from services section and used for an S3 client.",
+        "profile": "service_specific_s3",
+        "client_config": "endpoint_url_provided",
+        "environment": "default",
+        "service": "s3",
+        "output": {
+          "endpointUrl": "https://client-config.endpoint.aws"
+        }
+      },
+      {
+        "name": "Client configuration takes precedence over S3 Service-specific endpoint URL from configuration file and global endpoint URL from configuration file.",
+        "profile": "global_and_service_specific_s3",
+        "client_config": "endpoint_url_provided",
+        "environment": "default",
+        "service": "s3",
+        "output": {
+          "endpointUrl": "https://client-config.endpoint.aws"
+        }
+      },
+      {
+        "name": "Client configuration takes precedence over global endpoint url environment variable.",
+        "profile": "default",
+        "client_config": "endpoint_url_provided",
+        "environment": "global_only",
+        "service": "s3",
+        "output": {
+          "endpointUrl": "https://client-config.endpoint.aws"
+        }
+      },
+      {
+        "name": "Client configuration takes precedence over global endpoint url environment variable and global endpoint configuration option.",
+        "profile": "service_global_only",
+        "client_config": "endpoint_url_provided",
+        "environment": "global_only",
+        "service": "s3",
+        "output": {
+          "endpointUrl": "https://client-config.endpoint.aws"
+        }
+      },
+      {
+        "name": "Client configuration takes precedence over global endpoint url environment variable and service-specific endpoint configuration option.",
+        "profile": "service_specific_s3",
+        "client_config": "endpoint_url_provided",
+        "environment": "global_only",
+        "service": "s3",
+        "output": {
+          "endpointUrl": "https://client-config.endpoint.aws"
+        }
+      },
+      {
+        "name": "Client configuration takes precedence over global endpoint url environment variable, global endpoint configuration option, and service-specific endpoint configuration option.",
+        "profile": "global_and_service_specific_s3",
+        "client_config": "endpoint_url_provided",
+        "environment": "global_only",
+        "service": "s3",
+        "output": {
+          "endpointUrl": "https://client-config.endpoint.aws"
+        }
+      },
+      {
+        "name": "Client configuration takes precedence over service-specific endpoint url environment variable.",
+        "profile": "default",
+        "client_config": "endpoint_url_provided",
+        "environment": "service_specific_s3",
+        "service": "s3",
+        "output": {
+          "endpointUrl": "https://client-config.endpoint.aws"
+        }
+      },
+      {
+        "name": "Client configuration takes precedence over service-specific endpoint url environment variable and the global endpoint url configuration option.",
+        "profile": "service_global_only",
+        "client_config": "endpoint_url_provided",
+        "environment": "service_specific_s3",
+        "service": "s3",
+        "output": {
+          "endpointUrl": "https://client-config.endpoint.aws"
+        }
+      },
+      {
+        "name": "Client configuration takes precedence over service-specific endpoint url environment variable and the service-specific endpoint url configuration option.",
+        "profile": "service_specific_s3",
+        "client_config": "endpoint_url_provided",
+        "environment": "service_specific_s3",
+        "service": "s3",
+        "output": {
+          "endpointUrl": "https://client-config.endpoint.aws"
+        }
+      },
+      {
+        "name": "Client configuration takes precedence over service-specific endpoint url environment variable, the services-specific endpoint url configuration option, and the global endpoint url configuration option.",
+        "profile": "global_and_service_specific_s3",
+        "client_config": "endpoint_url_provided",
+        "environment": "service_specific_s3",
+        "service": "s3",
+        "output": {
+          "endpointUrl": "https://client-config.endpoint.aws"
+        }
+      },
+      {
+        "name": "Client configuration takes precedence over service-specific endpoint url environment variable and the global endpoint url environment variable.",
+        "profile": "default",
+        "client_config": "endpoint_url_provided",
+        "environment": "global_and_service_specific_s3",
+        "service": "s3",
+        "output": {
+          "endpointUrl": "https://client-config.endpoint.aws"
+        }
+      },
+      {
+        "name": "Client configuration takes precedence over service-specific endpoint url environment variable, the global endpoint url environment variable, and the global endpoint url configuration option.",
+        "profile": "service_global_only",
+        "client_config": "endpoint_url_provided",
+        "environment": "global_and_service_specific_s3",
+        "service": "s3",
+        "output": {
+          "endpointUrl": "https://client-config.endpoint.aws"
+        }
+      },
+      {
+        "name": "Client configuration takes precedence over service-specific endpoint url environment variable, the global endpoint url environment variable, and the service-specific endpoint url configuration option.",
+        "profile": "service_specific_s3",
+        "client_config": "endpoint_url_provided",
+        "environment": "global_and_service_specific_s3",
+        "service": "s3",
+        "output": {
+          "endpointUrl": "https://client-config.endpoint.aws"
+        }
+      },
+      {
+        "name": "Client configuration takes precedence over service-specific endpoint url environment variable, the global endpoint url environment variable, the service-specific endpoint URL configuration option, and the global endpoint URL configuration option.",
+        "profile": "global_and_service_specific_s3",
+        "client_config": "endpoint_url_provided",
+        "environment": "global_and_service_specific_s3",
+        "service": "s3",
+        "output": {
+          "endpointUrl": "https://client-config.endpoint.aws"
+        }
+      },
+      {
+        "name": "All configured endpoints ignored due to environment variable.",
+        "profile": "global_and_service_specific_s3",
+        "client_config": "default",
+        "environment": "ignore_global_and_service_specific_s3",
+        "service": "s3",
+        "output": {
+          "endpointUrl": "https://s3.fake-region-10.amazonaws.com"
+        }
+      },
+      {
+        "name": "All configured endpoints ignored due to shared config variable.",
+        "profile": "ignore_global_and_service_specific_s3",
+        "client_config": "default",
+        "environment": "global_and_service_specific_s3",
+        "service": "s3",
+        "output": {
+          "endpointUrl": "https://s3.fake-region-10.amazonaws.com"
+        }
+      },
+      {
+        "name": "All configured endpoints ignored due to ignore client config parameter.",
+        "profile": "global_and_service_specific_s3",
+        "client_config": "ignore_configured_endpoint_urls",
+        "environment": "global_and_service_specific_s3",
+        "service": "s3",
+        "output": {
+          "endpointUrl": "https://s3.fake-region-10.amazonaws.com"
+        }
+      },
+      {
+        "name": "Environment variable and shared config file configured endpoints ignored due to ignore shared config variable and client configured endpoint is used.",
+        "profile": "ignore_global_and_service_specific_s3",
+        "client_config": "endpoint_url_provided",
+        "environment": "global_and_service_specific_s3",
+        "service": "s3",
+        "output": {
+          "endpointUrl": "https://client-config.endpoint.aws"
+        }
+      },
+      {
+        "name": "Environment variable and shared config file configured endpoints ignored due to ignore environment variable and client configured endpoint is used.",
+        "profile": "global_and_service_specific_s3",
+        "client_config": "endpoint_url_provided",
+        "environment": "ignore_global_and_service_specific_s3",
+        "service": "s3",
+        "output": {
+          "endpointUrl": "https://client-config.endpoint.aws"
+        }
+      },
+      {
+        "name": "Environment variable and shared config file configured endpoints ignored due to ignore client config variable and client configured endpoint is used.",
+        "profile": "global_and_service_specific_s3",
+        "client_config": "provide_and_ignore_configured_endpoint_urls",
+        "environment": "global_and_service_specific_s3",
+        "service": "s3",
+        "output": {
+          "endpointUrl": "https://client-config.endpoint.aws"
+        }
+      },
+      {
+        "name": "DynamoDB service-specific endpoint url shared config variable is used when service-specific S3 shared config variable is also present.",
+        "profile": "service_specific_dynamodb_and_s3",
+        "client_config": "default",
+        "environment": "default",
+        "service": "dynamodb",
+        "output": {
+          "endpointUrl": "https://dynamodb.endpoint.aws"
+        }
+      },
+      {
+        "name": "DynamoDB service-specific endpoint url environment variable is used when service-specific S3 environment variable is also present.",
+        "profile": "default",
+        "client_config": "default",
+        "environment": "service_specific_dynamodb_and_s3",
+        "service": "dynamodb",
+        "output": {
+          "endpointUrl": "https://dynamodb-from-envvar.endpoint.aws"
+        }
+      }
+
+    ]
+  }
+  ]
+}
diff --git a/tests/functional/configured_endpoint_urls/test_configured_endpoint_url.py b/tests/functional/configured_endpoint_urls/test_configured_endpoint_url.py
new file mode 100644
index 000000000..40cc17e26
--- /dev/null
+++ b/tests/functional/configured_endpoint_urls/test_configured_endpoint_url.py
@@ -0,0 +1,249 @@
+# Copyright 2023 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 json
+from pathlib import Path
+from unittest import mock
+
+import pytest
+
+import botocore.configprovider
+import botocore.utils
+from botocore.compat import urlsplit
+from botocore.config import Config
+from tests import ClientHTTPStubber
+
+ENDPOINT_TESTDATA_FILE = Path(__file__).parent / "profile-tests.json"
+
+
+def dict_to_ini_section(ini_dict, section_header):
+    section_str = f'[{section_header}]\n'
+    for key, value in ini_dict.items():
+        if isinstance(value, dict):
+            section_str += f"{key} =\n"
+            for new_key, new_value in value.items():
+                section_str += f"  {new_key}={new_value}\n"
+        else:
+            section_str += f"{key}={value}\n"
+    return section_str + "\n"
+
+
+def create_cases():
+    with open(ENDPOINT_TESTDATA_FILE) as f:
+        test_suite = json.load(f)['testSuites'][0]
+
+    for test_case_data in test_suite['endpointUrlTests']:
+        yield pytest.param(
+            {
+                'service': test_case_data['service'],
+                'profile': test_case_data['profile'],
+                'expected_endpoint_url': test_case_data['output'][
+                    'endpointUrl'
+                ],
+                'client_args': get_create_client_args(
+                    test_suite['client_configs'].get(
+                        test_case_data['client_config'], {}
+                    )
+                ),
+                'config_file_contents': get_config_file_contents(
+                    test_case_data['profile'], test_suite
+                ),
+                'environment': test_suite['environments'].get(
+                    test_case_data['environment'], {}
+                ),
+            },
+            id=test_case_data['name'],
+        )
+
+
+def get_create_client_args(test_case_client_config):
+    create_client_args = {}
+
+    if 'endpoint_url' in test_case_client_config:
+        create_client_args['endpoint_url'] = test_case_client_config[
+            'endpoint_url'
+        ]
+
+    if 'ignore_configured_endpoint_urls' in test_case_client_config:
+        create_client_args['config'] = Config(
+            ignore_configured_endpoint_urls=test_case_client_config[
+                'ignore_configured_endpoint_urls'
+            ]
+        )
+
+    return create_client_args
+
+
+def get_config_file_contents(profile_name, test_suite):
+    profile = test_suite['profiles'][profile_name]
+
+    profile_str = dict_to_ini_section(
+        profile,
+        section_header=f"profile {profile_name}",
+    )
+
+    services_section_name = profile.get('services', None)
+
+    if services_section_name is None:
+        return profile_str
+
+    services_section = test_suite['services'][services_section_name]
+
+    service_section_str = dict_to_ini_section(
+        services_section,
+        section_header=f'services {services_section_name}',
+    )
+
+    return profile_str + service_section_str
+
+
+@pytest.fixture
+def client_creator(tmp_path):
+    tmp_config_file_path = tmp_path / 'config'
+    environ = {'AWS_CONFIG_FILE': str(tmp_config_file_path)}
+
+    def _do_create_client(
+        service,
+        profile,
+        client_args=None,
+        config_file_contents=None,
+        environment=None,
+    ):
+        environ.update(environment)
+        with open(tmp_config_file_path, 'w') as f:
+            f.write(config_file_contents)
+            f.flush()
+
+        return botocore.session.Session(profile=profile).create_client(
+            service, **client_args
+        )
+
+    with mock.patch('os.environ', environ):
+        yield _do_create_client
+
+
+def _normalize_endpoint(url):
+    split_endpoint = urlsplit(url)
+    actual_endpoint = f"{split_endpoint.scheme}://{split_endpoint.netloc}"
+    return actual_endpoint
+
+
+def assert_client_endpoint_url(client, expected_endpoint_url):
+    assert client.meta.endpoint_url == expected_endpoint_url
+
+
+def assert_endpoint_url_used_for_operation(
+    client, expected_endpoint_url, operation, params
+):
+    http_stubber = ClientHTTPStubber(client)
+    http_stubber.start()
+    http_stubber.add_response()
+
+    # Call an operation on the client
+    getattr(client, operation)(**params)
+
+    assert (
+        _normalize_endpoint(http_stubber.requests[0].url)
+        == expected_endpoint_url
+    )
+
+
+def _known_service_names_and_ids():
+    my_session = botocore.session.get_session()
+    loader = my_session.get_component('data_loader')
+    available_services = loader.list_available_services('service-2')
+
+    result = []
+    for service_name in available_services:
+        model = my_session.get_service_model(service_name)
+        result.append((model.service_name, model.service_id))
+    return sorted(result)
+
+
+SERVICE_TO_OPERATION = {'s3': 'list_buckets', 'dynamodb': 'list_tables'}
+
+
+@pytest.mark.parametrize("test_case", create_cases())
+def test_resolve_configured_endpoint_url(test_case, client_creator):
+    client = client_creator(
+        service=test_case['service'],
+        profile=test_case['profile'],
+        client_args=test_case['client_args'],
+        config_file_contents=test_case['config_file_contents'],
+        environment=test_case['environment'],
+    )
+
+    assert_endpoint_url_used_for_operation(
+        client=client,
+        expected_endpoint_url=test_case['expected_endpoint_url'],
+        operation=SERVICE_TO_OPERATION[test_case['service']],
+        params={},
+    )
+
+
+@pytest.mark.parametrize(
+    'service_name,service_id', _known_service_names_and_ids()
+)
+def test_expected_service_env_var_name_is_respected(
+    service_name, service_id, client_creator
+):
+    transformed_service_id = service_id.replace(' ', '_').upper()
+
+    client = client_creator(
+        service=service_name,
+        profile='default',
+        client_args={},
+        config_file_contents=(
+            '[profile default]\n'
+            'aws_access_key_id=123\n'
+            'aws_secret_access_key=456\n'
+            'region=fake-region-10\n'
+        ),
+        environment={
+            f'AWS_ENDPOINT_URL_{transformed_service_id}': 'https://endpoint-override'
+        },
+    )
+
+    assert_client_endpoint_url(
+        client=client, expected_endpoint_url='https://endpoint-override'
+    )
+
+
+@pytest.mark.parametrize(
+    'service_name,service_id', _known_service_names_and_ids()
+)
+def test_expected_service_config_section_name_is_respected(
+    service_name, service_id, client_creator
+):
+    transformed_service_id = service_id.replace(' ', '_').lower()
+
+    client = client_creator(
+        service=service_name,
+        profile='default',
+        client_args={},
+        config_file_contents=(
+            f'[profile default]\n'
+            f'services=my-services\n'
+            f'aws_access_key_id=123\n'
+            f'aws_secret_access_key=456\n'
+            f'region=fake-region-10\n\n'
+            f'[services my-services]\n'
+            f'{transformed_service_id} = \n'
+            f'  endpoint_url = https://endpoint-override\n\n'
+        ),
+        environment={},
+    )
+
+    assert_client_endpoint_url(
+        client=client, expected_endpoint_url='https://endpoint-override'
+    )
diff --git a/tests/functional/endpoint-rules/mgn/endpoint-tests-1.json b/tests/functional/endpoint-rules/mgn/endpoint-tests-1.json
index 9e52c4888..fcda59beb 100644
--- a/tests/functional/endpoint-rules/mgn/endpoint-tests-1.json
+++ b/tests/functional/endpoint-rules/mgn/endpoint-tests-1.json
@@ -416,17 +416,6 @@
                 "UseDualStack": false
             }
         },
-        {
-            "documentation": "For region us-iso-east-1 with FIPS enabled and DualStack enabled",
-            "expect": {
-                "error": "FIPS and DualStack are enabled, but this partition does not support one or both"
-            },
-            "params": {
-                "Region": "us-iso-east-1",
-                "UseFIPS": true,
-                "UseDualStack": true
-            }
-        },
         {
             "documentation": "For region us-iso-east-1 with FIPS enabled and DualStack disabled",
             "expect": {
@@ -440,17 +429,6 @@
                 "UseDualStack": false
             }
         },
-        {
-            "documentation": "For region us-iso-east-1 with FIPS disabled and DualStack enabled",
-            "expect": {
-                "error": "DualStack is enabled but this partition does not support DualStack"
-            },
-            "params": {
-                "Region": "us-iso-east-1",
-                "UseFIPS": false,
-                "UseDualStack": true
-            }
-        },
         {
             "documentation": "For region us-iso-east-1 with FIPS disabled and DualStack disabled",
             "expect": {
@@ -464,17 +442,6 @@
                 "UseDualStack": false
             }
         },
-        {
-            "documentation": "For region us-isob-east-1 with FIPS enabled and DualStack enabled",
-            "expect": {
-                "error": "FIPS and DualStack are enabled, but this partition does not support one or both"
-            },
-            "params": {
-                "Region": "us-isob-east-1",
-                "UseFIPS": true,
-                "UseDualStack": true
-            }
-        },
         {
             "documentation": "For region us-isob-east-1 with FIPS enabled and DualStack disabled",
             "expect": {
@@ -488,17 +455,6 @@
                 "UseDualStack": false
             }
         },
-        {
-            "documentation": "For region us-isob-east-1 with FIPS disabled and DualStack enabled",
-            "expect": {
-                "error": "DualStack is enabled but this partition does not support DualStack"
-            },
-            "params": {
-                "Region": "us-isob-east-1",
-                "UseFIPS": false,
-                "UseDualStack": true
-            }
-        },
         {
             "documentation": "For region us-isob-east-1 with FIPS disabled and DualStack disabled",
             "expect": {
@@ -562,12 +518,6 @@
                 "UseDualStack": true,
                 "Endpoint": "https://example.com"
             }
-        },
-        {
-            "documentation": "Missing region",
-            "expect": {
-                "error": "Invalid Configuration: Missing Region"
-            }
         }
     ],
     "version": "1.0"
diff --git a/tests/functional/models/sdk-default-configuration.json b/tests/functional/models/sdk-default-configuration.json
new file mode 100644
index 000000000..87278367d
--- /dev/null
+++ b/tests/functional/models/sdk-default-configuration.json
@@ -0,0 +1,55 @@
+{
+  "version": 1,
+  "base": {
+    "retryMode": "standard",
+    "stsRegionalEndpoints": "regional",
+    "s3UsEast1RegionalEndpoints": "regional",
+    "connectTimeoutInMillis": 9999000,
+    "tlsNegotiationTimeoutInMillis": 9999000
+  },
+  "modes": {
+    "standard": {
+      "connectTimeoutInMillis": {
+        "override": 9999000
+      },
+      "tlsNegotiationTimeoutInMillis": {
+        "override": 9999000
+      }
+    },
+    "in-region": {
+    },
+    "cross-region": {
+      "connectTimeoutInMillis": {
+        "override": 9999000
+      },
+      "tlsNegotiationTimeoutInMillis": {
+        "override": 9999000
+      }
+    },
+    "mobile": {
+      "connectTimeoutInMillis": {
+        "override": 99999000
+      },
+      "tlsNegotiationTimeoutInMillis": {
+        "override": 99999000
+      }
+    }
+  },
+  "documentation": {
+    "modes": {
+      "standard": "<p>FOR TESTING ONLY: The STANDARD mode provides the latest recommended default values that should be safe to run in most scenarios</p><p>Note that the default values vended from this mode might change as best practices may evolve. As a result, it is encouraged to perform tests when upgrading the SDK</p>",
+      "in-region": "<p>FOR TESTING ONLY: The IN_REGION mode builds on the standard mode and includes optimization tailored for applications which call AWS services from within the same AWS region</p><p>Note that the default values vended from this mode might change as best practices may evolve. As a result, it is encouraged to perform tests when upgrading the SDK</p>",
+      "cross-region": "<p>FOR TESTING ONLY: The CROSS_REGION mode builds on the standard mode and includes optimization tailored for applications which call AWS services in a different region</p><p>Note that the default values vended from this mode might change as best practices may evolve. As a result, it is encouraged to perform tests when upgrading the SDK</p>",
+      "mobile": "<p>FOR TESTING ONLY: The MOBILE mode builds on the standard mode and includes optimization tailored for mobile applications</p><p>Note that the default values vended from this mode might change as best practices may evolve. As a result, it is encouraged to perform tests when upgrading the SDK</p>",
+      "auto": "<p>FOR TESTING ONLY: The AUTO mode is an experimental mode that builds on the standard mode. The SDK will attempt to discover the execution environment to determine the appropriate settings automatically.</p><p>Note that the auto detection is heuristics-based and does not guarantee 100% accuracy. STANDARD mode will be used if the execution environment cannot be determined. The auto detection might query <a href=\"https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-instance-metadata.html\">EC2 Instance Metadata service</a>, which might introduce latency. Therefore we recommend choosing an explicit defaults_mode instead if startup latency is critical to your application</p>",
+      "legacy": "<p>FOR TESTING ONLY: The LEGACY mode provides default settings that vary per SDK and were used prior to establishment of defaults_mode</p>"
+    },
+    "configuration": {
+      "retryMode": "<p>FOR TESTING ONLY: A retry mode specifies how the SDK attempts retries. See <a href=\"https://docs.aws.amazon.com/sdkref/latest/guide/setting-global-retry_mode.html\">Retry Mode</a></p>",
+      "stsRegionalEndpoints": "<p>FOR TESTING ONLY: Specifies how the SDK determines the AWS service endpoint that it uses to talk to the AWS Security Token Service (AWS STS). See <a href=\"https://docs.aws.amazon.com/sdkref/latest/guide/setting-global-sts_regional_endpoints.html\">Setting STS Regional endpoints</a></p>",
+      "s3UsEast1RegionalEndpoints": "<p>FOR TESTING ONLY: Specifies how the SDK determines the AWS service endpoint that it uses to talk to the Amazon S3 for the us-east-1 region</p>",
+      "connectTimeoutInMillis": "<p>FOR TESTING ONLY: The amount of time after making an initial connection attempt on a socket, where if the client does not receive a completion of the connect handshake, the client gives up and fails the operation</p>",
+      "tlsNegotiationTimeoutInMillis": "<p>FOR TESTING ONLY: The maximum amount of time that a TLS handshake is allowed to take from the time the CLIENT HELLO message is sent to ethe time the client and server have fully negotiated ciphers and exchanged keys</p>"
+    }
+  }
+}
diff --git a/tests/functional/test_config_provider.py b/tests/functional/test_config_provider.py
index 020628691..57b3fd445 100644
--- a/tests/functional/test_config_provider.py
+++ b/tests/functional/test_config_provider.py
@@ -10,8 +10,11 @@
 # 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.
+from pathlib import Path
+
 import pytest
 
+import botocore.exceptions
 from botocore.config import Config
 from botocore.session import get_session
 
@@ -28,6 +31,13 @@ loader = session.get_component('data_loader')
 sdk_default_configuration = loader.load_data('sdk-default-configuration')
 
 
+def assert_client_uses_standard_defaults(client):
+    assert client.meta.config.s3['us_east_1_regional_endpoint'] == 'regional'
+    assert client.meta.config.connect_timeout == 3.1
+    assert client.meta.endpoint_url == 'https://sts.us-west-2.amazonaws.com'
+    assert client.meta.config.retries['mode'] == 'standard'
+
+
 @pytest.mark.parametrize("mode", sdk_default_configuration['base'])
 def test_no_new_sdk_default_configuration_values(mode):
     err_msg = (
@@ -45,7 +55,69 @@ def test_default_configurations_resolve_correctly():
     client = session.create_client(
         'sts', config=config, region_name='us-west-2'
     )
+    assert_client_uses_standard_defaults(client)
+
+
+@pytest.fixture
+def loader():
+    test_models_dir = Path(__file__).parent / 'models'
+    loader = botocore.loaders.Loader()
+    loader.search_paths.insert(0, test_models_dir)
+    return loader
+
+
+@pytest.fixture
+def session(loader):
+    session = botocore.session.Session()
+    session.register_component('data_loader', loader)
+    return session
+
+
+def assert_client_uses_legacy_defaults(client):
+    assert client.meta.config.s3 is None
+    assert client.meta.config.connect_timeout == 60
+    assert client.meta.endpoint_url == 'https://sts.amazonaws.com'
+    assert client.meta.config.retries['mode'] == 'legacy'
+
+
+def assert_client_uses_testing_defaults(client):
     assert client.meta.config.s3['us_east_1_regional_endpoint'] == 'regional'
-    assert client.meta.config.connect_timeout == 3.1
-    assert client.meta.endpoint_url == 'https://sts.us-west-2.amazonaws.com'
+    assert client.meta.config.connect_timeout == 9999
+    assert client.meta.endpoint_url == 'https://sts.amazonaws.com'
     assert client.meta.config.retries['mode'] == 'standard'
+
+
+class TestConfigurationDefaults:
+    def test_defaults_mode_resolved_from_config_store(self, session):
+        config_store = session.get_component('config_store')
+        config_store.set_config_variable('defaults_mode', 'standard')
+        client = session.create_client('sts', 'us-west-2')
+        assert_client_uses_testing_defaults(client)
+
+    def test_no_mutate_session_provider(self, session):
+        # Using the standard default mode should change the connect timeout
+        # on the client, but not the session
+        standard_client = session.create_client(
+            'sts', 'us-west-2', config=Config(defaults_mode='standard')
+        )
+        assert_client_uses_testing_defaults(standard_client)
+
+        # Using the legacy default mode should not change the connect timeout
+        # on the client or the session. By default the connect timeout for a client
+        # is 60 seconds, and unset on the session.
+        legacy_client = session.create_client('sts', 'us-west-2')
+        assert_client_uses_legacy_defaults(legacy_client)
+
+    def test_defaults_mode_resolved_from_client_config(self, session):
+        config = Config(defaults_mode='standard')
+        client = session.create_client('sts', 'us-west-2', config=config)
+        assert_client_uses_testing_defaults(client)
+
+    def test_defaults_mode_resolved_invalid_mode_exception(self, session):
+        with pytest.raises(botocore.exceptions.InvalidDefaultsMode):
+            config = Config(defaults_mode='invalid_default_mode')
+            session.create_client('sts', 'us-west-2', config=config)
+
+    def test_defaults_mode_resolved_legacy(self, session):
+        client = session.create_client('sts', 'us-west-2')
+        assert_client_uses_legacy_defaults(client)
diff --git a/tests/functional/test_endpoints.py b/tests/functional/test_endpoints.py
index 59ce8f043..1372f8ff8 100644
--- a/tests/functional/test_endpoints.py
+++ b/tests/functional/test_endpoints.py
@@ -13,69 +13,7 @@
 import pytest
 
 from botocore.session import get_session
-
-SERVICE_RENAMES = {
-    # Actual service name we use -> Allowed computed service name.
-    'alexaforbusiness': 'alexa-for-business',
-    'apigateway': 'api-gateway',
-    'application-autoscaling': 'application-auto-scaling',
-    'appmesh': 'app-mesh',
-    'autoscaling': 'auto-scaling',
-    'autoscaling-plans': 'auto-scaling-plans',
-    'ce': 'cost-explorer',
-    'cloudhsmv2': 'cloudhsm-v2',
-    'cloudsearchdomain': 'cloudsearch-domain',
-    'cognito-idp': 'cognito-identity-provider',
-    'config': 'config-service',
-    'cur': 'cost-and-usage-report-service',
-    'datapipeline': 'data-pipeline',
-    'directconnect': 'direct-connect',
-    'devicefarm': 'device-farm',
-    'discovery': 'application-discovery-service',
-    'dms': 'database-migration-service',
-    'ds': 'directory-service',
-    'dynamodbstreams': 'dynamodb-streams',
-    'elasticbeanstalk': 'elastic-beanstalk',
-    'elastictranscoder': 'elastic-transcoder',
-    'elb': 'elastic-load-balancing',
-    'elbv2': 'elastic-load-balancing-v2',
-    'es': 'elasticsearch-service',
-    'events': 'eventbridge',
-    'globalaccelerator': 'global-accelerator',
-    'iot-data': 'iot-data-plane',
-    'iot-jobs-data': 'iot-jobs-data-plane',
-    'iot1click-devices': 'iot-1click-devices-service',
-    'iot1click-projects': 'iot-1click-projects',
-    'iotevents-data': 'iot-events-data',
-    'iotevents': 'iot-events',
-    'iotwireless': 'iot-wireless',
-    'kinesisanalytics': 'kinesis-analytics',
-    'kinesisanalyticsv2': 'kinesis-analytics-v2',
-    'kinesisvideo': 'kinesis-video',
-    'lex-models': 'lex-model-building-service',
-    'lexv2-models': 'lex-models-v2',
-    'lex-runtime': 'lex-runtime-service',
-    'lexv2-runtime': 'lex-runtime-v2',
-    'logs': 'cloudwatch-logs',
-    'machinelearning': 'machine-learning',
-    'marketplacecommerceanalytics': 'marketplace-commerce-analytics',
-    'marketplace-entitlement': 'marketplace-entitlement-service',
-    'meteringmarketplace': 'marketplace-metering',
-    'mgh': 'migration-hub',
-    'sms-voice': 'pinpoint-sms-voice',
-    'resourcegroupstaggingapi': 'resource-groups-tagging-api',
-    'route53': 'route-53',
-    'route53domains': 'route-53-domains',
-    's3control': 's3-control',
-    'sdb': 'simpledb',
-    'secretsmanager': 'secrets-manager',
-    'serverlessrepo': 'serverlessapplicationrepository',
-    'servicecatalog': 'service-catalog',
-    'servicecatalog-appregistry': 'service-catalog-appregistry',
-    'stepfunctions': 'sfn',
-    'storagegateway': 'storage-gateway',
-}
-
+from botocore.utils import CLIENT_NAME_TO_HYPHENIZED_SERVICE_ID_OVERRIDES
 
 ENDPOINT_PREFIX_OVERRIDE = {
     # entry in endpoints.json -> actual endpoint prefix.
@@ -163,7 +101,7 @@ def test_endpoint_matches_service(endpoint_prefix):
 
 
 @pytest.mark.parametrize("service_name", AVAILABLE_SERVICES)
-def test_service_name_matches_endpoint_prefix(service_name):
+def test_client_name_matches_hyphenized_service_id(service_name):
     """Generates tests for each service to verify that the computed service
     named based on the service id matches the service name used to
     create a client (i.e the directory name in botocore/data)
@@ -174,7 +112,9 @@ def test_service_name_matches_endpoint_prefix(service_name):
 
     # Handle known exceptions where we have renamed the service directory
     # for one reason or another.
-    actual_service_name = SERVICE_RENAMES.get(service_name, service_name)
+    actual_service_name = CLIENT_NAME_TO_HYPHENIZED_SERVICE_ID_OVERRIDES.get(
+        service_name, service_name
+    )
 
     err_msg = (
         f"Actual service name `{actual_service_name}` does not match "
diff --git a/tests/unit/cfg/aws_services_config b/tests/unit/cfg/aws_services_config
new file mode 100644
index 000000000..cf9040c2a
--- /dev/null
+++ b/tests/unit/cfg/aws_services_config
@@ -0,0 +1,9 @@
+[default]
+endpoint_url = https://localhost:1234/
+services = my-services
+
+[services my-services]
+s3 =
+  endpoint_url = https://localhost:5678/
+dynamodb =
+  endpoint_url = https://localhost:8888/
diff --git a/tests/unit/test_config_provider.py b/tests/unit/test_config_provider.py
index 64760d9d2..4a7d91b0d 100644
--- a/tests/unit/test_config_provider.py
+++ b/tests/unit/test_config_provider.py
@@ -21,6 +21,7 @@ from botocore.configprovider import (
     BaseProvider,
     ChainProvider,
     ConfigChainFactory,
+    ConfiguredEndpointProvider,
     ConfigValueStore,
     ConstantProvider,
     DefaultConfigResolver,
@@ -363,6 +364,60 @@ class TestConfigValueStore(unittest.TestCase):
         self.assertIsInstance(provider, ConstantProvider)
         self.assertEqual(value, 'bar')
 
+    def test_deepcopy_preserves_overrides(self):
+        provider = ConstantProvider(100)
+        config_store = ConfigValueStore(mapping={'fake_variable': provider})
+        config_store.set_config_variable('fake_variable', 'override-value')
+
+        config_store_deepcopy = copy.deepcopy(config_store)
+
+        value = config_store_deepcopy.get_config_variable('fake_variable')
+        self.assertEqual(value, 'override-value')
+
+    def test_copy_preserves_provider_identities(self):
+        fake_variable_provider = ConstantProvider(100)
+        config_store = ConfigValueStore(
+            mapping={
+                'fake_variable': fake_variable_provider,
+            }
+        )
+
+        config_store_copy = copy.copy(config_store)
+
+        self.assertIs(
+            config_store.get_config_provider('fake_variable'),
+            config_store_copy.get_config_provider('fake_variable'),
+        )
+
+    def test_copy_preserves_overrides(self):
+        provider = ConstantProvider(100)
+        config_store = ConfigValueStore(mapping={'fake_variable': provider})
+        config_store.set_config_variable('fake_variable', 'override-value')
+
+        config_store_copy = copy.copy(config_store)
+
+        value = config_store_copy.get_config_variable('fake_variable')
+        self.assertEqual(value, 'override-value')
+
+    def test_copy_update_does_not_mutate_source_config_store(self):
+        fake_variable_provider = ConstantProvider(100)
+        config_store = ConfigValueStore(
+            mapping={
+                'fake_variable': fake_variable_provider,
+            }
+        )
+
+        config_store_copy = copy.copy(config_store)
+
+        another_variable_provider = ConstantProvider('ABC')
+
+        config_store_copy.set_config_provider(
+            'fake_variable', another_variable_provider
+        )
+
+        assert config_store.get_config_variable('fake_variable') == 100
+        assert config_store_copy.get_config_variable('fake_variable') == 'ABC'
+
 
 class TestInstanceVarProvider(unittest.TestCase):
     def assert_provides_value(self, name, instance_map, expected_value):
@@ -633,8 +688,8 @@ class TestSmartDefaults:
         return fake_session
 
     def _create_config_value_store(self, s3_mapping={}, **override_kwargs):
-        provider_foo = ConstantProvider(value='foo')
-        environment_provider_foo = EnvironmentProvider(
+        constant_provider = ConstantProvider(value='my_sts_regional_endpoint')
+        environment_provider = EnvironmentProvider(
             name='AWS_RETRY_MODE', env={'AWS_RETRY_MODE': None}
         )
         fake_session = mock.Mock(spec=session.Session)
@@ -642,8 +697,10 @@ class TestSmartDefaults:
         # Testing with three different providers to validate
         # SmartDefaultsConfigStoreFactory._get_new_chain_provider
         mapping = {
-            'sts_regional_endpoints': ChainProvider(providers=[provider_foo]),
-            'retry_mode': ChainProvider(providers=[environment_provider_foo]),
+            'sts_regional_endpoints': ChainProvider(
+                providers=[constant_provider]
+            ),
+            'retry_mode': ChainProvider(providers=[environment_provider]),
             's3': SectionConfigProvider('s3', fake_session, s3_mapping),
         }
         mapping.update(**override_kwargs)
@@ -657,11 +714,68 @@ class TestSmartDefaults:
 
     def test_config_store_deepcopy(self):
         config_store = ConfigValueStore()
-        config_store.set_config_provider('foo', ConstantProvider('bar'))
+        config_store.set_config_provider(
+            'constant_value', ConstantProvider('ABC')
+        )
         config_store_copy = copy.deepcopy(config_store)
-        config_store_copy.set_config_provider('fizz', ConstantProvider('buzz'))
-        assert config_store.get_config_variable('fizz') is None
-        assert config_store_copy.get_config_variable('foo') == 'bar'
+        config_store_copy.set_config_provider(
+            'constant_value_copy', ConstantProvider('123')
+        )
+        assert config_store.get_config_variable('constant_value_copy') is None
+        assert config_store_copy.get_config_variable('constant_value') == 'ABC'
+
+    def _create_config_value_store_to_test_merge(self):
+        environment_provider = EnvironmentProvider(
+            name='AWS_S3_US_EAST_1_REGIONAL_ENDPOINT',
+            env={},
+        )
+
+        s3_mapping = {
+            'us_east_1_regional_endpoint': ChainProvider(
+                providers=[environment_provider]
+            )
+        }
+
+        override_kwargs = {'connect_timeout': ConstantProvider(value=None)}
+
+        config_value_store = self._create_config_value_store(
+            s3_mapping=s3_mapping, **override_kwargs
+        )
+
+        return config_value_store
+
+    @pytest.mark.parametrize(
+        'config_variable,expected_value_before,expected_value_after',
+        [
+            ['retry_mode', None, 'standard'],
+            ['sts_regional_endpoints', 'my_sts_regional_endpoint', 'regional'],
+            ['connect_timeout', None, 2],
+            ['s3', None, {'us_east_1_regional_endpoint': 'regional'}],
+        ],
+    )
+    def test_config_store_providers_not_mutated_after_merge(
+        self,
+        config_variable,
+        expected_value_before,
+        expected_value_after,
+        smart_defaults_factory,
+    ):
+        """Test uses the standard default mode from the template"""
+
+        config_value_store = self._create_config_value_store_to_test_merge()
+
+        provider = config_value_store.get_config_provider(config_variable)
+
+        smart_defaults_factory.merge_smart_defaults(
+            config_value_store, 'standard', 'some-region'
+        )
+
+        assert provider.provide() == expected_value_before
+
+        assert (
+            config_value_store.get_config_variable(config_variable)
+            == expected_value_after
+        )
 
     @pytest.mark.parametrize(
         'defaults_mode, retry_mode, sts_regional_endpoints,'
@@ -710,7 +824,7 @@ class TestSmartDefaults:
         assert config_store.get_config_variable('connect_timeout') == 2
 
     def test_no_resolve_default_s3_values_on_config(
-        self, smart_defaults_factory, fake_session
+        self, smart_defaults_factory
     ):
         environment_provider = EnvironmentProvider(
             name='AWS_S3_US_EAST_1_REGIONAL_ENDPOINT',
@@ -829,3 +943,206 @@ class TestSmartDefaults:
             )
             mode = smart_defaults_factory.resolve_auto_mode('us-west-2')
             assert mode == 'standard'
+
+
+def create_cases():
+    service = 'batch'
+
+    return [
+        dict(
+            service=service,
+            environ_map={},
+            full_config_map={},
+            expected_value=None,
+        ),
+        dict(
+            service=service,
+            environ_map={'AWS_ENDPOINT_URL': 'global-from-env'},
+            full_config_map={},
+            expected_value='global-from-env',
+        ),
+        dict(
+            service=service,
+            environ_map={
+                f'AWS_ENDPOINT_URL_{service.upper()}': 'service-from-env',
+                'AWS_ENDPOINT_URL': 'global-from-env',
+            },
+            full_config_map={},
+            expected_value='service-from-env',
+        ),
+        dict(
+            service=service,
+            environ_map={
+                'AWS_ENDPOINT_URL': 'global-from-env',
+                'AWS_ENDPOINT_URL_S3': 's3-endpoint-url',
+            },
+            full_config_map={},
+            expected_value='global-from-env',
+        ),
+        dict(
+            service=service,
+            environ_map={},
+            full_config_map={
+                'profiles': {'default': {'endpoint_url': 'global-from-config'}}
+            },
+            expected_value='global-from-config',
+        ),
+        dict(
+            service=service,
+            environ_map={},
+            full_config_map={
+                'profiles': {
+                    'default': {
+                        'services': 'my-services',
+                    }
+                },
+                'services': {
+                    'my-services': {
+                        service: {'endpoint_url': "service-from-config"}
+                    }
+                },
+            },
+            expected_value='service-from-config',
+        ),
+        dict(
+            service=service,
+            environ_map={},
+            full_config_map={
+                'profiles': {
+                    'default': {
+                        'services': 'my-services',
+                        'endpoint_url': 'global-from-config',
+                    }
+                },
+                'services': {
+                    'my-services': {
+                        service: {'endpoint_url': "service-from-config"}
+                    }
+                },
+            },
+            expected_value='service-from-config',
+        ),
+        dict(
+            service=service,
+            environ_map={
+                'AWS_ENDPOINT_URL': 'global-from-env',
+            },
+            full_config_map={
+                'profiles': {
+                    'default': {
+                        'endpoint_url': 'global-from-config',
+                    }
+                },
+            },
+            expected_value='global-from-env',
+        ),
+        dict(
+            service=service,
+            environ_map={
+                f'AWS_ENDPOINT_URL_{service.upper()}': 'service-from-env',
+            },
+            full_config_map={
+                'profiles': {
+                    'default': {
+                        'endpoint_url': 'global-from-config',
+                    }
+                },
+            },
+            expected_value='service-from-env',
+        ),
+        dict(
+            service='s3',
+            environ_map={},
+            full_config_map={
+                'profiles': {
+                    'default': {
+                        'services': 'my-services',
+                        'endpoint_url': 'global-from-config',
+                    }
+                },
+                'services': {
+                    'my-services': {
+                        service: {'endpoint_url': "service-from-config"}
+                    }
+                },
+            },
+            expected_value='global-from-config',
+        ),
+        dict(
+            service='runtime.sagemaker',
+            environ_map={},
+            full_config_map={
+                'profiles': {
+                    'default': {
+                        'services': 'my-services',
+                    }
+                },
+                'services': {
+                    'my-services': {
+                        'sagemaker_runtime': {
+                            'endpoint_url': "service-from-config"
+                        }
+                    }
+                },
+            },
+            expected_value='service-from-config',
+        ),
+        dict(
+            service='apigateway',
+            environ_map={},
+            full_config_map={
+                'profiles': {
+                    'default': {
+                        'services': 'my-services',
+                    }
+                },
+                'services': {
+                    'my-services': {
+                        'api_gateway': {'endpoint_url': "service-from-config"}
+                    }
+                },
+            },
+            expected_value='service-from-config',
+        ),
+    ]
+
+
+class TestConfiguredEndpointProvider:
+    def assert_does_provide(
+        self,
+        service,
+        environ_map,
+        full_config_map,
+        expected_value,
+    ):
+        scoped_config_map = full_config_map.get('profiles', {}).get(
+            'default', {}
+        )
+
+        chain = ConfiguredEndpointProvider(
+            scoped_config=scoped_config_map,
+            full_config=full_config_map,
+            client_name=service,
+            environ=environ_map,
+        )
+        value = chain.provide()
+        assert value == expected_value
+
+    @pytest.mark.parametrize('test_case', create_cases())
+    def test_does_provide(self, test_case):
+        self.assert_does_provide(**test_case)
+
+    def test_is_deepcopyable(self):
+        env = {'AWS_ENDPOINT_URL_BATCH': 'https://endpoint-override'}
+        provider = ConfiguredEndpointProvider(
+            full_config={}, scoped_config={}, client_name='batch', environ=env
+        )
+
+        provider_deepcopy = copy.deepcopy(provider)
+        assert provider is not provider_deepcopy
+        assert provider.provide() == 'https://endpoint-override'
+        assert provider_deepcopy.provide() == 'https://endpoint-override'
+
+        env['AWS_ENDPOINT_URL_BATCH'] = 'https://another-new-endpoint-override'
+        assert provider.provide() == 'https://another-new-endpoint-override'
+        assert provider_deepcopy.provide() == 'https://endpoint-override'
diff --git a/tests/unit/test_configloader.py b/tests/unit/test_configloader.py
index 4a331c9e2..a6e02f7d4 100644
--- a/tests/unit/test_configloader.py
+++ b/tests/unit/test_configloader.py
@@ -188,6 +188,24 @@ class TestConfigLoader(unittest.TestCase):
         self.assertEqual(sso_config['sso_region'], 'us-east-1')
         self.assertEqual(sso_config['sso_start_url'], 'https://example.com')
 
+    def test_services_config(self):
+        filename = path('aws_services_config')
+        loaded_config = load_config(filename)
+        self.assertIn('profiles', loaded_config)
+        self.assertIn('default', loaded_config['profiles'])
+        self.assertIn('services', loaded_config)
+        self.assertIn('my-services', loaded_config['services'])
+        services_config = loaded_config['services']['my-services']
+        self.assertIn('s3', services_config)
+        self.assertIn('dynamodb', services_config)
+        self.assertEqual(
+            services_config['s3']['endpoint_url'], 'https://localhost:5678/'
+        )
+        self.assertEqual(
+            services_config['dynamodb']['endpoint_url'],
+            'https://localhost:8888/',
+        )
+
 
 if __name__ == "__main__":
     unittest.main()
diff --git a/tests/unit/test_session.py b/tests/unit/test_session.py
index ee4cad5a5..ef2495ebc 100644
--- a/tests/unit/test_session.py
+++ b/tests/unit/test_session.py
@@ -772,34 +772,6 @@ class TestCreateClient(BaseSessionTest):
             ]
             self.assertEqual(call_kwargs['api_version'], override_api_version)
 
-    @mock.patch('botocore.client.ClientCreator')
-    def test_defaults_mode_resolved_from_config_store(self, client_creator):
-        config_store = self.session.get_component('config_store')
-        config_store.set_config_variable('defaults_mode', 'standard')
-        self.session.create_client('sts', 'us-west-2')
-        self.assertIsNot(client_creator.call_args[0][-1], config_store)
-
-    @mock.patch('botocore.client.ClientCreator')
-    def test_defaults_mode_resolved_from_client_config(self, client_creator):
-        config_store = self.session.get_component('config_store')
-        config = botocore.config.Config(defaults_mode='standard')
-        self.session.create_client('sts', 'us-west-2', config=config)
-        self.assertIsNot(client_creator.call_args[0][-1], config_store)
-
-    @mock.patch('botocore.client.ClientCreator')
-    def test_defaults_mode_resolved_invalid_mode_exception(
-        self, client_creator
-    ):
-        with self.assertRaises(botocore.exceptions.InvalidDefaultsMode):
-            config = botocore.config.Config(defaults_mode='foo')
-            self.session.create_client('sts', 'us-west-2', config=config)
-
-    @mock.patch('botocore.client.ClientCreator')
-    def test_defaults_mode_resolved_legacy(self, client_creator):
-        config_store = self.session.get_component('config_store')
-        self.session.create_client('sts', 'us-west-2')
-        self.assertIs(client_creator.call_args[0][-1], config_store)
-
 
 class TestSessionComponent(BaseSessionTest):
     def test_internal_component(self):