main
py 298 lines 9.42 KB
Raw
1 import re
2 from enum import Enum
3 from typing import List
4 from typing import Optional
5
6 from pydantic import BaseModel
7 from pydantic import Field
8 from pydantic import field_validator
9
10 from app.connectors.grafana.schema.dashboards import DashboardProvisionRequest
11 from app.db.universal_models import CustomersMeta
12
13
14 class CustomerSubsctipion(Enum):
15 WAZUH = "Wazuh"
16 # OFFICE365 = "Office365"
17
18
19 class ProvisionNewCustomer(BaseModel):
20 customer_name: str = Field(
21 ...,
22 examples=["SOC Fortress"],
23 description="Name of the customer",
24 )
25 customer_code: str = Field(
26 ...,
27 examples=["SOCF"],
28 description="Code of the customer. Referenced in Wazuh Agent Label, Graylog Stream, etc.",
29 )
30 customer_index_name: str = Field(
31 ...,
32 examples=["socf"],
33 description="Index prefix for the customer's Graylog instance",
34 )
35 customer_grafana_org_name: str = Field(
36 ...,
37 examples=["SOCFortress"],
38 description="Name of the customer's Grafana organization",
39 )
40 hot_data_retention: int = Field(
41 ...,
42 examples=[30],
43 description="Number of days to retain hot data",
44 )
45 index_replicas: int = Field(
46 ...,
47 examples=[1],
48 description="Number of replicas for the customer's Graylog instance",
49 )
50 index_shards: int = Field(
51 ...,
52 examples=[1],
53 description="Number of shards for the customer's Graylog instance",
54 )
55 customer_subscription: List[CustomerSubsctipion] = Field(
56 ...,
57 examples=[["Wazuh"]],
58 description="List of subscriptions for the customer",
59 )
60 dashboards_to_include: DashboardProvisionRequest = Field(
61 ...,
62 description="Dashboards to include in the customer's Grafana instance",
63 examples=[
64 {
65 "dashboards": [
66 "WAZUH_SUMMARY",
67 ],
68 },
69 ],
70 )
71 wazuh_auth_password: Optional[str] = Field("n/a", description="Password for the Wazuh API user")
72 wazuh_registration_port: Optional[str] = Field(
73 "n/a",
74 description="Port for the Wazuh registration service",
75 )
76 wazuh_logs_port: Optional[str] = Field("n/a", description="Port for the Wazuh logs service")
77 wazuh_api_port: Optional[str] = Field("n/a", description="Port for the Wazuh API service")
78 wazuh_cluster_name: Optional[str] = Field("n/a", description="Name of the Wazuh cluster")
79 wazuh_cluster_key: Optional[str] = Field("n/a", description="Password for the Wazuh cluster")
80 wazuh_master_ip: Optional[str] = Field("n/a", description="IP address of the Wazuh master")
81 grafana_url: str = Field(..., description="URL of the Grafana instance")
82 grafana_org_id: Optional[str] = Field("0", description="ID of the Grafana organization")
83 only_insert_into_db: Optional[bool] = Field(
84 False,
85 description="Whether to only insert the customer into the database without provisioning any services",
86 )
87 graylog_index_id: Optional[str] = Field(
88 None,
89 description="ID of the Graylog index set",
90 )
91 graylog_stream_id: Optional[str] = Field(
92 None,
93 description="ID of the Graylog stream",
94 )
95 wazuh_worker_hostname: Optional[str] = Field(
96 None,
97 description="Hostname of the Wazuh worker",
98 )
99 provision_wazuh_worker: bool = Field(
100 False,
101 description="Whether to provision a Wazuh worker for the customer",
102 )
103 provision_ha_proxy: bool = Field(
104 False,
105 description="Whether to provision an HAProxy for the customer",
106 )
107 portainer_deployment: Optional[bool] = Field(
108 None,
109 description="Whether deployment of Portainer is occurring",
110 )
111
112 @field_validator("customer_index_name")
113 @classmethod
114 def validate_customer_index_name(cls, v):
115 pattern = r"^[a-z0-9][a-z0-9_+-]*$"
116 if not re.match(pattern, v):
117 raise ValueError(
118 "customer_index_name must start with a lowercase letter or number and can only contain lowercase letters, numbers, underscores, plus signs, and hyphens.",
119 )
120 return v
121
122
123 class CustomerProvisionMeta(BaseModel):
124 index_set_id: str
125 stream_id: str
126 pipeline_ids: List[str]
127 grafana_organization_id: int
128 wazuh_datasource_uid: str
129 grafana_edr_folder_id: int
130 iris_customer_id: Optional[int] = None
131
132
133 class CustomerProvisionResponse(BaseModel):
134 message: str = Field(
135 ...,
136 description="Message indicating the status of the customer provisioning process",
137 )
138 success: bool = Field(
139 ...,
140 description="Whether the customer provisioning process was successful or not",
141 )
142 customer_meta: CustomersMeta = Field(
143 ...,
144 description="Customer meta data for the newly provisioned customer",
145 )
146 wazuh_worker_provisioned: Optional[bool] = Field(
147 None,
148 description="Whether the Wazuh worker was provisioned successfully",
149 )
150
151
152 class GetDashboardsResponse(BaseModel):
153 available_dashboards: List[str] = Field(
154 ...,
155 description="List of dashboards available for provisioning",
156 )
157 message: str = Field(
158 ...,
159 description="Message indicating the status of the request",
160 )
161 success: bool = Field(..., description="Whether the request was successful or not")
162
163
164 class GetSubscriptionsResponse(BaseModel):
165 available_subscriptions: List[str] = Field(
166 ...,
167 description="List of subscriptions available for provisioning",
168 )
169 message: str = Field(
170 ...,
171 description="Message indicating the status of the request",
172 )
173 success: bool = Field(..., description="Whether the request was successful or not")
174
175
176 class CustomersMetaResponse(BaseModel):
177 message: str = Field(
178 ...,
179 description="Message indicating the status of the request",
180 )
181 success: bool = Field(..., description="Whether the request was successful or not")
182 customer_meta: CustomersMeta = Field(
183 ...,
184 description="Customer meta data for the newly provisioned customer",
185 )
186
187
188 class ProvisionHaProxyRequest(BaseModel):
189 customer_name: str = Field(
190 ...,
191 examples=["SOCFortress"],
192 description="The name of the customer",
193 )
194 wazuh_registration_port: str = Field(
195 ...,
196 examples=["1515"],
197 description="The port for the Wazuh registration service",
198 )
199 wazuh_logs_port: str = Field(
200 ...,
201 examples=["1514"],
202 description="The port for the Wazuh logs service",
203 )
204 wazuh_worker_hostname: Optional[str] = Field(
205 None,
206 examples=["worker1"],
207 description="The hostname of the Wazuh worker",
208 )
209 portainer_deployment: Optional[bool] = Field(
210 None,
211 examples=[True],
212 description="Whether deployment of Portainer is occurring",
213 )
214 swarm_nodes: Optional[List[str]] = Field(
215 None,
216 examples=[["127.0.0.1"]],
217 description="The IP addresses of the swarm nodes",
218 )
219
220
221 class ProvisionDashboardRequest(BaseModel):
222 customer_name: str = Field(
223 ...,
224 examples=["SOCFortress"],
225 description="The name of the customer",
226 )
227 dashboards_to_include: DashboardProvisionRequest = Field(
228 ...,
229 description="Dashboards to include in the customer's Grafana instance",
230 examples=[
231 {
232 "dashboards": [
233 "WAZUH_SUMMARY",
234 "EDR_WINDOWS_EVENT_LOGS",
235 "EDR_WAZUH_INVENOTRY",
236 "EDR_USERS_AND_GROUPS",
237 "EDR_SYSTEM_VULNERABILITIES",
238 "EDR_SYSTEM_SECURITY_AUDIT",
239 "EDR_SYSTEM_PROCESSES",
240 "EDR_PROCESS_INJECTION",
241 "EDR_OPEN_AUDIT",
242 "EDR_NETWORK_SCAN",
243 "EDR_NETWORK_CONNECTIONS",
244 "EDR_MITRE",
245 "EDR_FIM",
246 "EDR_DOCKER_MONITORING",
247 "EDR_DNS_REQUESTS",
248 "EDR_DLL_SIDE_LOADING",
249 "EDR_COMPLIANCE",
250 "EDR_AV_MALWARE_IOC",
251 "EDR_AGENT_INVENTORY",
252 "EDR_AD_INVENOTRY",
253 ],
254 "organizationId": 1,
255 "folderId": 1,
256 "datasourceUid": "wazuh",
257 },
258 ],
259 )
260 grafana_org_id: int = Field(
261 ...,
262 description="ID of the Grafana organization",
263 )
264 grafana_datasource_uid: str = Field(
265 ...,
266 description="UID of the Grafana datasource",
267 )
268 grafana_folder_id: int = Field(
269 ...,
270 description="ID of the Grafana folder",
271 )
272 grafana_url: str = Field(
273 ...,
274 description="URL of the Grafana instance",
275 )
276
277
278 class ProvisionDashboardResponse(BaseModel):
279 message: str = Field(
280 ...,
281 description="Message indicating the status of the request",
282 )
283 success: bool = Field(..., description="Whether the request was successful or not")
284
285
286 class UpdateOffice365OrgIdRequest(BaseModel):
287 office365_org_id: str = Field(
288 ...,
289 description="Office 365 organization ID",
290 )
291
292
293 class UpdateOffice365OrgIdResponse(BaseModel):
294 message: str = Field(
295 ...,
296 description="Message indicating the status of the request",
297 )
298 success: bool = Field(..., description="Whether the request was successful or not")