@cryptotaxi247 / netdata-1 / commits / 8e6261980

Add basic SSL support to SocketService framework.

This adds really basic SSL/TLS support to the python.d SocketService Framework. THis allows collecting data over a secured channel from remote systems, as well as handling of data collection from services that insist on the (usually overkill) use of X.509 client authentication. This adds an optional dependency on the `ssl` module from the Python standard library. Adds 3 new keys to the standard SocketService config: - `ssl` Simple boolean to enable SSL usage. Defaults to off. - `ssl_key` Specifies a path to a file containing the X.509 key to use for client authentication. Leave unset to not use any client authentication. - `ssl_cert` Specifies a path to a file containing the X.509 certificate to use for authentication. Leave unset to not do any client authentication. The `ssl` module is an odd case, as it may not be present on some systems (it's big, and it depends on a big library, so it's one of the common options to exclude on systems that need to save storage space). As such, the import is wrapped in a try/except clause that sets a global depending on whether or not the import succeeded. If the import fails, then SSL support is silently disabled.

Austin S. Hemmelgarn committed May 1, 2018 at 08:50 UTC 8e6261980e880c4f40b5fc5c1f4252594d2551c5
1 file changed +40 -1
python.d/python_modules/bases/FrameworkServices/SocketService.py
+40 -1
@@ -4,6 +4,13 @@
4
5 import socket
6
7 +try:
8 + import ssl
9 +except:
10 + _SSL_SUPPORT = False
11 +else:
12 + _SSL_SUPPORT = True
13 +
14 from bases.FrameworkServices.SimpleService import SimpleService
15
16
@@ -16,6 +23,9 @@ class SocketService(SimpleService):
23 self.unix_socket = None
24 self.dgram_socket = False
25 self.request = ''
26 + self.ssl = False
27 + self.cert = None
28 + self.key = None
29 self.__socket_config = None
30 self.__empty_request = "".encode()
31 SimpleService.__init__(self, configuration=configuration, name=name)
@@ -56,10 +66,24 @@ class SocketService(SimpleService):
66 self.__socket_config = None
67 return False
68
69 + if self.ssl:
70 + try:
71 + self.debug('Encapsulating socket with SSL')
72 + self._sock = ssl.wrap_socket(self._sock,
73 + keyfile=self.key,
74 + certfile=self.cert,
75 + server_side=False,
76 + cert_reqs=ssl.CERT_NONE)
77 + except (socket.error, ssl.SSLError) as error:
78 + self.error('Failed to wrap socket.')
79 + self._disconnect()
80 + self.__socket_config = None
81 + return False
82 +
83 try:
84 self.debug('connecting socket to "{address}", port {port}'.format(address=sa[0], port=sa[1]))
85 self._sock.connect(sa)
62 - except socket.error as error:
86 + except (socket.error, ssl.SSLError) as error:
87 self.error('Failed to connect to "{address}", port {port}, error: {error}'.format(address=sa[0],
88 port=sa[1],
89 error=error))
@@ -249,6 +273,21 @@ class SocketService(SimpleService):
273 except (KeyError, TypeError):
274 self.debug('No port specified. Using: "{0}"'.format(self.port))
275
276 + if _SSL_SUPPORT:
277 + try:
278 + self.ssl = bool(self.configuration['ssl'])
279 + except (KeyError, TypeError):
280 + self.debug('No SSL preference specified, not using SSL.')
281 + self.ssl = False
282 + else:
283 + try:
284 + self.key = str(self.configuration['ssl_key'])
285 + self.cert = str(self.configuration['ssl_cert'])
286 + except (KeyError, TypeError):
287 + self.debug('No SSL client certificate configuration found.')
288 + self.key = None
289 + self.cert = None
290 +
291 try:
292 self.request = str(self.configuration['request'])
293 except (KeyError, TypeError):