Compare commits

...

25 commits

Author SHA1 Message Date
Jan Dittberner ea68a363ca Fix Python 3.11 STARTTLS handling 2023-08-04 19:35:27 +02:00
Jan Dittberner c8f93d56dc Release 0.3.2
- Update version and copyright information
- Update changelog and icingaexchange.yml
2021-03-07 14:14:06 +01:00
Jan Dittberner 16e8cb41fe Improve README
- Update dependency versions to those of Debian Buster
- link to bug tracker
- fix minor formatting issues
2021-03-07 14:14:06 +01:00
Jan Dittberner 5438f7f089 Remove CA certificate statistics
The CA certificate statistics do not work with recent Python versions
and broke the plugin initialization.

Fixes #2
2021-03-07 14:14:06 +01:00
Jan Dittberner 76fbb73233 Release 0.3.1 move project home
-----BEGIN PGP SIGNATURE-----
 
 iQFIBAABCgAyFiEEKHuXKkUYdvdO9493DXkdyNc3wdkFAl0P7+YUHGphbkBkaXR0
 YmVybmVyLmluZm8ACgkQDXkdyNc3wdlXPggAgnZzoLWWJvsA3Fl0CqjGCivl0Hdb
 WKJ8huOCPiSKU54AeqScilWDZ+G9ksi9PnqVcQ5U1Th4pAAC89f5ccHgulf64quR
 3wDcCHublhDYQqy8gijOH4Z/McB13nMWQpLN8sJQ97p76abCqhZhbo7Pd6b5Duuc
 mfKK67aBe28qMp0rQdobUvKtkLAbnLMc+L0Tejw/qC9F8SQ+z01W6B7Jn7FKXSPc
 cnrpktaIC2AjhU2xzdbAW29oyn8I0yC8xwFDCZ+qGgeaIMVnFxslo+XCdEurcBHk
 p1bAc86O9Qo4yA0tVWqLqSym4SCDeYPQ2D0YTLEb6zG/NtootNagy5Hgcw==
 =k2P6
 -----END PGP SIGNATURE-----

Merge tag '0.3.1'

Release 0.3.1 move project home
2019-06-23 23:32:26 +02:00
Jan Dittberner 787115b4bb Merge branch 'release/0.3.1' into develop 2019-06-23 23:32:06 +02:00
Jan Dittberner 9999c4e868 Update Icinga exchange metadata 2019-06-23 23:31:53 +02:00
Jan Dittberner 57f1b5fb55 Update changes.md 2019-06-23 23:26:19 +02:00
Jan Dittberner 5f54f2ca45 Raise version number 2019-06-23 23:22:24 +02:00
Jan Dittberner cf0ec04526 Fix project URL 2019-06-23 23:16:21 +02:00
Jan Dittberner 8be4413b45 Fix command name in README
Fixes #1
2019-06-23 23:11:41 +02:00
Jan Dittberner e4651d7dac Update project URL 2019-06-23 23:10:30 +02:00
Jan Dittberner 1724ce9985 Release 0.3.0
-----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1
 
 iQEcBAABCgAGBQJXZZ/pAAoJEA15HcjXN8HZb78IALVycFS0xR6zzUNmn23FHMoq
 SdhNeCgchKmm3Gpnp5Vgrbpqmkj2YXR90U8S3kQU2NO/K5UzeE3dWnVD3GTvzkCi
 T0K5TOuooIhD9c6qYYPd8h4gzYDvA27iK1l0nv0U6teVIIxmXeRAIKa8goipJJlN
 NcdwrppCRJlXguqB8AcISAq048d2Q/Ut/E0mB/T1qAuZc1bHLsYFpamiAA9fS9yR
 SYPOEqChFZheG1Zbv3bMYy4RM00JwhxU/l7h+lN60FCTBuNFOXJsMr7s4iE5PkPA
 9HnOC+hyl/bc0/9jsY5q3JzuBpMBKcZpjGWe55la3nzcwbMAFZhnNluGnB3QvvU=
 =ME53
 -----END PGP SIGNATURE-----

Merge tag '0.3.0' into develop

Release 0.3.0

* tag '0.3.0':
2016-06-18 21:24:30 +02:00
Jan Dittberner c76fa75126 Merge branch 'release/0.3.0'
* release/0.3.0:
  Add changelog entry and metadata for 0.3.0
  Add --hostname option
2016-06-18 21:24:23 +02:00
Jan Dittberner c0280cc713 Add changelog entry and metadata for 0.3.0 2016-06-18 21:17:54 +02:00
Jan Dittberner 55ff04ba21 Add --hostname option
This commit adds a --hostname option that is mutually exclusive to
-H/--host-address. The idea is to make check_xmppng compatible with
check_v46. Thanks to Andreas Krause for the inspiration.
2016-06-18 21:13:17 +02:00
Jan Dittberner c7cce10d8e Release 0.2.1
-----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1
 
 iQEcBAABCgAGBQJWo95QAAoJEA15HcjXN8HZ9j8IANvHb8cKtailuaxrGsU+yZr1
 jST51KE3Tw92L5nWt66kk8lOF9FJVJ2vzyqF+Rm8RaBuDYp2osTV/bwJzIbHruFl
 fMZpNhNBuVFlbCfxQA4aIdvpUQDN62RIANFHU+IOdjtCp85VAlzcjH6qyO7E92ug
 1cBYuS5612pmilcAywimWI0gNkx+Bd0SQC+a1YaL2lR8N/42ufIAuzgtzcoZSOjf
 0v46D2+l3xiHE0efRfWlXJhchrcpfhw9n9msJjwVEOVO/PiLCzJEZNJxt6uar3Rh
 Lzt7hny+pv7rubN78rvhAgARhwjsCaQFR4aJWs87z33KuHTFizFtFRwgW+kKbLk=
 =ty7q
 -----END PGP SIGNATURE-----

