mirror of
https://github.com/ziirish/burp-ui.git
synced 2026-05-21 06:45:24 -06:00
refactoring + documentation
This commit is contained in:
parent
4db03d82d9
commit
b5f7873875
6 changed files with 247 additions and 138 deletions
|
|
@ -249,7 +249,7 @@ def init(conf=None, verbose=0, logfile=None, gunicorn=True, unittest=False, debu
|
|||
red = Redis(host=host, port=port)
|
||||
app.config['SESSION_TYPE'] = 'redis'
|
||||
app.config['SESSION_REDIS'] = red
|
||||
app.config['SESSION_USE_SIGNER'] = app.secret_key != None
|
||||
app.config['SESSION_USE_SIGNER'] = app.secret_key is not None
|
||||
app.config['SESSION_PERMANENT'] = False
|
||||
ses = Session()
|
||||
ses.init_app(app)
|
||||
|
|
|
|||
|
|
@ -12,13 +12,14 @@ import os
|
|||
import sys
|
||||
|
||||
from flask import Blueprint, Response, request
|
||||
from flask_restplus import Api
|
||||
from flask_restplus import Api as ApiPlus
|
||||
from flask_login import current_user
|
||||
from flask_cache import Cache
|
||||
from importlib import import_module
|
||||
from functools import wraps
|
||||
|
||||
from .._compat import IS_GUNICORN, PY3
|
||||
from ..exceptions import BUIserverException
|
||||
|
||||
if PY3: # pragma: no cover
|
||||
basestring = str
|
||||
|
|
@ -125,7 +126,7 @@ def api_login_required(func):
|
|||
return decorated_view
|
||||
|
||||
|
||||
class ApiWrapper(Api):
|
||||
class Api(ApiPlus):
|
||||
"""Wrapper class around :class:`flask_restplus.Api`"""
|
||||
cache = Cache(config={'CACHE_TYPE': 'null', 'CACHE_NO_NULL_WARNING': True})
|
||||
loaded = False
|
||||
|
|
@ -157,4 +158,14 @@ class ApiWrapper(Api):
|
|||
|
||||
|
||||
apibp = Blueprint('api', __name__, url_prefix='/api')
|
||||
api = ApiWrapper(apibp, title='Burp-UI API', description='Burp-UI API to interact with burp', doc='/doc', decorators=[api_login_required])
|
||||
api = Api(apibp, title='Burp-UI API', description='Burp-UI API to interact with burp', doc='/doc', decorators=[api_login_required])
|
||||
|
||||
|
||||
@api.errorhandler(BUIserverException)
|
||||
def handle_bui_server_exception(error):
|
||||
"""Forward a BUIserverException to the final user
|
||||
|
||||
:param error: Custom exception
|
||||
:type error: :class:`burpui.exceptions.BUIserverException`
|
||||
"""
|
||||
return {'message': error.description}, error.code
|
||||
|
|
|
|||
|
|
@ -143,11 +143,7 @@ class ServerBackup(Resource):
|
|||
(not api.bui.acl.is_client_allowed(self.username,
|
||||
name,
|
||||
server) and not
|
||||
self.is_admin and
|
||||
(to and not
|
||||
api.bui.acl.is_client_allowed(self.username,
|
||||
to,
|
||||
server)))):
|
||||
self.is_admin)):
|
||||
self.abort(
|
||||
403,
|
||||
'You are not allowed to schedule a backup for this client'
|
||||
|
|
|
|||
|
|
@ -41,12 +41,12 @@ class Restore(Resource):
|
|||
- ``pass``: password to use for encrypted backups
|
||||
"""
|
||||
parser = api.parser()
|
||||
parser.add_argument('pass', help='Password to use for encrypted backups', location=('form', 'json'), nullable=True)
|
||||
parser.add_argument('format', required=False, help='Returning archive format', location=('form', 'json'), choices=('zip', 'tar.gz', 'tar.bz2'), default='zip', nullable=True)
|
||||
parser.add_argument('strip', type=int, help='Number of elements to strip in the path', default=0, location=('form', 'json'), nullable=True)
|
||||
parser.add_argument('list', required=True, help='List of files/directories to restore', location=('form', 'json'), nullable=False)
|
||||
parser.add_argument('pass', help='Password to use for encrypted backups', nullable=True)
|
||||
parser.add_argument('format', required=False, help='Returning archive format', choices=('zip', 'tar.gz', 'tar.bz2'), default='zip', nullable=True)
|
||||
parser.add_argument('strip', type=int, help='Number of elements to strip in the path', default=0, nullable=True)
|
||||
parser.add_argument('list', required=True, help='List of files/directories to restore', nullable=False)
|
||||
# FIXME: the example json seems interpreted during the raise of the exception
|
||||
# parser.add_argument('list', required=True, help='List of files/directories to restore (example: \'{"restore":[{"folder":true,"key":"/etc"}]}\')', location=('form', 'json'), nullable=False)
|
||||
# parser.add_argument('list', required=True, help='List of files/directories to restore (example: \'{"restore":[{"folder":true,"key":"/etc"}]}\')', nullable=False)
|
||||
|
||||
@ns.expect(parser, validate=True)
|
||||
@ns.doc(
|
||||
|
|
@ -230,11 +230,11 @@ class ServerRestore(Resource):
|
|||
- ``restoreto-sc``: restore files on an other client
|
||||
"""
|
||||
parser = api.parser()
|
||||
parser.add_argument('list-sc', required=True, help='List of files/directories to restore', location='form', nullable=False)
|
||||
parser.add_argument('strip-sc', type=int, help='Number of elements to strip in the path', default=0, location='form', nullable=True)
|
||||
parser.add_argument('prefix-sc', help='Prefix to the restore path', location='form', nullable=True)
|
||||
parser.add_argument('force-sc', type=boolean, help='Whether to overwrite existing files', default=False, location='form', nullable=True)
|
||||
parser.add_argument('restoreto-sc', help='Restore files on an other client', location='form', nullable=True)
|
||||
parser.add_argument('list-sc', required=True, help='List of files/directories to restore', nullable=False)
|
||||
parser.add_argument('strip-sc', type=int, help='Number of elements to strip in the path', default=0, nullable=True)
|
||||
parser.add_argument('prefix-sc', help='Prefix to the restore path', nullable=True)
|
||||
parser.add_argument('force-sc', type=boolean, help='Whether to overwrite existing files', default=False, nullable=True)
|
||||
parser.add_argument('restoreto-sc', help='Restore files on an other client', nullable=True)
|
||||
|
||||
list_fields = api.model('ListRestoreFiles', {
|
||||
'key': fields.String(
|
||||
|
|
|
|||
|
|
@ -5,11 +5,11 @@ from . import api, cache_key, parallel_loop
|
|||
from .custom import fields, Resource
|
||||
from ..exceptions import BUIserverException
|
||||
|
||||
ns = api.namespace('servers', 'Servers methods')
|
||||
if not api.bui.standalone:
|
||||
ns = api.namespace('servers', 'Servers methods')
|
||||
|
||||
|
||||
@ns.route('/stats', endpoint='servers_stats')
|
||||
class ServersStats(Resource):
|
||||
@ns.route('/stats', endpoint='servers_stats')
|
||||
class ServersStats(Resource):
|
||||
"""The :class:`burpui.api.servers.ServersStats` resource allows you to
|
||||
retrieve statistics about servers/agents.
|
||||
|
||||
|
|
@ -54,7 +54,6 @@ class ServersStats(Resource):
|
|||
"""
|
||||
|
||||
r = []
|
||||
if hasattr(api.bui.cli, 'servers'):
|
||||
restrict = []
|
||||
check = False
|
||||
if api.bui.acl and not self.is_admin:
|
||||
|
|
@ -85,9 +84,8 @@ class ServersStats(Resource):
|
|||
|
||||
return r
|
||||
|
||||
|
||||
@ns.route('/report', endpoint='servers_report')
|
||||
class ServersReport(Resource):
|
||||
@ns.route('/report', endpoint='servers_report')
|
||||
class ServersReport(Resource):
|
||||
"""The :class:`burpui.api.servers.ServersReport` resource allows you to
|
||||
retrieve a report about servers/agents.
|
||||
|
||||
|
|
@ -156,7 +154,6 @@ class ServersReport(Resource):
|
|||
:returns: The *JSON* described above.
|
||||
"""
|
||||
r = {}
|
||||
if hasattr(api.bui.cli, 'servers'):
|
||||
restrict = []
|
||||
check = False
|
||||
if api.bui.acl and not self.is_admin:
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@
|
|||
"""
|
||||
from . import api
|
||||
from .custom import Resource
|
||||
from .custom.inputs import boolean
|
||||
from .._compat import unquote
|
||||
from flask import jsonify, request, url_for
|
||||
from werkzeug.datastructures import ImmutableMultiDict
|
||||
|
|
@ -28,6 +29,17 @@ class ServerSettings(Resource):
|
|||
This resource is part of the :mod:`burpui.api.settings` module.
|
||||
"""
|
||||
|
||||
@ns.doc(
|
||||
params={
|
||||
'conf': 'Path of the configuration file',
|
||||
'server': 'Which server to collect data from when in multi-agent mode',
|
||||
},
|
||||
responses={
|
||||
200: 'Success',
|
||||
403: 'Insufficient permissions',
|
||||
500: 'Internal failure',
|
||||
}
|
||||
)
|
||||
def post(self, conf=None, server=None):
|
||||
"""Saves the server configuration"""
|
||||
# Only the admin can edit the configuration
|
||||
|
|
@ -37,6 +49,17 @@ class ServerSettings(Resource):
|
|||
noti = api.bui.cli.store_conf_srv(request.form, conf, server)
|
||||
return {'notif': noti}, 200
|
||||
|
||||
@ns.doc(
|
||||
params={
|
||||
'conf': 'Path of the configuration file',
|
||||
'server': 'Which server to collect data from when in multi-agent mode',
|
||||
},
|
||||
responses={
|
||||
200: 'Success',
|
||||
403: 'Insufficient permissions',
|
||||
500: 'Internal failure',
|
||||
}
|
||||
)
|
||||
def get(self, conf=None, server=None):
|
||||
"""Reads the server configuration
|
||||
|
||||
|
|
@ -193,6 +216,16 @@ class ServerSettings(Resource):
|
|||
endpoint='clients_list')
|
||||
class ClientsList(Resource):
|
||||
|
||||
@ns.doc(
|
||||
params={
|
||||
'server': 'Which server to collect data from when in multi-agent mode',
|
||||
},
|
||||
responses={
|
||||
200: 'Success',
|
||||
403: 'Insufficient permissions',
|
||||
500: 'Internal failure',
|
||||
}
|
||||
)
|
||||
def get(self, server=None):
|
||||
"""Returns a list of clients"""
|
||||
# Only the admin can edit the configuration
|
||||
|
|
@ -217,6 +250,21 @@ class ClientSettings(Resource):
|
|||
parser = api.parser()
|
||||
parser.add_argument('newclient', required=True, help="No 'newclient' provided")
|
||||
|
||||
parser_delete = api.parser()
|
||||
parser_delete.add_argument('revoke', type=boolean, help='Whether to revoke the certificate or not', default=False, nullable=True)
|
||||
parser_delete.add_argument('delcert', type=boolean, help='Whether to delete the certificate or not', default=False, nullable=True)
|
||||
|
||||
@ns.doc(
|
||||
params={
|
||||
'server': 'Which server to collect data from when in multi-agent mode',
|
||||
},
|
||||
responses={
|
||||
200: 'Success',
|
||||
400: 'Missing parameter',
|
||||
403: 'Insufficient permissions',
|
||||
500: 'Internal failure',
|
||||
}
|
||||
)
|
||||
def put(self, server=None):
|
||||
"""Creates a new client"""
|
||||
# Only the admin can edit the configuration
|
||||
|
|
@ -243,6 +291,18 @@ class ClientSettings(Resource):
|
|||
api.cache.clear()
|
||||
return {'notif': noti}, 201
|
||||
|
||||
@ns.doc(
|
||||
params={
|
||||
'server': 'Which server to collect data from when in multi-agent mode',
|
||||
'client': 'Client name',
|
||||
'conf': 'Path of the configuration file',
|
||||
},
|
||||
responses={
|
||||
200: 'Success',
|
||||
403: 'Insufficient permissions',
|
||||
500: 'Internal failure',
|
||||
}
|
||||
)
|
||||
def post(self, server=None, client=None, conf=None):
|
||||
"""Saves a given client configuration"""
|
||||
# Only the admin can edit the configuration
|
||||
|
|
@ -252,6 +312,18 @@ class ClientSettings(Resource):
|
|||
noti = api.bui.cli.store_conf_cli(request.form, client, conf, server)
|
||||
return {'notif': noti}
|
||||
|
||||
@ns.doc(
|
||||
params={
|
||||
'server': 'Which server to collect data from when in multi-agent mode',
|
||||
'client': 'Client name',
|
||||
'conf': 'Path of the configuration file',
|
||||
},
|
||||
responses={
|
||||
200: 'Success',
|
||||
403: 'Insufficient permissions',
|
||||
500: 'Internal failure',
|
||||
}
|
||||
)
|
||||
def get(self, server=None, client=None, conf=None):
|
||||
"""Reads a given client configuration"""
|
||||
# Only the admin can edit the configuration
|
||||
|
|
@ -275,7 +347,19 @@ class ClientSettings(Resource):
|
|||
'defaults': api.bui.cli.get_parser_attr('defaults', server)
|
||||
}
|
||||
|
||||
@ns.doc(
|
||||
params={
|
||||
'server': 'Which server to collect data from when in multi-agent mode',
|
||||
'client': 'Client name',
|
||||
},
|
||||
responses={
|
||||
200: 'Success',
|
||||
403: 'Insufficient permissions',
|
||||
500: 'Internal failure',
|
||||
}
|
||||
)
|
||||
def delete(self, server=None, client=None):
|
||||
"""Deletes a given client"""
|
||||
# Only the admin can edit the configuration
|
||||
if api.bui.acl and not self.is_admin:
|
||||
self.abort(403, 'Sorry, you don\'t have rights to access the setting panel')
|
||||
|
|
@ -295,6 +379,17 @@ class PathExpander(Resource):
|
|||
parser = api.parser()
|
||||
parser.add_argument('path', required=True, help="No 'path' provided")
|
||||
|
||||
@ns.doc(
|
||||
params={
|
||||
'server': 'Which server to collect data from when in multi-agent mode',
|
||||
'client': 'Client name',
|
||||
},
|
||||
responses={
|
||||
200: 'Success',
|
||||
403: 'Insufficient permissions',
|
||||
500: 'Internal failure',
|
||||
}
|
||||
)
|
||||
def get(self, server=None, client=None):
|
||||
"""Expends a given path
|
||||
|
||||
|
|
@ -313,10 +408,20 @@ class PathExpander(Resource):
|
|||
|
||||
|
||||
@ns.route('/options',
|
||||
'<server>/options',
|
||||
'/<server>/options',
|
||||
endpoint='setting_options')
|
||||
class SettingOptions(Resource):
|
||||
|
||||
@ns.doc(
|
||||
params={
|
||||
'server': 'Which server to collect data from when in multi-agent mode',
|
||||
},
|
||||
responses={
|
||||
200: 'Success',
|
||||
403: 'Insufficient permissions',
|
||||
500: 'Internal failure',
|
||||
}
|
||||
)
|
||||
def get(self, server=None):
|
||||
"""Returns various setting options"""
|
||||
if api.bui.acl and not self.is_admin:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue