implement S2S checks
- C2S and S2S are quite similar, only stream initialization is a bit different - rename methods to make this clear - remove branching for client and server - use one ContentHandler for client and server - add more debug logging - always return all metrics
This commit is contained in:
parent
81eb543c8f
commit
5e299f687e
1 changed files with 37 additions and 25 deletions
62
check_xmpp
62
check_xmpp
|
@ -52,7 +52,7 @@ class XmppStreamError(object):
|
||||||
return self.condition
|
return self.condition
|
||||||
|
|
||||||
|
|
||||||
class XmppClientServerResponseHandler(ContentHandler):
|
class XmppResponseHandler(ContentHandler):
|
||||||
seen_elements = set()
|
seen_elements = set()
|
||||||
mechanisms = []
|
mechanisms = []
|
||||||
starttls = False
|
starttls = False
|
||||||
|
@ -66,7 +66,7 @@ class XmppClientServerResponseHandler(ContentHandler):
|
||||||
|
|
||||||
def __init__(self, expect_starttls):
|
def __init__(self, expect_starttls):
|
||||||
self.expect_starttls = expect_starttls
|
self.expect_starttls = expect_starttls
|
||||||
super(XmppClientServerResponseHandler, self).__init__()
|
super(XmppResponseHandler, self).__init__()
|
||||||
|
|
||||||
def startElementNS(self, name, qname, attrs):
|
def startElementNS(self, name, qname, attrs):
|
||||||
self.inelem.append(name)
|
self.inelem.append(name)
|
||||||
|
@ -170,12 +170,9 @@ class Xmpp(nagiosplugin.Resource):
|
||||||
self.parser.setFeature(feature_namespaces, True)
|
self.parser.setFeature(feature_namespaces, True)
|
||||||
|
|
||||||
def set_content_handler(self):
|
def set_content_handler(self):
|
||||||
if self.is_server:
|
self.contenthandler = XmppResponseHandler(
|
||||||
pass # TODO: make server parser
|
expect_starttls=self.starttls)
|
||||||
else:
|
self.parser.setContentHandler(self.contenthandler)
|
||||||
self.contenthandler = XmppClientServerResponseHandler(
|
|
||||||
expect_starttls=self.starttls)
|
|
||||||
self.parser.setContentHandler(self.contenthandler)
|
|
||||||
|
|
||||||
def get_addrinfo(self):
|
def get_addrinfo(self):
|
||||||
if self.ipv6 is None:
|
if self.ipv6 is None:
|
||||||
|
@ -212,6 +209,7 @@ class Xmpp(nagiosplugin.Resource):
|
||||||
self, message_str, timeout=0.1, expected_state=None
|
self, message_str, timeout=0.1, expected_state=None
|
||||||
):
|
):
|
||||||
self.socket.sendall(message_str.encode('utf-8'))
|
self.socket.sendall(message_str.encode('utf-8'))
|
||||||
|
_LOG.debug("wrote %s", message_str)
|
||||||
chunks = []
|
chunks = []
|
||||||
while True:
|
while True:
|
||||||
rready, wready, xready = select([self.socket], [], [], timeout)
|
rready, wready, xready = select([self.socket], [], [], timeout)
|
||||||
|
@ -221,7 +219,9 @@ class Xmpp(nagiosplugin.Resource):
|
||||||
chunks.append(data)
|
chunks.append(data)
|
||||||
else:
|
else:
|
||||||
break
|
break
|
||||||
self.parser.feed(b''.join(chunks).decode('utf-8'))
|
xmltext = b''.join(chunks).decode('utf-8')
|
||||||
|
_LOG.debug("read %s", xmltext)
|
||||||
|
self.parser.feed(xmltext)
|
||||||
if (
|
if (
|
||||||
expected_state is not None and
|
expected_state is not None and
|
||||||
self.contenthandler.state != expected_state
|
self.contenthandler.state != expected_state
|
||||||
|
@ -229,17 +229,23 @@ class Xmpp(nagiosplugin.Resource):
|
||||||
raise XmppException(
|
raise XmppException(
|
||||||
"unexpected state %s" % self.contenthandler.state)
|
"unexpected state %s" % self.contenthandler.state)
|
||||||
|
|
||||||
def handle_server(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def start_stream(self):
|
def start_stream(self):
|
||||||
self.handle_xmpp_stanza((
|
if self.is_server:
|
||||||
"<?xml version='1.0' ?><stream:stream to='{servername}' "
|
self.handle_xmpp_stanza((
|
||||||
"xmlns='jabber:client' "
|
"<?xml version='1.0' ?><stream:stream to='{servername}' "
|
||||||
"xmlns:stream='http://etherx.jabber.org/streams' "
|
"xmlns='jabber:server' "
|
||||||
"version='1.0'>"
|
"xmlns:stream='http://etherx.jabber.org/streams' "
|
||||||
).format(servername=self.servername),
|
"version='1.0'>"
|
||||||
expected_state=XMPP_STATE_RECEIVED_FEATURES)
|
).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):
|
||||||
context = ssl.create_default_context()
|
context = ssl.create_default_context()
|
||||||
|
@ -268,6 +274,7 @@ class Xmpp(nagiosplugin.Resource):
|
||||||
return context
|
return context
|
||||||
|
|
||||||
def initiate_tls(self):
|
def initiate_tls(self):
|
||||||
|
_LOG.debug("start initiate_tls()")
|
||||||
self.handle_xmpp_stanza(
|
self.handle_xmpp_stanza(
|
||||||
"<starttls xmlns='{xmlns}'/>".format(xmlns=NS_IETF_XMPP_TLS),
|
"<starttls xmlns='{xmlns}'/>".format(xmlns=NS_IETF_XMPP_TLS),
|
||||||
expected_state=XMPP_STATE_PROCEED_STARTTLS)
|
expected_state=XMPP_STATE_PROCEED_STARTTLS)
|
||||||
|
@ -275,6 +282,7 @@ class Xmpp(nagiosplugin.Resource):
|
||||||
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")
|
||||||
except ssl.SSLError as ssle:
|
except ssl.SSLError as ssle:
|
||||||
raise XmppException("SSL error %s" % ssle.strerror)
|
raise XmppException("SSL error %s" % ssle.strerror)
|
||||||
except ssl.CertificateError as certerr:
|
except ssl.CertificateError as certerr:
|
||||||
|
@ -297,25 +305,26 @@ class Xmpp(nagiosplugin.Resource):
|
||||||
self.start_stream()
|
self.start_stream()
|
||||||
if not self.contenthandler.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()")
|
||||||
|
|
||||||
def handle_client(self):
|
def handle_xmpp(self):
|
||||||
|
_LOG.debug("start handle_xmpp()")
|
||||||
self.start_stream()
|
self.start_stream()
|
||||||
if not self.contenthandler.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.contenthandler.tlsrequired:
|
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()")
|
||||||
|
|
||||||
def probe(self):
|
def probe(self):
|
||||||
start = datetime.now()
|
start = datetime.now()
|
||||||
|
_LOG.debug("start probe() at %s", start)
|
||||||
try:
|
try:
|
||||||
addrinfo = self.get_addrinfo()
|
addrinfo = self.get_addrinfo()
|
||||||
self.socket = self.open_socket(addrinfo)
|
self.socket = self.open_socket(addrinfo)
|
||||||
try:
|
try:
|
||||||
if self.is_server:
|
self.handle_xmpp()
|
||||||
self.handle_server()
|
|
||||||
else:
|
|
||||||
self.handle_client()
|
|
||||||
finally:
|
finally:
|
||||||
self.socket.close()
|
self.socket.close()
|
||||||
self.parser.close()
|
self.parser.close()
|
||||||
|
@ -326,8 +335,11 @@ class Xmpp(nagiosplugin.Resource):
|
||||||
except XmppException as e:
|
except XmppException as e:
|
||||||
self.state = nagiosplugin.Critical
|
self.state = nagiosplugin.Critical
|
||||||
self.cause = e.message
|
self.cause = e.message
|
||||||
return nagiosplugin.Metric("time", "unknown")
|
_LOG.debug("got an XmppException %s", e)
|
||||||
|
yield nagiosplugin.Metric('time', 'unknown')
|
||||||
|
return nagiosplugin.Metric('daysleft', 'unknown')
|
||||||
end = datetime.now()
|
end = datetime.now()
|
||||||
|
_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.daysleft, 'd')
|
yield nagiosplugin.Metric('daysleft', self.daysleft, 'd')
|
||||||
|
|
Loading…
Reference in a new issue