@ayurak/sdk 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +370 -0
- package/dist/index.d.mts +547 -0
- package/dist/index.d.ts +547 -0
- package/dist/index.js +787 -0
- package/dist/index.mjs +750 -0
- package/package.json +59 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,787 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/index.ts
|
|
21
|
+
var index_exports = {};
|
|
22
|
+
__export(index_exports, {
|
|
23
|
+
Aribot: () => Aribot,
|
|
24
|
+
AribotError: () => AribotError,
|
|
25
|
+
AuthenticationError: () => AuthenticationError,
|
|
26
|
+
CloudSecurityAPI: () => CloudSecurityAPI,
|
|
27
|
+
ComplianceAPI: () => ComplianceAPI,
|
|
28
|
+
NotFoundError: () => NotFoundError,
|
|
29
|
+
PipelineAPI: () => PipelineAPI,
|
|
30
|
+
RateLimitError: () => RateLimitError,
|
|
31
|
+
ServerError: () => ServerError,
|
|
32
|
+
ThreatModelingAPI: () => ThreatModelingAPI,
|
|
33
|
+
ValidationError: () => ValidationError
|
|
34
|
+
});
|
|
35
|
+
module.exports = __toCommonJS(index_exports);
|
|
36
|
+
|
|
37
|
+
// src/errors.ts
|
|
38
|
+
var AribotError = class extends Error {
|
|
39
|
+
constructor(message, statusCode, response) {
|
|
40
|
+
super(message);
|
|
41
|
+
this.name = "AribotError";
|
|
42
|
+
this.statusCode = statusCode;
|
|
43
|
+
this.response = response;
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
var AuthenticationError = class extends AribotError {
|
|
47
|
+
constructor(message, statusCode, response) {
|
|
48
|
+
super(message, statusCode, response);
|
|
49
|
+
this.name = "AuthenticationError";
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
var RateLimitError = class extends AribotError {
|
|
53
|
+
constructor(message, retryAfter, statusCode, response) {
|
|
54
|
+
super(message, statusCode, response);
|
|
55
|
+
this.name = "RateLimitError";
|
|
56
|
+
this.retryAfter = retryAfter;
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
var ValidationError = class extends AribotError {
|
|
60
|
+
constructor(message, errors = [], statusCode, response) {
|
|
61
|
+
super(message, statusCode, response);
|
|
62
|
+
this.name = "ValidationError";
|
|
63
|
+
this.errors = errors;
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
var NotFoundError = class extends AribotError {
|
|
67
|
+
constructor(message, statusCode, response) {
|
|
68
|
+
super(message, statusCode, response);
|
|
69
|
+
this.name = "NotFoundError";
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
var ServerError = class extends AribotError {
|
|
73
|
+
constructor(message, statusCode, response) {
|
|
74
|
+
super(message, statusCode, response);
|
|
75
|
+
this.name = "ServerError";
|
|
76
|
+
}
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
// src/http.ts
|
|
80
|
+
var DEFAULT_BASE_URL = "https://api.aribot.ayurak.com/aribot-api";
|
|
81
|
+
var DEFAULT_TIMEOUT = 3e4;
|
|
82
|
+
var MAX_RETRIES = 3;
|
|
83
|
+
function sleep(ms) {
|
|
84
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
85
|
+
}
|
|
86
|
+
var HttpClient = class {
|
|
87
|
+
constructor(options) {
|
|
88
|
+
this.apiKey = options.apiKey;
|
|
89
|
+
this.baseUrl = (options.baseUrl || DEFAULT_BASE_URL).replace(/\/$/, "");
|
|
90
|
+
this.timeout = options.timeout || DEFAULT_TIMEOUT;
|
|
91
|
+
}
|
|
92
|
+
async handleResponse(response) {
|
|
93
|
+
let data = {};
|
|
94
|
+
try {
|
|
95
|
+
const text = await response.text();
|
|
96
|
+
if (text) {
|
|
97
|
+
data = JSON.parse(text);
|
|
98
|
+
}
|
|
99
|
+
} catch {
|
|
100
|
+
data = {};
|
|
101
|
+
}
|
|
102
|
+
if (response.status === 401) {
|
|
103
|
+
throw new AuthenticationError(
|
|
104
|
+
data.detail || "Invalid API key",
|
|
105
|
+
401,
|
|
106
|
+
data
|
|
107
|
+
);
|
|
108
|
+
}
|
|
109
|
+
if (response.status === 403) {
|
|
110
|
+
throw new AuthenticationError(
|
|
111
|
+
data.detail || "Access denied",
|
|
112
|
+
403,
|
|
113
|
+
data
|
|
114
|
+
);
|
|
115
|
+
}
|
|
116
|
+
if (response.status === 404) {
|
|
117
|
+
throw new NotFoundError(
|
|
118
|
+
data.detail || "Resource not found",
|
|
119
|
+
404,
|
|
120
|
+
data
|
|
121
|
+
);
|
|
122
|
+
}
|
|
123
|
+
if (response.status === 422) {
|
|
124
|
+
throw new ValidationError(
|
|
125
|
+
data.detail || "Validation error",
|
|
126
|
+
data.errors || [],
|
|
127
|
+
422,
|
|
128
|
+
data
|
|
129
|
+
);
|
|
130
|
+
}
|
|
131
|
+
if (response.status === 429) {
|
|
132
|
+
const retryAfter = response.headers.get("Retry-After");
|
|
133
|
+
throw new RateLimitError(
|
|
134
|
+
data.detail || "Rate limit exceeded",
|
|
135
|
+
retryAfter ? parseInt(retryAfter, 10) : void 0,
|
|
136
|
+
429,
|
|
137
|
+
data
|
|
138
|
+
);
|
|
139
|
+
}
|
|
140
|
+
if (response.status >= 500) {
|
|
141
|
+
throw new ServerError(
|
|
142
|
+
data.detail || "Server error",
|
|
143
|
+
response.status,
|
|
144
|
+
data
|
|
145
|
+
);
|
|
146
|
+
}
|
|
147
|
+
if (response.status >= 400) {
|
|
148
|
+
throw new AribotError(
|
|
149
|
+
data.detail || `Request failed with status ${response.status}`,
|
|
150
|
+
response.status,
|
|
151
|
+
data
|
|
152
|
+
);
|
|
153
|
+
}
|
|
154
|
+
return data;
|
|
155
|
+
}
|
|
156
|
+
async request(method, path, options = {}, retry = 0) {
|
|
157
|
+
const url = new URL(path, this.baseUrl);
|
|
158
|
+
if (options.params) {
|
|
159
|
+
for (const [key, value] of Object.entries(options.params)) {
|
|
160
|
+
url.searchParams.set(key, String(value));
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
const headers = {
|
|
164
|
+
"X-API-Key": this.apiKey,
|
|
165
|
+
"User-Agent": "aribot-js/1.0.0"
|
|
166
|
+
};
|
|
167
|
+
let body;
|
|
168
|
+
if (options.formData) {
|
|
169
|
+
body = options.formData;
|
|
170
|
+
} else if (options.body) {
|
|
171
|
+
headers["Content-Type"] = "application/json";
|
|
172
|
+
body = JSON.stringify(options.body);
|
|
173
|
+
}
|
|
174
|
+
const controller = new AbortController();
|
|
175
|
+
const timeoutId = setTimeout(() => controller.abort(), this.timeout);
|
|
176
|
+
try {
|
|
177
|
+
const response = await fetch(url.toString(), {
|
|
178
|
+
method,
|
|
179
|
+
headers,
|
|
180
|
+
body,
|
|
181
|
+
signal: controller.signal
|
|
182
|
+
});
|
|
183
|
+
clearTimeout(timeoutId);
|
|
184
|
+
return await this.handleResponse(response);
|
|
185
|
+
} catch (error) {
|
|
186
|
+
clearTimeout(timeoutId);
|
|
187
|
+
if (error instanceof RateLimitError) {
|
|
188
|
+
if (retry < MAX_RETRIES && error.retryAfter) {
|
|
189
|
+
await sleep(Math.min(error.retryAfter * 1e3, 6e4));
|
|
190
|
+
return this.request(method, path, options, retry + 1);
|
|
191
|
+
}
|
|
192
|
+
throw error;
|
|
193
|
+
}
|
|
194
|
+
if (error instanceof AribotError) {
|
|
195
|
+
throw error;
|
|
196
|
+
}
|
|
197
|
+
if (error instanceof Error && error.name === "AbortError") {
|
|
198
|
+
if (retry < MAX_RETRIES) {
|
|
199
|
+
await sleep(Math.pow(2, retry) * 1e3);
|
|
200
|
+
return this.request(method, path, options, retry + 1);
|
|
201
|
+
}
|
|
202
|
+
throw new AribotError("Request timed out");
|
|
203
|
+
}
|
|
204
|
+
if (retry < MAX_RETRIES) {
|
|
205
|
+
await sleep(Math.pow(2, retry) * 1e3);
|
|
206
|
+
return this.request(method, path, options, retry + 1);
|
|
207
|
+
}
|
|
208
|
+
throw new AribotError("Connection error");
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
async get(path, params) {
|
|
212
|
+
return this.request("GET", path, { params });
|
|
213
|
+
}
|
|
214
|
+
async post(path, body, formData) {
|
|
215
|
+
return this.request("POST", path, { body, formData });
|
|
216
|
+
}
|
|
217
|
+
async put(path, body) {
|
|
218
|
+
return this.request("PUT", path, { body });
|
|
219
|
+
}
|
|
220
|
+
async patch(path, body) {
|
|
221
|
+
return this.request("PATCH", path, { body });
|
|
222
|
+
}
|
|
223
|
+
async delete(path) {
|
|
224
|
+
return this.request("DELETE", path);
|
|
225
|
+
}
|
|
226
|
+
};
|
|
227
|
+
|
|
228
|
+
// src/threat-modeling.ts
|
|
229
|
+
function sleep2(ms) {
|
|
230
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
231
|
+
}
|
|
232
|
+
var ThreatModelingAPI = class {
|
|
233
|
+
constructor(http) {
|
|
234
|
+
this.http = http;
|
|
235
|
+
}
|
|
236
|
+
/**
|
|
237
|
+
* Upload and analyze a diagram for threats
|
|
238
|
+
*/
|
|
239
|
+
async analyzeDiagram(file, options = {}) {
|
|
240
|
+
const {
|
|
241
|
+
filename = "diagram",
|
|
242
|
+
analysisDepth = "comprehensive",
|
|
243
|
+
wait = true,
|
|
244
|
+
timeout = 3e5
|
|
245
|
+
} = options;
|
|
246
|
+
const formData = new FormData();
|
|
247
|
+
formData.append("file", file, filename);
|
|
248
|
+
formData.append("filename", filename);
|
|
249
|
+
formData.append("analysis_depth", analysisDepth);
|
|
250
|
+
const result = await this.http.post(
|
|
251
|
+
"/v2/threat-modeling/diagrams/upload-and-analyze/",
|
|
252
|
+
void 0,
|
|
253
|
+
formData
|
|
254
|
+
);
|
|
255
|
+
if (!wait) {
|
|
256
|
+
return result;
|
|
257
|
+
}
|
|
258
|
+
const diagramId = result.diagram_id;
|
|
259
|
+
if (!diagramId) {
|
|
260
|
+
return result;
|
|
261
|
+
}
|
|
262
|
+
return this.waitForAnalysis(diagramId, timeout);
|
|
263
|
+
}
|
|
264
|
+
async waitForAnalysis(diagramId, timeout) {
|
|
265
|
+
const start = Date.now();
|
|
266
|
+
while (Date.now() - start < timeout) {
|
|
267
|
+
const diagram = await this.get(diagramId);
|
|
268
|
+
const status = diagram.status;
|
|
269
|
+
if (["completed", "analyzed", "done"].includes(status)) {
|
|
270
|
+
return diagram;
|
|
271
|
+
}
|
|
272
|
+
if (["failed", "error"].includes(status)) {
|
|
273
|
+
throw new Error(`Analysis failed: ${diagram.error || "Unknown error"}`);
|
|
274
|
+
}
|
|
275
|
+
await sleep2(5e3);
|
|
276
|
+
}
|
|
277
|
+
throw new Error(`Analysis did not complete within ${timeout}ms`);
|
|
278
|
+
}
|
|
279
|
+
/**
|
|
280
|
+
* List diagrams
|
|
281
|
+
*/
|
|
282
|
+
async list(options = {}) {
|
|
283
|
+
const { page = 1, limit = 25, status, search } = options;
|
|
284
|
+
const params = { page, limit };
|
|
285
|
+
if (status) params.status = status;
|
|
286
|
+
if (search) params.search = search;
|
|
287
|
+
return await this.http.get("/v1/tm/diagrams/", params);
|
|
288
|
+
}
|
|
289
|
+
/**
|
|
290
|
+
* Get diagram details
|
|
291
|
+
*/
|
|
292
|
+
async get(diagramId) {
|
|
293
|
+
return await this.http.get(`/v1/tm/diagrams/${diagramId}/`);
|
|
294
|
+
}
|
|
295
|
+
/**
|
|
296
|
+
* Get threats for a diagram
|
|
297
|
+
*/
|
|
298
|
+
async getThreats(diagramId) {
|
|
299
|
+
const result = await this.http.get(`/v1/tm/diagrams/${diagramId}/threats/`);
|
|
300
|
+
if (Array.isArray(result)) {
|
|
301
|
+
return result;
|
|
302
|
+
}
|
|
303
|
+
const data = result;
|
|
304
|
+
return data.results || data.threats || [];
|
|
305
|
+
}
|
|
306
|
+
/**
|
|
307
|
+
* Get components detected in diagram
|
|
308
|
+
*/
|
|
309
|
+
async getComponents(diagramId) {
|
|
310
|
+
const result = await this.http.get(`/v1/tm/diagrams/${diagramId}/components/`);
|
|
311
|
+
if (Array.isArray(result)) {
|
|
312
|
+
return result;
|
|
313
|
+
}
|
|
314
|
+
const data = result;
|
|
315
|
+
return data.results || data.components || [];
|
|
316
|
+
}
|
|
317
|
+
/**
|
|
318
|
+
* Run AI-powered analysis on diagram
|
|
319
|
+
*/
|
|
320
|
+
async analyzeWithAI(diagramId, analysisTypes) {
|
|
321
|
+
const body = {};
|
|
322
|
+
if (analysisTypes) {
|
|
323
|
+
body.analysis_types = analysisTypes;
|
|
324
|
+
}
|
|
325
|
+
return await this.http.post(
|
|
326
|
+
`/v2/threat-modeling/diagrams/${diagramId}/analyze-with-ai/`,
|
|
327
|
+
body
|
|
328
|
+
);
|
|
329
|
+
}
|
|
330
|
+
/**
|
|
331
|
+
* Delete a diagram
|
|
332
|
+
*/
|
|
333
|
+
async delete(diagramId) {
|
|
334
|
+
await this.http.delete(`/v1/tm/diagrams/${diagramId}/`);
|
|
335
|
+
}
|
|
336
|
+
/**
|
|
337
|
+
* Get threat modeling dashboard
|
|
338
|
+
*/
|
|
339
|
+
async dashboard(period = "month", includeTrends = true) {
|
|
340
|
+
return await this.http.get("/v1/tm/dashboard/", {
|
|
341
|
+
period,
|
|
342
|
+
include_trends: includeTrends
|
|
343
|
+
});
|
|
344
|
+
}
|
|
345
|
+
};
|
|
346
|
+
|
|
347
|
+
// src/compliance.ts
|
|
348
|
+
var ComplianceAPI = class {
|
|
349
|
+
constructor(http) {
|
|
350
|
+
this.http = http;
|
|
351
|
+
}
|
|
352
|
+
/**
|
|
353
|
+
* Run compliance scan on a diagram
|
|
354
|
+
*/
|
|
355
|
+
async scan(diagramId, options = {}) {
|
|
356
|
+
const { standards, includeRecommendations = true } = options;
|
|
357
|
+
const body = {
|
|
358
|
+
include_recommendations: includeRecommendations
|
|
359
|
+
};
|
|
360
|
+
if (standards) {
|
|
361
|
+
body.standards = standards;
|
|
362
|
+
}
|
|
363
|
+
return await this.http.post(
|
|
364
|
+
`/v2/compliances/diagram-compliance/${diagramId}/scan/`,
|
|
365
|
+
body
|
|
366
|
+
);
|
|
367
|
+
}
|
|
368
|
+
/**
|
|
369
|
+
* Get compliance report for a diagram
|
|
370
|
+
*/
|
|
371
|
+
async getReport(diagramId, format = "json") {
|
|
372
|
+
return await this.http.get(
|
|
373
|
+
`/v2/compliances/diagram-compliance/${diagramId}/report/`,
|
|
374
|
+
{ format }
|
|
375
|
+
);
|
|
376
|
+
}
|
|
377
|
+
/**
|
|
378
|
+
* List available compliance standards
|
|
379
|
+
*/
|
|
380
|
+
async listStandards() {
|
|
381
|
+
const result = await this.http.get("/v2/compliances/standards/");
|
|
382
|
+
if (Array.isArray(result)) {
|
|
383
|
+
return result;
|
|
384
|
+
}
|
|
385
|
+
const data = result;
|
|
386
|
+
return data.results || data.standards || [];
|
|
387
|
+
}
|
|
388
|
+
/**
|
|
389
|
+
* Get details of a compliance standard
|
|
390
|
+
*/
|
|
391
|
+
async getStandard(standardId) {
|
|
392
|
+
return await this.http.get(
|
|
393
|
+
`/v2/compliances/standards/${standardId}/`
|
|
394
|
+
);
|
|
395
|
+
}
|
|
396
|
+
/**
|
|
397
|
+
* List controls for a compliance standard
|
|
398
|
+
*/
|
|
399
|
+
async listControls(standardId, category) {
|
|
400
|
+
const params = {};
|
|
401
|
+
if (category) params.category = category;
|
|
402
|
+
const result = await this.http.get(
|
|
403
|
+
`/v2/compliances/standards/${standardId}/controls/`,
|
|
404
|
+
params
|
|
405
|
+
);
|
|
406
|
+
if (Array.isArray(result)) {
|
|
407
|
+
return result;
|
|
408
|
+
}
|
|
409
|
+
const data = result;
|
|
410
|
+
return data.results || data.controls || [];
|
|
411
|
+
}
|
|
412
|
+
/**
|
|
413
|
+
* Get compliance gaps for a diagram
|
|
414
|
+
*/
|
|
415
|
+
async getGaps(diagramId, standardId) {
|
|
416
|
+
const params = {};
|
|
417
|
+
if (standardId) params.standard = standardId;
|
|
418
|
+
const result = await this.http.get(
|
|
419
|
+
`/v2/compliances/diagram-compliance/${diagramId}/gaps/`,
|
|
420
|
+
params
|
|
421
|
+
);
|
|
422
|
+
if (Array.isArray(result)) {
|
|
423
|
+
return result;
|
|
424
|
+
}
|
|
425
|
+
const data = result;
|
|
426
|
+
return data.results || data.gaps || [];
|
|
427
|
+
}
|
|
428
|
+
/**
|
|
429
|
+
* Create a custom compliance standard
|
|
430
|
+
*/
|
|
431
|
+
async addCustomStandard(name, description, controls) {
|
|
432
|
+
return await this.http.post("/v2/compliances/standards/", {
|
|
433
|
+
name,
|
|
434
|
+
description,
|
|
435
|
+
controls
|
|
436
|
+
});
|
|
437
|
+
}
|
|
438
|
+
/**
|
|
439
|
+
* Get compliance dashboard metrics
|
|
440
|
+
*/
|
|
441
|
+
async dashboard(period = "month") {
|
|
442
|
+
return await this.http.get("/v2/compliances/dashboard/", {
|
|
443
|
+
period
|
|
444
|
+
});
|
|
445
|
+
}
|
|
446
|
+
};
|
|
447
|
+
|
|
448
|
+
// src/cloud.ts
|
|
449
|
+
var CloudSecurityAPI = class {
|
|
450
|
+
constructor(http) {
|
|
451
|
+
this.http = http;
|
|
452
|
+
}
|
|
453
|
+
/**
|
|
454
|
+
* Run cloud security scan
|
|
455
|
+
*/
|
|
456
|
+
async scan(projectId, options = {}) {
|
|
457
|
+
const body = { project_id: projectId };
|
|
458
|
+
if (options.provider) body.provider = options.provider;
|
|
459
|
+
if (options.regions) body.regions = options.regions;
|
|
460
|
+
if (options.services) body.services = options.services;
|
|
461
|
+
if (options.complianceStandards) body.compliance_standards = options.complianceStandards;
|
|
462
|
+
return await this.http.post("/v2/cloud-security/scans/", body);
|
|
463
|
+
}
|
|
464
|
+
/**
|
|
465
|
+
* Get scan details and results
|
|
466
|
+
*/
|
|
467
|
+
async getScan(scanId) {
|
|
468
|
+
return await this.http.get(`/v2/cloud-security/scans/${scanId}/`);
|
|
469
|
+
}
|
|
470
|
+
/**
|
|
471
|
+
* List cloud security scans
|
|
472
|
+
*/
|
|
473
|
+
async listScans(options = {}) {
|
|
474
|
+
const { projectId, provider, status, page = 1, limit = 25 } = options;
|
|
475
|
+
const params = { page, limit };
|
|
476
|
+
if (projectId) params.project_id = projectId;
|
|
477
|
+
if (provider) params.provider = provider;
|
|
478
|
+
if (status) params.status = status;
|
|
479
|
+
return await this.http.get("/v2/cloud-security/scans/", params);
|
|
480
|
+
}
|
|
481
|
+
/**
|
|
482
|
+
* Get findings from a scan
|
|
483
|
+
*/
|
|
484
|
+
async getFindings(scanId, options = {}) {
|
|
485
|
+
const { severity, service, status } = options;
|
|
486
|
+
const params = {};
|
|
487
|
+
if (severity) params.severity = severity;
|
|
488
|
+
if (service) params.service = service;
|
|
489
|
+
if (status) params.status = status;
|
|
490
|
+
const result = await this.http.get(`/v2/cloud-security/scans/${scanId}/findings/`, params);
|
|
491
|
+
if (Array.isArray(result)) {
|
|
492
|
+
return result;
|
|
493
|
+
}
|
|
494
|
+
const data = result;
|
|
495
|
+
return data.results || data.findings || [];
|
|
496
|
+
}
|
|
497
|
+
/**
|
|
498
|
+
* Connect a cloud account for scanning
|
|
499
|
+
*/
|
|
500
|
+
async connectAccount(provider, credentials, options = {}) {
|
|
501
|
+
const body = {
|
|
502
|
+
provider,
|
|
503
|
+
credentials
|
|
504
|
+
};
|
|
505
|
+
if (options.name) body.name = options.name;
|
|
506
|
+
if (options.regions) body.regions = options.regions;
|
|
507
|
+
return await this.http.post("/v2/cloud-security/accounts/", body);
|
|
508
|
+
}
|
|
509
|
+
/**
|
|
510
|
+
* List connected cloud accounts
|
|
511
|
+
*/
|
|
512
|
+
async listAccounts(provider) {
|
|
513
|
+
const params = {};
|
|
514
|
+
if (provider) params.provider = provider;
|
|
515
|
+
const result = await this.http.get("/v2/cloud-security/accounts/", params);
|
|
516
|
+
if (Array.isArray(result)) {
|
|
517
|
+
return result;
|
|
518
|
+
}
|
|
519
|
+
const data = result;
|
|
520
|
+
return data.results || data.accounts || [];
|
|
521
|
+
}
|
|
522
|
+
/**
|
|
523
|
+
* Disconnect a cloud account
|
|
524
|
+
*/
|
|
525
|
+
async deleteAccount(accountId) {
|
|
526
|
+
await this.http.delete(`/v2/cloud-security/accounts/${accountId}/`);
|
|
527
|
+
}
|
|
528
|
+
/**
|
|
529
|
+
* Mark a finding as resolved
|
|
530
|
+
*/
|
|
531
|
+
async resolveFinding(findingId, resolution, notes) {
|
|
532
|
+
const body = { resolution };
|
|
533
|
+
if (notes) body.notes = notes;
|
|
534
|
+
return await this.http.post(
|
|
535
|
+
`/v2/cloud-security/findings/${findingId}/resolve/`,
|
|
536
|
+
body
|
|
537
|
+
);
|
|
538
|
+
}
|
|
539
|
+
/**
|
|
540
|
+
* Suppress a finding
|
|
541
|
+
*/
|
|
542
|
+
async suppressFinding(findingId, reason, durationDays) {
|
|
543
|
+
const body = { reason };
|
|
544
|
+
if (durationDays) body.duration_days = durationDays;
|
|
545
|
+
return await this.http.post(
|
|
546
|
+
`/v2/cloud-security/findings/${findingId}/suppress/`,
|
|
547
|
+
body
|
|
548
|
+
);
|
|
549
|
+
}
|
|
550
|
+
/**
|
|
551
|
+
* Get remediation steps for a finding
|
|
552
|
+
*/
|
|
553
|
+
async getRemediation(findingId) {
|
|
554
|
+
return await this.http.get(
|
|
555
|
+
`/v2/cloud-security/findings/${findingId}/remediation/`
|
|
556
|
+
);
|
|
557
|
+
}
|
|
558
|
+
/**
|
|
559
|
+
* Get cloud security dashboard
|
|
560
|
+
*/
|
|
561
|
+
async dashboard(projectId, period = "month") {
|
|
562
|
+
const params = { period };
|
|
563
|
+
if (projectId) params.project_id = projectId;
|
|
564
|
+
return await this.http.get("/v2/cloud-security/dashboard/", params);
|
|
565
|
+
}
|
|
566
|
+
};
|
|
567
|
+
|
|
568
|
+
// src/pipeline.ts
|
|
569
|
+
function sleep3(ms) {
|
|
570
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
571
|
+
}
|
|
572
|
+
var PipelineAPI = class {
|
|
573
|
+
constructor(http) {
|
|
574
|
+
this.http = http;
|
|
575
|
+
}
|
|
576
|
+
/**
|
|
577
|
+
* Create a pipeline project
|
|
578
|
+
*/
|
|
579
|
+
async createProject(name, options = {}) {
|
|
580
|
+
const body = {
|
|
581
|
+
name,
|
|
582
|
+
default_branch: options.defaultBranch || "main"
|
|
583
|
+
};
|
|
584
|
+
if (options.repositoryUrl) body.repository_url = options.repositoryUrl;
|
|
585
|
+
if (options.scanTypes) body.scan_types = options.scanTypes;
|
|
586
|
+
return await this.http.post("/v1/pipeline/projects/", body);
|
|
587
|
+
}
|
|
588
|
+
/**
|
|
589
|
+
* List pipeline projects
|
|
590
|
+
*/
|
|
591
|
+
async listProjects(page = 1, limit = 25) {
|
|
592
|
+
return await this.http.get("/v1/pipeline/projects/", { page, limit });
|
|
593
|
+
}
|
|
594
|
+
/**
|
|
595
|
+
* Get project details
|
|
596
|
+
*/
|
|
597
|
+
async getProject(projectId) {
|
|
598
|
+
return await this.http.get(`/v1/pipeline/projects/${projectId}/`);
|
|
599
|
+
}
|
|
600
|
+
/**
|
|
601
|
+
* Delete a pipeline project
|
|
602
|
+
*/
|
|
603
|
+
async deleteProject(projectId) {
|
|
604
|
+
await this.http.delete(`/v1/pipeline/projects/${projectId}/`);
|
|
605
|
+
}
|
|
606
|
+
/**
|
|
607
|
+
* Run pipeline security scan
|
|
608
|
+
*/
|
|
609
|
+
async scan(projectId, options = {}) {
|
|
610
|
+
const {
|
|
611
|
+
commitSha,
|
|
612
|
+
branch,
|
|
613
|
+
scanTypes,
|
|
614
|
+
failOnSeverity,
|
|
615
|
+
wait = false,
|
|
616
|
+
timeout = 6e5
|
|
617
|
+
} = options;
|
|
618
|
+
const body = { project_id: projectId };
|
|
619
|
+
if (commitSha) body.commit_sha = commitSha;
|
|
620
|
+
if (branch) body.branch = branch;
|
|
621
|
+
if (scanTypes) body.scan_types = scanTypes;
|
|
622
|
+
if (failOnSeverity) body.fail_on_severity = failOnSeverity;
|
|
623
|
+
const result = await this.http.post("/v1/pipeline/scans/", body);
|
|
624
|
+
if (!wait) {
|
|
625
|
+
return result;
|
|
626
|
+
}
|
|
627
|
+
const scanId = result.scan_id;
|
|
628
|
+
if (!scanId) {
|
|
629
|
+
return result;
|
|
630
|
+
}
|
|
631
|
+
return this.waitForScan(scanId, timeout);
|
|
632
|
+
}
|
|
633
|
+
async waitForScan(scanId, timeout) {
|
|
634
|
+
const start = Date.now();
|
|
635
|
+
while (Date.now() - start < timeout) {
|
|
636
|
+
const scan = await this.getScan(scanId);
|
|
637
|
+
const status = scan.status;
|
|
638
|
+
if (["completed", "passed", "failed"].includes(status)) {
|
|
639
|
+
return scan;
|
|
640
|
+
}
|
|
641
|
+
if (status === "error") {
|
|
642
|
+
throw new Error(`Scan error: ${scan.error || "Unknown error"}`);
|
|
643
|
+
}
|
|
644
|
+
await sleep3(5e3);
|
|
645
|
+
}
|
|
646
|
+
throw new Error(`Scan did not complete within ${timeout}ms`);
|
|
647
|
+
}
|
|
648
|
+
/**
|
|
649
|
+
* Get scan details and results
|
|
650
|
+
*/
|
|
651
|
+
async getScan(scanId) {
|
|
652
|
+
return await this.http.get(`/v1/pipeline/scans/${scanId}/`);
|
|
653
|
+
}
|
|
654
|
+
/**
|
|
655
|
+
* List pipeline scans
|
|
656
|
+
*/
|
|
657
|
+
async listScans(options = {}) {
|
|
658
|
+
const { projectId, status, branch, page = 1, limit = 25 } = options;
|
|
659
|
+
const params = { page, limit };
|
|
660
|
+
if (projectId) params.project_id = projectId;
|
|
661
|
+
if (status) params.status = status;
|
|
662
|
+
if (branch) params.branch = branch;
|
|
663
|
+
return await this.http.get("/v1/pipeline/scans/", params);
|
|
664
|
+
}
|
|
665
|
+
/**
|
|
666
|
+
* Get findings from a scan
|
|
667
|
+
*/
|
|
668
|
+
async getFindings(scanId, options = {}) {
|
|
669
|
+
const { scanType, severity } = options;
|
|
670
|
+
const params = {};
|
|
671
|
+
if (scanType) params.type = scanType;
|
|
672
|
+
if (severity) params.severity = severity;
|
|
673
|
+
const result = await this.http.get(`/v1/pipeline/scans/${scanId}/findings/`, params);
|
|
674
|
+
if (Array.isArray(result)) {
|
|
675
|
+
return result;
|
|
676
|
+
}
|
|
677
|
+
const data = result;
|
|
678
|
+
return data.results || data.findings || [];
|
|
679
|
+
}
|
|
680
|
+
/**
|
|
681
|
+
* Get SAST (static analysis) findings
|
|
682
|
+
*/
|
|
683
|
+
async getSastFindings(scanId) {
|
|
684
|
+
return this.getFindings(scanId, { scanType: "sast" });
|
|
685
|
+
}
|
|
686
|
+
/**
|
|
687
|
+
* Get SCA (dependency) findings
|
|
688
|
+
*/
|
|
689
|
+
async getScaFindings(scanId) {
|
|
690
|
+
return this.getFindings(scanId, { scanType: "sca" });
|
|
691
|
+
}
|
|
692
|
+
/**
|
|
693
|
+
* Get secrets detection findings
|
|
694
|
+
*/
|
|
695
|
+
async getSecretsFindings(scanId) {
|
|
696
|
+
return this.getFindings(scanId, { scanType: "secrets" });
|
|
697
|
+
}
|
|
698
|
+
/**
|
|
699
|
+
* Configure security gates for a project
|
|
700
|
+
*/
|
|
701
|
+
async configureGates(projectId, gates) {
|
|
702
|
+
return await this.http.patch(
|
|
703
|
+
`/v1/pipeline/projects/${projectId}/gates/`,
|
|
704
|
+
gates
|
|
705
|
+
);
|
|
706
|
+
}
|
|
707
|
+
/**
|
|
708
|
+
* Set scan as baseline (suppress existing findings)
|
|
709
|
+
*/
|
|
710
|
+
async addBaseline(projectId, scanId) {
|
|
711
|
+
return await this.http.post(`/v1/pipeline/projects/${projectId}/baseline/`, {
|
|
712
|
+
baseline_scan_id: scanId
|
|
713
|
+
});
|
|
714
|
+
}
|
|
715
|
+
/**
|
|
716
|
+
* Suppress a finding
|
|
717
|
+
*/
|
|
718
|
+
async suppressFinding(findingId, reason, expiresAt) {
|
|
719
|
+
const body = { reason };
|
|
720
|
+
if (expiresAt) body.expires_at = expiresAt;
|
|
721
|
+
return await this.http.post(
|
|
722
|
+
`/v1/pipeline/findings/${findingId}/suppress/`,
|
|
723
|
+
body
|
|
724
|
+
);
|
|
725
|
+
}
|
|
726
|
+
/**
|
|
727
|
+
* Get pipeline security dashboard
|
|
728
|
+
*/
|
|
729
|
+
async dashboard(projectId, period = "month") {
|
|
730
|
+
const params = { period };
|
|
731
|
+
if (projectId) params.project_id = projectId;
|
|
732
|
+
return await this.http.get("/v1/pipeline/dashboard/", params);
|
|
733
|
+
}
|
|
734
|
+
};
|
|
735
|
+
|
|
736
|
+
// src/client.ts
|
|
737
|
+
var Aribot = class {
|
|
738
|
+
/**
|
|
739
|
+
* Create Aribot client
|
|
740
|
+
*
|
|
741
|
+
* @param apiKey - Your Aribot API key
|
|
742
|
+
* @param options - Client configuration options
|
|
743
|
+
*/
|
|
744
|
+
constructor(apiKey, options = {}) {
|
|
745
|
+
this.http = new HttpClient({
|
|
746
|
+
apiKey,
|
|
747
|
+
baseUrl: options.baseUrl,
|
|
748
|
+
timeout: options.timeout
|
|
749
|
+
});
|
|
750
|
+
this.threatModeling = new ThreatModelingAPI(this.http);
|
|
751
|
+
this.compliance = new ComplianceAPI(this.http);
|
|
752
|
+
this.cloud = new CloudSecurityAPI(this.http);
|
|
753
|
+
this.pipeline = new PipelineAPI(this.http);
|
|
754
|
+
}
|
|
755
|
+
/**
|
|
756
|
+
* Check API health status
|
|
757
|
+
*/
|
|
758
|
+
async health() {
|
|
759
|
+
return await this.http.get("/health/");
|
|
760
|
+
}
|
|
761
|
+
/**
|
|
762
|
+
* Get current user/organization info
|
|
763
|
+
*/
|
|
764
|
+
async me() {
|
|
765
|
+
return await this.http.get("/v1/users/me/");
|
|
766
|
+
}
|
|
767
|
+
/**
|
|
768
|
+
* Get API usage statistics
|
|
769
|
+
*/
|
|
770
|
+
async usage(period = "month") {
|
|
771
|
+
return await this.http.get("/v1/usage/", { period });
|
|
772
|
+
}
|
|
773
|
+
};
|
|
774
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
775
|
+
0 && (module.exports = {
|
|
776
|
+
Aribot,
|
|
777
|
+
AribotError,
|
|
778
|
+
AuthenticationError,
|
|
779
|
+
CloudSecurityAPI,
|
|
780
|
+
ComplianceAPI,
|
|
781
|
+
NotFoundError,
|
|
782
|
+
PipelineAPI,
|
|
783
|
+
RateLimitError,
|
|
784
|
+
ServerError,
|
|
785
|
+
ThreatModelingAPI,
|
|
786
|
+
ValidationError
|
|
787
|
+
});
|