Compare commits

..

4 commits

13 changed files with 228 additions and 324 deletions

View file

@ -1,4 +1,4 @@
# `check_xmppng` - check plugin for XMPP # check_xmppng - check plugin for XMPP
This program implements a nagios check plugin for XMPP servers implementing the This program implements a nagios check plugin for XMPP servers implementing the
XMPP protocol as specified in [RFC 6120](http://tools.ietf.org/html/rfc6120). XMPP protocol as specified in [RFC 6120](http://tools.ietf.org/html/rfc6120).
@ -10,9 +10,8 @@ The program implements the following features:
* support STARTTLS as specified in RFC 6120 section 5. * support STARTTLS as specified in RFC 6120 section 5.
* check the validity of the server certificate presented by the XMPP server * check the validity of the server certificate presented by the XMPP server
The plugin has been implemented because of insufficiencies in `check_ssl_cert` The plugin has been implemented because of insufficiencies in check_ssl_cert
and the existing and the existing [check_xmpp](https://exchange.icinga.org/exchange/check_xmpp).
[`check_xmpp`](https://exchange.icinga.org/exchange/check_xmpp).
Maximum acceptable timeouts as well as minimum acceptable number of days the Maximum acceptable timeouts as well as minimum acceptable number of days the
server certificate needs to be valid can be specified as command line server certificate needs to be valid can be specified as command line
@ -31,14 +30,14 @@ the Python standard library:
The software has been developed and tested with the following versions: The software has been developed and tested with the following versions:
* Python 3.7.3 * Python 3.4.2
* defusedxml 0.5.0 * defusedxml 0.4.1
* nagiosplugin 1.2.4 * nagiosplugin 1.2.2
## License ## License
`check_xmppng` is free software: you can redistribute it and/or modify it under check_xmppng is free software: you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software the terms of the GNU General Public License as published by the Free Software
Foundation, either version 3 of the License, or (at your option) any later Foundation, either version 3 of the License, or (at your option) any later
version. version.
@ -55,10 +54,10 @@ http://www.gnu.org/licenses/.
## Usage ## Usage
``` ```
usage: check_xmppng [-h] -H HOST_ADDRESS [-p PORT] [--s2s | --c2s] [-4 | -6] usage: check_xmpp [-h] -H HOST_ADDRESS [-p PORT] [--s2s | --c2s] [-4 | -6]
[--servername SERVERNAME] [--starttls] [-w SECONDS] [--servername SERVERNAME] [--starttls] [-w SECONDS]
[-c SECONDS] [--no-check-certificates] [-r CAROOTS] [-c SECONDS] [--no-check-certificates] [-r CAROOTS]
[--warn-days WARNDAYS] [--crit-days CRITDAYS] [-v] [--warn-days WARNDAYS] [--crit-days CRITDAYS] [-v]
Check XMPP services Check XMPP services
@ -96,6 +95,5 @@ optional arguments:
## Contact ## Contact
If you want to provide feedback or bug reports please use the [bug If you want to provide feedback or bug reports please send me a mail to
tracker](https://git.dittberner.info/jan/check_xmppng/issues) or send me an jan (at) dittberner [dot] info.
email to jan (at) dittberner [dot] info.

View file

@ -1,31 +1,5 @@
# change log # change log
## version 0.3.3 2023-08-04
* fix starttls behaviour with Python 3.11
## version 0.3.2 2021-03-07
* remove broken CA certificate statistics
## version 0.3.1 2019-06-23
* move to new project location
## version 0.3.0 2016-06-18
* add alternative --hostname parameter to make check_xmpp compatible with
check_v46 (thanks to Andreas Krause for the idea)
## version 0.2.1 2016-01-23
* fix perfdata output for daysvalid metric
## version 0.2 2015-12-29
* improve human readable output by returning both response time as well as
certificate expiry
## version 0.1.2 2015-02-11 ## version 0.1.2 2015-02-11
* first icinga exchange release * first icinga exchange release

View file

@ -2,7 +2,7 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# #
# Nagios compatible check for XMPP servers. # Nagios compatible check for XMPP servers.
# Copyright (C) 2015-2021 Jan Dittberner # Copyright (C) 2015 Jan Dittberner
# #
# This program is free software: you can redistribute it and/or modify # This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by
@ -31,7 +31,8 @@ from defusedxml.sax import make_parser
import nagiosplugin import nagiosplugin
__author__ = "Jan Dittberner" __author__ = "Jan Dittberner"
__version__ = "0.3.2" __version__ = "0.1.2"
NS_IETF_XMPP_SASL = 'urn:ietf:params:xml:ns:xmpp-sasl' NS_IETF_XMPP_SASL = 'urn:ietf:params:xml:ns:xmpp-sasl'
NS_IETF_XMPP_TLS = 'urn:ietf:params:xml:ns:xmpp-tls' NS_IETF_XMPP_TLS = 'urn:ietf:params:xml:ns:xmpp-tls'
@ -54,14 +55,10 @@ class XmppException(Exception):
Custom exception class. Custom exception class.
""" """
def __init__(self, message): def __init__(self, message):
self.message = message self.message = message
super(XmppException, self).__init__() super(XmppException, self).__init__()
def __str__(self):
return self.message
class XmppStreamError(object): class XmppStreamError(object):
""" """
@ -72,7 +69,7 @@ class XmppStreamError(object):
text = None text = None
other_elements = {} other_elements = {}
def __str__(self): def str(self):
if self.text: if self.text:
return "{condition}: {text}".format( return "{condition}: {text}".format(
condition=self.condition, text=self.text) condition=self.condition, text=self.text)
@ -87,13 +84,12 @@ class XmppResponseHandler(ContentHandler):
seen_elements = set() seen_elements = set()
mechanisms = [] mechanisms = []
starttls = False starttls = False
tls_required = False tlsrequired = False
capabilities = {} capabilities = {}
state = XMPP_STATE_NEW state = XMPP_STATE_NEW
stream_info = None streaminfo = None
error_instance = None
in_elem = [] inelem = []
level = 0 level = 0
def __init__(self, expect_starttls): def __init__(self, expect_starttls):
@ -101,35 +97,35 @@ class XmppResponseHandler(ContentHandler):
super(XmppResponseHandler, self).__init__() super(XmppResponseHandler, self).__init__()
def startElementNS(self, name, qname, attrs): def startElementNS(self, name, qname, attrs):
self.in_elem.append(name) self.inelem.append(name)
self.seen_elements.add(name) self.seen_elements.add(name)
if name == (NS_ETHERX_STREAMS, 'stream'): if name == (NS_ETHERX_STREAMS, 'stream'):
self.state = XMPP_STATE_STREAM_START self.state = XMPP_STATE_STREAM_START
self.stream_info = dict([ self.streaminfo = dict([
(qname, attrs.getValueByQName(qname)) for (qname, attrs.getValueByQName(qname)) for
qname in attrs.getQNames()]) qname in attrs.getQNames()])
elif name == (NS_IETF_XMPP_TLS, 'starttls'): elif name == (NS_IETF_XMPP_TLS, 'starttls'):
self.starttls = True self.starttls = True
elif ( elif (
self.in_elem[-2] == (NS_IETF_XMPP_TLS, 'starttls') and self.inelem[-2] == (NS_IETF_XMPP_TLS, 'starttls') and
name == (NS_IETF_XMPP_TLS, 'required') name == (NS_IETF_XMPP_TLS, 'required')
): ):
self.tls_required = True self.tlsrequired = True
_LOG.info("info other side requires TLS") _LOG.info("info other side requires TLS")
elif name == (NS_JABBER_CAPS, 'c'): elif name == (NS_JABBER_CAPS, 'c'):
for qname in attrs.getQNames(): for qname in attrs.getQNames():
self.capabilities[qname] = attrs.getValueByQName(qname) self.capabilities[qname] = attrs.getValueByQName(qname)
elif name == (NS_ETHERX_STREAMS, 'error'): elif name == (NS_ETHERX_STREAMS, 'error'):
self.state = XMPP_STATE_ERROR self.state = XMPP_STATE_ERROR
self.error_instance = XmppStreamError() self.errorinstance = XmppStreamError()
elif ( elif (
self.state == XMPP_STATE_ERROR and self.state == XMPP_STATE_ERROR and
name != (NS_IETF_XMPP_STREAMS, 'text') name != (NS_IETF_XMPP_STREAMS, 'text')
): ):
if name[0] == NS_IETF_XMPP_STREAMS: if name[0] == NS_IETF_XMPP_STREAMS:
self.error_instance.condition = name[1] self.errorinstance.condition = name[1]
else: else:
self.error_instance.other_elements[name] = {'attrs': dict([ self.errorinstance.other_elements[name] = {'attrs': dict([
(qname, attrs.getValueByQName(qname)) for (qname, attrs.getValueByQName(qname)) for
qname in attrs.getQNames() qname in attrs.getQNames()
])} ])}
@ -142,25 +138,25 @@ class XmppResponseHandler(ContentHandler):
self.state = XMPP_STATE_FINISHED self.state = XMPP_STATE_FINISHED
elif name == (NS_ETHERX_STREAMS, 'error'): elif name == (NS_ETHERX_STREAMS, 'error'):
raise XmppException("XMPP stream error: {error}".format( raise XmppException("XMPP stream error: {error}".format(
error=self.error_instance)) error=self.errorinstance))
elif name == (NS_IETF_XMPP_TLS, 'proceed'): elif name == (NS_IETF_XMPP_TLS, 'proceed'):
self.state = XMPP_STATE_PROCEED_STARTTLS self.state = XMPP_STATE_PROCEED_STARTTLS
elif name == (NS_IETF_XMPP_TLS, 'failure'): elif name == (NS_IETF_XMPP_TLS, 'failure'):
raise XmppException("starttls initiation failed") raise XmppException("starttls initiation failed")
_LOG.debug('end %s', name) _LOG.debug('end %s', name)
del self.in_elem[-1] del self.inelem[-1]
def characters(self, content): def characters(self, content):
elem = self.in_elem[-1] elem = self.inelem[-1]
if elem == (NS_IETF_XMPP_SASL, 'mechanism'): if elem == (NS_IETF_XMPP_SASL, 'mechanism'):
self.mechanisms.append(content) self.mechanisms.append(content)
elif self.state == XMPP_STATE_ERROR: elif self.state == XMPP_STATE_ERROR:
if elem == (NS_IETF_XMPP_STREAMS, 'text'): if elem == (NS_IETF_XMPP_STREAMS, 'text'):
self.error_instance.text = content self.errorinstance.text = content
else: else:
self.error_instance.other_elements[elem]['text'] = content self.errorinstance.other_elements[elem]['text'] = content
else: else:
_LOG.warning('ignored content in %s: %s', self.in_elem, content) _LOG.warning('ignored content in %s: %s', self.inelem, content)
def is_valid_start(self): def is_valid_start(self):
if not self.state == XMPP_STATE_RECEIVED_FEATURES: if not self.state == XMPP_STATE_RECEIVED_FEATURES:
@ -168,43 +164,14 @@ class XmppResponseHandler(ContentHandler):
if self.expect_starttls is True and self.starttls is False: if self.expect_starttls is True and self.starttls is False:
raise XmppException('expected STARTTLS capable service') raise XmppException('expected STARTTLS capable service')
if ( if (
'version' not in self.stream_info or 'version' not in self.streaminfo or
self.stream_info['version'] != '1.0' self.streaminfo['version'] != '1.0'
): ):
_LOG.warning( _LOG.warning(
'unknown stream version %s', self.stream_info['version']) 'unknown stream version %s', self.streaminfo['version'])
return True return True
def open_socket(addrinfo):
"""
Open a client socket based on information in the addrinfo list of
tuples.
"""
new_socket = None
for res in addrinfo:
af, socktype, proto, canonname, sa = res
try:
new_socket = socket.socket(af, socktype, proto)
except socket.error:
new_socket = None
continue
try:
new_socket.connect(sa)
except socket.error:
new_socket.close()
new_socket = None
continue
break
if new_socket is None:
raise XmppException("could not open socket")
return new_socket
class Xmpp(nagiosplugin.Resource): class Xmpp(nagiosplugin.Resource):
""" """
Xmpp resource. Xmpp resource.
@ -213,13 +180,11 @@ class Xmpp(nagiosplugin.Resource):
state = nagiosplugin.Unknown state = nagiosplugin.Unknown
cause = None cause = None
socket = None socket = None
days_left = None daysleft = None
parser = None
content_handler = None
def __init__( def __init__(
self, host_address, port, ipv6, is_server, starttls, self, host_address, port, ipv6, is_server, starttls,
servername, checkcerts, caroots servername, checkcerts, caroots
): ):
self.address = host_address self.address = host_address
self.port = port self.port = port
@ -227,8 +192,8 @@ class Xmpp(nagiosplugin.Resource):
self.is_server = is_server self.is_server = is_server
self.starttls = starttls self.starttls = starttls
self.servername = servername self.servername = servername
self.check_certs = checkcerts self.checkcerts = checkcerts
self.ca_roots = caroots self.caroots = caroots
self.make_parser() self.make_parser()
self.set_content_handler() self.set_content_handler()
@ -245,28 +210,53 @@ class Xmpp(nagiosplugin.Resource):
Set the XMPP SAX content handler. Set the XMPP SAX content handler.
""" """
self.content_handler = XmppResponseHandler( self.contenthandler = XmppResponseHandler(
expect_starttls=self.starttls) expect_starttls=self.starttls)
self.parser.setContentHandler(self.content_handler) self.parser.setContentHandler(self.contenthandler)
def get_addr_info(self): def get_addrinfo(self):
""" """
Perform the DNS lookup and return a list of potential socket address Perform the DNS lookup and return a list of potential socket address
tuples as returned by :py:method:`socket.getaddrinfo`. tuples as returned by :py:method:`socket.getaddrinfo`.
""" """
if self.ipv6 is None: if self.ipv6 is None:
addr_family = 0 addrfamily = 0
elif self.ipv6 is True: elif self.ipv6 is True:
addr_family = socket.AF_INET6 addrfamily = socket.AF_INET6
else: else:
addr_family = socket.AF_INET addrfamily = socket.AF_INET
return socket.getaddrinfo( return socket.getaddrinfo(
self.address, self.port, addr_family, socket.SOCK_STREAM, self.address, self.port, addrfamily, socket.SOCK_STREAM,
socket.IPPROTO_TCP) socket.IPPROTO_TCP)
self.result = nagiosplugin.Critical
def open_socket(self, addrinfo):
"""
Open a client socket based on information in the addrinfo list of
tuples.
"""
for res in addrinfo:
af, socktype, proto, canonname, sa = res
try:
s = socket.socket(af, socktype, proto)
except socket.error:
s = None
continue
try:
s.connect(sa)
except socket.error:
s.close()
s = None
continue
break
if s is None:
raise XmppException("could not open socket")
return s
def handle_xmpp_stanza( def handle_xmpp_stanza(
self, message_str, timeout=0.1, expected_state=None self, message_str, timeout=0.1, expected_state=None
): ):
""" """
Handle a single XMPP message. Handle a single XMPP message.
@ -293,28 +283,37 @@ class Xmpp(nagiosplugin.Resource):
chunks.append(data) chunks.append(data)
else: else:
break break
xml_text = b''.join(chunks).decode('utf-8') xmltext = b''.join(chunks).decode('utf-8')
_LOG.debug("read %s", xml_text) _LOG.debug("read %s", xmltext)
self.parser.feed(xml_text) self.parser.feed(xmltext)
if ( if (
expected_state is not None and expected_state is not None and
self.content_handler.state != expected_state self.contenthandler.state != expected_state
): ):
raise XmppException( raise XmppException(
"unexpected state %s" % self.content_handler.state) "unexpected state %s" % self.contenthandler.state)
def start_stream(self): def start_stream(self):
""" """
Start a XMPP conversation with the server. Start a XMPP conversation with the server.
""" """
namespace = "jabber:server" if self.is_server else "jabber:client" if self.is_server:
self.handle_xmpp_stanza((
self.handle_xmpp_stanza( "<?xml version='1.0' ?><stream:stream to='{servername}' "
f"<stream:stream xmlns:stream='{NS_ETHERX_STREAMS}' xmlns='{namespace}' to='{self.servername}'" "xmlns='jabber:server' "
f" version='1.0'>", "xmlns:stream='http://etherx.jabber.org/streams' "
expected_state=XMPP_STATE_RECEIVED_FEATURES "version='1.0'>"
) ).format(servername=self.servername),
expected_state=XMPP_STATE_RECEIVED_FEATURES)
else:
self.handle_xmpp_stanza((
"<?xml version='1.0' ?><stream:stream to='{servername}' "
"xmlns='jabber:client' "
"xmlns:stream='http://etherx.jabber.org/streams' "
"version='1.0'>"
).format(servername=self.servername),
expected_state=XMPP_STATE_RECEIVED_FEATURES)
def setup_ssl_context(self): def setup_ssl_context(self):
""" """
@ -322,19 +321,28 @@ class Xmpp(nagiosplugin.Resource):
""" """
context = ssl.create_default_context() context = ssl.create_default_context()
if not self.check_certs: context.options = ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3
if not self.checkcerts:
context.check_hostname = False context.check_hostname = False
context.verify_mode = ssl.CERT_NONE context.verify_mode = ssl.CERT_NONE
else: else:
context.verify_mode = ssl.CERT_REQUIRED context.verify_mode = ssl.CERT_REQUIRED
if self.ca_roots: if self.caroots:
if os.path.isfile(self.ca_roots): if os.path.isfile(self.caroots):
kwargs = {'cafile': self.ca_roots} kwargs = {'cafile': self.caroots}
else: else:
kwargs = {'capath': self.ca_roots} kwargs = {'capath': self.caroots}
context.load_verify_locations(**kwargs) context.load_verify_locations(**kwargs)
else: else:
context.load_default_certs() context.load_default_certs()
stats = context.cert_store_stats()
if stats['x509_ca'] == 0:
_LOG.info(
"tried to load CA certificates from default locations, but"
" could not find any CA certificates.")
raise XmppException('no CA certificates found')
else:
_LOG.debug('certificate store statistics: %s', stats)
return context return context
def initiate_tls(self): def initiate_tls(self):
@ -346,22 +354,21 @@ class Xmpp(nagiosplugin.Resource):
""" """
_LOG.debug("start initiate_tls()") _LOG.debug("start initiate_tls()")
self.handle_xmpp_stanza( self.handle_xmpp_stanza(
f"<starttls xmlns='{NS_IETF_XMPP_TLS}'/>", "<starttls xmlns='{xmlns}'/>".format(xmlns=NS_IETF_XMPP_TLS),
timeout=0.5,
expected_state=XMPP_STATE_PROCEED_STARTTLS) expected_state=XMPP_STATE_PROCEED_STARTTLS)
sslcontext = self.setup_ssl_context() sslcontext = self.setup_ssl_context()
try: try:
self.socket = sslcontext.wrap_socket( self.socket = sslcontext.wrap_socket(
self.socket, server_hostname=self.servername) self.socket, server_hostname=self.servername)
_LOG.info("TLS socket setup successful") _LOG.info("TLS socket setup successful")
except ssl.CertificateError as certificate_error: except ssl.SSLError as ssle:
raise XmppException("Certificate error %s" % certificate_error) raise XmppException("SSL error %s" % ssle.strerror)
except ssl.SSLError as ssl_error: except ssl.CertificateError as certerr:
raise XmppException("SSL error %s" % ssl_error.strerror) raise XmppException("Certificate error %s" % certerr)
self.starttls = False self.starttls = False
# reset infos retrieved previously as written in RFC 3920 sec. 5. # reset infos retrieved previously as written in RFC 3920 sec. 5.
self.parser.reset() self.parser.reset()
if self.check_certs: if self.checkcerts:
certinfo = self.socket.getpeercert() certinfo = self.socket.getpeercert()
_LOG.debug("got the following certificate info: %s", certinfo) _LOG.debug("got the following certificate info: %s", certinfo)
_LOG.info( _LOG.info(
@ -369,12 +376,12 @@ class Xmpp(nagiosplugin.Resource):
certinfo['notBefore'], certinfo['notAfter']) certinfo['notBefore'], certinfo['notAfter'])
enddate = ssl.cert_time_to_seconds(certinfo['notAfter']) enddate = ssl.cert_time_to_seconds(certinfo['notAfter'])
remaining = datetime.fromtimestamp(enddate) - datetime.now() remaining = datetime.fromtimestamp(enddate) - datetime.now()
self.days_left = remaining.days self.daysleft = remaining.days
# start new parsing # start new parsing
self.make_parser() self.make_parser()
self.set_content_handler() self.set_content_handler()
self.start_stream() self.start_stream()
if not self.content_handler.is_valid_start(): if not self.contenthandler.is_valid_start():
raise XmppException("no valid response to XMPP client request") raise XmppException("no valid response to XMPP client request")
_LOG.debug("end initiate_tls()") _LOG.debug("end initiate_tls()")
@ -385,9 +392,9 @@ class Xmpp(nagiosplugin.Resource):
""" """
_LOG.debug("start handle_xmpp()") _LOG.debug("start handle_xmpp()")
self.start_stream() self.start_stream()
if not self.content_handler.is_valid_start(): if not self.contenthandler.is_valid_start():
raise XmppException("no valid response to XMPP client request") raise XmppException("no valid response to XMPP client request")
if self.starttls is True or self.content_handler.tls_required: if self.starttls is True or self.contenthandler.tlsrequired:
self.initiate_tls() self.initiate_tls()
self.handle_xmpp_stanza("</stream:stream>") self.handle_xmpp_stanza("</stream:stream>")
_LOG.debug("end handle_xmpp()") _LOG.debug("end handle_xmpp()")
@ -401,8 +408,8 @@ class Xmpp(nagiosplugin.Resource):
start = datetime.now() start = datetime.now()
_LOG.debug("start probe() at %s", start) _LOG.debug("start probe() at %s", start)
try: try:
addrinfo = self.get_addr_info() addrinfo = self.get_addrinfo()
self.socket = open_socket(addrinfo) self.socket = self.open_socket(addrinfo)
try: try:
self.handle_xmpp() self.handle_xmpp()
finally: finally:
@ -411,7 +418,6 @@ class Xmpp(nagiosplugin.Resource):
except socket.gaierror as e: except socket.gaierror as e:
self.state = nagiosplugin.Critical self.state = nagiosplugin.Critical
self.cause = str(e) self.cause = str(e)
_LOG.debug("got an gaierror %s", e)
return nagiosplugin.Metric("time", "unknown") return nagiosplugin.Metric("time", "unknown")
except XmppException as e: except XmppException as e:
self.state = nagiosplugin.Critical self.state = nagiosplugin.Critical
@ -423,7 +429,7 @@ class Xmpp(nagiosplugin.Resource):
_LOG.debug("end probe() at %s", end) _LOG.debug("end probe() at %s", end)
yield nagiosplugin.Metric( yield nagiosplugin.Metric(
'time', (end - start).total_seconds(), 's', min=0) 'time', (end - start).total_seconds(), 's', min=0)
yield nagiosplugin.Metric('daysleft', self.days_left, 'd') yield nagiosplugin.Metric('daysleft', self.daysleft, 'd')
class XmppContext(nagiosplugin.ScalarContext): class XmppContext(nagiosplugin.ScalarContext):
@ -449,50 +455,31 @@ class DaysValidContext(nagiosplugin.Context):
Context for checking the certificate expiry date. Context for checking the certificate expiry date.
""" """
fmt_hint = "less than {value} days"
def __init__( def __init__(
self, name, warndays=0, critdays=0, self, name, warndays=0, critdays=0,
fmt_metric='certificate valid for {value} days' fmt_metric='certificate expires in {value} days'
): ):
super(DaysValidContext, self).__init__(name, fmt_metric=fmt_metric) super(DaysValidContext, self).__init__(name, fmt_metric=fmt_metric)
self.warning = nagiosplugin.Range('@%d:' % warndays) self.warning = nagiosplugin.Range('@%d:' % warndays)
self.critical = nagiosplugin.Range('@%d:' % critdays) self.critical = nagiosplugin.Range('@%d:' % critdays)
self.warndays = warndays
self.critdays = critdays
def evaluate(self, metric, resource): def evaluate(self, metric, resource):
if resource.check_certs and metric.value is not None: if resource.checkcerts and metric.value is not None:
hint = self.describe(metric)
if self.critical.match(metric.value): if self.critical.match(metric.value):
return nagiosplugin.Result( return nagiosplugin.Result(nagiosplugin.Critical, hint, metric)
nagiosplugin.Critical,
hint=self.fmt_hint.format(value=self.critdays),
metric=metric)
if self.warning.match(metric.value): if self.warning.match(metric.value):
return nagiosplugin.Result( return nagiosplugin.Result(nagiosplugin.Warn, hint, metric)
nagiosplugin.Warn, return nagiosplugin.Result(nagiosplugin.Ok, hint, metric)
hint=self.fmt_hint.format(value=self.warndays),
metric=metric)
return nagiosplugin.Result(
nagiosplugin.Ok, "", metric)
return nagiosplugin.Result(nagiosplugin.Ok) return nagiosplugin.Result(nagiosplugin.Ok)
def performance(self, metric, resource): def performance(self, metric, resource):
if resource.check_certs and metric.value is not None: if resource.checkcerts and metric.value is not None:
return nagiosplugin.Performance('daysvalid', metric.value, '') return nagiosplugin.Performance('daysvalid', metric.value, 'd')
return None return None
class XmppSummary(nagiosplugin.Summary):
"""
Summary instance that outputs all metrics if the check results are ok.
"""
def ok(self, results):
return ", ".join([str(res) for res in results])
@nagiosplugin.guarded @nagiosplugin.guarded
def main(): def main():
""" """
@ -501,11 +488,8 @@ def main():
""" """
import argparse import argparse
parser = argparse.ArgumentParser(description="Check XMPP services") parser = argparse.ArgumentParser(description="Check XMPP services")
host_address = parser.add_mutually_exclusive_group(required=True) parser.add_argument(
host_address.add_argument("-H", "--host-address", help="host address") "-H", "--host-address", help="host address", required=True)
host_address.add_argument(
"--hostname", help="host name, alternative for host-address",
dest="host_address")
parser.add_argument( parser.add_argument(
"-p", "--port", help="port", type=int) "-p", "--port", help="port", type=int)
is_server = parser.add_mutually_exclusive_group() is_server = parser.add_mutually_exclusive_group()
@ -567,10 +551,8 @@ def main():
] ]
check = nagiosplugin.Check( check = nagiosplugin.Check(
Xmpp(**kwargs), Xmpp(**kwargs),
XmppContext( XmppContext('time', warning, critical),
'time', warning, critical, fmt_metric="request took {value}{uom}"), DaysValidContext('daysleft', warndays, critdays)
DaysValidContext('daysleft', warndays, critdays),
XmppSummary(),
) )
check.main(verbose=verbose, timeout=0) check.main(verbose=verbose, timeout=0)

12
debian/changelog vendored Normal file
View file

@ -0,0 +1,12 @@
nagios-check-xmppng (0.1.2-1~bpo8+1) jessie-backports; urgency=medium
* Rebuild for jessie-backports.
* set jessie-backports as debian branch in debian/gbp.conf
-- Jan Dittberner <jandd@debian.org> Sun, 20 Sep 2015 18:38:33 +0200
nagios-check-xmppng (0.1.2-1) unstable; urgency=medium
* Initial release. (Closes: #777732)
-- Jan Dittberner <jandd@debian.org> Thu, 12 Feb 2015 00:49:30 +0100

1
debian/compat vendored Normal file
View file

@ -0,0 +1 @@
9

30
debian/control vendored Normal file
View file

@ -0,0 +1,30 @@
Source: nagios-check-xmppng
Section: net
Priority: extra
Maintainer: Jan Dittberner <jandd@debian.org>
Homepage: https://exchange.icinga.org/jandd/check_xmppng
Build-Depends: debhelper (>= 9)
Standards-Version: 3.9.6
Vcs-Browser: https://git.dittberner.info/?p=check_xmpp.git
Vcs-Git: https://git.dittberner.info/check_xmpp.git -b debian
Package: nagios-check-xmppng
Architecture: all
Depends: python3 (>= 3.4),
python3-defusedxml (>= 0.4.1),
python3-nagiosplugin (>= 1.2.2),
${misc:Depends}
Suggests: icinga | icinga2 | nagios3
Description: monitoring plugin to check XMPP servers
a nagios compatible check plugin for XMPP servers implementing the XMPP
protocol as specified in RFC 6120.
.
The plugin provides the following features:
.
- check client to server (C2S) as well as server to server (S2S) ports
- check XMPP servers on IPv6 and IPv4 addresses
- support STARTTLS as specified in RFC 6120 section 5.
- check the validity of the server certificate presented by the XMPP server
.
The plugin has been implemented because of insufficiencies in the existing
check_ssl_cert and check_xmpp plugins.

24
debian/copyright vendored Normal file
View file

@ -0,0 +1,24 @@
Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
Upstream-Name: check_xmppng
Upstream-Contact: Jan Dittberner <jan@dittberner.info>
Source: https://git.dittberner.info/?p=check_xmpp.git
Files: *
Copyright: 2015 Jan Dittberner
License: GPL-3
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
.
This program 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 General Public License for more details.
.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
.
On Debian systems, the full text of the GNU General Public
License version 3 can be found in the file
`/usr/share/common-licenses/GPL-3'.

1
debian/docs vendored Normal file
View file

@ -0,0 +1 @@
README.md

8
debian/gbp.conf vendored Normal file
View file

@ -0,0 +1,8 @@
[DEFAULT]
debian-branch = jessie-backports
upstream-branch = master
upstream-tag = %(version)s
no-create-orig = True
[import-orig]
pristine-tar = False

1
debian/install vendored Normal file
View file

@ -0,0 +1 @@
check_xmppng /usr/lib/nagios/plugins/

10
debian/rules vendored Executable file
View file

@ -0,0 +1,10 @@
#!/usr/bin/make -f
# -*- makefile -*-
#export DH_VERBOSE=1
override_dh_installchangelogs:
dh_installchangelogs changes.md
%:
dh $@

1
debian/source/format vendored Normal file
View file

@ -0,0 +1 @@
3.0 (quilt)

View file

@ -1,150 +1,12 @@
name: check_xmppng name: check_xmppng
description: "file:///README.md" description: "file:///README.md"
url: "https://git.dittberner.info/jan/check_xmppng" url: "https://git.dittberner.info/?p=check_xmpp.git"
tags: XMPP, X.509 tags: XMPP, X.509
vendor: vendor:
target: Messaging target: Messaging
type: Plugin type: Plugin
license: gplv3 license: gplv3
releases: releases:
- name: 0.3.3
description: "fix CA certificate check"
files:
-
name: check_xmppng
url: "file:///check_xmppng"
description: "Check command"
checksum: fdf942cb5c778aaa395a0ed1eba6dcda
-
name: COPYING
url: "file:///COPYING"
description: "GPL 3.0 license text"
checksum: d32239bcb673463ab874e80d47fae504
-
name: README.md
url: "file:///README.md"
description: "documentation"
checksum: 701ad7a882406a1f552a118d471a0b45
-
name: changes.md
url: "file:///changes.md"
description: "change log"
checksum: 0e23c919b413a4214c323b1953909c14
- name: 0.3.2
description: "fix CA certificate check"
files:
-
name: check_xmppng
url: "file:///check_xmppng"
description: "Check command"
checksum: e0ded038e79a2538d3b0c99cdc599810
-
name: COPYING
url: "file:///COPYING"
description: "GPL 3.0 license text"
checksum: d32239bcb673463ab874e80d47fae504
-
name: README.md
url: "file:///README.md"
description: "documentation"
checksum: 701ad7a882406a1f552a118d471a0b45
-
name: changes.md
url: "file:///changes.md"
description: "change log"
checksum: 60adfa1bf31c5a5fefb57ca55d186c7b
- name: 0.3.1
description: "new project home"
files:
-
name: check_xmppng
url: "file:///check_xmppng"
description: "Check command"
checksum: 3ba088ad712e7eff3897b0be70dc5437
-
name: COPYING
url: "file:///COPYING"
description: "GPL 3.0 license text"
checksum: d32239bcb673463ab874e80d47fae504
-
name: README.md
url: "file:///README.md"
description: "documentation"
checksum: 1e6f6632b12e4ef5fc4f02c3ea65da8a
-
name: changes.md
url: "file:///changes.md"
description: "change log"
checksum: df32115e17a931a083c2c9065c998147
- name: 0.3.0
description: "add --hostname option"
files:
-
name: check_xmppng
url: "file:///check_xmppng"
description: "Check command"
checksum: 9774a26db6c54af4a51902b90ffe13bc
-
name: COPYING
url: "file:///COPYING"
description: "GPL 3.0 license text"
checksum: d32239bcb673463ab874e80d47fae504
-
name: README.md
url: "file:///README.md"
description: "documentation"
checksum: 1e6f6632b12e4ef5fc4f02c3ea65da8a
-
name: changes.md
url: "file:///changes.md"
description: "change log"
checksum: f2c1f311817cbb51eac4c62b9c097579
- name: 0.2.1
description: "fixed perfdata output"
files:
-
name: check_xmppng
url: "file:///check_xmppng"
description: "Check command"
checksum: 992ee1b3209bba6ddb29b46c939b2978
-
name: COPYING
url: "file:///COPYING"
description: "GPL 3.0 license text"
checksum: d32239bcb673463ab874e80d47fae504
-
name: README.md
url: "file:///README.md"
description: "documentation"
checksum: 1e6f6632b12e4ef5fc4f02c3ea65da8a
-
name: changes.md
url: "file:///changes.md"
description: "change log"
checksum: a7a17e05c732e24f7b0529fb868a172f
- name: 0.2
description: "better human readable output"
files:
-
name: check_xmppng
url: "file:///check_xmppng"
description: "Check command"
checksum: 7369095c7daad89e04e0fbdd81ef0e00
-
name: COPYING
url: "file:///COPYING"
description: "GPL 3.0 license text"
checksum: d32239bcb673463ab874e80d47fae504
-
name: README.md
url: "file:///README.md"
description: "documentation"
checksum: 1e6f6632b12e4ef5fc4f02c3ea65da8a
-
name: changes.md
url: "file:///changes.md"
description: "change log"
checksum: f09a79d4762efc8c5a97e6d9f301b398
- -
name: 0.1.2 name: 0.1.2
description: "first icingaexchange release" description: "first icingaexchange release"