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:
Jan Dittberner 2015-02-11 00:37:06 +01:00
parent 81eb543c8f
commit 5e299f687e

View file

@ -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,10 +170,7 @@ 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
else:
self.contenthandler = XmppClientServerResponseHandler(
expect_starttls=self.starttls) expect_starttls=self.starttls)
self.parser.setContentHandler(self.contenthandler) self.parser.setContentHandler(self.contenthandler)
@ -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,10 +229,16 @@ 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):
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(( self.handle_xmpp_stanza((
"<?xml version='1.0' ?><stream:stream to='{servername}' " "<?xml version='1.0' ?><stream:stream to='{servername}' "
"xmlns='jabber:client' " "xmlns='jabber:client' "
@ -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')