main
py 246 lines 9.77 KB
Raw
1 from fastapi import APIRouter
2 from fastapi import Depends
3 from fastapi import HTTPException
4 from fastapi import Query
5 from fastapi import Security
6 from loguru import logger
7 from sqlalchemy.ext.asyncio import AsyncSession
8 from sqlalchemy.future import select
9
10 from app.auth.utils import AuthHandler
11 from app.db.db_session import get_db
12 from app.db.universal_models import Agents
13 from app.healthchecks.agents.schema.agents import AgentHealthCheckResponse
14 from app.healthchecks.agents.schema.agents import HostLogsSearchBody
15 from app.healthchecks.agents.schema.agents import HostLogsSearchResponse
16 from app.healthchecks.agents.schema.agents import TimeCriteriaModel
17 from app.healthchecks.agents.services.agents import host_logs
18 from app.healthchecks.agents.services.agents import velociraptor_agent_healthcheck
19 from app.healthchecks.agents.services.agents import velociraptor_agents_healthcheck
20 from app.healthchecks.agents.services.agents import wazuh_agent_healthcheck
21 from app.healthchecks.agents.services.agents import wazuh_agents_healthcheck
22
23 healtcheck_agents_router = APIRouter()
24
25
26 @healtcheck_agents_router.get(
27 "/wazuh",
28 response_model=AgentHealthCheckResponse,
29 description="Get Wazuh agents healthcheck",
30 dependencies=[Security(AuthHandler().require_any_scope("admin", "analyst"))],
31 )
32 async def get_wazuh_agent_healthcheck(
33 session: AsyncSession = Depends(get_db),
34 minutes: int = Query(
35 60,
36 description="Number of minutes within which the agent should have been last seen to be considered healthy.",
37 ),
38 hours: int = Query(
39 0,
40 description="Number of hours within which the agent should have been last seen to be considered healthy.",
41 ),
42 days: int = Query(
43 0,
44 description="Number of days within which the agent should have been last seen to be considered healthy.",
45 ),
46 ) -> AgentHealthCheckResponse:
47 """
48 Get the healthcheck of Wazuh agents based on the specified time criteria.
49
50 Args:
51 session (AsyncSession): The asynchronous database session.
52 minutes (int): Number of minutes within which the agent should have been last seen to be considered healthy. Default is 60.
53 hours (int): Number of hours within which the agent should have been last seen to be considered healthy. Default is 0.
54 days (int): Number of days within which the agent should have been last seen to be considered healthy. Default is 0.
55
56 Returns:
57 AgentHealthCheckResponse: The response containing the healthcheck information of Wazuh agents.
58 """
59 time_criteria = TimeCriteriaModel(minutes=minutes, hours=hours, days=days)
60
61 # Asynchronously fetch all agents
62 result = await session.execute(select(Agents))
63 agents = result.scalars().all()
64 return await wazuh_agents_healthcheck(agents, time_criteria)
65
66
67 @healtcheck_agents_router.get(
68 "/wazuh/{agent_id}",
69 response_model=AgentHealthCheckResponse,
70 description="Get Wazuh agent healthcheck by agent_id",
71 dependencies=[Security(AuthHandler().require_any_scope("admin", "analyst"))],
72 )
73 async def get_wazuh_agent_healthcheck_by_agent_id(
74 agent_id: str,
75 session: AsyncSession = Depends(get_db),
76 minutes: int = Query(
77 60,
78 description="Number of minutes within which the agent should have been last seen to be considered healthy.",
79 ),
80 hours: int = Query(
81 0,
82 description="Number of hours within which the agent should have been last seen to be considered healthy.",
83 ),
84 days: int = Query(
85 0,
86 description="Number of days within which the agent should have been last seen to be considered healthy.",
87 ),
88 ) -> AgentHealthCheckResponse:
89 """
90 Get the healthcheck of a Wazuh agent by agent_id.
91
92 Args:
93 agent_id (str): The ID of the agent.
94 session (AsyncSession, optional): The database session. Defaults to Depends(get_db).
95 minutes (int, optional): Number of minutes within which the agent should have been last seen to be considered healthy. Defaults to 60.
96 hours (int, optional): Number of hours within which the agent should have been last seen to be considered healthy. Defaults to 0.
97 days (int, optional): Number of days within which the agent should have been last seen to be considered healthy. Defaults to 0.
98
99 Returns:
100 AgentHealthCheckResponse: The healthcheck response for the agent.
101
102 Raises:
103 HTTPException: If the agent with the specified agent_id is not found.
104 """
105 time_criteria = TimeCriteriaModel(minutes=minutes, hours=hours, days=days)
106
107 # Asynchronously fetch the agent by id
108 result = await session.execute(select(Agents).filter(Agents.agent_id == agent_id))
109 agent = result.scalars().first()
110
111 if not agent:
112 raise HTTPException(
113 status_code=404,
114 detail=f"Agent with agent_id {agent_id} not found",
115 )
116 return await wazuh_agent_healthcheck(agent, time_criteria)
117
118
119 @healtcheck_agents_router.get(
120 "/velociraptor",
121 response_model=AgentHealthCheckResponse,
122 description="Get Velociraptor agents healthcheck",
123 dependencies=[Security(AuthHandler().require_any_scope("admin", "analyst"))],
124 )
125 async def get_velociraptor_agent_healthcheck(
126 session: AsyncSession = Depends(get_db),
127 minutes: int = Query(
128 60,
129 description="Number of minutes within which the agent should have been last seen to be considered healthy.",
130 ),
131 hours: int = Query(
132 0,
133 description="Number of hours within which the agent should have been last seen to be considered healthy.",
134 ),
135 days: int = Query(
136 0,
137 description="Number of days within which the agent should have been last seen to be considered healthy.",
138 ),
139 ) -> AgentHealthCheckResponse:
140 """
141 Get Velociraptor agents healthcheck.
142
143 Args:
144 session (AsyncSession): The async session object.
145 minutes (int): Number of minutes within which the agent should have been last seen to be considered healthy. Default is 60.
146 hours (int): Number of hours within which the agent should have been last seen to be considered healthy. Default is 0.
147 days (int): Number of days within which the agent should have been last seen to be considered healthy. Default is 0.
148
149 Returns:
150 AgentHealthCheckResponse: The response model containing the healthcheck results.
151 """
152 time_criteria = TimeCriteriaModel(minutes=minutes, hours=hours, days=days)
153
154 # Asynchronously fetch all agents
155 result = await session.execute(select(Agents))
156 agents = result.scalars().all()
157 return await velociraptor_agents_healthcheck(agents, time_criteria)
158
159
160 @healtcheck_agents_router.get(
161 "/velociraptor/{agent_id}",
162 response_model=AgentHealthCheckResponse,
163 description="Get Velociraptor agent healthcheck by agent_id",
164 dependencies=[Security(AuthHandler().require_any_scope("admin", "analyst"))],
165 )
166 async def get_velociraptor_agent_healthcheck_by_agent_id(
167 agent_id: str,
168 session: AsyncSession = Depends(get_db),
169 minutes: int = Query(
170 60,
171 description="Number of minutes within which the agent should have been last seen to be considered healthy.",
172 ),
173 hours: int = Query(
174 0,
175 description="Number of hours within which the agent should have been last seen to be considered healthy.",
176 ),
177 days: int = Query(
178 0,
179 description="Number of days within which the agent should have been last seen to be considered healthy.",
180 ),
181 ) -> AgentHealthCheckResponse:
182 """
183 Get Velociraptor agent healthcheck by agent_id.
184
185 Args:
186 agent_id (str): The ID of the agent.
187 session (AsyncSession, optional): The database session. Defaults to Depends(get_db).
188 minutes (int, optional): Number of minutes within which the agent should have been last seen to be considered healthy. Defaults to 60.
189 hours (int, optional): Number of hours within which the agent should have been last seen to be considered healthy. Defaults to 0.
190 days (int, optional): Number of days within which the agent should have been last seen to be considered healthy. Defaults to 0.
191
192 Returns:
193 AgentHealthCheckResponse: The agent health check response.
194 """
195 time_criteria = TimeCriteriaModel(minutes=minutes, hours=hours, days=days)
196
197 # Asynchronously fetch the agent by id
198 result = await session.execute(select(Agents).filter(Agents.agent_id == agent_id))
199 agent = result.scalars().first()
200 if not agent:
201 raise HTTPException(
202 status_code=404,
203 detail=f"Agent with agent_id {agent_id} not found",
204 )
205 return await velociraptor_agent_healthcheck(agent, time_criteria)
206
207
208 @healtcheck_agents_router.post(
209 "/logs",
210 response_model=HostLogsSearchResponse,
211 description="Get host logs",
212 dependencies=[
213 Security(AuthHandler().get_current_user, scopes=["admin", "analyst"]),
214 ],
215 )
216 async def get_host_logs(
217 body: HostLogsSearchBody,
218 session: AsyncSession = Depends(get_db),
219 ) -> HostLogsSearchResponse:
220 """
221 Get host logs for a specific agent.
222
223 Args:
224 body (HostLogsSearchBody): The search criteria for host logs.
225 session (AsyncSession, optional): The database session. Defaults to Depends(get_db).
226
227 Returns:
228 HostLogsSearchResponse: The response containing the host logs.
229
230 Raises:
231 HTTPException: If the agent with the specified hostname is not found.
232 """
233 logger.info(f"Received request to get host logs for {body.agent_name}")
234
235 # Asynchronously verify the agent exists
236 result = await session.execute(
237 select(Agents).filter(Agents.hostname == body.agent_name),
238 )
239 agent = result.scalars().first()
240
241 if not agent:
242 raise HTTPException(
243 status_code=404,
244 detail=f"Agent with hostname {body.agent_name} not found",
245 )
246 return await host_logs(body)