mirror of
https://github.com/ziirish/burp-ui.git
synced 2026-05-29 22:02:15 -06:00
1752 lines
57 KiB
Python
1752 lines
57 KiB
Python
# -*- coding: utf8 -*-
|
|
"""
|
|
.. module:: burpui.api.admin
|
|
:platform: Unix
|
|
:synopsis: Burp-UI admin api module.
|
|
|
|
.. moduleauthor:: Ziirish <hi+burpui@ziirish.me>
|
|
|
|
"""
|
|
from . import api
|
|
from ..engines.server import BUIServer # noqa
|
|
from ..sessions import session_manager
|
|
from ..misc.acl.meta import meta_grants
|
|
from ..utils import NOTIF_OK
|
|
from .custom import fields, Resource
|
|
# from ..exceptions import BUIserverException
|
|
|
|
from flask import current_app
|
|
from flask_login import current_user
|
|
from flask_babel import gettext
|
|
|
|
import json
|
|
|
|
bui = current_app # type: BUIServer
|
|
ns = api.namespace('admin', 'Admin methods')
|
|
|
|
user_fields = ns.model('Users', {
|
|
'id': fields.String(required=True, description='User id'),
|
|
'name': fields.String(required=True, description='User name'),
|
|
'backend': fields.String(required=True, description='Backend name'),
|
|
})
|
|
grant_fields = ns.model('Grants', {
|
|
'id': fields.String(required=True, description='Grant id'),
|
|
'grant': fields.String(required=True, description='Grant content'),
|
|
'backend': fields.String(required=True, description='Backend name'),
|
|
})
|
|
group_fields = ns.model('Groups', {
|
|
'id': fields.String(required=True, description='Group id'),
|
|
'grant': fields.String(required=True, description='Group grant content'),
|
|
'members': fields.List(fields.String, required=True, description='Group members'),
|
|
'backend': fields.String(required=True, description='Backend name'),
|
|
})
|
|
groups_fields = ns.model('GroupsFields', {
|
|
'name': fields.String(required=True, description='Group name'),
|
|
'inherit': fields.List(fields.String, required=False, description='This group is inherited by'),
|
|
})
|
|
groups_list_fields = ns.model('GroupsList', {
|
|
'groups': fields.List(fields.Nested(groups_fields), required=True, description='Groups list'),
|
|
})
|
|
group_members_fields = ns.model('GroupMembers', {
|
|
'members': fields.List(fields.String, required=True, description='Group members'),
|
|
'grant': fields.String(required=True, description='Group grant content'),
|
|
})
|
|
is_moderator_fields = ns.model('IsModerator', {
|
|
'moderator': fields.Boolean(required=True, description='Is the member a moderator'),
|
|
'inherit': fields.List(fields.String, required=False, description='What provides this grant if inherited'),
|
|
})
|
|
moderator_members_fields = ns.model('ModeratorMembers', {
|
|
'members': fields.List(fields.String, required=True, description='Moderator members'),
|
|
'grant': fields.String(required=True, description='Moderator grant content'),
|
|
})
|
|
moderators_fields = ns.model('Moderators', {
|
|
'members': fields.List(fields.String, required=True, description='Moderator members'),
|
|
'grant': fields.String(required=True, description='Moderator grant content'),
|
|
'backend': fields.String(required=True, description='Backend name'),
|
|
})
|
|
is_admin_fields = ns.model('IsAdmin', {
|
|
'admin': fields.Boolean(required=True, description='Is the member an admin'),
|
|
'inherit': fields.List(fields.String, required=False, description='What provides this grant if inherited'),
|
|
})
|
|
admin_members_fields = ns.model('AdminMembers', {
|
|
'members': fields.List(fields.String, required=True, description='Admin members'),
|
|
})
|
|
admins_fields = ns.model('Admins', {
|
|
'members': fields.List(fields.String, required=True, description='Admin members'),
|
|
'backend': fields.String(required=True, description='Backend name'),
|
|
})
|
|
session_fields = ns.model('Sessions', {
|
|
'uuid': fields.String(description='Session id'),
|
|
'ip': fields.String(description='IP address'),
|
|
'ua': fields.String(description='User-Agent'),
|
|
'permanent': fields.Boolean(description='Remember cookie'),
|
|
'api': fields.Boolean(description='API login'),
|
|
'expire': fields.DateTime(description='Expiration date'),
|
|
'timestamp': fields.DateTime(description='Last seen'),
|
|
'current': fields.Boolean(description='Is current session', default=False)
|
|
})
|
|
acl_backend_fields = ns.model('AclBackends', {
|
|
'name': fields.String(required=True, description='Backend name'),
|
|
'description': fields.String(required=True, description='Backend description'),
|
|
'type': fields.String(required=False, description='Backend type'),
|
|
'priority': fields.Integer(required=False, description='Backend priority'),
|
|
'add_grant': fields.Boolean(required=False, default=False, description='Support grant creation'),
|
|
'mod_grant': fields.Boolean(required=False, default=False, description='Support grant edition'),
|
|
'del_grant': fields.Boolean(required=False, default=False, description='Support grant deletion'),
|
|
'add_group': fields.Boolean(required=False, default=False, description='Support group creation'),
|
|
'mod_group': fields.Boolean(required=False, default=False, description='Support group edition'),
|
|
'del_group': fields.Boolean(required=False, default=False, description='Support group deletion'),
|
|
'add_group_member': fields.Boolean(required=False, default=False, description='Support group member addition'),
|
|
'del_group_member': fields.Boolean(required=False, default=False, description='Support group member deletion'),
|
|
'add_moderator': fields.Boolean(required=False, default=False, description='Support moderator creation'),
|
|
'mod_moderator': fields.Boolean(required=False, default=False, description='Support moderator edition'),
|
|
'del_moderator': fields.Boolean(required=False, default=False, description='Support moderator deletion'),
|
|
'add_admin': fields.Boolean(required=False, default=False, description='Support admin creation'),
|
|
'del_admin': fields.Boolean(required=False, default=False, description='Support admin deletion'),
|
|
})
|
|
auth_backend_fields = ns.model('Backends', {
|
|
'name': fields.String(required=True, description='Backend name'),
|
|
'description': fields.String(required=True, description='Backend description'),
|
|
'type': fields.String(required=False, description='Backend type'),
|
|
'priority': fields.Integer(required=False, description='Backend priority'),
|
|
'add': fields.Boolean(required=False, default=False, description='Support user creation'),
|
|
'mod': fields.Boolean(required=False, default=False, description='Support user edition'),
|
|
'del': fields.Boolean(required=False, default=False, description='Support user deletion'),
|
|
})
|
|
|
|
|
|
@ns.route('/me', endpoint='admin_me')
|
|
class AdminMe(Resource):
|
|
"""The :class:`burpui.api.admin.AdminMe` resource allows you to
|
|
retrieve informations about your currently logged in user.
|
|
|
|
This resource is part of the :mod:`burpui.api.admin` module.
|
|
"""
|
|
|
|
@ns.marshal_with(user_fields)
|
|
def get(self):
|
|
"""Returns the current user informations
|
|
|
|
**GET** method provided by the webservice.
|
|
|
|
:returns: User
|
|
"""
|
|
ret = getattr(current_user, 'real', current_user)
|
|
return ret
|
|
|
|
|
|
@ns.route('/acl/isAdmin/<member>',
|
|
'/acl/<backend>/isAdmin/<member>',
|
|
endpoint='acl_is_admin')
|
|
@ns.doc(
|
|
params={
|
|
'member': 'Username',
|
|
}
|
|
)
|
|
class AclIsAdmin(Resource):
|
|
"""The :class:`burpui.api.admin.AclIsAdmin` resources allows you to check
|
|
if a given member is admin or not.
|
|
|
|
This resource is part of the :mod:`burpui.api.admin` module.
|
|
"""
|
|
|
|
@api.acl_admin_or_moderator_required(message="Not allowed to view admins list")
|
|
@ns.marshal_with(is_admin_fields)
|
|
@ns.doc(
|
|
responses={
|
|
403: 'Insufficient permissions',
|
|
404: 'No backend found',
|
|
},
|
|
)
|
|
def get(self, member, backend=None):
|
|
"""Checks if a given member is admin"""
|
|
if not backend:
|
|
(ret, inh) = meta_grants.is_admin(member)
|
|
return {'admin': ret, 'inherit': inh}
|
|
try:
|
|
handler = getattr(bui, 'acl_handler')
|
|
except AttributeError:
|
|
handler = None
|
|
|
|
if not handler or len(handler.backends) == 0:
|
|
self.abort(404, "No acl backend found")
|
|
if backend not in handler.backends:
|
|
self.abort(404, "No acl backend '{}' found".format(backend))
|
|
loader = handler.backends[backend]
|
|
return {'admin': member in loader.admins}
|
|
|
|
|
|
@ns.route('/acl/admins',
|
|
'/acl/<backend>/admins',
|
|
endpoint='acl_admins')
|
|
@ns.doc(
|
|
params={
|
|
'backend': 'Backend name',
|
|
}
|
|
)
|
|
class AclAdminss(Resource):
|
|
"""The :class:`burpui.api.admin.AclAdminss` resource allows you to
|
|
retrieve a list of admins.
|
|
|
|
This resource is part of the :mod:`burpui.api.admin` module.
|
|
"""
|
|
|
|
@api.acl_admin_or_moderator_required(message="Not allowed to view groups list")
|
|
@ns.marshal_list_with(admins_fields, code=200, description='Success')
|
|
@ns.doc(
|
|
responses={
|
|
403: 'Insufficient permissions',
|
|
404: 'No backend found',
|
|
},
|
|
)
|
|
def get(self, name=None, backend=None):
|
|
"""Returns a list of admins
|
|
|
|
**GET** method provided by the webservice.
|
|
|
|
:returns: Moderators
|
|
"""
|
|
try:
|
|
handler = getattr(bui, 'acl_handler')
|
|
except AttributeError:
|
|
handler = None
|
|
|
|
if not handler or len(handler.backends) == 0:
|
|
self.abort(404, "No acl backend found")
|
|
ret = []
|
|
for _, loader in handler.backends.items():
|
|
append = {
|
|
'members': loader.admins,
|
|
'backend': loader.name
|
|
}
|
|
if (backend and backend == append['backend']) or backend is None:
|
|
return [append]
|
|
ret.append(append)
|
|
return ret
|
|
|
|
|
|
@ns.route('/acl/admin',
|
|
'/acl/<backend>/admin',
|
|
'/acl/<backend>/admin/<member>',
|
|
endpoint='acl_admin')
|
|
@ns.doc(
|
|
params={
|
|
'backend': 'ACL backend',
|
|
'member': 'Admin member',
|
|
}
|
|
)
|
|
class AclAdmin(Resource):
|
|
"""The :class:`burpui.api.admin.AclAdmins` resource allows you to
|
|
retrieve a list of admins and add/delete them if your
|
|
acl backend support those actions.
|
|
|
|
This resource is part of the :mod:`burpui.api.admin` module.
|
|
"""
|
|
parser = ns.parser()
|
|
parser.add_argument('memberNames', required=False, help='Admin members', action='append')
|
|
parser.add_argument('backendName', required=False, help='Backend name')
|
|
|
|
@api.acl_admin_or_moderator_required(message="Not allowed to view admins list")
|
|
@ns.marshal_with(admin_members_fields, code=200, description='Success')
|
|
@ns.doc(
|
|
responses={
|
|
403: 'Insufficient permissions',
|
|
404: 'No backend found',
|
|
},
|
|
)
|
|
def get(self, backend):
|
|
"""Returns a list of admin users
|
|
|
|
**GET** method provided by the webservice.
|
|
|
|
:returns: Members
|
|
"""
|
|
try:
|
|
handler = getattr(bui, 'acl_handler')
|
|
except AttributeError:
|
|
handler = None
|
|
|
|
if not handler or len(handler.backends) == 0:
|
|
self.abort(404, "No acl backend found")
|
|
if backend not in handler.backends:
|
|
self.abort(404, "No acl backend '{}' found".format(backend))
|
|
ret = {}
|
|
loader = handler.backends[backend]
|
|
ret = {
|
|
'members': loader.admins
|
|
}
|
|
return ret
|
|
|
|
@api.disabled_on_demo()
|
|
@api.acl_admin_required(message="Not allowed to add admin members")
|
|
@ns.expect(parser)
|
|
@ns.doc(
|
|
responses={
|
|
403: 'Insufficient permissions',
|
|
404: 'No backend found',
|
|
},
|
|
)
|
|
def put(self, backend=None, member=None):
|
|
"""Add a member as admin
|
|
|
|
**PUT** method provided by the webservice.
|
|
"""
|
|
args = self.parser.parse_args()
|
|
backend = backend or args['backendName']
|
|
try:
|
|
handler = getattr(bui, 'acl_handler')
|
|
except AttributeError:
|
|
handler = None
|
|
|
|
if not handler or len(handler.backends) == 0:
|
|
self.abort(404, "No acl backend found")
|
|
if backend not in handler.backends:
|
|
self.abort(404, "No acl backend '{}' found".format(backend))
|
|
|
|
loader = handler.backends[backend]
|
|
|
|
members = [member] if member else (args['memberNames'] or [])
|
|
|
|
if loader.add_admin is False:
|
|
self.abort(
|
|
500,
|
|
"The '{}' backend does not support moderator member addition"
|
|
"".format(backend)
|
|
)
|
|
|
|
ret = []
|
|
status = 200
|
|
|
|
for member in members:
|
|
success, message, code = loader.add_admin(
|
|
member
|
|
)
|
|
status = 201 if success else 200
|
|
ret.append([code, message])
|
|
return ret, status
|
|
|
|
@api.disabled_on_demo()
|
|
@api.acl_admin_required(message="Not allowed to remove admin members")
|
|
@ns.expect(parser)
|
|
@ns.doc(
|
|
responses={
|
|
403: 'Insufficient permissions',
|
|
404: 'No backend found',
|
|
},
|
|
)
|
|
def delete(self, backend=None, member=None):
|
|
"""Remove an admin member
|
|
|
|
**DELETE** method provided by the webservice.
|
|
"""
|
|
args = self.parser.parse_args()
|
|
backend = backend or args['backendName']
|
|
try:
|
|
handler = getattr(bui, 'acl_handler')
|
|
except AttributeError:
|
|
handler = None
|
|
|
|
if not handler or len(handler.backends) == 0:
|
|
self.abort(404, "No acl backend found")
|
|
if backend not in handler.backends:
|
|
self.abort(40422, "No acl backend '{}' found".format(backend))
|
|
|
|
loader = handler.backends[backend]
|
|
|
|
members = [member] if member else (args['memberNames'] or [])
|
|
|
|
if loader.del_admin is False:
|
|
self.abort(
|
|
500,
|
|
"The '{}' backend does not support admin member deletion"
|
|
"".format(backend)
|
|
)
|
|
|
|
ret = []
|
|
status = 200
|
|
|
|
for member in members:
|
|
success, message, code = loader.del_admin(
|
|
member
|
|
)
|
|
status = 201 if success else 200
|
|
ret.append([code, message])
|
|
return ret, status
|
|
|
|
|
|
@ns.route('/acl/isModerator/<member>',
|
|
'/acl/<backend>/isModerator/<member>',
|
|
endpoint='acl_is_moderator')
|
|
@ns.doc(
|
|
params={
|
|
'member': 'Username',
|
|
}
|
|
)
|
|
class AclIsModerator(Resource):
|
|
"""The :class:`burpui.api.admin.AclIsModerator` resources allows you to check
|
|
if a given member is moderator or not.
|
|
|
|
This resource is part of the :mod:`burpui.api.admin` module.
|
|
"""
|
|
|
|
@api.acl_admin_or_moderator_required(message="Not allowed to view admins list")
|
|
@ns.marshal_with(is_moderator_fields)
|
|
@ns.doc(
|
|
responses={
|
|
403: 'Insufficient permissions',
|
|
404: 'No backend found',
|
|
},
|
|
)
|
|
def get(self, member, backend=None):
|
|
"""Checks if a given member is moderator"""
|
|
if not backend:
|
|
(ret, inh) = meta_grants.is_moderator(member)
|
|
return {'moderator': ret, 'inherit': inh}
|
|
try:
|
|
handler = getattr(bui, 'acl_handler')
|
|
except AttributeError:
|
|
handler = None
|
|
|
|
if not handler or len(handler.backends) == 0:
|
|
self.abort(404, "No acl backend found")
|
|
if backend not in handler.backends:
|
|
self.abort(404, "No acl backend '{}' found".format(backend))
|
|
loader = handler.backends[backend]
|
|
return {'moderator': member in loader.moderators}
|
|
|
|
|
|
@ns.route('/acl/moderators',
|
|
'/acl/<backend>/moderators',
|
|
endpoint='acl_moderators')
|
|
@ns.doc(
|
|
params={
|
|
'backend': 'Backend name',
|
|
}
|
|
)
|
|
class AclModerators(Resource):
|
|
"""The :class:`burpui.api.admin.AclModerators` resource allows you to
|
|
retrieve a list of moderators.
|
|
|
|
This resource is part of the :mod:`burpui.api.admin` module.
|
|
"""
|
|
|
|
@api.acl_admin_or_moderator_required(message="Not allowed to view groups list")
|
|
@ns.marshal_list_with(moderators_fields, code=200, description='Success')
|
|
@ns.doc(
|
|
responses={
|
|
403: 'Insufficient permissions',
|
|
404: 'No backend found',
|
|
},
|
|
)
|
|
def get(self, name=None, backend=None):
|
|
"""Returns a list of moderators
|
|
|
|
**GET** method provided by the webservice.
|
|
|
|
:returns: Moderators
|
|
"""
|
|
try:
|
|
handler = getattr(bui, 'acl_handler')
|
|
except AttributeError:
|
|
handler = None
|
|
|
|
if not handler or len(handler.backends) == 0:
|
|
self.abort(404, "No acl backend found")
|
|
ret = []
|
|
for _, loader in handler.backends.items():
|
|
append = {
|
|
'grant': loader.moderator,
|
|
'members': loader.moderators,
|
|
'backend': loader.name
|
|
}
|
|
if (backend and backend == append['backend']) or backend is None:
|
|
return [append]
|
|
ret.append(append)
|
|
return ret
|
|
|
|
|
|
@ns.route('/acl/moderator',
|
|
'/acl/<backend>/moderator',
|
|
'/acl/<backend>/moderator/<member>',
|
|
endpoint='acl_moderator')
|
|
@ns.doc(
|
|
params={
|
|
'backend': 'ACL backend',
|
|
'member': 'Moderator member',
|
|
}
|
|
)
|
|
class AclModerator(Resource):
|
|
"""The :class:`burpui.api.admin.AclModerator` resource allows you to
|
|
retrieve a list of moderators and add/delete them if your
|
|
acl backend support those actions.
|
|
|
|
This resource is part of the :mod:`burpui.api.admin` module.
|
|
"""
|
|
parser = ns.parser()
|
|
parser.add_argument('memberNames', required=False, help='Moderator members', action='append')
|
|
parser.add_argument('backendName', required=False, help='Backend name')
|
|
|
|
parser_mod = ns.parser()
|
|
parser_mod.add_argument('grant', required=False, help='Moderator grants')
|
|
|
|
@api.acl_admin_or_moderator_required(message="Not allowed to view moderators list")
|
|
@ns.marshal_with(moderator_members_fields, code=200, description='Success')
|
|
@ns.doc(
|
|
responses={
|
|
403: 'Insufficient permissions',
|
|
404: 'No backend found',
|
|
},
|
|
)
|
|
def get(self, backend):
|
|
"""Returns a list of moderator users
|
|
|
|
**GET** method provided by the webservice.
|
|
|
|
:returns: Members
|
|
"""
|
|
try:
|
|
handler = getattr(bui, 'acl_handler')
|
|
except AttributeError:
|
|
handler = None
|
|
|
|
if not handler or len(handler.backends) == 0:
|
|
self.abort(404, "No acl backend found")
|
|
if backend not in handler.backends:
|
|
self.abort(404, "No acl backend '{}' found".format(backend))
|
|
ret = {}
|
|
loader = handler.backends[backend]
|
|
ret = {
|
|
'members': loader.moderators,
|
|
'grant': loader.moderator
|
|
}
|
|
return ret
|
|
|
|
@api.disabled_on_demo()
|
|
@api.acl_admin_or_moderator_required(message="Not allowed to add moderator members")
|
|
@ns.expect(parser)
|
|
@ns.doc(
|
|
responses={
|
|
403: 'Insufficient permissions',
|
|
404: 'No backend found',
|
|
},
|
|
)
|
|
def put(self, backend=None, member=None):
|
|
"""Add a member as moderator
|
|
|
|
**PUT** method provided by the webservice.
|
|
"""
|
|
args = self.parser.parse_args()
|
|
backend = backend or args['backendName']
|
|
try:
|
|
handler = getattr(bui, 'acl_handler')
|
|
except AttributeError:
|
|
handler = None
|
|
|
|
if not handler or len(handler.backends) == 0:
|
|
self.abort(404, "No acl backend found")
|
|
if backend not in handler.backends:
|
|
self.abort(404, "No acl backend '{}' found".format(backend))
|
|
|
|
loader = handler.backends[backend]
|
|
|
|
members = [member] if member else (args['memberNames'] or [])
|
|
|
|
if loader.add_moderator is False:
|
|
self.abort(
|
|
500,
|
|
"The '{}' backend does not support moderator member addition"
|
|
"".format(backend)
|
|
)
|
|
|
|
ret = []
|
|
status = 200
|
|
for member in members:
|
|
success, message, code = loader.add_moderator(
|
|
member
|
|
)
|
|
ret.append([code, message])
|
|
status = 201 if success else 200
|
|
return ret, status
|
|
|
|
@api.disabled_on_demo()
|
|
@api.acl_admin_or_moderator_required(message="Not allowed to remove moderator members")
|
|
@ns.expect(parser)
|
|
@ns.doc(
|
|
responses={
|
|
403: 'Insufficient permissions',
|
|
404: 'No backend found',
|
|
},
|
|
)
|
|
def delete(self, backend=None, member=None):
|
|
"""Remove a moderator member
|
|
|
|
**DELETE** method provided by the webservice.
|
|
"""
|
|
args = self.parser.parse_args()
|
|
backend = backend or args['backendName']
|
|
try:
|
|
handler = getattr(bui, 'acl_handler')
|
|
except AttributeError:
|
|
handler = None
|
|
|
|
if not handler or len(handler.backends) == 0:
|
|
self.abort(404, "No acl backend found")
|
|
if backend not in handler.backends:
|
|
self.abort(404, "No acl backend '{}' found".format(backend))
|
|
|
|
loader = handler.backends[backend]
|
|
|
|
members = [member] if member else (args['memberNames'] or [])
|
|
|
|
if loader.del_moderator is False:
|
|
self.abort(
|
|
500,
|
|
"The '{}' backend does not support moderator member deletion"
|
|
"".format(backend)
|
|
)
|
|
|
|
ret = []
|
|
status = 200
|
|
for member in members:
|
|
success, message, code = loader.del_moderator(
|
|
member
|
|
)
|
|
ret.append([code, message])
|
|
status = 201 if success else 200
|
|
return ret, status
|
|
|
|
@api.disabled_on_demo()
|
|
@api.acl_admin_or_moderator_required(message="Not allowed to update moderator grants")
|
|
@ns.expect(parser_mod)
|
|
@ns.doc(
|
|
responses={
|
|
403: 'Insufficient permissions',
|
|
404: 'No backend found',
|
|
},
|
|
)
|
|
def post(self, backend):
|
|
"""Update moderator grants
|
|
|
|
**POST** method provided by the webservice.
|
|
"""
|
|
args = self.parser_mod.parse_args()
|
|
try:
|
|
handler = getattr(bui, 'acl_handler')
|
|
except AttributeError:
|
|
handler = None
|
|
|
|
if not handler or len(handler.backends) == 0:
|
|
self.abort(404, "No acl backend found")
|
|
if backend not in handler.backends:
|
|
self.abort(404, "No acl backend '{}' found".format(backend))
|
|
|
|
loader = handler.backends[backend]
|
|
|
|
grants = args['grant']
|
|
|
|
if loader.mod_moderator is False:
|
|
self.abort(
|
|
500,
|
|
"The '{}' backend does not support moderator grants edition"
|
|
"".format(backend)
|
|
)
|
|
|
|
success, message, code = loader.mod_moderator(
|
|
grants
|
|
)
|
|
status = 201 if success else 200
|
|
return [[code, message]], status
|
|
|
|
|
|
@ns.route('/acl/group',
|
|
'/acl/<backend>/group/<name>',
|
|
'/acl/<backend>/group/<name>/<member>',
|
|
endpoint='acl_group_members')
|
|
@ns.doc(
|
|
params={
|
|
'name': 'Group name',
|
|
'backend': 'ACL backend',
|
|
'member': 'Group member',
|
|
}
|
|
)
|
|
class AclGroup(Resource):
|
|
"""The :class:`burpui.api.admin.AclGroup` resource allows you to
|
|
retrieve a list of members in a given group and add/delete them if your
|
|
acl backend support those actions.
|
|
|
|
This resource is part of the :mod:`burpui.api.admin` module.
|
|
"""
|
|
parser = ns.parser()
|
|
parser.add_argument('memberNames', required=False, help='Group members', action='append')
|
|
parser.add_argument('groupName', required=False, help='Group name')
|
|
parser.add_argument('backendName', required=False, help='Backend name')
|
|
|
|
@api.acl_admin_or_moderator_required(message="Not allowed to view groups list")
|
|
@ns.marshal_with(group_members_fields, code=200, description='Success')
|
|
@ns.doc(
|
|
responses={
|
|
403: 'Insufficient permissions',
|
|
404: 'No backend found',
|
|
},
|
|
)
|
|
def get(self, name, backend):
|
|
"""Returns a list of users in a giver group
|
|
|
|
**GET** method provided by the webservice.
|
|
|
|
:returns: Members
|
|
"""
|
|
try:
|
|
handler = getattr(bui, 'acl_handler')
|
|
except AttributeError:
|
|
handler = None
|
|
|
|
if not handler or len(handler.backends) == 0:
|
|
self.abort(404, "No acl backend found")
|
|
if backend not in handler.backends:
|
|
self.abort(404, "No acl backend '{}' found".format(backend))
|
|
ret = {}
|
|
loader = handler.backends[backend]
|
|
groups = loader.groups
|
|
gname = '@{}'.format(name)
|
|
if groups and gname in groups:
|
|
ret = {
|
|
'members': groups[gname].get('members', []),
|
|
'grant': groups[gname].get('grants', '')
|
|
}
|
|
return ret
|
|
|
|
@api.disabled_on_demo()
|
|
@api.acl_admin_or_moderator_required(message="Not allowed to add member in group")
|
|
@ns.expect(parser)
|
|
@ns.doc(
|
|
responses={
|
|
403: 'Insufficient permissions',
|
|
404: 'No backend found',
|
|
},
|
|
)
|
|
def put(self, name=None, backend=None, member=None):
|
|
"""Add a member in a given group
|
|
|
|
**PUT** method provided by the webservice.
|
|
"""
|
|
args = self.parser.parse_args()
|
|
name = name or args['groupName']
|
|
backend = backend or args['backendName']
|
|
try:
|
|
handler = getattr(bui, 'acl_handler')
|
|
except AttributeError:
|
|
handler = None
|
|
|
|
if not handler or len(handler.backends) == 0:
|
|
self.abort(404, "No acl backend found")
|
|
if backend not in handler.backends:
|
|
self.abort(404, "No acl backend '{}' found".format(backend))
|
|
|
|
loader = handler.backends[backend]
|
|
|
|
members = [member] if member else (args['memberNames'] or [])
|
|
|
|
if loader.add_group_member is False:
|
|
self.abort(
|
|
500,
|
|
"The '{}' backend does not support group member addition"
|
|
"".format(backend)
|
|
)
|
|
|
|
ret = []
|
|
status = 200
|
|
for member in members:
|
|
success, message, code = loader.add_group_member(
|
|
name,
|
|
member
|
|
)
|
|
ret.append([code, message])
|
|
status = 201 if success else 200
|
|
return ret, status
|
|
|
|
@api.disabled_on_demo()
|
|
@api.acl_admin_or_moderator_required(message="Not allowed to remove member in group")
|
|
@ns.expect(parser)
|
|
@ns.doc(
|
|
responses={
|
|
403: 'Insufficient permissions',
|
|
404: 'No backend found',
|
|
},
|
|
)
|
|
def delete(self, name, backend, member=None):
|
|
"""Remove a member from a given group
|
|
|
|
**DELETE** method provided by the webservice.
|
|
"""
|
|
args = self.parser.parse_args()
|
|
try:
|
|
handler = getattr(bui, 'acl_handler')
|
|
except AttributeError:
|
|
handler = None
|
|
|
|
if not handler or len(handler.backends) == 0:
|
|
self.abort(404, "No acl backend found")
|
|
if backend not in handler.backends:
|
|
self.abort(404, "No acl backend '{}' found".format(backend))
|
|
|
|
loader = handler.backends[backend]
|
|
|
|
members = [member] if member else (args['memberNames'] or [])
|
|
|
|
if loader.del_group_member is False:
|
|
self.abort(
|
|
500,
|
|
"The '{}' backend does not support group member deletion"
|
|
"".format(backend)
|
|
)
|
|
|
|
ret = []
|
|
status = 200
|
|
for member in members:
|
|
success, message, code = loader.del_group_member(
|
|
name,
|
|
member
|
|
)
|
|
ret.append([code, message])
|
|
status = 201 if success else 200
|
|
return ret, status
|
|
|
|
|
|
@ns.route('/acl/groupsOf/<member>',
|
|
endpoint='acl_groups_of')
|
|
@ns.doc(
|
|
params={
|
|
'member': 'Username',
|
|
}
|
|
)
|
|
class AclGroupsOf(Resource):
|
|
"""The :class:`burpui.api.admin.AclGroupsOf` resource allows you to retrieve
|
|
a list of groups of a given user.
|
|
|
|
This resource is part of the :mod:`burpui.api.admin` module.
|
|
"""
|
|
|
|
@api.acl_admin_or_moderator_required(message="Not allowed to view groups list")
|
|
@ns.marshal_with(groups_list_fields, code=200, description='Success')
|
|
@ns.doc(
|
|
responses={
|
|
403: 'Insufficient permissions',
|
|
404: 'No backend found',
|
|
},
|
|
)
|
|
def get(self, member):
|
|
"""Returns a list of group
|
|
|
|
**GET** method provided by the webservice.
|
|
|
|
:returns: Groups
|
|
"""
|
|
return {'groups': [{'name': name, 'inherit': inherit} for name, inherit in meta_grants.get_member_groups(member)]}
|
|
|
|
|
|
@ns.route('/acl/groups',
|
|
'/acl/<backend>/groups',
|
|
'/acl/groups/<name>',
|
|
'/acl/<backend>/groups/<name>',
|
|
endpoint='acl_groups')
|
|
@ns.doc(
|
|
params={
|
|
'name': 'Group name',
|
|
'backend': 'Backend name',
|
|
}
|
|
)
|
|
class AclGroups(Resource):
|
|
"""The :class:`burpui.api.admin.AclGroups` resource allows you to
|
|
retrieve a list of groups and to add/update/delete them if your
|
|
acl backend support those actions.
|
|
|
|
This resource is part of the :mod:`burpui.api.admin` module.
|
|
"""
|
|
parser_add = ns.parser()
|
|
parser_add.add_argument('group', required=True, help='Group name', location='values')
|
|
parser_add.add_argument('grant', required=True, help='Group grant content')
|
|
parser_add.add_argument('backend', help='Backend', location='values')
|
|
|
|
parser_mod = ns.parser()
|
|
parser_mod.add_argument('grant', required=True, help='Group grant content')
|
|
parser_mod.add_argument('backend', help='Backend', location='values')
|
|
|
|
parser_del = ns.parser()
|
|
parser_del.add_argument('backend', help='Backend', location='values')
|
|
|
|
@api.acl_admin_or_moderator_required(message="Not allowed to view groups list")
|
|
@ns.marshal_list_with(group_fields, code=200, description='Success')
|
|
@ns.doc(
|
|
responses={
|
|
403: 'Insufficient permissions',
|
|
404: 'No backend found',
|
|
},
|
|
)
|
|
def get(self, name=None, backend=None):
|
|
"""Returns a list of group
|
|
|
|
**GET** method provided by the webservice.
|
|
|
|
:returns: Groups
|
|
"""
|
|
try:
|
|
handler = getattr(bui, 'acl_handler')
|
|
except AttributeError:
|
|
handler = None
|
|
|
|
if not handler or len(handler.backends) == 0:
|
|
self.abort(404, "No acl backend found")
|
|
ret = []
|
|
for _, loader in handler.backends.items():
|
|
groups = loader.groups
|
|
if groups:
|
|
for _id, group in groups.items():
|
|
append = {
|
|
'id': _id.lstrip('@'),
|
|
'grant': group.get('grants', ''),
|
|
'members': group.get('members', []),
|
|
'backend': loader.name
|
|
}
|
|
if name and name == append['id']:
|
|
if (backend and backend == append['backend']) or backend is None:
|
|
return [append]
|
|
ret.append(append)
|
|
return ret
|
|
|
|
@api.disabled_on_demo()
|
|
@api.acl_admin_or_moderator_required(message="Not allowed to create groups")
|
|
@ns.expect(parser_add)
|
|
@ns.doc(
|
|
responses={
|
|
200: 'Request performed with errors',
|
|
201: 'Success',
|
|
403: 'Not allowed',
|
|
400: 'Missing parameters',
|
|
404: 'Backend not found',
|
|
500: 'Backend does not support this operation',
|
|
},
|
|
)
|
|
def put(self, backend=None):
|
|
"""Create a new group"""
|
|
args = self.parser_add.parse_args()
|
|
backend = backend or args['backend']
|
|
|
|
try:
|
|
handler = getattr(bui, 'acl_handler')
|
|
except AttributeError:
|
|
handler = None
|
|
|
|
if not handler or len(handler.backends) == 0 or \
|
|
backend not in handler.backends:
|
|
self.abort(404, "No acl backend found")
|
|
|
|
loader = handler.backends[backend]
|
|
|
|
if loader.add_group is False:
|
|
self.abort(
|
|
500,
|
|
"The '{}' backend does not support group creation"
|
|
"".format(backend)
|
|
)
|
|
|
|
success, message, code = loader.add_group(
|
|
args['group'],
|
|
args['grant']
|
|
)
|
|
status = 201 if success else 200
|
|
return [[code, message]], status
|
|
|
|
@api.disabled_on_demo()
|
|
@api.acl_admin_or_moderator_required(message="Not allowed to delete this group")
|
|
@ns.expect(parser_del)
|
|
@ns.doc(
|
|
responses={
|
|
200: 'Request performed with errors',
|
|
201: 'Success',
|
|
403: 'Not allowed',
|
|
400: 'Missing parameters',
|
|
404: 'Backend not found',
|
|
500: 'Backend does not support this operation',
|
|
},
|
|
)
|
|
def delete(self, name, backend=None):
|
|
"""Delete a group"""
|
|
args = self.parser_del.parse_args()
|
|
backend = backend or args['backend']
|
|
|
|
try:
|
|
handler = getattr(bui, 'acl_handler')
|
|
except AttributeError:
|
|
handler = None
|
|
|
|
if not handler or len(handler.backends) == 0 or \
|
|
backend not in handler.backends:
|
|
self.abort(404, "No acl backend found")
|
|
|
|
loader = handler.backends[backend]
|
|
|
|
if loader.del_group is False:
|
|
self.abort(
|
|
500,
|
|
"The '{}' backend does not support group deletion"
|
|
"".format(backend)
|
|
)
|
|
|
|
success, message, code = loader.del_group(
|
|
name
|
|
)
|
|
status = 201 if success else 200
|
|
return [[code, message]], status
|
|
|
|
@api.disabled_on_demo()
|
|
@api.acl_admin_or_moderator_required(message="Not allowed to modify this group")
|
|
@ns.expect(parser_mod)
|
|
@ns.doc(
|
|
responses={
|
|
200: 'Request performed with errors',
|
|
201: 'Success',
|
|
403: 'Not allowed',
|
|
400: 'Missing parameters',
|
|
404: 'Backend not found',
|
|
500: 'Backend does not support this operation',
|
|
},
|
|
)
|
|
def post(self, name, backend=None):
|
|
"""Change a group"""
|
|
args = self.parser_mod.parse_args()
|
|
backend = backend or args['backend']
|
|
|
|
try:
|
|
handler = getattr(bui, 'acl_handler')
|
|
except AttributeError:
|
|
handler = None
|
|
|
|
if not handler or len(handler.backends) == 0 or \
|
|
backend not in handler.backends:
|
|
self.abort(404, "No acl backend found")
|
|
|
|
loader = handler.backends[backend]
|
|
|
|
if loader.mod_group is False:
|
|
self.abort(
|
|
500,
|
|
"The '{}' backend does not support group modification"
|
|
"".format(backend)
|
|
)
|
|
|
|
success, message, code = loader.mod_group(
|
|
name,
|
|
args['grant']
|
|
)
|
|
status = 201 if success else 200
|
|
return [[code, message]], status
|
|
|
|
|
|
@ns.route('/acl/grants',
|
|
'/acl/<backend>/grants',
|
|
'/acl/grants/<name>',
|
|
'/acl/<backend>/grants/<name>',
|
|
endpoint='acl_grants')
|
|
@ns.doc(
|
|
params={
|
|
'name': 'Grant name',
|
|
'backend': 'Backend name',
|
|
}
|
|
)
|
|
class AclGrants(Resource):
|
|
"""The :class:`burpui.api.admin.AclGrants` resource allows you to
|
|
retrieve a list of grants and to add/update/delete them if your
|
|
acl backend support those actions.
|
|
|
|
This resource is part of the :mod:`burpui.api.admin` module.
|
|
"""
|
|
parser_add = ns.parser()
|
|
parser_add.add_argument('grant', required=True, help='Grant name')
|
|
parser_add.add_argument('content', required=True, help='Grant content')
|
|
parser_add.add_argument('backend', help='Backend')
|
|
|
|
parser_mod = ns.parser()
|
|
parser_mod.add_argument('content', required=True, help='Grant content')
|
|
parser_mod.add_argument('backend', help='Backend')
|
|
|
|
parser_del = ns.parser()
|
|
parser_del.add_argument('backend', help='Backend', location='values')
|
|
|
|
@api.acl_admin_or_moderator_required(message="Not allowed to view grants list")
|
|
@ns.marshal_list_with(grant_fields, code=200, description='Success')
|
|
@ns.doc(
|
|
responses={
|
|
403: 'Insufficient permissions',
|
|
404: 'No backend found',
|
|
},
|
|
)
|
|
def get(self, name=None, backend=None):
|
|
"""Returns a list of grants
|
|
|
|
**GET** method provided by the webservice.
|
|
|
|
:returns: Grants
|
|
"""
|
|
try:
|
|
handler = getattr(bui, 'acl_handler')
|
|
except AttributeError:
|
|
handler = None
|
|
|
|
if not handler or len(handler.backends) == 0:
|
|
self.abort(404, "No acl backend found")
|
|
ret = []
|
|
for _, loader in handler.backends.items():
|
|
grants = loader.grants
|
|
if grants:
|
|
for _id, grant in grants.items():
|
|
append = {
|
|
'id': _id,
|
|
'grant': json.dumps(grant),
|
|
'backend': loader.name
|
|
}
|
|
if name and name == _id:
|
|
if (backend and backend == loader.name) or backend is None:
|
|
return [append]
|
|
ret.append(append)
|
|
return ret
|
|
|
|
@api.disabled_on_demo()
|
|
@api.acl_admin_or_moderator_required(message="Not allowed to create grants")
|
|
@ns.expect(parser_add)
|
|
@ns.doc(
|
|
responses={
|
|
200: 'Request performed with errors',
|
|
201: 'Success',
|
|
403: 'Not allowed',
|
|
400: 'Missing parameters',
|
|
404: 'Backend not found',
|
|
500: 'Backend does not support this operation',
|
|
},
|
|
)
|
|
def put(self, backend=None):
|
|
"""Create a new grant"""
|
|
args = self.parser_add.parse_args()
|
|
backend = backend or args['backend']
|
|
|
|
try:
|
|
handler = getattr(bui, 'acl_handler')
|
|
except AttributeError:
|
|
handler = None
|
|
|
|
if not handler or len(handler.backends) == 0 or \
|
|
backend not in handler.backends:
|
|
self.abort(404, "No acl backend found")
|
|
|
|
loader = handler.backends[backend]
|
|
|
|
if loader.add_grant is False:
|
|
self.abort(
|
|
500,
|
|
"The '{}' backend does not support grant creation"
|
|
"".format(backend)
|
|
)
|
|
|
|
success, message, code = loader.add_grant(
|
|
args['grant'],
|
|
args['content']
|
|
)
|
|
status = 201 if success else 200
|
|
return [[code, message]], status
|
|
|
|
@api.disabled_on_demo()
|
|
@api.acl_admin_or_moderator_required(message="Not allowed to delete this grant")
|
|
@ns.expect(parser_del)
|
|
@ns.doc(
|
|
responses={
|
|
200: 'Request performed with errors',
|
|
201: 'Success',
|
|
403: 'Not allowed',
|
|
400: 'Missing parameters',
|
|
404: 'Backend not found',
|
|
500: 'Backend does not support this operation',
|
|
},
|
|
)
|
|
def delete(self, name, backend=None):
|
|
"""Delete a grant"""
|
|
args = self.parser_del.parse_args()
|
|
backend = backend or args['backend']
|
|
|
|
try:
|
|
handler = getattr(bui, 'acl_handler')
|
|
except AttributeError:
|
|
handler = None
|
|
|
|
if not handler or len(handler.backends) == 0 or \
|
|
backend not in handler.backends:
|
|
self.abort(404, "No acl backend found")
|
|
|
|
loader = handler.backends[backend]
|
|
|
|
if loader.del_grant is False:
|
|
self.abort(
|
|
500,
|
|
"The '{}' backend does not support grant deletion"
|
|
"".format(backend)
|
|
)
|
|
|
|
success, message, code = loader.del_grant(
|
|
name
|
|
)
|
|
status = 201 if success else 200
|
|
return [[code, message]], status
|
|
|
|
@api.disabled_on_demo()
|
|
@api.acl_admin_or_moderator_required(message="Not allowed to modify this grant")
|
|
@ns.expect(parser_mod)
|
|
@ns.doc(
|
|
responses={
|
|
200: 'Request performed with errors',
|
|
201: 'Success',
|
|
403: 'Not allowed',
|
|
400: 'Missing parameters',
|
|
404: 'Backend not found',
|
|
500: 'Backend does not support this operation',
|
|
},
|
|
)
|
|
def post(self, name, backend=None):
|
|
"""Change a grant"""
|
|
args = self.parser_mod.parse_args()
|
|
backend = backend or args['backend']
|
|
|
|
try:
|
|
handler = getattr(bui, 'acl_handler')
|
|
except AttributeError:
|
|
handler = None
|
|
|
|
if not handler or len(handler.backends) == 0 or \
|
|
backend not in handler.backends:
|
|
self.abort(404, "No acl backend found")
|
|
|
|
loader = handler.backends[backend]
|
|
|
|
if loader.mod_grant is False:
|
|
self.abort(
|
|
500,
|
|
"The '{}' backend does not support grant modification"
|
|
"".format(backend)
|
|
)
|
|
|
|
success, message, code = loader.mod_grant(
|
|
name,
|
|
args['content']
|
|
)
|
|
status = 201 if success else 200
|
|
return [[code, message]], status
|
|
|
|
|
|
@ns.route('/acl/backend/<backend>', endpoint='acl_backend')
|
|
class AclBackend(Resource):
|
|
"""The :class:`burpui.api.admin.AclBackend` resource allows you to
|
|
retrieve a given ACL backend with its capabilities.
|
|
|
|
This resource is part of the :mod:`burpui.api.admin` module.
|
|
"""
|
|
|
|
@api.acl_admin_or_moderator_required(message="Not allowed to view backends list")
|
|
@ns.marshal_with(acl_backend_fields, code=200, description='Success')
|
|
@ns.doc(
|
|
responses={
|
|
403: 'Insufficient permissions',
|
|
404: 'No backend found',
|
|
},
|
|
)
|
|
def get(self, backend):
|
|
"""Returns a given ACL backend
|
|
|
|
**GET** method provided by the webservice.
|
|
|
|
:returns: Backend
|
|
"""
|
|
try:
|
|
handler = getattr(bui, 'acl_handler')
|
|
except AttributeError:
|
|
handler = None
|
|
|
|
if not handler or len(handler.backends) == 0:
|
|
self.abort(404, "No authentication backend found")
|
|
if backend not in handler.backends:
|
|
self.abort(404, "ACL backend {} not found".format(backend))
|
|
loader = handler.backends[backend]
|
|
back = {}
|
|
back['name'] = backend
|
|
back['description'] = gettext(loader.__doc__)
|
|
back['type'] = 'authorization'
|
|
back['priority'] = getattr(loader, 'priority', -1)
|
|
for method in ['add_grant', 'del_grant', 'mod_grant', 'add_group', 'del_group', 'mod_group', 'add_group_member', 'del_group_member', 'add_moderator', 'del_moderator', 'mod_moderator', 'add_admin', 'del_admin']:
|
|
back[method] = getattr(loader, method, False) is not False
|
|
|
|
return back
|
|
|
|
|
|
@ns.route('/acl/backends', endpoint='acl_backends')
|
|
class AclBackends(Resource):
|
|
"""The :class:`burpui.api.admin.AclBackends` resource allows you to
|
|
retrieve a list of ACL backends with their capabilities.
|
|
|
|
This resource is part of the :mod:`burpui.api.admin` module.
|
|
"""
|
|
|
|
@api.acl_admin_or_moderator_required(message="Not allowed to view backends list")
|
|
@ns.marshal_list_with(acl_backend_fields, code=200, description='Success')
|
|
@ns.doc(
|
|
responses={
|
|
403: 'Insufficient permissions',
|
|
404: 'No backend found',
|
|
},
|
|
)
|
|
def get(self):
|
|
"""Returns a list of backends
|
|
|
|
**GET** method provided by the webservice.
|
|
|
|
:returns: Backends
|
|
"""
|
|
try:
|
|
handler = getattr(bui, 'acl_handler')
|
|
except AttributeError:
|
|
handler = None
|
|
|
|
if not handler or len(handler.backends) == 0:
|
|
self.abort(404, "No authentication backend found")
|
|
ret = []
|
|
for name, backend in handler.backends.items():
|
|
back = {}
|
|
back['name'] = name
|
|
back['description'] = gettext(backend.__doc__)
|
|
back['type'] = 'authorization'
|
|
back['priority'] = getattr(backend, 'priority', -1)
|
|
for method in ['add_grant', 'del_grant', 'mod_grant', 'add_group', 'del_group', 'mod_group', 'add_group_member', 'del_group_member', 'add_moderator', 'del_moderator', 'mod_moderator', 'add_admin', 'del_admin']:
|
|
back[method] = getattr(backend, method, False) is not False
|
|
ret.append(back)
|
|
|
|
return ret
|
|
|
|
|
|
@ns.route('/auth/users',
|
|
'/auth/<backend>/users',
|
|
'/auth/users/<name>',
|
|
'/auth/<backend>/users/<name>',
|
|
endpoint='auth_users')
|
|
@ns.doc(
|
|
params={
|
|
'name': 'Username',
|
|
'backend': 'Authentication backend',
|
|
}
|
|
)
|
|
class AuthUsers(Resource):
|
|
"""The :class:`burpui.api.admin.AuthUsers` resource allows you to
|
|
retrieve a list of users and to add/update/delete them if your
|
|
authentication backend support those actions.
|
|
|
|
This resource is part of the :mod:`burpui.api.admin` module.
|
|
"""
|
|
parser_add = ns.parser()
|
|
parser_add.add_argument('username', required=True, help='Username')
|
|
parser_add.add_argument('password', required=True, help='Password')
|
|
parser_add.add_argument('backend', help='Backend')
|
|
|
|
parser_mod = ns.parser()
|
|
parser_mod.add_argument('password', required=True, help='Password')
|
|
parser_mod.add_argument('backend', help='Backend')
|
|
parser_mod.add_argument('old_password', required=False, help='Old password')
|
|
|
|
parser_del = ns.parser()
|
|
parser_del.add_argument('backend', help='Backend')
|
|
|
|
@api.acl_admin_or_moderator_required(message="Not allowed to view users list")
|
|
@ns.marshal_list_with(user_fields, code=200, description='Success')
|
|
@ns.doc(
|
|
responses={
|
|
403: 'Insufficient permissions',
|
|
404: 'No backend found',
|
|
},
|
|
)
|
|
def get(self, name=None, backend=None):
|
|
"""Returns a list of users
|
|
|
|
**GET** method provided by the webservice.
|
|
|
|
:returns: Users
|
|
"""
|
|
try:
|
|
handler = getattr(bui, 'uhandler')
|
|
except AttributeError:
|
|
handler = None
|
|
|
|
if not handler or len(handler.backends) == 0:
|
|
self.abort(404, "No authentication backend found")
|
|
ret = []
|
|
for _, backend in handler.backends.items():
|
|
loader = backend.loader
|
|
preload_users = getattr(backend, 'preload_users', True)
|
|
try:
|
|
users = getattr(loader, 'users')
|
|
except AttributeError:
|
|
continue
|
|
if users:
|
|
if isinstance(users, list):
|
|
for user in users:
|
|
append = {
|
|
'id': backend.user(user).get_id() if preload_users else user,
|
|
'name': user,
|
|
'backend': backend.name
|
|
}
|
|
if name and name == append['id']:
|
|
if (backend and backend == append['backend']) or backend is None:
|
|
return append
|
|
ret.append(append)
|
|
elif isinstance(users, dict):
|
|
for user, _ in users.items():
|
|
append = {
|
|
'id': backend.user(user).get_id(),
|
|
'name': user,
|
|
'backend': backend.name
|
|
}
|
|
if name and name == append['id']:
|
|
if (backend and backend == append['backend']) or backend is None:
|
|
return append
|
|
ret.append(append)
|
|
return ret
|
|
|
|
@api.disabled_on_demo()
|
|
@api.acl_admin_or_moderator_required(message="Not allowed to create users")
|
|
@ns.expect(parser_add)
|
|
@ns.doc(
|
|
responses={
|
|
200: 'Request performed with errors',
|
|
201: 'Success',
|
|
403: 'Not allowed',
|
|
400: 'Missing parameters',
|
|
404: 'Backend not found',
|
|
500: 'Backend does not support this operation',
|
|
},
|
|
)
|
|
def put(self, name=None, backend=None):
|
|
"""Create a new user"""
|
|
args = self.parser_add.parse_args()
|
|
username = name or args['username']
|
|
backend = backend or args['backend']
|
|
|
|
try:
|
|
handler = getattr(bui, 'uhandler')
|
|
except AttributeError:
|
|
handler = None
|
|
|
|
if not handler or len(handler.backends) == 0 or \
|
|
backend not in handler.backends:
|
|
self.abort(404, "No authentication backend found")
|
|
|
|
backend = handler.backends[backend]
|
|
|
|
if backend.add_user is False:
|
|
self.abort(
|
|
500,
|
|
"The '{}' backend does not support user creation"
|
|
"".format(backend)
|
|
)
|
|
|
|
success, message, code = backend.add_user(
|
|
username,
|
|
args['password']
|
|
)
|
|
status = 201 if success else 200
|
|
return [[code, message]], status
|
|
|
|
@api.disabled_on_demo()
|
|
@api.acl_admin_or_moderator_required(message="Not allowed to delete this user")
|
|
@ns.expect(parser_del)
|
|
@ns.doc(
|
|
responses={
|
|
200: 'Request performed with errors',
|
|
201: 'Success',
|
|
403: 'Not allowed',
|
|
400: 'Missing parameters',
|
|
404: 'Backend not found',
|
|
500: 'Backend does not support this operation',
|
|
},
|
|
)
|
|
def delete(self, name, backend=None):
|
|
"""Delete a user"""
|
|
args = self.parser_del.parse_args()
|
|
backend = backend or args['backend']
|
|
|
|
try:
|
|
handler = getattr(bui, 'uhandler')
|
|
except AttributeError:
|
|
handler = None
|
|
|
|
if not handler or len(handler.backends) == 0 or \
|
|
backend not in handler.backends:
|
|
self.abort(404, "No authentication backend found")
|
|
|
|
backend = handler.backends[backend]
|
|
|
|
if backend.del_user is False:
|
|
self.abort(
|
|
500,
|
|
"The '{}' backend does not support user deletion"
|
|
"".format(backend)
|
|
)
|
|
|
|
success, message, code = backend.del_user(
|
|
name
|
|
)
|
|
status = 201 if success else 200
|
|
return [[code, message]], status
|
|
|
|
@api.disabled_on_demo()
|
|
@api.acl_own_or_admin(key='name', message="Not allowed to modify this user")
|
|
@ns.expect(parser_mod)
|
|
@ns.doc(
|
|
responses={
|
|
200: 'Request performed with errors',
|
|
201: 'Success',
|
|
403: 'Not allowed',
|
|
400: 'Missing parameters',
|
|
404: 'Backend not found',
|
|
500: 'Backend does not support this operation',
|
|
},
|
|
)
|
|
def post(self, name, backend=None):
|
|
"""Change user password"""
|
|
args = self.parser_mod.parse_args()
|
|
backend = backend or args['backend']
|
|
is_admin = True
|
|
|
|
if not current_user.is_anonymous:
|
|
is_admin = current_user.acl.is_admin()
|
|
|
|
if not is_admin and not args['old_password']:
|
|
self.abort(400, "Old password required")
|
|
|
|
try:
|
|
handler = getattr(bui, 'uhandler')
|
|
except AttributeError:
|
|
handler = None
|
|
|
|
if not handler or len(handler.backends) == 0 or \
|
|
backend not in handler.backends:
|
|
self.abort(404, "No authentication backend found")
|
|
|
|
backend = handler.backends[backend]
|
|
|
|
if backend.change_password is False:
|
|
self.abort(
|
|
500,
|
|
"The '{}' backend does not support user modification"
|
|
"".format(backend)
|
|
)
|
|
|
|
success, message, code = backend.change_password(
|
|
name,
|
|
args['password'],
|
|
args.get('old_password')
|
|
)
|
|
status = 201 if success else 200
|
|
return [[code, message]], status
|
|
|
|
|
|
@ns.route('/auth/backend/<backend>', endpoint='auth_backend')
|
|
class AuthBackend(Resource):
|
|
"""The :class:`burpui.api.admin.AuthBackend` resource allows you to
|
|
retrieve a given authentication backend and its capabilities.
|
|
|
|
This resource is part of the :mod:`burpui.api.admin` module.
|
|
"""
|
|
|
|
@api.acl_admin_or_moderator_required(message="Not allowed to view backends list")
|
|
@ns.marshal_with(auth_backend_fields, code=200, description='Success')
|
|
@ns.doc(
|
|
responses={
|
|
403: 'Insufficient permissions',
|
|
404: 'No backend found',
|
|
},
|
|
)
|
|
def get(self, backend):
|
|
"""Returns a given authentication backend
|
|
|
|
**GET** method provided by the webservice.
|
|
|
|
:returns: Backend
|
|
"""
|
|
try:
|
|
handler = getattr(bui, 'uhandler')
|
|
except AttributeError:
|
|
handler = None
|
|
|
|
if not handler or len(handler.backends) == 0:
|
|
self.abort(404, "No authentication backend found")
|
|
if backend not in handler.backends:
|
|
self.abort(404, "No authentication backend {} found".format(backend))
|
|
back = handler.backends[backend]
|
|
ret = {
|
|
'name': backend,
|
|
'description': gettext(back.__doc__),
|
|
'type': 'authentication',
|
|
'priority': getattr(back, 'priority', -1),
|
|
'add': getattr(back, 'add_user', False) is not False,
|
|
'del': getattr(back, 'del_user', False) is not False,
|
|
'mod': getattr(back, 'change_password', False) is not False,
|
|
}
|
|
|
|
return ret
|
|
|
|
|
|
@ns.route('/auth/backends', endpoint='auth_backends')
|
|
class AuthBackends(Resource):
|
|
"""The :class:`burpui.api.admin.AuthBackends` resource allows you to
|
|
retrieve a list of backends and to add/update/delete users if your
|
|
authentication backend support those actions.
|
|
|
|
This resource is part of the :mod:`burpui.api.admin` module.
|
|
"""
|
|
|
|
@api.acl_admin_or_moderator_required(message="Not allowed to view backends list")
|
|
@ns.marshal_list_with(auth_backend_fields, code=200, description='Success')
|
|
@ns.doc(
|
|
responses={
|
|
403: 'Insufficient permissions',
|
|
404: 'No backend found',
|
|
},
|
|
)
|
|
def get(self):
|
|
"""Returns a list of backends
|
|
|
|
**GET** method provided by the webservice.
|
|
|
|
:returns: Backends
|
|
"""
|
|
try:
|
|
handler = getattr(bui, 'uhandler')
|
|
except AttributeError:
|
|
handler = None
|
|
|
|
if not handler or len(handler.backends) == 0:
|
|
self.abort(404, "No authentication backend found")
|
|
ret = []
|
|
for name, backend in handler.backends.items():
|
|
ret.append({
|
|
'name': name,
|
|
'description': gettext(backend.__doc__),
|
|
'type': 'authentication',
|
|
'priority': backend.priority,
|
|
'add': backend.add_user is not False,
|
|
'del': backend.del_user is not False,
|
|
'mod': backend.change_password is not False,
|
|
})
|
|
|
|
return ret
|
|
|
|
|
|
@ns.route('/session/<user>',
|
|
'/session/<user>/<uuid:id>',
|
|
endpoint='other_sessions')
|
|
@ns.doc(
|
|
params={
|
|
'user': 'User to get sessions from',
|
|
'id': 'Session id',
|
|
}
|
|
)
|
|
class OtherSessions(Resource):
|
|
"""The :class:`burpui.api.admin.OtherSessions` resource allows you to
|
|
retrieve a list of sessions for a given user.
|
|
|
|
This resource is part of the :mod:`burpui.api.admin` module.
|
|
"""
|
|
|
|
@ns.marshal_list_with(session_fields, code=200, description='Success')
|
|
@ns.doc(
|
|
responses={
|
|
403: 'Insufficient permissions',
|
|
404: 'User not found',
|
|
},
|
|
)
|
|
def get(self, user=None, id=None):
|
|
"""Returns a list of sessions
|
|
|
|
**GET** method provided by the webservice.
|
|
|
|
:returns: Sessions
|
|
"""
|
|
if id:
|
|
return session_manager.get_session_by_id(str(id))
|
|
if not user:
|
|
self.abort(404, 'User not found')
|
|
return session_manager.get_user_sessions(user)
|
|
|
|
|
|
@ns.route('/me/session',
|
|
'/me/session/<uuid:id>',
|
|
endpoint='user_sessions')
|
|
@ns.doc(
|
|
params={
|
|
'id': 'Session id',
|
|
}
|
|
)
|
|
class MySessions(Resource):
|
|
"""The :class:`burpui.api.admin.MySessions` resource allows you to
|
|
retrieve a list of sessions and invalidate them for the current user.
|
|
|
|
This resource is part of the :mod:`burpui.api.admin` module.
|
|
"""
|
|
|
|
@ns.marshal_list_with(session_fields, code=200, description='Success')
|
|
@ns.doc(
|
|
responses={
|
|
403: 'Insufficient permissions',
|
|
404: 'User not found',
|
|
},
|
|
)
|
|
def get(self, id=None):
|
|
"""Returns a list of sessions
|
|
|
|
**GET** method provided by the webservice.
|
|
|
|
:returns: Sessions
|
|
"""
|
|
if id:
|
|
return session_manager.get_session_by_id(str(id))
|
|
user = getattr(current_user, 'name', None)
|
|
if not user:
|
|
self.abort(404, 'User not found')
|
|
return session_manager.get_user_sessions(user)
|
|
|
|
@api.disabled_on_demo()
|
|
@ns.doc(
|
|
responses={
|
|
201: 'Success',
|
|
403: 'Insufficient permissions',
|
|
404: 'User or session not found',
|
|
400: 'Wrong request'
|
|
}
|
|
)
|
|
def delete(self, id=None):
|
|
"""Delete a given session
|
|
|
|
Note: ``id`` is mandatory
|
|
"""
|
|
if not id:
|
|
self.abort(400, 'Missing id')
|
|
user = getattr(current_user, 'name', None)
|
|
if not user:
|
|
self.abort(404, 'User not found')
|
|
store = session_manager.get_session_by_id(str(id))
|
|
if not store:
|
|
self.abort('Session not found')
|
|
if store.user != user:
|
|
if not current_user.is_anonymous and \
|
|
not current_user.acl.is_admin() and \
|
|
not current_user.acl.is_moderator():
|
|
self.abort(403, 'Insufficient permissions')
|
|
if current_user.acl.is_moderator() and \
|
|
meta_grants.is_admin(store.user):
|
|
self.abort(403, 'Insufficient permissions')
|
|
if session_manager.invalidate_session_by_id(store.uuid):
|
|
session_manager.delete_session_by_id(store.uuid)
|
|
return [NOTIF_OK, 'Session {} successfully revoked'.format(id)], 201
|