captive.whump.shanti-portal/portal.py

129 lines
3.5 KiB
Python
Raw Normal View History

# Captiveportal web application using Bottle.py
import json
from pprint import pprint
from importlib import import_module
2016-04-05 14:40:37 +00:00
from configparser import RawConfigParser
from logging import Formatter, getLogger, DEBUG, WARN, INFO
from logging.handlers import SysLogHandler, RotatingFileHandler
from redis import Redis
from rq import Queue
2016-04-05 14:40:37 +00:00
from bottle import route, run, default_app
from bottle import request, response, template, static_file
2016-04-05 14:40:37 +00:00
config = RawConfigParser()
config.readfp(open('./portal.cfg'))
config.read(['/etc/captiveportal/portal.cfg', './portal_local.cfg'])
# Plugins configuration is separate so plugins can be disabled by having
# their section removed/commented from the config file.
plugin_config = RawConfigParser()
plugin_config.readfp(open('./plugins.cfg'))
plugin_config.read(['/etc/captiveportal/plugins.cfg'])
2016-04-05 14:40:37 +00:00
# Setup logging
logFormatter = Formatter(config.get('logging', 'log_format'))
2016-04-05 14:40:37 +00:00
l = getLogger('captiveportal')
if config.get('logging', 'log_handler') == 'syslog':
syslog_address = config.get('logging', 'syslog_address')
if syslog_address.startswith('/'):
logHandler = SysLogHandler(
2016-04-05 14:40:37 +00:00
address=syslog_address,
facility=SysLogHandler.LOG_LOCAL0
)
else:
logHandler = SysLogHandler(
2016-04-05 14:40:37 +00:00
address=(
config.get('logging', 'syslog_address'),
config.getint('logging', 'syslog_port')
),
facility=SysLogHandler.LOG_LOCAL0
)
else:
logHandler = RotatingFileHandler(
2016-04-05 14:40:37 +00:00
config.get('logging', 'log_file'),
maxBytes=config.getint('logging', 'log_max_bytes'),
backupCount=config.getint('logging', 'log_max_copies')
)
logHandler.setFormatter(logFormatter)
l.addHandler(logHandler)
2016-04-05 14:40:37 +00:00
if config.get('logging', 'log_debug'):
l.setLevel(DEBUG)
else:
l.setLevel(WARN)
# Redis Queue
R = Redis(
host=config.get('portal', 'redis_host'),
port=config.getint('portal', 'redis_port')
)
2016-04-05 14:40:37 +00:00
@route('/')
def portalindex():
return template('portalindex')
2016-04-05 14:40:37 +00:00
@route('/static/<path:path>')
def server_static(path):
return static_file(path, root='./static')
2016-04-05 14:40:37 +00:00
@route('/approve', method='POST')
def approve_client():
response.content_type = 'application/json'
jobs = dispatch_plugins()
2016-04-05 14:40:37 +00:00
# TODO: return job ID
# Maybe use the client IP as job ID to enable easier lookups of the job
# status.
return json.dumps(jobs)
2016-04-05 14:40:37 +00:00
# Add plugins to job queue
def dispatch_plugins():
Q = Queue(connection=R)
jobs = []
for plugin in plugin_config.sections():
l.debug('Loading plugin {plugin}'.format(
plugin=plugin
2016-04-05 14:40:37 +00:00
))
arg = {}
2016-04-05 14:40:37 +00:00
# Import some values from WSGI environ
arg['environ'] = {}
for key in request.environ:
value = request.environ.get(key)
if isinstance(value, (int, str, float, dict, set, tuple)):
arg['environ'][key] = value
2016-04-05 14:40:37 +00:00
plugin_module = import_module('plugins.'+plugin)
2016-04-05 14:40:37 +00:00
try:
plugin_job = Q.enqueue(
plugin_module.run,
arg
2016-04-05 14:40:37 +00:00
)
except Exception as e:
l.error('{plugin}: {error}'.format(
error=str(e),
plugin=plugin
2016-04-05 14:40:37 +00:00
))
continue
jobs.append(plugin_job)
2016-04-05 14:40:37 +00:00
if __name__ == '__main__':
run(
host=config.get('portal', 'listen_host'),
port=config.getint('portal', 'listen_port')
)
debug(config.getbool('portal', 'debug'))
else:
application = default_app()