From 5314ddd87e7ff20f14d7eef599c7edcf95e64e07 Mon Sep 17 00:00:00 2001 From: mbirger Date: Tue, 4 Sep 2018 09:11:12 +0200 Subject: [PATCH] Add support for authentication using certificates client_cert and ca_certs are new parameters of CMRESHandler. CERT_AUTH is an alais for NO_AUTH to support both cert + HTTP auth for other authentication methods. --- cmreslogging/handlers.py | 33 ++++++++++++++++++++++++++------- 1 file changed, 26 insertions(+), 7 deletions(-) diff --git a/cmreslogging/handlers.py b/cmreslogging/handlers.py index 52e250a..92ca680 100644 --- a/cmreslogging/handlers.py +++ b/cmreslogging/handlers.py @@ -38,11 +38,13 @@ class AuthType(Enum): - No authentication - Basic authentication - Kerberos or SSO authentication (on windows and linux) + - Authentication using certificate """ NO_AUTH = 0 BASIC_AUTH = 1 KERBEROS_AUTH = 2 AWS_SIGNED_AUTH = 3 + CERT_AUTH = 4 class IndexNameFrequency(Enum): """ Index type supported @@ -75,6 +77,8 @@ class IndexNameFrequency(Enum): __DEFAULT_ES_DOC_TYPE = 'python_log' __DEFAULT_RAISE_ON_EXCEPTION = False __DEFAULT_TIMESTAMP_FIELD_NAME = "timestamp" + __DEFAULT_CLIENT_CERT = None + __DEFAULT_CA_CERTS = None __LOGGING_FILTER_FIELDS = ['msecs', 'relativeCreated', @@ -138,7 +142,9 @@ def __init__(self, es_doc_type=__DEFAULT_ES_DOC_TYPE, es_additional_fields=__DEFAULT_ADDITIONAL_FIELDS, raise_on_indexing_exceptions=__DEFAULT_RAISE_ON_EXCEPTION, - default_timestamp_field_name=__DEFAULT_TIMESTAMP_FIELD_NAME): + default_timestamp_field_name=__DEFAULT_TIMESTAMP_FIELD_NAME, + client_cert=__DEFAULT_CLIENT_CERT, + ca_certs=__DEFAULT_CA_CERTS): """ Handler constructor :param hosts: The list of hosts that elasticsearch clients will connect. The list can be provided @@ -172,6 +178,8 @@ def __init__(self, to the logs, such the application, environment, etc. :param raise_on_indexing_exceptions: A boolean, True only for debugging purposes to raise exceptions caused when + :param client_cert: String (path to a cert) or tuple (in the case of cert + key). Passed to requests session. + :param ca_certs: String, path to CA certificate (or a bundle). :return: A ready to be used CMRESHandler. """ logging.Handler.__init__(self) @@ -194,6 +202,8 @@ def __init__(self, 'host_ip': socket.gethostbyname(socket.gethostname())}) self.raise_on_indexing_exceptions = raise_on_indexing_exceptions self.default_timestamp_field_name = default_timestamp_field_name + self.client_cert = client_cert + self.ca_certs = ca_certs self._client = None self._buffer = [] @@ -209,13 +219,17 @@ def __schedule_flush(self): self._timer.start() def __get_es_client(self): - if self.auth_type == CMRESHandler.AuthType.NO_AUTH: + if self.auth_type in [CMRESHandler.AuthType.NO_AUTH, CMRESHandler.AuthType.CERT_AUTH]: + if self.auth_type == CMRESHandler.AuthType.CERT_AUTH and self.client_cert is None: + raise ValueError("client_cert parameter is required for CERT_AUTH") if self._client is None: self._client = Elasticsearch(hosts=self.hosts, use_ssl=self.use_ssl, verify_certs=self.verify_certs, connection_class=RequestsHttpConnection, - serializer=self.serializer) + serializer=self.serializer, + client_cert=self.client_cert, + ca_certs=self.ca_certs) return self._client if self.auth_type == CMRESHandler.AuthType.BASIC_AUTH: @@ -225,7 +239,9 @@ def __get_es_client(self): use_ssl=self.use_ssl, verify_certs=self.verify_certs, connection_class=RequestsHttpConnection, - serializer=self.serializer) + serializer=self.serializer, + client_cert=self.client_cert, + ca_certs=self.ca_certs) return self._client if self.auth_type == CMRESHandler.AuthType.KERBEROS_AUTH: @@ -237,7 +253,9 @@ def __get_es_client(self): verify_certs=self.verify_certs, connection_class=RequestsHttpConnection, http_auth=HTTPKerberosAuth(mutual_authentication=DISABLED), - serializer=self.serializer) + serializer=self.serializer, + client_cert=self.client_cert, + ca_certs=self.ca_certs) if self.auth_type == CMRESHandler.AuthType.AWS_SIGNED_AUTH: if not AWS4AUTH_SUPPORTED: @@ -250,8 +268,9 @@ def __get_es_client(self): use_ssl=self.use_ssl, verify_certs=True, connection_class=RequestsHttpConnection, - serializer=self.serializer - ) + serializer=self.serializer, + client_cert=self.client_cert, + ca_certs=self.ca_certs) return self._client raise ValueError("Authentication method not supported")