Merge tag '0.2.1' into develop

Release 0.2.1

* tag '0.2.1':
  Update changes.md and icingaexchange.yml
2016-01-23 21:10:57 +01:00
Jan Dittberner 827b00dff8 Merge branch 'release/0.2.1'
* release/0.2.1:
  Update changes.md and icingaexchange.yml
  Fix performance data output
2016-01-23 21:10:53 +01:00
Jan Dittberner 6a4254c8a5 Update changes.md and icingaexchange.yml 2016-01-23 21:10:08 +01:00
Jan Dittberner 2c50b91b1a Fix performance data output
This commit fixes the unit of measure of daysvalid to be conformant to
the performance data specification at
http://docs.icinga.org/latest/de/perfdata.html#pluginperfdata by
omiting the invalid unit 'd' at the end of the value.
2016-01-23 20:48:32 +01:00
Jan Dittberner e8b04bd40d Release 0.2
-----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1
 
 iQEcBAABCgAGBQJWgvqrAAoJEA15HcjXN8HZ+hQIAJ1cZ0OXpfGTKcrfkv3OwVoO
 ZdfrgjBVqLp3PaMRUADNG/5VHl2VpBvwkOlWKZIcUJQZtB0iRPa6HEh+dPhLCP5+
 pC8R5kXI1TdmBH3SRs7kF20MpQKCIobWuPjMzkSW1D+0iqKXrGK/Xgaq8CJCTKDT
 K0TjC4Y/bDOgLDMp0su1hAAx3lxM4gz7977NhI71UjZMnKk3IkNWIAVK1kMObrWB
 tCPC7LGaRs1DjR3HS5XZVcIaWPwKvxse4vqXPOECQYqtGWBu8PSIdXIheTfAmKXk
 trrEkQ7E3TwuhUEYIVxV+6j/sgjlbPi3qsCXvH/E55zYZ6MrKEE/kYtnqTxqVTo=
 =FPiU
 -----END PGP SIGNATURE-----

Merge tag '0.2' into develop

Release 0.2

* tag '0.2':
  Add new release to icingaexchange.yml
  Finalize version number
2015-12-29 22:27:07 +01:00
Jan Dittberner 3469355a4b Merge branch 'release/0.2'
* release/0.2:
  Add new release to icingaexchange.yml
  Finalize version number
  Improve human readable output
2015-12-29 22:27:02 +01:00
Jan Dittberner f8e1a0eb38 Add new release to icingaexchange.yml 2015-12-29 22:25:30 +01:00
Jan Dittberner 37351a87a0 Finalize version number 2015-12-29 22:25:03 +01:00
Jan Dittberner 11a16bb362 Improve human readable output
This change introduces more readable and useful output by adding the
certificate expiration to the human readable string. The response time
is now formatted too.
2015-12-29 22:17:59 +01:00
4 changed files with 324 additions and 140 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
XMPP protocol as specified in [RFC 6120](http://tools.ietf.org/html/rfc6120).
@ -10,8 +10,9 @@ The program implements the following features:
* 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 check_ssl_cert
and the existing [check_xmpp](https://exchange.icinga.org/exchange/check_xmpp).
The plugin has been implemented because of insufficiencies in `check_ssl_cert`
and the existing
[`check_xmpp`](https://exchange.icinga.org/exchange/check_xmpp).
Maximum acceptable timeouts as well as minimum acceptable number of days the
server certificate needs to be valid can be specified as command line
@ -30,14 +31,14 @@ the Python standard library:
The software has been developed and tested with the following versions:
* Python 3.4.2
* defusedxml 0.4.1
* nagiosplugin 1.2.2
* Python 3.7.3
* defusedxml 0.5.0
* nagiosplugin 1.2.4
## 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
Foundation, either version 3 of the License, or (at your option) any later
version.
@ -54,10 +55,10 @@ http://www.gnu.org/licenses/.
## Usage
```
usage: check_xmpp [-h] -H HOST_ADDRESS [-p PORT] [--s2s | --c2s] [-4 | -6]
[--servername SERVERNAME] [--starttls] [-w SECONDS]
[-c SECONDS] [--no-check-certificates] [-r CAROOTS]
[--warn-days WARNDAYS] [--crit-days CRITDAYS] [-v]
usage: check_xmppng [-h] -H HOST_ADDRESS [-p PORT] [--s2s | --c2s] [-4 | -6]
[--servername SERVERNAME] [--starttls] [-w SECONDS]
[-c SECONDS] [--no-check-certificates] [-r CAROOTS]
[--warn-days WARNDAYS] [--crit-days CRITDAYS] [-v]
Check XMPP services
@ -95,5 +96,6 @@ optional arguments:
## Contact
If you want to provide feedback or bug reports please send me a mail to
jan (at) dittberner [dot] info.
If you want to provide feedback or bug reports please use the [bug
tracker](https://git.dittberner.info/jan/check_xmppng/issues) or send me an
email to jan (at) dittberner [dot] info.

View file

@ -1,5 +1,31 @@
# 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
* first icinga exchange release

View file

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

View file

@ -1,12 +1,150 @@
name: check_xmppng
description: "file:///README.md"
url: "https://git.dittberner.info/?p=check_xmpp.git"
url: "https://git.dittberner.info/jan/check_xmppng"
tags: XMPP, X.509
vendor:
target: Messaging
type: Plugin
license: gplv3
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
description: "first icingaexchange release"