Add purge single case route and schema
Taylor committed
Jan 11, 2024 at 10:27 UTC
33360b689163b313f5190006d06501893c7dbdee
3 files changed
+53
-10
backend/app/connectors/dfir_iris/routes/cases.py
+25
-5
@@ -7,7 +7,7 @@ from fastapi import Security
7
from loguru import logger
8
9
from app.auth.utils import AuthHandler
10
-from app.connectors.dfir_iris.schema.cases import CaseOlderThanBody
10
+from app.connectors.dfir_iris.schema.cases import CaseOlderThanBody, PurgeCaseResponse
11
from app.connectors.dfir_iris.schema.cases import CaseResponse
12
from app.connectors.dfir_iris.schema.cases import CasesBreachedResponse
13
from app.connectors.dfir_iris.schema.cases import SingleCaseBody
@@ -17,7 +17,7 @@ from app.connectors.dfir_iris.services.cases import get_all_cases
17
from app.connectors.dfir_iris.services.cases import get_cases_older_than
18
from app.connectors.dfir_iris.services.cases import get_single_case
19
from app.connectors.dfir_iris.utils.universal import check_case_exists
20
-from app.connectors.dfir_iris.services.cases import purge_cases
20
+from app.connectors.dfir_iris.services.cases import purge_cases, delete_single_case
21
22
23
async def verify_case_exists(case_id: int) -> int:
@@ -101,20 +101,40 @@ async def get_cases_older_than_route(case_older_than_body: CaseOlderThanBody = D
101
102
@dfir_iris_cases_router.delete(
103
"/purge",
104
- response_model=CaseResponse,
104
+ response_model=PurgeCaseResponse,
105
description="Purge all cases",
106
dependencies=[Security(AuthHandler().require_any_scope("admin", "analyst"))],
107
)
108
-async def purge_cases_route() -> CaseResponse:
108
+async def purge_cases_route() -> PurgeCaseResponse:
109
"""
110
Purge all cases.
111
112
Returns:
113
- CaseResponse: The response containing all cases.
113
+ PurgeCaseResponse: The response containing the purge status.
114
"""
115
logger.info("Purging all cases")
116
return await purge_cases()
117
118
+@dfir_iris_cases_router.delete(
119
+ "/purge/{case_id}",
120
+ response_model=PurgeCaseResponse,
121
+ description="Purge a single case",
122
+ dependencies=[Security(AuthHandler().require_any_scope("admin", "analyst"))],
123
+)
124
+async def purge_single_case_route(case_id: int = Depends(verify_case_exists)) -> PurgeCaseResponse:
125
+ """
126
+ Purge a single case by its ID.
127
+
128
+ Args:
129
+ case_id (int): The ID of the case to purge.
130
+
131
+ Returns:
132
+ PurgeCaseResponse: The response containing the purge status.
133
+ """
134
+ logger.info(f"Purging case {case_id}")
135
+ single_case_body = SingleCaseBody(case_id=case_id)
136
+ return await delete_single_case(single_case_body.case_id)
137
+
138
139
@dfir_iris_cases_router.get(
140
"/{case_id}",
backend/app/connectors/dfir_iris/schema/cases.py
+4
@@ -34,6 +34,10 @@ class CaseResponse(BaseModel):
34
message: str
35
success: bool
36
37
+class PurgeCaseResponse(BaseModel):
38
+ message: str
39
+ success: bool
40
+
41
42
class ModificationHistoryItem(BaseModel):
43
action: str
backend/app/connectors/dfir_iris/services/cases.py
+24
-5
@@ -6,7 +6,7 @@ from dfir_iris_client.case import Case
6
from fastapi import HTTPException
7
from loguru import logger
8
9
-from app.connectors.dfir_iris.schema.cases import CaseOlderThanBody
9
+from app.connectors.dfir_iris.schema.cases import CaseOlderThanBody, PurgeCaseResponse
10
from app.connectors.dfir_iris.schema.cases import CaseResponse
11
from app.connectors.dfir_iris.schema.cases import CasesBreachedResponse
12
from app.connectors.dfir_iris.schema.cases import SingleCaseBody
@@ -130,12 +130,12 @@ async def get_single_case(case_id: SingleCaseBody) -> SingleCaseResponse:
130
result = await fetch_and_parse_data(dfir_iris_client, case.get_case, case_id)
131
return SingleCaseResponse(success=True, message="Successfully fetched single case", case=result["data"])
132
133
-async def purge_cases() -> CaseResponse:
133
+async def purge_cases() -> PurgeCaseResponse:
134
"""
135
Purges all cases from DFIR-IRIS.
136
137
Returns:
138
- CaseResponse: The response object containing the success status, message, and cases data.
138
+ PurgeCaseResponse: The response containing the purge status.
139
140
Raises:
141
HTTPException: If there is an error purging the cases.
@@ -148,7 +148,7 @@ async def purge_cases() -> CaseResponse:
148
for case_id in case_ids:
149
await purge_case(dfir_iris_client, case, case_id)
150
151
- return CaseResponse(success=True, message="Successfully purged all cases")
151
+ return PurgeCaseResponse(success=True, message="Successfully purged all cases")
152
153
154
async def get_case_ids_to_purge() -> List[int]:
@@ -178,7 +178,7 @@ def handle_cases_retrieval_failure(result: Dict) -> None:
178
raise HTTPException(status_code=500, detail=error_message)
179
180
181
-async def purge_case(client, case, case_id) -> None:
181
+async def purge_case(client, case, case_id) -> PurgeCaseResponse:
182
"""
183
Purges a single case.
184
@@ -190,8 +190,27 @@ async def purge_case(client, case, case_id) -> None:
190
try:
191
logger.info(f"Purging case: {case_id}")
192
await fetch_and_parse_data(client, case.delete_case, case_id)
193
+ return PurgeCaseResponse(success=True, message=f"Successfully purged case {case_id}")
194
except Exception as err:
195
error_message = f"Failed to purge case {case_id}: {err}"
196
logger.error(error_message)
197
raise HTTPException(status_code=500, detail=error_message)
198
199
+async def delete_single_case(case_id: SingleCaseBody) -> PurgeCaseResponse:
200
+ """
201
+ Deletes a single case from DFIR-IRIS based on the provided case ID.
202
+
203
+ Args:
204
+ case_id (SingleCaseBody): The ID of the case to delete.
205
+
206
+ Returns:
207
+ SingleCaseResponse: The response containing the deleted case.
208
+
209
+ Raises:
210
+ Any exceptions raised during the execution of the function will be propagated.
211
+ """
212
+ dfir_iris_client = await create_dfir_iris_client("DFIR-IRIS")
213
+ case = Case(session=dfir_iris_client)
214
+ result = await fetch_and_parse_data(dfir_iris_client, case.delete_case, case_id)
215
+ return PurgeCaseResponse(success=True, message="Successfully deleted single case")
216
+