summaryrefslogtreecommitdiffstats
path: root/collectors/python.d.plugin/python_modules/bases/FrameworkServices/SocketService.py
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--collectors/python.d.plugin/python_modules/bases/FrameworkServices/SocketService.py (renamed from python.d/python_modules/bases/FrameworkServices/SocketService.py)64
1 files changed, 56 insertions, 8 deletions
diff --git a/python.d/python_modules/bases/FrameworkServices/SocketService.py b/collectors/python.d.plugin/python_modules/bases/FrameworkServices/SocketService.py
index 8d27ae660..e85455307 100644
--- a/python.d/python_modules/bases/FrameworkServices/SocketService.py
+++ b/collectors/python.d.plugin/python_modules/bases/FrameworkServices/SocketService.py
@@ -1,9 +1,18 @@
# -*- coding: utf-8 -*-
# Description:
# Author: Pawel Krupa (paulfantom)
+# Author: Ilya Mashchenko (l2isbad)
+# SPDX-License-Identifier: GPL-3.0-or-later
import socket
+try:
+ import ssl
+except ImportError:
+ _TLS_SUPPORT = False
+else:
+ _TLS_SUPPORT = True
+
from bases.FrameworkServices.SimpleService import SimpleService
@@ -16,6 +25,9 @@ class SocketService(SimpleService):
self.unix_socket = None
self.dgram_socket = False
self.request = ''
+ self.tls = False
+ self.cert = None
+ self.key = None
self.__socket_config = None
self.__empty_request = "".encode()
SimpleService.__init__(self, configuration=configuration, name=name)
@@ -26,7 +38,7 @@ class SocketService(SimpleService):
message=message))
else:
if self.__socket_config is not None:
- af, sock_type, proto, canon_name, sa = self.__socket_config
+ _, _, _, _, sa = self.__socket_config
self.error('socket to "{address}" port {port}: {message}'.format(address=sa[0],
port=sa[1],
message=message))
@@ -44,7 +56,7 @@ class SocketService(SimpleService):
self.error("Cannot create socket to 'None':")
return False
- af, sock_type, proto, canon_name, sa = res
+ af, sock_type, proto, _, sa = res
try:
self.debug('Creating socket to "{address}", port {port}'.format(address=sa[0], port=sa[1]))
self._sock = socket.socket(af, sock_type, proto)
@@ -56,10 +68,24 @@ class SocketService(SimpleService):
self.__socket_config = None
return False
+ if self.tls:
+ try:
+ self.debug('Encapsulating socket with TLS')
+ self._sock = ssl.wrap_socket(self._sock,
+ keyfile=self.key,
+ certfile=self.cert,
+ server_side=False,
+ cert_reqs=ssl.CERT_NONE)
+ except (socket.error, ssl.SSLError) as error:
+ self.error('Failed to wrap socket.')
+ self._disconnect()
+ self.__socket_config = None
+ return False
+
try:
self.debug('connecting socket to "{address}", port {port}'.format(address=sa[0], port=sa[1]))
self._sock.connect(sa)
- except socket.error as error:
+ except (socket.error, ssl.SSLError) as error:
self.error('Failed to connect to "{address}", port {port}, error: {error}'.format(address=sa[0],
port=sa[1],
error=error))
@@ -147,7 +173,7 @@ class SocketService(SimpleService):
pass
self._sock = None
- def _send(self):
+ def _send(self, request=None):
"""
Send request.
:return: boolean
@@ -155,8 +181,8 @@ class SocketService(SimpleService):
# Send request if it is needed
if self.request != self.__empty_request:
try:
- self.debug('sending request: {0}'.format(self.request))
- self._sock.send(self.request)
+ self.debug('sending request: {0}'.format(request or self.request))
+ self._sock.send(request or self.request)
except Exception as error:
self._socket_error('error sending request: {0}'.format(error))
self._disconnect()
@@ -197,7 +223,7 @@ class SocketService(SimpleService):
self.debug('final response: {0}'.format(data))
return data
- def _get_raw_data(self, raw=False):
+ def _get_raw_data(self, raw=False, request=None):
"""
Get raw data with low-level "socket" module.
:param raw: set `True` to return bytes
@@ -211,7 +237,7 @@ class SocketService(SimpleService):
return None
# Send request if it is needed
- if not self._send():
+ if not self._send(request):
return None
data = self._receive(raw)
@@ -249,6 +275,28 @@ class SocketService(SimpleService):
except (KeyError, TypeError):
self.debug('No port specified. Using: "{0}"'.format(self.port))
+ self.tls = bool(self.configuration.get('tls', self.tls))
+ if self.tls and not _TLS_SUPPORT:
+ self.warning('TLS requested but no TLS module found, disabling TLS support.')
+ self.tls = False
+ if _TLS_SUPPORT and not self.tls:
+ self.debug('No TLS preference specified, not using TLS.')
+
+ if self.tls and _TLS_SUPPORT:
+ self.key = self.configuration.get('tls_key_file')
+ self.cert = self.configuration.get('tls_cert_file')
+ if not self.cert:
+ # If there's not a valid certificate, clear the key too.
+ self.debug('No valid TLS client certificate configuration found.')
+ self.key = None
+ self.cert = None
+ elif not self.key:
+ # If a key isn't listed, the config may still be
+ # valid, because there may be a key attached to the
+ # certificate.
+ self.info('No TLS client key specified, assuming it\'s attached to the certificate.')
+ self.key = None
+
try:
self.request = str(self.configuration['request'])
except (KeyError, TypeError):