diff options
Diffstat (limited to 'src/routers')
-rw-r--r-- | src/routers/__init__.py | 9 | ||||
-rw-r--r-- | src/routers/collector.py | 152 | ||||
-rw-r--r-- | src/routers/scanner.py | 93 |
3 files changed, 254 insertions, 0 deletions
diff --git a/src/routers/__init__.py b/src/routers/__init__.py new file mode 100644 index 0000000..300ed3a --- /dev/null +++ b/src/routers/__init__.py @@ -0,0 +1,9 @@ +from fastapi import APIRouter + +from .collector import router as collector_router +from .scanner import router as scanner_router + +router = APIRouter() + +router.include_router(collector_router, tags=['collector']) +router.include_router(scanner_router, tags=['scanner']) diff --git a/src/routers/collector.py b/src/routers/collector.py new file mode 100644 index 0000000..7d91609 --- /dev/null +++ b/src/routers/collector.py @@ -0,0 +1,152 @@ +import sys +import time + +import requests +from db.db import DictDB +from db.index import CouchIindex +from fastapi import APIRouter, Depends, Request +from fastapi.responses import JSONResponse +from fastapi_jwt_auth import AuthJWT + +router = APIRouter() + +for i in range(10): + try: + db = DictDB() + except requests.exceptions.ConnectionError: + print('Database not responding, will try again soon.' + + f'Attempt {i + 1} of 10.') + else: + break + time.sleep(10) +else: + print('Database did not respond after 10 attempts, quitting.') + sys.exit(-1) + + +def get_data(key=None, limit=25, skip=0, ip=None, + port=None, asn=None, domain=None): + if key: + return db.get(key) + + selectors = dict() + indexes = CouchIindex().dict() + selectors['domain'] = domain + + if ip and 'ip' in indexes: + selectors['ip'] = ip + if port and 'port' in indexes: + selectors['port'] = port + if asn and 'asn' in indexes: + selectors['asn'] = asn + + data = db.search(**selectors, limit=limit, skip=skip) + + return data + + +@router.get('/get') +async def get(key=None, limit=25, skip=0, ip=None, port=None, + asn=None, Authorize: AuthJWT = Depends()): + + Authorize.jwt_required() + + data = [] + raw_jwt = Authorize.get_raw_jwt() + + if "read" not in raw_jwt: + return JSONResponse( + content={ + "status": "error", + "message": "Could not find read claim in JWT token", + }, + status_code=400, + ) + else: + domains = raw_jwt["read"] + + for domain in domains: + data.extend(get_data(key, limit, skip, ip, port, asn, domain)) + + return JSONResponse(content={"status": "success", "docs": data}) + + +@router.get('/get/{key}') +async def get_key(key=None, Authorize: AuthJWT = Depends()): + + Authorize.jwt_required() + + raw_jwt = Authorize.get_raw_jwt() + + if "read" not in raw_jwt: + return JSONResponse( + content={ + "status": "error", + "message": "Could not find read claim in JWT token", + }, + status_code=400, + ) + else: + allowed_domains = raw_jwt["read"] + + data = get_data(key) + + if data["domain"] not in allowed_domains: + return JSONResponse( + content={ + "status": "error", + "message": "User not authorized to view this object", + }, + status_code=400, + ) + + return JSONResponse(content={"status": "success", "docs": data}) + + +@router.post('/add') +async def add(data: Request, Authorize: AuthJWT = Depends()): + + Authorize.jwt_required() + + json_data = await data.json() + + key = db.add(json_data) + + return JSONResponse(content={"status": "success", "docs": key}) + + +@router.delete('/delete/{key}') +async def delete(key, Authorize: AuthJWT = Depends()): + + Authorize.jwt_required() + + raw_jwt = Authorize.get_raw_jwt() + + if "write" not in raw_jwt: + return JSONResponse( + content={ + "status": "error", + "message": "Could not find write claim in JWT token", + }, + status_code=400, + ) + else: + allowed_domains = raw_jwt["write"] + + data = get_data(key) + + if data["domain"] not in allowed_domains: + return JSONResponse( + content={ + "status": "error", + "message": "User not authorized to delete this object", + }, + status_code=400, + ) + + if db.delete(key) is None: + return JSONResponse(content={"status": "error", + "message": "Document not found"}, + status_code=400) + + return JSONResponse(content={"status": "success", "docs": data}) diff --git a/src/routers/scanner.py b/src/routers/scanner.py new file mode 100644 index 0000000..645cd74 --- /dev/null +++ b/src/routers/scanner.py @@ -0,0 +1,93 @@ +from uuid import UUID + +from db.scanner import Scanner +from fastapi import APIRouter, Depends, Request +from fastapi.responses import JSONResponse +from fastapi_jwt_auth import AuthJWT + +router = APIRouter() + + +@router.post('/scanner/{uuid}') +async def scanner(uuid, data: Request, Authorize: AuthJWT = Depends()): + Authorize.jwt_required() + + json_data = await data.json() + + if not Scanner.get(uuid=uuid): + return JSONResponse(content={"status": "error", + "message": "Scanner don't exist."}, + status_code=400) + + if 'targets' in json_data: + if isinstance(json_data['targets'], str): + Scanner.comment(uuid, json_data['targets']) + else: + return JSONResponse(content={"status": "error", + "message": "Targets should be a string."}, + status_code=400) + if 'scanner' in json_data: + if isinstance(json_data['comment'], str): + Scanner.comment(uuid, json_data['scanner']) + else: + return JSONResponse(content={"status": "error", + "message": "Scanner should be a string."}, + status_code=400) + if 'comment' in json_data: + if isinstance(json_data['comment'], str): + Scanner.comment(uuid, json_data['comment']) + else: + return JSONResponse(content={"status": "error", + "message": "Comment should be a string."}, + status_code=400) + if 'enabled' in json_data: + if isinstance(json_data['enabled'], bool): + if json_data['enabled'] is True: + Scanner.enable(uuid) + elif json_data['enabled'] is False: + Scanner.disable(uuid) + else: + return JSONResponse(content={"status": "error", + "message": "Enabled should be boolean."}, + status_code=400) + + +@router.get('/callhome/{uuid}') +async def callhome(uuid, data: Request, Authorize: AuthJWT = Depends()): + Authorize.jwt_required() + + raw_jwt = Authorize.get_raw_jwt() + + if 'user' not in raw_jwt or raw_jwt['user'] != "scanner": + return JSONResponse(content={"status": "error", + "message": "Invalid token type."}, + status_code=400) + + try: + UUID(uuid).version + except ValueError: + return JSONResponse(content={"status": "error", + "message": "Invalid UUID."}, + status_code=400) + + scanner_data = Scanner.get(uuid=uuid) + + if scanner_data: + if not Scanner.is_enabled(uuid): + return JSONResponse(content={"status": "error", + "message": "Scanner disabled."}, + status_code=400) + else: + return JSONResponse(content={"status": "success", + "data": scanner_data}, + status_code=200) + + else: + if Scanner.add(uuid): + return JSONResponse(content={"status": "error", + "message": "Scanner added but disabled."}, + status_code=400) + else: + return JSONResponse(content={"status": "error", + "message": "Failed to add scanner."}, + status_code=400) |