diff --git a/.gitignore b/.gitignore index b9595c37d..271d4a62c 100644 --- a/.gitignore +++ b/.gitignore @@ -20,6 +20,7 @@ docs/node_modules frontend/node_modules frontend/.pnp frontend/.pnp.js +xfd_backend_venv/ # testing backend/coverage diff --git a/backend/src/xfd_django/xfd_api/api_methods/blocklist.py b/backend/src/xfd_django/xfd_api/api_methods/blocklist.py new file mode 100644 index 000000000..6db299027 --- /dev/null +++ b/backend/src/xfd_django/xfd_api/api_methods/blocklist.py @@ -0,0 +1,22 @@ +"""Blocklist API.""" + +# Third-Party Libraries +from fastapi import HTTPException +from xfd_mini_dl.models import Blocklist + + +async def handle_check_ip(ip_address: str): + """ + Determine if an IP exists in our blocklist table. + + Returns: + { status: "BLOCKED" or "UNBLOCKED" } + """ + ip_obj = None + try: + ip_obj = Blocklist.objects.get(ip=ip_address) + except Exception as e: + raise HTTPException(status_code=500, details=str(e)) + if ip_obj: + return {"status": "BLOCKED"} + return {"status": "UNBLOCKED"} diff --git a/backend/src/xfd_django/xfd_api/schema_models/scan.py b/backend/src/xfd_django/xfd_api/schema_models/scan.py index a65cdacb6..f282bb570 100644 --- a/backend/src/xfd_django/xfd_api/schema_models/scan.py +++ b/backend/src/xfd_django/xfd_api/schema_models/scan.py @@ -309,4 +309,13 @@ class GenericMessageResponseModel(BaseModel): memory="16384", description="Loops through all domains and determines if their associated IP can be found in a report Cidr block.", ), + "updateBlocklist": ScanSchema( + type="fargate", + isPassive=True, + global_scan=True, + numChunks=0, + cpu="1024", + memory="8192", + description="Updates blocked ip records against blocklist.de global IP blocklist", + ), } diff --git a/backend/src/xfd_django/xfd_api/views.py b/backend/src/xfd_django/xfd_api/views.py index 004e95cf7..00537dfbf 100644 --- a/backend/src/xfd_django/xfd_api/views.py +++ b/backend/src/xfd_django/xfd_api/views.py @@ -14,6 +14,7 @@ from .api_methods import auth as auth_methods from .api_methods import notification as notification_methods from .api_methods import organization, proxy, scan, scan_tasks, user +from .api_methods.blocklist import handle_check_ip from .api_methods.cpe import get_cpes_by_id from .api_methods.cve import get_cves_by_id, get_cves_by_name from .api_methods.domain import export_domains, get_domain_by_id, search_domains @@ -1262,3 +1263,20 @@ async def call_update_vulnerability( object: a single vulnerability object that has been modified. """ return update_vulnerability(vulnerability_id, data, current_user) + + +# ======================================== +# Blocklist Endpoints +# ======================================== + + +@api_router.get( + "/blocklist/check", + dependencies=[Depends(get_current_active_user)], + tags=["Blocklist"], +) +async def get_blocklist( + request: Request, ip_address: str = Query(..., description="IP address to check") +): + """Determine if IP is on the blocklist.""" + return await handle_check_ip(ip_address) diff --git a/backend/src/xfd_django/xfd_mini_dl/models.py b/backend/src/xfd_django/xfd_mini_dl/models.py index 0a18b249c..9679e107e 100644 --- a/backend/src/xfd_django/xfd_mini_dl/models.py +++ b/backend/src/xfd_django/xfd_mini_dl/models.py @@ -5640,6 +5640,27 @@ class Meta: unique_together = (("cpe_product_name", "version_number"),) +class Blocklist(models.Model): + """Define Blocklist Model.""" + + id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) + ip = InetAddressField( + null=False, blank=False, unique=True + ) # <-- Removed trailing comma + created_at = models.DateTimeField(auto_now=False) # <-- Removed trailing comma + + class Meta: + """Set Blocklist model metadata.""" + + app_label = app_label_name + managed = manage_db + db_table = "blocklist" + indexes = [ + models.Index(fields=["ip"]), # Reinforces index on 'ip' field + models.Index(fields=["created_at"]), # Speeds up sorting by 'updated_at' + ] + + # # THese are all views, so they shouldn't be generated via the ORM # # This should be a view not a table @@ -6398,5 +6419,6 @@ class Meta: # class Meta: # """Set VwIscoreOrgsIpCounts model metadata.""" + # managed = False # db_table = "vw_iscore_orgs_ip_counts"""" Django ORM models """