Repository: boto/botocore
Pull request #695 (2015-10-20 21:39:04)

Port ca_bundle from AWS CLI into botocore session
This takes the work from aws/aws-cli#1379 and moves
it into the botocore session.

The benefit in doing this is that botocore/boto3
can now support the ca_bundle option from
~/.aws/config, which gives better interop between
the AWS CLI and the python SDK.

There will also need to be a corresponding PR to
aws/aws-cli that removes this entry from the env vars
passed to the session created in CLIDriver.

cc @kyleknap @mtdowling @rayluo @JordonPhillips 


Patch:
diff --git a/botocore/client.py b/botocore/client.py
index 6f1f36e4d..d28dd8b19 100644
--- a/botocore/client.py
+++ b/botocore/client.py
@@ -191,6 +191,14 @@ class ClientCreator(object):
 
         config_kwargs['s3'] = s3_configuration
 
+    def _resolve_verify_value(self, provided_verify_value, scoped_config):
+        # If a user provides a value for "verify" then we don't do anything.
+        # We always use explicit values provided.
+        if provided_verify_value is not None:
+            return provided_verify_value
+        elif scoped_config is not None:
+            return scoped_config.get('ca_bundle')
+
     def _get_client_args(self, service_model, region_name, is_secure,
                          endpoint_url, verify, credentials,
                          scoped_config, client_config):
@@ -203,6 +211,7 @@ class ClientCreator(object):
 
         response_parser = botocore.parsers.create_parser(protocol)
 
+        verify = self._resolve_verify_value(verify, scoped_config)
         # Determine what region the user provided either via the
         # region_name argument or the client_config.
         if region_name is None:
diff --git a/botocore/session.py b/botocore/session.py
index ba88c040f..21fcc0410 100644
--- a/botocore/session.py
+++ b/botocore/session.py
@@ -78,9 +78,8 @@ class Session(object):
         'region': ('region', 'AWS_DEFAULT_REGION', None, None),
         'data_path': ('data_path', 'AWS_DATA_PATH', None, None),
         'config_file': (None, 'AWS_CONFIG_FILE', '~/.aws/config', None),
+        'ca_bundle': ('ca_bundle', 'AWS_CA_BUNDLE', None, None),
 
-        # These variables are intended for internal use so don't have any
-        # user settable values.
         # This is the shared credentials file amongst sdks.
         'credentials_file': (None, 'AWS_SHARED_CREDENTIALS_FILE',
                              '~/.aws/credentials', None),


Test patch:
diff --git a/tests/unit/test_client.py b/tests/unit/test_client.py
index a7032a0aa..5160f05d6 100644
--- a/tests/unit/test_client.py
+++ b/tests/unit/test_client.py
@@ -1091,3 +1091,18 @@ class TestAutoGeneratedClient(unittest.TestCase):
             mock.call('before-sign.s3', utils.switch_to_virtual_host_style),
             client.meta.events.register.call_args_list
         )
+
+    def test_create_with_ca_bundle_from_scoped_config(self):
+        creator = self.create_client_creator()
+        creator.create_client('myservice', 'us-west-2',
+                              scoped_config={'ca_bundle': 'mycerts.pem'})
+        call_kwargs = self.endpoint_creator.create_endpoint.call_args[1]
+        self.assertEqual(call_kwargs['verify'], 'mycerts.pem')
+
+    def test_verify_takes_precedence_over_scoped_config(self):
+        creator = self.create_client_creator()
+        creator.create_client('myservice', 'us-west-2',
+                              verify='verify.pem',
+                              scoped_config={'ca_bundle': 'mycerts.pem'})
+        call_kwargs = self.endpoint_creator.create_endpoint.call_args[1]
+        self.assertEqual(call_kwargs['verify'], 'verify.pem')