main
py 179 lines 6.09 KB
Raw
1 from fastapi import APIRouter
2 from fastapi import Depends
3 from fastapi import HTTPException
4 from fastapi import Security
5 from loguru import logger
6 from sqlalchemy.ext.asyncio import AsyncSession
7 from sqlalchemy.future import select
8
9 from app.auth.utils import AuthHandler
10 from app.connectors.velociraptor.schema.artifacts import CollectArtifactResponse
11 from app.connectors.velociraptor.schema.flows import FlowResponse
12 from app.connectors.velociraptor.schema.flows import RetrieveFlowRequest
13 from app.connectors.velociraptor.services.flows import get_flow
14 from app.connectors.velociraptor.services.flows import get_flows
15 from app.db.db_session import get_db
16 from app.db.universal_models import Agents
17
18 velociraptor_flows_router = APIRouter()
19
20
21 async def get_velociraptor_id(session: AsyncSession, hostname: str) -> str:
22 """
23 Retrieves the velociraptor_id associated with the given hostname.
24
25 Args:
26 session (AsyncSession): The database session.
27 hostname (str): The hostname of the agent.
28
29 Returns:
30 str: The velociraptor_id associated with the hostname.
31
32 Raises:
33 HTTPException: If the agent with the given hostname is not found or if the velociraptor_id is not available.
34 """
35 logger.info(f"Getting velociraptor_id from hostname {hostname}")
36 # log all the agents
37 agents = await session.execute(select(Agents))
38 for agent in agents.scalars().all():
39 logger.info(f"agent: {agent}")
40 result = await session.execute(select(Agents).filter(Agents.hostname == hostname))
41 agent = result.scalars().first()
42
43 if not agent:
44 raise HTTPException(
45 status_code=404,
46 detail=f"Agent with hostname {hostname} not found",
47 )
48
49 if agent.velociraptor_id == "n/a":
50 raise HTTPException(
51 status_code=404,
52 detail=f"Velociraptor ID for hostname {hostname} is not available",
53 )
54
55 logger.info(f"velociraptor_id for hostname {hostname} is {agent.velociraptor_id}")
56 return agent.velociraptor_id
57
58
59 async def get_velociraptor_org(session: AsyncSession, hostname: str) -> str:
60 """
61 Retrieves the velociraptor_org associated with the given hostname.
62
63 Args:
64 session (AsyncSession): The database session.
65 hostname (str): The hostname of the agent.
66
67 Returns:
68 str: The velociraptor_org associated with the hostname.
69
70 Raises:
71 HTTPException: If the agent with the given hostname is not found or if the velociraptor_org is not available.
72 """
73 logger.info(f"Getting velociraptor_org from hostname {hostname}")
74 result = await session.execute(select(Agents).filter(Agents.hostname == hostname))
75 agent = result.scalars().first()
76
77 if not agent:
78 raise HTTPException(
79 status_code=404,
80 detail=f"Agent with hostname: {hostname} not found",
81 )
82
83 if agent.velociraptor_org is None:
84 raise HTTPException(
85 status_code=404,
86 detail=f"Velociraptor ORG for hostname {hostname} is not available",
87 )
88
89 logger.info(f"velociraptor_org for hostname {hostname} is {agent.velociraptor_org}")
90 return agent.velociraptor_org
91
92
93 async def get_velociraptor_org_via_client_id(session: AsyncSession, client_id: str) -> str:
94 """
95 Retrieves the velociraptor_org associated with the given hostname.
96
97 Args:
98 session (AsyncSession): The database session.
99 hostname (str): The hostname of the agent.
100
101 Returns:
102 str: The velociraptor_org associated with the hostname.
103
104 Raises:
105 HTTPException: If the agent with the given hostname is not found or if the velociraptor_org is not available.
106 """
107 logger.info(f"Getting velociraptor_org from client id {client_id}")
108 result = await session.execute(select(Agents).filter(Agents.velociraptor_id == client_id))
109 agent = result.scalars().first()
110
111 if not agent:
112 raise HTTPException(
113 status_code=404,
114 detail=f"Agent with client id {client_id} not found",
115 )
116
117 if agent.velociraptor_org is None:
118 raise HTTPException(
119 status_code=404,
120 detail=f"Velociraptor ORG for hostname {client_id} is not available",
121 )
122
123 logger.info(f"velociraptor_org for hostname {client_id} is {agent.velociraptor_org}")
124 return agent.velociraptor_org
125
126
127 @velociraptor_flows_router.get(
128 "/{hostname}",
129 response_model=FlowResponse,
130 description="Get all artifacts for a specific host's OS prefix",
131 dependencies=[Security(AuthHandler().require_any_scope("admin", "analyst"))],
132 )
133 async def get_all_flows_for_hostname(
134 hostname: str,
135 session: AsyncSession = Depends(get_db),
136 ) -> FlowResponse:
137 """
138 Retrieve ran flows for a specific host.
139
140 Args:
141 hostname (str): The hostname of the host.
142 session (AsyncSession, optional): The database session. Defaults to Depends(get_db).
143
144 Returns:
145 FlowResponse: The response containing the retrieved flows.
146 """
147 logger.info(f"Fetching all flows for hostname {hostname}")
148
149 velociraptor_id = await get_velociraptor_id(session, hostname)
150 velociraptor_org = await get_velociraptor_org(
151 session,
152 hostname,
153 )
154 logger.info(f"velociraptor_id for hostname {hostname} is {velociraptor_id}")
155 return await get_flows(velociraptor_id, velociraptor_org)
156
157
158 @velociraptor_flows_router.post(
159 "/retrieve",
160 response_model=CollectArtifactResponse,
161 description="Retrieve a flow based on the flow_id",
162 dependencies=[Security(AuthHandler().require_any_scope("admin", "analyst"))],
163 )
164 async def retrieve_flow(
165 retrieve_flow_request: RetrieveFlowRequest,
166 session: AsyncSession = Depends(get_db),
167 ) -> CollectArtifactResponse:
168 """
169 Retrieve ran flows for a specific host.
170
171 Args:
172 retrieve_flow_request (RetrieveFlowRequest): The request containing the flow_id.
173
174
175 Returns:
176 CollectArtifactResponse: The response containing the retrieved flows.
177 """
178 logger.info(f"Fetching flow for flow_id {retrieve_flow_request.session_id}")
179 return await get_flow(retrieve_flow_request, await get_velociraptor_org_via_client_id(session, retrieve_flow_request.client_id))