From 7be0894fce064b03e121d2952a0787936f42ec0c Mon Sep 17 00:00:00 2001 From: Stavros Sachtouris <saxtouri@admin.grnet.gr> Date: Thu, 28 May 2015 18:52:00 +0300 Subject: [PATCH] On SSL error, fall back to default certificates Create a decorator "ssl_fall_back" which catches a KamakiSSLError, patches kamaki with the default certificates bundle and reruns the failed method. The decorator is used on the "SyncerSettings._get_pithos_client" method, because this is the first point of SSL failure. The default certificates bundle is acquired from the package "certifi", which has been added to dependencies. --- agkyra/syncer/setup.py | 24 +++++++++++++++++++++--- setup.py | 1 + 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/agkyra/syncer/setup.py b/agkyra/syncer/setup.py index 5ac804e..34517be 100644 --- a/agkyra/syncer/setup.py +++ b/agkyra/syncer/setup.py @@ -22,7 +22,7 @@ from agkyra.syncer.database import SqliteFileStateDB from agkyra.syncer.messaging import Messager from agkyra.syncer import utils -from kamaki.clients import ClientError +from kamaki.clients import ClientError, KamakiSSLError from kamaki.clients.astakos import AstakosClient from kamaki.clients.pithos import PithosClient @@ -50,6 +50,23 @@ def get_instance(elems): return utils.hash_string(data) +def ssl_fall_back(method): + """Catch an SSL error while executing a method, patch kamaki and retry""" + def wrap(self, *args, **kwargs): + try: + return method(self, *args, **kwargs) + except KamakiSSLError as ssle: + logger.debug('Kamaki SSL failed %s' % ssle) + logger.info( + 'Kamaki SSL failed, fall back to certifi (mozilla certs)') + import certifi + https.patch_with_certs(certifi.where()) + return method(self, *args, **kwargs) + wrap.__name__ = method.__name__ + wrap.__doc__ = method.__doc__ + return wrap + + class SyncerSettings(): def __init__(self, auth_url, auth_token, container, local_root_path, *args, **kwargs): @@ -155,6 +172,7 @@ class SyncerSettings(): os.mkdir(path) return path + @ssl_fall_back def _get_pithos_client(self, auth_url, token, container): try: astakos = AstakosClient(auth_url, token) @@ -176,8 +194,8 @@ class SyncerSettings(): client.get_container_info(container) except ClientError as e: if e.status == 404: - logger.warning("Container '%s' does not exist, creating..." - % container) + logger.warning( + "Container '%s' does not exist, creating..." % container) try: client.create_container(container) except ClientError: diff --git a/setup.py b/setup.py index 4d32e98..8cbfae1 100644 --- a/setup.py +++ b/setup.py @@ -40,6 +40,7 @@ INSTALL_REQUIRES = [ 'watchdog', 'psutil', 'ws4py', + 'certifi', ] EXTRAS_REQUIRES = { -- GitLab