| 17 | |
| 18 | |
| 19 | class RestApi(BaseWorld): |
| 20 | |
| 21 | def __init__(self, services): |
| 22 | self.log = logging.getLogger('rest_api') |
| 23 | self.data_svc = services.get('data_svc') |
| 24 | self.app_svc = services.get('app_svc') |
| 25 | self.auth_svc = services.get('auth_svc') |
| 26 | self.file_svc = services.get('file_svc') |
| 27 | self.rest_svc = services.get('rest_svc') |
| 28 | asyncio.get_event_loop().create_task(CampaignPack(services).enable()) |
| 29 | asyncio.get_event_loop().create_task(AdvancedPack(services).enable()) |
| 30 | |
| 31 | async def enable(self): |
| 32 | self.app_svc.application.router.add_static('/assets', 'plugins/magma/dist/assets/', append_version=True) |
| 33 | # TODO: only serve static files in legacy plugin mode |
| 34 | self.app_svc.application.router.add_static('/gui', 'static/', append_version=True) |
| 35 | # unauthorized GUI endpoints |
| 36 | self.app_svc.application.router.add_route('GET', '/', self.landing) |
| 37 | self.app_svc.application.router.add_route('POST', '/enter', self.validate_login) |
| 38 | self.app_svc.application.router.add_route('POST', '/logout', self.logout) |
| 39 | # unauthorized API endpoints |
| 40 | self.app_svc.application.router.add_route('*', '/file/download', self.download_file) |
| 41 | self.app_svc.application.router.add_route('POST', '/file/upload', self.upload_file) |
| 42 | # authorized API endpoints |
| 43 | self.app_svc.application.router.add_route('*', '/api/rest', self.rest_core) |
| 44 | self.app_svc.application.router.add_route('GET', '/api/{index}', self.rest_core_info) |
| 45 | self.app_svc.application.router.add_route('GET', '/file/download_exfil', self.download_exfil_file) |
| 46 | self.app_svc.application.router.add_route('GET', '/{tail:(?!plugin/|api/v2/).*}', self.handle_catch) |
| 47 | |
| 48 | async def validate_login(self, request): |
| 49 | return await self.auth_svc.login_user(request) |
| 50 | |
| 51 | async def logout(self, request): |
| 52 | await self.auth_svc.logout_user(request) |
| 53 | |
| 54 | async def landing(self, request): |
| 55 | return render_template("index.html", request, {}) |
| 56 | |
| 57 | async def handle_catch(self, request): |
| 58 | return render_template("index.html", request, {}) |
| 59 | |
| 60 | @check_authorization |
| 61 | async def rest_core(self, request): |
| 62 | try: |
| 63 | access = dict(access=tuple(await self.auth_svc.get_permissions(request))) |
| 64 | data = dict(await request.json()) |
| 65 | index = data.pop('index') |
| 66 | options = dict( |
| 67 | DELETE=dict( |
| 68 | agents=lambda d: self.rest_svc.delete_agent(d), |
| 69 | operations=lambda d: self.rest_svc.delete_operation(d), |
| 70 | abilities=lambda d: self.rest_svc.delete_ability(d), |
| 71 | adversaries=lambda d: self.rest_svc.delete_adversary(d) |
| 72 | ), |
| 73 | PUT=dict( |
| 74 | adversaries=lambda d: self.rest_svc.persist_adversary(access, d), |
| 75 | abilities=lambda d: self.rest_svc.persist_ability(access, d), |
| 76 | sources=lambda d: self.rest_svc.persist_source(access, d), |
no outgoing calls