kumistatus/servertools/__init__.py

192 lines
5.7 KiB
Python
Raw Normal View History

2017-06-22 15:54:11 +00:00
import datetime
import encodings.idna
import httptools
2017-06-22 15:54:11 +00:00
import os
import porttools
import setuptools
import skstools
import socket
import socketserver
import ssltools
import sys
import syslog
import threading
SYSLOG = 0
STDOUT = 1
STDDEB = 2 # STDOUT + Debug
SILENT = 9 # Quiet mode
SSL = 0
PORT = 1
2017-06-22 15:54:11 +00:00
SKS = 2
HTTP = 3
logging = STDOUT
try:
exec("logging = " + setuptools.getSetting("Log", "sink"))
except:
pass
def logger(message, prio=syslog.LOG_INFO, sink=logging):
if sink in (STDOUT, STDDEB):
if prio not in (syslog.LOG_NOTICE, syslog.LOG_INFO, syslog.LOG_DEBUG):
print(message)
sys.stderr.write(message)
elif prio != syslog.LOG_DEBUG or sink == STDDEB:
print(message)
elif sink == SYSLOG:
syslog.openlog("KumiStatusServer", syslog.LOG_PID)
syslog.syslog(prio, message)
elif sink != SILENT:
try:
sys.stderr.write("Unknown logging level %s, assuming STDOUT from now on." % str(sink))
except:
pass
logging = STDOUT
logger(message, prio, logging)
def listIncluded(host, section):
if not setuptools.getListSetting("Server", "ignorelist"):
for i in setuptools.getListSetting("HTTP" if section == HTTP else "SSL" if section == SSL else "Ports" if section == PORT else "SKS", "sites" if section == HTTP else "hosts"):
if encodings.idna.ToASCII(i[0].lower()).decode("UTF-8") == encodings.idna.ToASCII(host.lower()).decode("UTF-8"):
return True
return False
return True
class TCPHandler(socketserver.StreamRequestHandler):
def readString(self):
return self.rfile.readline().strip()
def sendString(self, string):
self.request.sendall((string + "\n").encode('utf8'))
def requestHandler(self, request):
pass
def worker(self, message):
content = message.split()
command = content[0].lower()
try:
if command == "hi":
try:
return "HI: Kumi Status v0.8.15 (KSP) at %s" % setuptools.getSetting("Server", "host") or socket.gethostname()
except Exception as e:
print(e)
2017-06-22 15:54:11 +00:00
elif command in ("heartbeat", "hb", "ping"):
return "OK: Still here? Wow."
2017-06-22 15:54:11 +00:00
elif command in ("stat", "status"):
return "UA: Not currently implemented."
2017-06-22 15:54:11 +00:00
elif command in ("ssl", "tls"):
try:
2016-07-20 17:14:45 +00:00
host = encodings.idna.ToASCII(str(content[1])).decode("UTF-8")
try:
port = int(content[2])
except IndexError:
port = 443
if listIncluded(host, SSL):
expiry = ssltools.getRemoteExpiry(host, port)
if expiry > datetime.datetime.now():
2016-07-20 16:17:06 +00:00
dm = "%s certificate is valid until: %s" % (content[1], expiry)
try:
delta = int(content[3])
except:
delta = 0
if expiry < datetime.datetime.now() + datetime.timedelta(days=delta):
return "AL: %s" % dm
return "OK: %s" % dm
else:
return "AL: %s certificate has expired on: %s" % (content[1], expiry)
else:
return "NM: %s is not being monitored!" % content[1]
2016-07-20 17:14:45 +00:00
except Exception as e:
print(e)
return "ER: Could not verify SSL certificate on %s:%i. Is the server down?" % (content[1], int(content[2]))
2017-06-22 15:54:11 +00:00
elif command == "port":
host = encodings.idna.ToASCII(str(content[1])).decode("UTF-8")
port = int(content[2])
if listIncluded(host, PORT):
if porttools.isPortOpen(host, port):
return "OK: Port %i is open on %s." % (port, content[1])
else:
return "ER: Port %i is not open on %s." % (port, content[1])
else:
return "NM: %s is not being monitored!" % content[1]
2017-06-22 15:54:11 +00:00
elif command in ("sks", "keyserver"):
host = encodings.idna.ToASCII(str(content[1])).decode("UTF-8")
if listIncluded(host, SKS):
if skstools.getStatus(host):
return "OK: SKS is running on %s and included in the pools." % content[0]
2017-06-22 15:54:11 +00:00
else:
return "ER: The SKS keyserver at %s is not included in the pools." % content[1]
else:
return "NM: %s is not being monitored!" % content[1]
elif command in ("req", "request"):
return "NI: Requesting monitoring is not yet implemented."
2017-06-22 15:54:11 +00:00
elif command == "help":
return "UA: Not currently implemented."
2017-06-22 15:54:11 +00:00
elif command in ("http", "web"):
site = encodings.idna.ToASCII(str(content[1])).decode("UTF-8")
if listIncluded(site, HTTP):
status = httptools.getStatus(site)
if status == 200:
return "OK: Site %s seems to be working fine." % content[1]
elif status == None:
return "ER: Site %s looks down from here!" % content[1]
else:
return "ER: Site %s returns status code %s!" % (content[1], status)
else:
return "NM: %s is not being monitored!" % content[1]
else:
return "IM: Unknown command %s." % command
2017-06-22 15:54:11 +00:00
except TypeError as e:
2016-07-20 16:17:06 +00:00
return "IM: Invalid values passed to %s. Try HELP %s." % (command, command)
except IndexError as e:
2016-07-20 16:17:06 +00:00
return "IM: Invalid values passed to %s. Try HELP %s." % (command, command)
def handle(self):
try:
remote = self.client_address[0] + ":" + str(self.client_address[1])
logger("New connection from %s." % remote, syslog.LOG_INFO)
self.sendString(self.worker("hi"))
while True:
message = self.readString().decode('utf8')
if not message:
logger("Connection from %s closed." % remote, syslog.LOG_DEBUG)
break
logger("%s said: %s" % (remote, message))
try:
response = self.worker(message)
except:
response = "EM: Something went terribly wrong. Sorry about that."
if response:
self.sendString(response)
logger("Sent to %s: %s" % (remote, response), syslog.LOG_DEBUG)
except Exception as e:
logger(e, syslog.LOG_CRIT)
class TCPServer(socketserver.ThreadingMixIn, socketserver.TCPServer):
pass
def shutdown(reboot = False, status = 0):
if reboot:
args = sys.argv[:]
args.insert(0, sys.executable)
try:
os.execv(sys.executable, args)
except:
logger("Restart failed. Shutting down.")
exit(status)