main
ts 247 lines 6.64 KB
Raw
1 import type {
2 BulkProvisionGraylogAlertRequest,
3 BulkProvisionGraylogAlertResponse,
4 ExecuteGraylogQueryRequest,
5 ExecuteSearchRequest,
6 ExecuteSearchResponse,
7 GraylogProvisioningStatusResponse,
8 GraylogQueryResponse,
9 MitreCoverageQuery,
10 MitreCoverageResponse,
11 PlatformFilter,
12 ProvisionGraylogAlertRequest,
13 ProvisionGraylogAlertResponse,
14 RefreshResponse,
15 RuleDetailResponse,
16 RuleListQuery,
17 RuleListResponse,
18 RulesByIdsRequest,
19 RulesByIdsResponse,
20 RuleStatsResponse
21 } from "@/types/copilotSearches.d"
22 import type { FlaskBaseResponse } from "@/types/flask.d"
23 import { HttpClient } from "../httpClient"
24
25 export default {
26 /**
27 * List all detection rules with optional filtering
28 */
29 getRules(query?: RuleListQuery, signal?: AbortSignal) {
30 return HttpClient.get<FlaskBaseResponse & RuleListResponse>(`/copilot_searches`, {
31 params: {
32 platform: query?.platform,
33 status: query?.status,
34 severity: query?.severity,
35 mitre_id: query?.mitre_id,
36 search: query?.search,
37 has_graylog: query?.has_graylog,
38 skip: query?.skip || 0,
39 limit: query?.limit || 100
40 },
41 signal
42 })
43 },
44
45 /**
46 * List all Linux detection rules
47 */
48 getLinuxRules(query?: Omit<RuleListQuery, "platform">, signal?: AbortSignal) {
49 return HttpClient.get<FlaskBaseResponse & RuleListResponse>(`/copilot_searches/linux`, {
50 params: {
51 status: query?.status,
52 severity: query?.severity,
53 mitre_id: query?.mitre_id,
54 search: query?.search,
55 has_graylog: query?.has_graylog,
56 skip: query?.skip || 0,
57 limit: query?.limit || 100
58 },
59 signal
60 })
61 },
62
63 /**
64 * List all Windows detection rules
65 */
66 getWindowsRules(query?: Omit<RuleListQuery, "platform">, signal?: AbortSignal) {
67 return HttpClient.get<FlaskBaseResponse & RuleListResponse>(`/copilot_searches/windows`, {
68 params: {
69 status: query?.status,
70 severity: query?.severity,
71 mitre_id: query?.mitre_id,
72 search: query?.search,
73 has_graylog: query?.has_graylog,
74 skip: query?.skip || 0,
75 limit: query?.limit || 100
76 },
77 signal
78 })
79 },
80
81 /**
82 * List all PowerShell detection rules
83 */
84 getPowershellRules(query?: Omit<RuleListQuery, "platform">, signal?: AbortSignal) {
85 return HttpClient.get<FlaskBaseResponse & RuleListResponse>(`/copilot_searches/powershell`, {
86 params: {
87 status: query?.status,
88 severity: query?.severity,
89 mitre_id: query?.mitre_id,
90 search: query?.search,
91 has_graylog: query?.has_graylog,
92 skip: query?.skip || 0,
93 limit: query?.limit || 100
94 },
95 signal
96 })
97 },
98
99 /**
100 * List all detection rules that have CVE tags
101 */
102 getCveRules(query?: Omit<RuleListQuery, "platform">, signal?: AbortSignal) {
103 return HttpClient.get<FlaskBaseResponse & RuleListResponse>(`/copilot_searches/cve`, {
104 params: {
105 status: query?.status,
106 severity: query?.severity,
107 mitre_id: query?.mitre_id,
108 search: query?.search,
109 has_graylog: query?.has_graylog,
110 skip: query?.skip || 0,
111 limit: query?.limit || 100
112 },
113 signal
114 })
115 },
116
117 /**
118 * Get statistics about loaded detection rules
119 */
120 getStats(signal?: AbortSignal) {
121 return HttpClient.get<FlaskBaseResponse & RuleStatsResponse>(`/copilot_searches/stats`, {
122 signal
123 })
124 },
125
126 /**
127 * Get full details of a specific rule by its ID
128 */
129 getRuleById(ruleId: string, signal?: AbortSignal) {
130 return HttpClient.get<FlaskBaseResponse & RuleDetailResponse>(`/copilot_searches/id/${ruleId}`, {
131 signal
132 })
133 },
134
135 /**
136 * Get full details of a specific rule by its name
137 */
138 getRuleByName(ruleName: string, signal?: AbortSignal) {
139 return HttpClient.get<FlaskBaseResponse & RuleDetailResponse>(
140 `/copilot_searches/name/${encodeURIComponent(ruleName)}`,
141 {
142 signal
143 }
144 )
145 },
146
147 /**
148 * Get all rules that detect a specific MITRE ATT&CK technique
149 */
150 getRulesByMitre(techniqueId: string, platform?: PlatformFilter, signal?: AbortSignal) {
151 return HttpClient.get<FlaskBaseResponse & RuleListResponse>(`/copilot_searches/mitre/${techniqueId}`, {
152 params: {
153 platform
154 },
155 signal
156 })
157 },
158
159 /**
160 * Manually refresh the rules cache from GitHub
161 */
162 refreshCache() {
163 return HttpClient.post<FlaskBaseResponse & RefreshResponse>(`/copilot_searches/refresh`)
164 },
165
166 /**
167 * Execute a detection rule search against the Wazuh indexer
168 */
169 executeSearch(request: ExecuteSearchRequest) {
170 return HttpClient.post<FlaskBaseResponse & ExecuteSearchResponse>(`/copilot_searches/execute`, request)
171 },
172
173 /**
174 * Generate a Graylog query from a rule with parameter substitution
175 */
176 generateGraylogQuery(request: ExecuteGraylogQueryRequest) {
177 return HttpClient.post<FlaskBaseResponse & GraylogQueryResponse>(`/copilot_searches/graylog`, request)
178 },
179
180 /**
181 * Provision a Graylog event definition from a CoPilot Search rule
182 */
183 provisionGraylogAlert(request: ProvisionGraylogAlertRequest) {
184 return HttpClient.post<FlaskBaseResponse & ProvisionGraylogAlertResponse>(
185 `/copilot_searches/provision/graylog`,
186 request
187 )
188 },
189
190 /**
191 * Provision multiple CoPilot Search rules as Graylog event definitions in a single call.
192 * Per-rule failures are reported in `results` rather than aborting the batch.
193 */
194 bulkProvisionGraylogAlerts(request: BulkProvisionGraylogAlertRequest) {
195 return HttpClient.post<FlaskBaseResponse & BulkProvisionGraylogAlertResponse>(
196 `/copilot_searches/provision/graylog/bulk`,
197 request
198 )
199 },
200
201 /**
202 * For each rule ID, check whether a matching Graylog event definition already exists.
203 * Used to mark rules as "in Graylog" without forcing a re-provision.
204 */
205 checkGraylogProvisioningStatus(ids: string[]) {
206 return HttpClient.post<FlaskBaseResponse & GraylogProvisioningStatusResponse>(
207 `/copilot_searches/provision/graylog/check`,
208 { ids }
209 )
210 },
211
212 /**
213 * Fetch many rule summaries by ID in one round-trip
214 */
215 getRulesByIds(ids: string[], signal?: AbortSignal) {
216 const body: RulesByIdsRequest = { ids }
217 return HttpClient.post<FlaskBaseResponse & RulesByIdsResponse>(`/copilot_searches/by-ids`, body, {
218 signal
219 })
220 },
221
222 /**
223 * MITRE ATT&CK matrix annotated with per-technique CoPilot Search rule coverage.
224 * Optional filters narrow which rules contribute to coverage (e.g. Windows-only).
225 */
226 getMitreCoverage(query?: MitreCoverageQuery, signal?: AbortSignal) {
227 return HttpClient.get<FlaskBaseResponse & MitreCoverageResponse>(`/copilot_searches/mitre/coverage`, {
228 params: {
229 platform: query?.platform,
230 severity: query?.severity,
231 status: query?.status,
232 has_graylog: query?.has_graylog,
233 search: query?.search
234 },
235 signal
236 })
237 },
238
239 /**
240 * Force re-fetch of the MITRE ATT&CK STIX bundle
241 */
242 refreshMitreMatrix() {
243 return HttpClient.post<FlaskBaseResponse & { tactics: number; techniques: number }>(
244 `/copilot_searches/mitre/refresh`
245 )
246 }
247 }