Ver código fonte

server: add /vpn log target

Helge Jung 9 anos atrás
pai
commit
16e0fb5481
1 arquivos alterados com 76 adições e 0 exclusões
  1. 76 0
      ffstatus/server.py

+ 76 - 0
ffstatus/server.py

@@ -9,6 +9,7 @@ import json
 import logging
 import re
 from SocketServer import ThreadingMixIn
+import time
 
 class BatcaveHttpRequestHandler(BaseHTTPRequestHandler):
 	def __init__(self, request, client_address, server):
@@ -39,6 +40,10 @@ class BatcaveHttpRequestHandler(BaseHTTPRequestHandler):
 			self.respond_list(query)
 			return
 
+		if path == 'vpn':
+			self.respond_vpn(query)
+			return
+
 		m = re.match(r'node/([a-f0-9]{12})(?P<cmd>\.json|/[a-zA-Z0-9_\-]+)$', path)
 		if m != None:
 			cmd = m.group('cmd')
@@ -149,6 +154,77 @@ class BatcaveHttpRequestHandler(BaseHTTPRequestHandler):
 		self.send_headers('text/plain' if isinstance(value, basestring) else 'text/json')
 		self.wfile.write(value if isinstance(value, basestring) else json.dumps(value))
 
+	def respond_vpn(self, query):
+		storage = self.server.storage
+		peername = query['peer'] if 'peer' in query else None
+		key = query['key'] if 'key' in query else None
+		action = query['action'] if 'action' in query else None
+		remote = query['remote'] if 'remote' in query else None
+		gw = query['gw'] if 'gw' in query else None
+
+		if action == 'list':
+			self.respond_vpnlist()
+			return
+
+		if action != 'establish' and action != 'disestablish':
+			self.logger.error('VPN: unknown action \'{0}\''.format(action))
+			self.send_error(400, 'Invalid action.')
+			return
+
+		for k,v in { 'peername': peername, 'key': key, 'remote': remote, 'gw': gw }.items():
+			if v is None or len(v.strip()) == 0:
+				self.logger.error('VPN {0}: no or empty {1}'.format(action, k))
+				self.send_error(400, 'Missing value for ' + str(k))
+				return
+
+		if key is None or re.match(r'^[a-fA-F0-9]+$', key) is None:
+			self.logger.error('VPN peer \'{0}\' {1}: bad key \'{2}\''.format(peername, action, key))
+			self.send_error(400, 'Bad key.')
+			return
+
+		if not 'vpn' in storage.data: storage.data['vpn'] = {}
+		if not key in storage.data['vpn']: storage.data['vpn'][key] = { 'active': {}, 'last': {} }
+		item = storage.data['vpn'][key]
+
+		if action == 'establish':
+			item['active'][gw] = { 'establish': time.time(), 'peer': peername, 'remote': remote }
+		elif action == 'disestablish':
+			active = {}
+			if gw in item['active']:
+				active = item['active'][gw]
+				del(item['active'][gw])
+			active['disestablish'] = time.time()
+			item['last'][gw] = active
+		else:
+			self.send_error(500, 'Unknown action not filtered (' + str(action) + ')')
+			return
+
+		self.send_headers('text/plain')
+		self.wfile.write('OK')
+
+		storage.save()
+
+	def respond_vpnlist(self):
+		storage = self.server.storage
+
+		self.send_headers()
+		self.wfile.write('<!DOCTYPE html>\n')
+		self.wfile.write('<html><head><title>BATCAVE - VPN LIST</title></head>\n')
+		self.wfile.write('<body>\n')
+		self.wfile.write('<table>\n<thead><tr><th>key</th><th>active</th><th>last</th></tr></thead>\n')
+		
+		if 'vpn' in storage.data:
+			for key in storage.data['vpn']:
+				item = storage.data['vpn'][key]
+				self.wfile.write('<tr><td>' + str(key) + '</td>')
+				self.wfile.write('<td>' + json.dumps(item['active'] if 'active' in item else {}) + '</td>')
+				self.wfile.write('<td>' + json.dumps(item['last'] if 'last' in item else {}) + '</td>')
+				self.wfile.write('</tr>\n')
+
+		self.wfile.write('</table>\n')
+		self.wfile.write('</body>')
+		self.wfile.write('</html>')
+
 class ApiServer(ThreadingMixIn, HTTPServer):
 	def __init__(self, endpoint, storage):
 		HTTPServer.__init__(self, endpoint, BatcaveHttpRequestHandler)