From 1adbb2bb2a9426003087911eb9a5a8d082acf9eb Mon Sep 17 00:00:00 2001 From: nicolargo Date: Sat, 8 Apr 2017 15:50:20 +0200 Subject: [PATCH] New plugin to scan remote Web sites (URL) (issue #981) --- NEWS | 1 + conf/glances.conf | 19 +++++- docs/_static/ports.png | Bin 10291 -> 11041 bytes docs/aoa/ports.rst | 19 +++++- glances/compat.py | 2 + glances/plugins/glances_ports.py | 108 ++++++++++++++++++++--------- glances/web_list.py | 113 +++++++++++++++++++++++++++++++ 7 files changed, 228 insertions(+), 34 deletions(-) create mode 100644 glances/web_list.py diff --git a/NEWS b/NEWS index da750506..8cf05c18 100644 --- a/NEWS +++ b/NEWS @@ -7,6 +7,7 @@ Version 2.9.2 Enhancements and new features: + * New plugin to scan remote Web sites (URL) (issue #981) * Use -> and <- arrows keys to switch between processing sort (issue #1075) * Add trends in the Curses interface (issue #1077) diff --git a/conf/glances.conf b/conf/glances.conf index 013b8067..a2aa5cbd 100644 --- a/conf/glances.conf +++ b/conf/glances.conf @@ -217,12 +217,14 @@ refresh=30 timeout=3 # If port_default_gateway is True, add the default gateway on top of the scan list port_default_gateway=True +# # Define the scan list (1 < x < 255) # port_x_host (name or IP) is mandatory # port_x_port (TCP port number) is optional (if not set, use ICMP) # port_x_description is optional (if not set, define to host:port) # port_x_timeout is optional and overwrite the default timeout value # port_x_rtt_warning is optional and defines the warning threshold in ms +# #port_1_host=192.168.0.1 #port_1_port=80 #port_1_description=Home Box @@ -232,10 +234,25 @@ port_default_gateway=True #port_3_host=www.google.com #port_3_description=Internet ICMP #port_3_rtt_warning=1000 -#port_4_host=www.google.com #port_4_description=Internet Web +#port_4_host=www.google.com #port_4_port=80 #port_4_rtt_warning=1000 +# +# Define Web (URL) monitoring list (1 < x < 255) +# web_x_url is the URL to monitor (example: http://my.site.com/folder) +# web_x_description is optional (if not set, define to URL) +# web_x_timeout is optional and overwrite the default timeout value +# web_x_rtt_warning is optional and defines the warning respond time in ms (approximatively) +# +#web_1_url=https://blog.nicolargo.com +#web_1_description=My Blog +#web_1_rtt_warning=3000 +#web_2_url=https://github.com +#web_3_url=http://www.google.fr +#web_3_description=Google Fr +#web_4_url=https://blog.nicolargo.com/nonexist +#web_4_description=Intranet [docker] # Thresholds for CPU and MEM (in %) diff --git a/docs/_static/ports.png b/docs/_static/ports.png index 03edf63d22694d5dcd7c187d77af0ef91088ca78..f65c8453af13c0ad9cedce37236a28b2fad91f72 100644 GIT binary patch literal 11041 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 literal 10291 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 web['rtt_warning']: + return 'WARNING' + + return 'OK' + def msg_curse(self, args=None, max_width=None): """Return the dict to display in the curse interface.""" # Init the return message @@ -118,23 +138,36 @@ class Plugin(GlancesPlugin): # Build the string message for p in self.stats: - if p['host'] is None: - status = 'None' - elif p['status'] is None: - status = 'Scanning' - elif isinstance(p['status'], bool_type) and p['status'] is True: - status = 'Open' - elif p['status'] == 0: - status = 'Timeout' - else: - # Convert second to ms - status = '{0:.0f}ms'.format(p['status'] * 1000.0) + if 'host' in p: + if p['host'] is None: + status = 'None' + elif p['status'] is None: + status = 'Scanning' + elif isinstance(p['status'], bool_type) and p['status'] is True: + status = 'Open' + elif p['status'] == 0: + status = 'Timeout' + else: + # Convert second to ms + status = '{0:.0f}ms'.format(p['status'] * 1000.0) - msg = '{:14.14} '.format(p['description']) - ret.append(self.curse_add_line(msg)) - msg = '{:>8}'.format(status) - ret.append(self.curse_add_line(msg, self.get_alert(p))) - ret.append(self.curse_new_line()) + msg = '{:14.14} '.format(p['description']) + ret.append(self.curse_add_line(msg)) + msg = '{:>8}'.format(status) + ret.append(self.curse_add_line(msg, self.get_ports_alert(p))) + ret.append(self.curse_new_line()) + elif 'url' in p: + msg = '{:14.14} '.format(p['description']) + ret.append(self.curse_add_line(msg)) + if isinstance(p['status'], numbers.Number): + status = 'Code {}'.format(p['status']) + elif p['status'] is None: + status = 'Scanning' + else: + status = p['status'] + msg = '{:>8}'.format(status) + ret.append(self.curse_add_line(msg, self.get_web_alert(p))) + ret.append(self.curse_new_line()) # Delete the last empty line try: @@ -144,18 +177,10 @@ class Plugin(GlancesPlugin): return ret - def _port_scan_all(self, stats): - """Scan all host/port of the given stats""" - for p in stats: - self._port_scan(p) - # Had to wait between two scans - # If not, result are not ok - time.sleep(1) - class ThreadScanner(threading.Thread): """ - Specific thread for the port scanner. + Specific thread for the port/web scanner. stats is a list of dict """ @@ -176,12 +201,18 @@ class ThreadScanner(threading.Thread): Infinite loop, should be stopped by calling the stop() method""" for p in self._stats: - self._port_scan(p) + # End of the thread has been asked if self.stopped(): break - # Had to wait between two scans - # If not, result are not ok - time.sleep(1) + # Scan a port (ICMP or TCP) + if 'port' in p: + self._port_scan(p) + # Had to wait between two scans + # If not, result are not ok + time.sleep(1) + # Scan an URL + elif 'url' in p and requests_tag: + self._web_scan(p) @property def stats(self): @@ -202,6 +233,21 @@ class ThreadScanner(threading.Thread): """Return True is the thread is stopped""" return self._stopper.isSet() + def _web_scan(self, web): + """Scan the Web/URL (dict) and update the status key""" + try: + req = requests.head(web['url'], + allow_redirects=True, + timeout=web['timeout']) + except Exception as e: + logger.debug(e) + web['status'] = 'Error' + web['elapsed'] = 0 + else: + web['status'] = req.status_code + web['elapsed'] = req.elapsed.total_seconds() + return web + def _port_scan(self, port): """Scan the port structure (dict) and update the status key""" if int(port['port']) == 0: diff --git a/glances/web_list.py b/glances/web_list.py new file mode 100644 index 00000000..23300a96 --- /dev/null +++ b/glances/web_list.py @@ -0,0 +1,113 @@ +# -*- coding: utf-8 -*- +# +# This file is part of Glances. +# +# Copyright (C) 2017 Nicolargo +# +# Glances is free software; you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Glances is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with this program. If not, see . + +"""Manage the Glances web/url list (Ports plugin).""" + +from glances.compat import range, urlparse +from glances.logger import logger + + +class GlancesWebList(object): + + """Manage the Web/Url list for the ports plugin.""" + + _section = "ports" + _default_refresh = 60 + _default_timeout = 3 + + def __init__(self, config=None, args=None): + # web_list is a list of dict (JSON compliant) + # [ {'url': 'http://blog.nicolargo.com', + # 'refresh': 30, + # 'description': 'My blog', + # 'status': 404} ... ] + # Load the configuration file + self._web_list = self.load(config) + + def load(self, config): + """Load the web list from the configuration file.""" + web_list = [] + + if config is None: + logger.debug("No configuration file available. Cannot load ports list.") + elif not config.has_section(self._section): + logger.debug("No [%s] section in the configuration file. Cannot load ports list." % self._section) + else: + logger.debug("Start reading the [%s] section in the configuration file" % self._section) + + refresh = int(config.get_value(self._section, 'refresh', default=self._default_refresh)) + timeout = int(config.get_value(self._section, 'timeout', default=self._default_timeout)) + + # Read the web/url list + for i in range(1, 256): + new_web = {} + postfix = 'web_%s_' % str(i) + + # Read mandatories configuration key: host + new_web['url'] = config.get_value(self._section, '%s%s' % (postfix, 'url')) + if new_web['url'] is None: + continue + url_parse = urlparse(new_web['url']) + if not bool(url_parse.scheme) or not bool(url_parse.netloc): + logger.error('Bad URL (%s) in the [%s] section of configuration file.' % (new_web['url'], + self._section)) + continue + + # Read optionals configuration keys + # Default description is the URL without the http:// + new_web['description'] = config.get_value(self._section, + '%sdescription' % postfix, + default="%s" % url_parse.netloc) + + # Default status + new_web['status'] = None + new_web['elapsed'] = 0 + + # Refresh rate in second + new_web['refresh'] = refresh + + # Timeout in second + new_web['timeout'] = int(config.get_value(self._section, + '%stimeout' % postfix, + default=timeout)) + + # RTT warning + new_web['rtt_warning'] = config.get_value(self._section, + '%srtt_warning' % postfix, + default=None) + if new_web['rtt_warning'] is not None: + # Convert to second + new_web['rtt_warning'] = int(new_web['rtt_warning']) / 1000.0 + + # Add the server to the list + logger.debug("Add Web URL %s to the static list" % new_web['url']) + web_list.append(new_web) + + # Ports list loaded + logger.debug("Web list loaded: %s" % web_list) + + return web_list + + def get_web_list(self): + """Return the current server list (dict of dict).""" + return self._web_list + + def set_server(self, pos, key, value): + """Set the key to the value for the pos (position in the list).""" + self._web_list[pos][key] = value