diff --git a/botocore/client.py b/botocore/client.py index d54c47eac5..6d3bd3acff 100644 --- a/botocore/client.py +++ b/botocore/client.py @@ -11,6 +11,8 @@ # ANY KIND, either express or implied. See the License for the specific # language governing permissions and limitations under the License. import logging +import os +import warnings from botocore import waiter, xform_name from botocore.args import ClientArgsCreator @@ -606,8 +608,21 @@ def _create_endpoint( resolved, region_name, endpoint_url ) if endpoint_url is None: - # Use the sslCommonName over the hostname for Python 2.6 compat. - hostname = resolved.get('sslCommonName', resolved.get('hostname')) + sslCommonName = resolved.get('sslCommonName') + hostname = resolved.get('hostname') + is_disabled = ensure_boolean( + os.environ.get('BOTO_DISABLE_COMMONNAME', False) + ) + if not is_disabled and sslCommonName is not None: + warnings.warn( + f'The {service_name} client is currently using a ' + f'deprecated endpoint: {sslCommonName}. In the next ' + f'minor version this will be moved to {hostname}. ' + 'See https://github.com/boto/botocore/issues/2705 ' + 'for more details.', + category=FutureWarning, + ) + hostname = sslCommonName endpoint_url = self._make_url( hostname, is_secure, resolved.get('protocols', []) ) diff --git a/tests/unit/test_client.py b/tests/unit/test_client.py index e952ddd0b9..59699f4660 100644 --- a/tests/unit/test_client.py +++ b/tests/unit/test_client.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. +import os from contextlib import closing +import pytest + import botocore import botocore.config from botocore import client, exceptions, hooks @@ -1607,6 +1610,27 @@ def test_client_close_context_manager(self): self.endpoint.close.assert_called_once_with() + def test_sslCommonName_warning(self): + creator = self.create_client_creator() + self.endpoint_data['sslCommonName'] = 'bar' + + with self.assertWarns(FutureWarning) as warning: + creator.create_client( + 'myservice', 'us-west-2', credentials=self.credentials + ) + self.assertEqual(len(warning.warnings), 1) + + @mock.patch.dict(os.environ, {'BOTO_DISABLE_COMMONNAME': 'true'}) + def test_BOTO_DISABLE_COMMONNAME(self): + creator = self.create_client_creator() + self.endpoint_data['sslCommonName'] = 'bar' + + with pytest.warns(None) as warning: + creator.create_client( + 'myservice', 'us-west-2', credentials=self.credentials + ) + self.assertEqual(len(warning), 0) + class TestClientErrors(TestAutoGeneratedClient): def add_error_response(self, error_response):