summaryrefslogtreecommitdiff
path: root/src/routers
diff options
context:
space:
mode:
Diffstat (limited to 'src/routers')
-rw-r--r--src/routers/__init__.py9
-rw-r--r--src/routers/collector.py152
-rw-r--r--src/routers/scanner.py93
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)