From f0f7eba51fd21741938f4900a4ba7ee06f9aa69a Mon Sep 17 00:00:00 2001 From: Dave Hall Date: Tue, 15 Mar 2016 00:59:19 +1100 Subject: [PATCH] Add SSL support See vklochan/python-logstash#28 Adds initial support for SSL. The implementation supports the following features: * Remote certificate validation * Custom CA bundles * Client side certs SSL is now on by default. --- logstash/handler_tcp.py | 39 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 37 insertions(+), 2 deletions(-) diff --git a/logstash/handler_tcp.py b/logstash/handler_tcp.py index cc687bd..1cd68b6 100644 --- a/logstash/handler_tcp.py +++ b/logstash/handler_tcp.py @@ -1,4 +1,5 @@ -from logging.handlers import DatagramHandler, SocketHandler +import ssl +from logging.handlers import SocketHandler from logstash import formatter @@ -12,10 +13,22 @@ class TCPLogstashHandler(SocketHandler, object): :param fqdn; Indicates whether to show fully qualified domain name or not (default False). :param version: version of logstash event schema (default is 0). :param tags: list of tags for a logger (default is None). + :param ssl: Should SSL be enabled for the connection? Default is True. + :param ssl_verify: Should the server's SSL certificate be verified? + :param keyfile: The path to client side SSL key file (default is None). + :param certfile: The path to client side SSL certificate file (default is None). + :param ca_certs: The path to the file containing recognised CA certificates. System wide CA certs are used if omitted. """ - def __init__(self, host, port=5959, message_type='logstash', tags=None, fqdn=False, version=0): + def __init__(self, host, port=5959, message_type='logstash', tags=None, fqdn=False, version=0, ssl=True, ssl_verify=True, keyfile=None, certfile=None, ca_certs=None): super(TCPLogstashHandler, self).__init__(host, port) + + self.ssl = ssl + self.ssl_verify = ssl_verify + self.keyfile = keyfile + self.certfile = certfile + self.ca_certs = ca_certs + if version == 1: self.formatter = formatter.LogstashFormatterVersion1(message_type, tags, fqdn) else: @@ -23,3 +36,25 @@ def __init__(self, host, port=5959, message_type='logstash', tags=None, fqdn=Fal def makePickle(self, record): return self.formatter.format(record) + b'\n' + + + def makeSocket(self, timeout=1): + s = super(TCPLogstashHandler, self).makeSocket(timeout) + + if not self.ssl: + return s + + context = ssl.create_default_context(cafile=self.ca_certs) + context.verify_mode = ssl.CERT_REQUIRED + if not self.ssl_verify: + if self.ca_certs: + context.verify_mode = ssl.CERT_OPTIONAL + else: + context.verify_mode = ssl.CERT_NONE + context.check_hostname = False + + # Client side certificate auth. + if self.certfile and self.keyfile: + context.load_cert_chain(self.certfile, keyfile=self.keyfile) + + return context.wrap_socket(s, server_hostname=self.host) \ No newline at end of file