@ayurak/aribot-cli 1.2.0 → 1.3.1
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 +56 -1
- package/dist/cli.js +463 -78
- package/dist/sdk.d.ts +8 -1
- package/dist/sdk.js +32 -10
- package/package.json +7 -2
- package/src/cli.ts +498 -81
- package/src/sdk.ts +35 -10
- package/tests/e2e.test.ts +244 -0
- package/tests/sdk.test.ts +500 -0
- package/vitest.config.ts +17 -0
package/src/sdk.ts
CHANGED
|
@@ -402,25 +402,50 @@ class ThreatModelingResource {
|
|
|
402
402
|
class CloudSecurityResource {
|
|
403
403
|
constructor(private client: AribotClient) {}
|
|
404
404
|
|
|
405
|
-
async
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
});
|
|
405
|
+
async listCustomers(): Promise<any[]> {
|
|
406
|
+
const data = await this.client.request<any>('GET', '/v1/customers/');
|
|
407
|
+
return data.results || [];
|
|
409
408
|
}
|
|
410
409
|
|
|
411
|
-
async
|
|
412
|
-
|
|
410
|
+
async listAccounts(customerId?: number): Promise<any[]> {
|
|
411
|
+
if (customerId) {
|
|
412
|
+
const data = await this.client.request<any>('GET', `/v1/customers/${customerId}/accounts/`);
|
|
413
|
+
return data.results || [];
|
|
414
|
+
}
|
|
415
|
+
// Fallback - try to get from first customer with accounts
|
|
416
|
+
const customers = await this.listCustomers();
|
|
417
|
+
for (const cust of customers) {
|
|
418
|
+
if (cust.ac_count > 0) {
|
|
419
|
+
return this.listAccounts(cust.id);
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
return [];
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
async listViolations(options: { severity?: string; platform?: string; limit?: number } = {}): Promise<any[]> {
|
|
426
|
+
const data = await this.client.request<any>('GET', '/v2/compliances/unified-violations/', {
|
|
413
427
|
params: {
|
|
414
|
-
status: options.status || 'open',
|
|
415
428
|
limit: options.limit || 50,
|
|
416
|
-
...(options.severity && { severity: options.severity })
|
|
429
|
+
...(options.severity && { severity: options.severity }),
|
|
430
|
+
...(options.platform && { platform: options.platform })
|
|
417
431
|
}
|
|
418
432
|
});
|
|
419
|
-
return data.results || data.
|
|
433
|
+
return Array.isArray(data) ? data : (data.results || data.violations || []);
|
|
420
434
|
}
|
|
421
435
|
|
|
422
436
|
async getDashboard(): Promise<any> {
|
|
423
|
-
return this.client.request('GET', '/v2/
|
|
437
|
+
return this.client.request('GET', '/v2/compliances/dashboard/trends/');
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
async scanPosture(cloudProvider?: string): Promise<any> {
|
|
441
|
+
return this.client.request('POST', '/v2/cloud-security/scan/', {
|
|
442
|
+
params: cloudProvider ? { provider: cloudProvider } : {}
|
|
443
|
+
});
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
async getFindings(options: { severity?: string; status?: string; limit?: number } = {}): Promise<SecurityFinding[]> {
|
|
447
|
+
// Use unified-violations endpoint which actually has data
|
|
448
|
+
return this.listViolations(options) as any;
|
|
424
449
|
}
|
|
425
450
|
|
|
426
451
|
async remediate(findingId: string, autoFix: boolean = false): Promise<any> {
|
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* End-to-end tests against real Aribot API
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { describe, it, expect, beforeAll } from 'vitest';
|
|
6
|
+
import { AribotClient } from '../src/sdk';
|
|
7
|
+
|
|
8
|
+
// Get API key from environment or config
|
|
9
|
+
const API_KEY = process.env.ARIBOT_API_KEY || 'wjS8VemIqOugwjeBjma70fGQoUTFGiKddc6-fbMVgPo';
|
|
10
|
+
const BASE_URL = process.env.ARIBOT_BASE_URL || 'https://api.aribot.ayurak.com/aribot-api';
|
|
11
|
+
|
|
12
|
+
describe('E2E: AribotClient', () => {
|
|
13
|
+
let client: AribotClient;
|
|
14
|
+
|
|
15
|
+
beforeAll(() => {
|
|
16
|
+
client = new AribotClient({ apiKey: API_KEY, baseUrl: BASE_URL });
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
describe('Threat Modeling', () => {
|
|
20
|
+
it('should list diagrams', async () => {
|
|
21
|
+
const result = await client.threatModeling.list({ limit: 10 });
|
|
22
|
+
|
|
23
|
+
console.log(`\n[Diagrams] Found ${result.results?.length || 0} diagrams`);
|
|
24
|
+
|
|
25
|
+
expect(result).toBeDefined();
|
|
26
|
+
if (result.results && result.results.length > 0) {
|
|
27
|
+
const first = result.results[0];
|
|
28
|
+
console.log(` First: ${first.name || 'Unnamed'} (${first.id.slice(0, 8)}...)`);
|
|
29
|
+
console.log(` Stage: ${first.stage}, Threats: ${first.threats_count}`);
|
|
30
|
+
|
|
31
|
+
expect(first.id).toBeDefined();
|
|
32
|
+
expect(first.stage).toBeDefined();
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
it('should get diagram details', async () => {
|
|
37
|
+
const diagrams = await client.threatModeling.list({ limit: 1 });
|
|
38
|
+
|
|
39
|
+
if (!diagrams.results || diagrams.results.length === 0) {
|
|
40
|
+
console.log('\n[Diagram Details] No diagrams available - skipping');
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const diagramId = diagrams.results[0].id;
|
|
45
|
+
const diagram = await client.threatModeling.get(diagramId);
|
|
46
|
+
|
|
47
|
+
console.log(`\n[Diagram Details] ${diagram.name || 'Unnamed'}`);
|
|
48
|
+
console.log(` ID: ${diagram.id}`);
|
|
49
|
+
console.log(` Stage: ${diagram.stage}`);
|
|
50
|
+
console.log(` Threats: ${diagram.threats_count}`);
|
|
51
|
+
|
|
52
|
+
expect(diagram.id).toBe(diagramId);
|
|
53
|
+
expect(diagram.stage).toBeDefined();
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
it('should get threats for diagram', async () => {
|
|
57
|
+
const diagrams = await client.threatModeling.list({ limit: 1 });
|
|
58
|
+
|
|
59
|
+
if (!diagrams.results || diagrams.results.length === 0) {
|
|
60
|
+
console.log('\n[Threats] No diagrams available - skipping');
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
try {
|
|
65
|
+
const diagramId = diagrams.results[0].id;
|
|
66
|
+
const threats = await client.threatModeling.getThreats(diagramId);
|
|
67
|
+
|
|
68
|
+
console.log(`\n[Threats] Found ${threats.length} threats for diagram`);
|
|
69
|
+
for (const threat of threats.slice(0, 3)) {
|
|
70
|
+
console.log(` - [${(threat.severity || 'N/A').toUpperCase()}] ${threat.title || 'Unknown'}`);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
expect(Array.isArray(threats)).toBe(true);
|
|
74
|
+
} catch (error: any) {
|
|
75
|
+
console.log(`\n[Threats] Error: ${error.message}`);
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
describe('Cloud Security', () => {
|
|
81
|
+
it('should list customers', async () => {
|
|
82
|
+
try {
|
|
83
|
+
const customers = await client.cloudSecurity.listCustomers();
|
|
84
|
+
|
|
85
|
+
console.log(`\n[Customers] Found ${customers.length} customers`);
|
|
86
|
+
for (const cust of customers.slice(0, 3)) {
|
|
87
|
+
console.log(` - ${cust.name} (ID: ${cust.id}, Accounts: ${cust.ac_count || 0})`);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
expect(customers.length).toBeGreaterThan(0);
|
|
91
|
+
} catch (error: any) {
|
|
92
|
+
console.log(`\n[Customers] Error: ${error.message}`);
|
|
93
|
+
}
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
it('should list cloud accounts', async () => {
|
|
97
|
+
try {
|
|
98
|
+
const accounts = await client.cloudSecurity.listAccounts(1);
|
|
99
|
+
|
|
100
|
+
console.log(`\n[Cloud Accounts] Found ${accounts.length} accounts`);
|
|
101
|
+
for (const acc of accounts.slice(0, 3)) {
|
|
102
|
+
console.log(` - ${acc.name} (${acc.service}) - Compliance: ${acc.compliance || 0}%`);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
expect(accounts.length).toBeGreaterThan(0);
|
|
106
|
+
} catch (error: any) {
|
|
107
|
+
console.log(`\n[Cloud Accounts] Error: ${error.message}`);
|
|
108
|
+
}
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
it('should list security violations', async () => {
|
|
112
|
+
try {
|
|
113
|
+
const violations = await client.cloudSecurity.listViolations({ limit: 10 });
|
|
114
|
+
|
|
115
|
+
console.log(`\n[Security Violations] Found ${violations.length} violations`);
|
|
116
|
+
for (const v of violations.slice(0, 5)) {
|
|
117
|
+
console.log(` - [${(v.severity || 'N/A').toUpperCase()}] ${v.rule_name || 'Unknown'} - ${v.resource_name || 'N/A'}`);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
expect(violations.length).toBeGreaterThan(0);
|
|
121
|
+
} catch (error: any) {
|
|
122
|
+
console.log(`\n[Security Violations] Error: ${error.message}`);
|
|
123
|
+
}
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
it('should filter violations by severity', async () => {
|
|
127
|
+
try {
|
|
128
|
+
const violations = await client.cloudSecurity.listViolations({ severity: 'high', limit: 5 });
|
|
129
|
+
|
|
130
|
+
console.log(`\n[High Severity Violations] Found ${violations.length} violations`);
|
|
131
|
+
for (const v of violations.slice(0, 3)) {
|
|
132
|
+
console.log(` - ${v.rule_name || 'Unknown'} (${v.platform || 'N/A'})`);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
expect(Array.isArray(violations)).toBe(true);
|
|
136
|
+
} catch (error: any) {
|
|
137
|
+
console.log(`\n[High Severity Violations] Error: ${error.message}`);
|
|
138
|
+
}
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
it('should get security dashboard', async () => {
|
|
142
|
+
try {
|
|
143
|
+
const dashboard = await client.cloudSecurity.getDashboard();
|
|
144
|
+
|
|
145
|
+
console.log(`\n[Cloud Dashboard]`);
|
|
146
|
+
console.log(` Response keys: ${Object.keys(dashboard).join(', ')}`);
|
|
147
|
+
console.log(` Fix velocity: ${dashboard.fix_velocity || 'N/A'}`);
|
|
148
|
+
console.log(` Time range: ${dashboard.time_range || 'N/A'}`);
|
|
149
|
+
|
|
150
|
+
expect(dashboard).toBeDefined();
|
|
151
|
+
} catch (error: any) {
|
|
152
|
+
console.log(`\n[Cloud Dashboard] Error: ${error.message}`);
|
|
153
|
+
}
|
|
154
|
+
});
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
describe('Compliance', () => {
|
|
158
|
+
it('should list compliance standards', async () => {
|
|
159
|
+
try {
|
|
160
|
+
const standards = await client.compliance.listStandards();
|
|
161
|
+
|
|
162
|
+
console.log(`\n[Compliance Standards] Found ${standards.length} standards`);
|
|
163
|
+
const items = Array.isArray(standards) ? standards : [];
|
|
164
|
+
for (const std of items.slice(0, 5)) {
|
|
165
|
+
console.log(` - ${std.name || std.id || 'Unknown'}`);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
expect(standards).toBeDefined();
|
|
169
|
+
} catch (error: any) {
|
|
170
|
+
console.log(`\n[Compliance Standards] Error: ${error.message}`);
|
|
171
|
+
}
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
it('should get compliance dashboard', async () => {
|
|
175
|
+
try {
|
|
176
|
+
const dashboard = await client.compliance.getDashboard();
|
|
177
|
+
|
|
178
|
+
console.log(`\n[Compliance Dashboard]`);
|
|
179
|
+
console.log(` Response keys: ${Object.keys(dashboard).slice(0, 5).join(', ')}`);
|
|
180
|
+
|
|
181
|
+
expect(dashboard).toBeDefined();
|
|
182
|
+
} catch (error: any) {
|
|
183
|
+
console.log(`\n[Compliance Dashboard] Error: ${error.message}`);
|
|
184
|
+
}
|
|
185
|
+
});
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
describe('Economics Intelligence', () => {
|
|
189
|
+
it('should get economics dashboard', async () => {
|
|
190
|
+
try {
|
|
191
|
+
const dashboard = await client.economics.getDashboard();
|
|
192
|
+
|
|
193
|
+
console.log(`\n[Economics Dashboard]`);
|
|
194
|
+
console.log(` Response keys: ${Object.keys(dashboard).slice(0, 5).join(', ')}`);
|
|
195
|
+
|
|
196
|
+
expect(dashboard).toBeDefined();
|
|
197
|
+
} catch (error: any) {
|
|
198
|
+
console.log(`\n[Economics Dashboard] Error: ${error.message}`);
|
|
199
|
+
}
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
it('should get market intelligence', async () => {
|
|
203
|
+
try {
|
|
204
|
+
const intel = await client.economics.getMarketIntelligence();
|
|
205
|
+
|
|
206
|
+
console.log(`\n[Market Intelligence]`);
|
|
207
|
+
console.log(` Response keys: ${Object.keys(intel).slice(0, 5).join(', ')}`);
|
|
208
|
+
|
|
209
|
+
expect(intel).toBeDefined();
|
|
210
|
+
} catch (error: any) {
|
|
211
|
+
console.log(`\n[Market Intelligence] Error: ${error.message}`);
|
|
212
|
+
}
|
|
213
|
+
});
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
describe('User', () => {
|
|
217
|
+
it('should get current user info', async () => {
|
|
218
|
+
try {
|
|
219
|
+
const user = await client.user.me();
|
|
220
|
+
|
|
221
|
+
console.log(`\n[User Info]`);
|
|
222
|
+
console.log(` Email: ${user.email || 'N/A'}`);
|
|
223
|
+
console.log(` Company: ${user.company?.name || user.company_name || 'N/A'}`);
|
|
224
|
+
|
|
225
|
+
expect(user).toBeDefined();
|
|
226
|
+
} catch (error: any) {
|
|
227
|
+
console.log(`\n[User Info] Error: ${error.message}`);
|
|
228
|
+
}
|
|
229
|
+
});
|
|
230
|
+
|
|
231
|
+
it('should get API usage', async () => {
|
|
232
|
+
try {
|
|
233
|
+
const usage = await client.user.getUsage();
|
|
234
|
+
|
|
235
|
+
console.log(`\n[API Usage]`);
|
|
236
|
+
console.log(` Response keys: ${Object.keys(usage).slice(0, 5).join(', ')}`);
|
|
237
|
+
|
|
238
|
+
expect(usage).toBeDefined();
|
|
239
|
+
} catch (error: any) {
|
|
240
|
+
console.log(`\n[API Usage] Error: ${error.message}`);
|
|
241
|
+
}
|
|
242
|
+
});
|
|
243
|
+
});
|
|
244
|
+
});
|