@ayurak/aribot-cli 1.0.5 → 1.0.8
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 +222 -39
- package/aribot-report-183b4bd7.json +1569 -0
- package/dist/cli.d.ts +10 -1
- package/dist/cli.js +1173 -8
- package/dist/index.d.ts +19 -0
- package/dist/index.js +35 -0
- package/dist/sdk.d.ts +349 -0
- package/dist/sdk.js +808 -0
- package/package.json +34 -4
- package/src/cli.ts +1264 -9
- package/src/index.ts +42 -0
- package/src/sdk.ts +1017 -0
package/src/cli.ts
CHANGED
|
@@ -1,6 +1,15 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
/**
|
|
3
|
-
* Aribot CLI -
|
|
3
|
+
* Aribot CLI - Economic, Regulatory & Security APIs for Modern Applications
|
|
4
|
+
*
|
|
5
|
+
* Analyze your tech stack. Optimize architecture. Model costs. Identify threats dynamically.
|
|
6
|
+
*
|
|
7
|
+
* Features:
|
|
8
|
+
* - Advanced Threat Modeling (STRIDE, PASTA, NIST, Aristiun Framework)
|
|
9
|
+
* - 100+ Compliance Standards (SOC2, ISO27001, PCI-DSS, GDPR, HIPAA...)
|
|
10
|
+
* - Cloud Security (CSPM/CNAPP)
|
|
11
|
+
* - Economic Intelligence & FinOps
|
|
12
|
+
* - Red Team Automation
|
|
4
13
|
*
|
|
5
14
|
* Usage:
|
|
6
15
|
* aribot login # Authenticate with API key
|
|
@@ -26,7 +35,7 @@ const program = new Command();
|
|
|
26
35
|
|
|
27
36
|
program
|
|
28
37
|
.name('aribot')
|
|
29
|
-
.description('
|
|
38
|
+
.description('Aribot - Economic, Regulatory & Security APIs for Modern Applications')
|
|
30
39
|
.version('1.0.5');
|
|
31
40
|
|
|
32
41
|
// Helper to get auth headers
|
|
@@ -57,6 +66,24 @@ async function apiRequest(endpoint: string, options: any = {}): Promise<any> {
|
|
|
57
66
|
return response.json();
|
|
58
67
|
}
|
|
59
68
|
|
|
69
|
+
// Resolve short UUID to full UUID
|
|
70
|
+
async function resolveDiagramId(shortId: string): Promise<string> {
|
|
71
|
+
// If it already looks like a full UUID, return it
|
|
72
|
+
if (shortId.includes('-') || shortId.length >= 32) {
|
|
73
|
+
return shortId;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// Fetch diagrams and find by prefix match
|
|
77
|
+
const data = await apiRequest('/v2/threat-modeling/diagrams/?limit=100');
|
|
78
|
+
const match = data.results?.find((d: any) => d.id.startsWith(shortId));
|
|
79
|
+
|
|
80
|
+
if (!match) {
|
|
81
|
+
throw new Error(`No diagram found matching ID: ${shortId}`);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
return match.id;
|
|
85
|
+
}
|
|
86
|
+
|
|
60
87
|
// Login command
|
|
61
88
|
program
|
|
62
89
|
.command('login')
|
|
@@ -213,7 +240,10 @@ program
|
|
|
213
240
|
const spinner = ora('Fetching threats...').start();
|
|
214
241
|
|
|
215
242
|
try {
|
|
216
|
-
|
|
243
|
+
// Resolve short UUID to full UUID
|
|
244
|
+
const fullId = await resolveDiagramId(diagramId);
|
|
245
|
+
|
|
246
|
+
let url = `/v2/threat-modeling/diagrams/${fullId}/threats/`;
|
|
217
247
|
if (options.severity) {
|
|
218
248
|
url += `?severity=${options.severity}`;
|
|
219
249
|
}
|
|
@@ -255,19 +285,32 @@ program
|
|
|
255
285
|
const spinner = ora(`Exporting ${options.format.toUpperCase()} report...`).start();
|
|
256
286
|
|
|
257
287
|
try {
|
|
288
|
+
// Resolve short UUID to full UUID
|
|
289
|
+
const fullId = await resolveDiagramId(diagramId);
|
|
290
|
+
|
|
258
291
|
const fetch = (await import('node-fetch')).default;
|
|
259
|
-
const
|
|
292
|
+
const headers = getHeaders();
|
|
293
|
+
|
|
294
|
+
// Choose endpoint based on format
|
|
295
|
+
let endpoint: string;
|
|
296
|
+
if (options.format === 'csv') {
|
|
297
|
+
endpoint = `/v2/threat-modeling/diagrams/${fullId}/export/csv/`;
|
|
298
|
+
} else if (options.format === 'pdf') {
|
|
299
|
+
endpoint = `/v2/threat-modeling/diagrams/${fullId}/unified-report/?format=pdf`;
|
|
300
|
+
} else {
|
|
301
|
+
endpoint = `/v2/threat-modeling/diagrams/${fullId}/report/`;
|
|
302
|
+
}
|
|
260
303
|
|
|
261
304
|
const response = await fetch(
|
|
262
|
-
`${API_BASE}
|
|
263
|
-
{ headers
|
|
305
|
+
`${API_BASE}${endpoint}`,
|
|
306
|
+
{ headers }
|
|
264
307
|
);
|
|
265
308
|
|
|
266
309
|
if (!response.ok) {
|
|
267
310
|
throw new Error(`Export failed: ${response.status}`);
|
|
268
311
|
}
|
|
269
312
|
|
|
270
|
-
const outputPath = options.output || `aribot-report-${
|
|
313
|
+
const outputPath = options.output || `aribot-report-${fullId.slice(0, 8)}.${options.format}`;
|
|
271
314
|
|
|
272
315
|
if (options.format === 'json') {
|
|
273
316
|
const data = await response.json();
|
|
@@ -292,7 +335,10 @@ program
|
|
|
292
335
|
const spinner = ora('Generating AI threats...').start();
|
|
293
336
|
|
|
294
337
|
try {
|
|
295
|
-
|
|
338
|
+
// Resolve short UUID to full UUID
|
|
339
|
+
const fullId = await resolveDiagramId(diagramId);
|
|
340
|
+
|
|
341
|
+
await apiRequest(`/v2/threat-modeling/diagrams/${fullId}/generate-threats/`, {
|
|
296
342
|
method: 'POST'
|
|
297
343
|
});
|
|
298
344
|
|
|
@@ -302,7 +348,7 @@ program
|
|
|
302
348
|
let attempts = 0;
|
|
303
349
|
while (attempts < 30) {
|
|
304
350
|
await new Promise(r => setTimeout(r, 2000));
|
|
305
|
-
const status = await apiRequest(`/v2/threat-modeling/diagrams/${
|
|
351
|
+
const status = await apiRequest(`/v2/threat-modeling/diagrams/${fullId}/`);
|
|
306
352
|
|
|
307
353
|
if (status.ai_threats_generated) {
|
|
308
354
|
spinner.succeed(`Generated ${status.threats_count} threats`);
|
|
@@ -348,4 +394,1213 @@ program
|
|
|
348
394
|
}
|
|
349
395
|
});
|
|
350
396
|
|
|
397
|
+
// Status command - Check API status and rate limits
|
|
398
|
+
program
|
|
399
|
+
.command('status')
|
|
400
|
+
.description('Check API status and rate limits')
|
|
401
|
+
.action(async () => {
|
|
402
|
+
const spinner = ora('Checking API status...').start();
|
|
403
|
+
|
|
404
|
+
try {
|
|
405
|
+
const fetch = (await import('node-fetch')).default;
|
|
406
|
+
|
|
407
|
+
// Check health endpoint (no auth required)
|
|
408
|
+
const healthResponse = await fetch(`${API_BASE}/health/`);
|
|
409
|
+
const health = await healthResponse.json() as any;
|
|
410
|
+
|
|
411
|
+
spinner.stop();
|
|
412
|
+
console.log(chalk.bold('\nAPI Status:\n'));
|
|
413
|
+
console.log(` Status: ${health.status === 'healthy' ? chalk.green('✓ Healthy') : chalk.red('✗ Unhealthy')}`);
|
|
414
|
+
console.log(` Version: ${chalk.cyan(health.version || 'N/A')}`);
|
|
415
|
+
console.log(` Features: ${health.features_enabled ? chalk.green('Enabled') : chalk.yellow('Disabled')}`);
|
|
416
|
+
|
|
417
|
+
// Check rate limits if authenticated
|
|
418
|
+
const apiKey = config.get('apiKey') as string;
|
|
419
|
+
if (apiKey) {
|
|
420
|
+
try {
|
|
421
|
+
const limits = await apiRequest('/v2/developer-portal/rate-limits/usage/');
|
|
422
|
+
console.log(chalk.bold('\nRate Limits:\n'));
|
|
423
|
+
console.log(` Requests/min: ${limits.requests_per_minute?.used || 0}/${limits.requests_per_minute?.limit || 'unlimited'}`);
|
|
424
|
+
console.log(` Requests/hour: ${limits.requests_per_hour?.used || 0}/${limits.requests_per_hour?.limit || 'unlimited'}`);
|
|
425
|
+
console.log(` Requests/day: ${limits.requests_per_day?.used || 0}/${limits.requests_per_day?.limit || 'unlimited'}`);
|
|
426
|
+
} catch {
|
|
427
|
+
console.log(chalk.dim('\nRate limit info requires authentication'));
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
} catch (error) {
|
|
431
|
+
spinner.fail('Failed to check status');
|
|
432
|
+
console.error(error);
|
|
433
|
+
}
|
|
434
|
+
});
|
|
435
|
+
|
|
436
|
+
// Compliance command - Run compliance assessment
|
|
437
|
+
program
|
|
438
|
+
.command('compliance')
|
|
439
|
+
.description('Run compliance assessment on a diagram')
|
|
440
|
+
.argument('[diagram-id]', 'Diagram ID to assess')
|
|
441
|
+
.option('-s, --standard <standard>', 'Compliance standard (SOC2, ISO27001, NIST, PCI-DSS, GDPR, HIPAA)', 'SOC2')
|
|
442
|
+
.option('--list-standards', 'List all available compliance standards')
|
|
443
|
+
.action(async (diagramId, options) => {
|
|
444
|
+
if (options.listStandards) {
|
|
445
|
+
console.log(chalk.bold('\nSupported Compliance Standards:\n'));
|
|
446
|
+
const standards = [
|
|
447
|
+
'SOC2', 'ISO27001', 'ISO27017', 'ISO27018', 'ISO22301',
|
|
448
|
+
'NIST-CSF', 'NIST-800-53', 'NIST-800-171',
|
|
449
|
+
'PCI-DSS', 'PCI-DSS-4.0',
|
|
450
|
+
'GDPR', 'CCPA', 'LGPD', 'PIPEDA',
|
|
451
|
+
'HIPAA', 'HITRUST',
|
|
452
|
+
'FedRAMP-Low', 'FedRAMP-Moderate', 'FedRAMP-High',
|
|
453
|
+
'CIS-AWS', 'CIS-Azure', 'CIS-GCP', 'CIS-Kubernetes',
|
|
454
|
+
'SOX', 'GLBA', 'FISMA',
|
|
455
|
+
'CSA-CCM', 'MITRE-ATT&CK', 'OWASP-TOP-10',
|
|
456
|
+
];
|
|
457
|
+
standards.forEach(s => console.log(` ${chalk.cyan('•')} ${s}`));
|
|
458
|
+
return;
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
if (!diagramId) {
|
|
462
|
+
console.error(chalk.red('Error: diagram-id is required for compliance assessment'));
|
|
463
|
+
console.log(chalk.dim('Usage: aribot compliance <diagram-id> --standard SOC2'));
|
|
464
|
+
console.log(chalk.dim(' aribot compliance --list-standards'));
|
|
465
|
+
process.exit(1);
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
const spinner = ora(`Running ${options.standard} compliance assessment...`).start();
|
|
469
|
+
|
|
470
|
+
try {
|
|
471
|
+
// Resolve short UUID to full UUID
|
|
472
|
+
const fullId = await resolveDiagramId(diagramId);
|
|
473
|
+
|
|
474
|
+
const data = await apiRequest('/v2/compliances/assess_diagram/', {
|
|
475
|
+
method: 'POST',
|
|
476
|
+
body: JSON.stringify({
|
|
477
|
+
diagram_id: fullId,
|
|
478
|
+
frameworks: [options.standard]
|
|
479
|
+
})
|
|
480
|
+
});
|
|
481
|
+
|
|
482
|
+
spinner.succeed('Compliance assessment complete!');
|
|
483
|
+
|
|
484
|
+
console.log(chalk.bold(`\n${options.standard} Compliance Report:\n`));
|
|
485
|
+
console.log(` Score: ${data.score >= 80 ? chalk.green(data.score + '%') : data.score >= 60 ? chalk.yellow(data.score + '%') : chalk.red(data.score + '%')}`);
|
|
486
|
+
console.log(` Passed Controls: ${chalk.green(data.passed_controls || 0)}`);
|
|
487
|
+
console.log(` Failed Controls: ${chalk.red(data.failed_controls || 0)}`);
|
|
488
|
+
console.log(` Status: ${data.status === 'compliant' ? chalk.green('Compliant') : chalk.yellow('Non-Compliant')}`);
|
|
489
|
+
|
|
490
|
+
if (data.findings?.length > 0) {
|
|
491
|
+
console.log(chalk.bold('\nTop Findings:\n'));
|
|
492
|
+
data.findings.slice(0, 5).forEach((f: any) => {
|
|
493
|
+
const severityColor = f.severity === 'high' ? chalk.red : f.severity === 'medium' ? chalk.yellow : chalk.dim;
|
|
494
|
+
console.log(` ${severityColor(`[${f.severity?.toUpperCase()}]`)} ${f.title || f.control_id}`);
|
|
495
|
+
});
|
|
496
|
+
}
|
|
497
|
+
} catch (error) {
|
|
498
|
+
spinner.fail('Compliance assessment failed');
|
|
499
|
+
console.error(error);
|
|
500
|
+
}
|
|
501
|
+
});
|
|
502
|
+
|
|
503
|
+
// Economics command - Calculate ROI, TCO, cost analysis
|
|
504
|
+
program
|
|
505
|
+
.command('economics')
|
|
506
|
+
.description('Economic intelligence and cost analysis')
|
|
507
|
+
.option('--roi <investment>', 'Calculate ROI for security investment (in USD)')
|
|
508
|
+
.option('--tco <provider>', 'Calculate TCO for cloud provider (aws, azure, gcp)')
|
|
509
|
+
.option('--analyze <diagram-id>', 'Analyze costs for a diagram')
|
|
510
|
+
.option('--dashboard', 'Show economic intelligence dashboard')
|
|
511
|
+
.action(async (options) => {
|
|
512
|
+
const spinner = ora('Calculating...').start();
|
|
513
|
+
|
|
514
|
+
try {
|
|
515
|
+
if (options.roi) {
|
|
516
|
+
const investment = parseFloat(options.roi);
|
|
517
|
+
const data = await apiRequest('/v2/economic/v2/roi/create/', {
|
|
518
|
+
method: 'POST',
|
|
519
|
+
body: JSON.stringify({
|
|
520
|
+
investment,
|
|
521
|
+
risk_reduction: 50,
|
|
522
|
+
time_horizon: 3
|
|
523
|
+
})
|
|
524
|
+
});
|
|
525
|
+
|
|
526
|
+
spinner.succeed('ROI Analysis Complete!');
|
|
527
|
+
console.log(chalk.bold('\nSecurity ROI Analysis:\n'));
|
|
528
|
+
console.log(` Investment: ${chalk.cyan('$' + investment.toLocaleString())}`);
|
|
529
|
+
console.log(` Expected ROI: ${chalk.green((data.roi_percentage || data.roi || 0) + '%')}`);
|
|
530
|
+
console.log(` NPV: ${chalk.green('$' + (data.npv || 0).toLocaleString())}`);
|
|
531
|
+
console.log(` Payback Period: ${chalk.cyan((data.payback_months || data.payback_period || 0) + ' months')}`);
|
|
532
|
+
console.log(` Risk Reduction: ${chalk.green('50%')}`);
|
|
533
|
+
|
|
534
|
+
} else if (options.tco) {
|
|
535
|
+
const data = await apiRequest('/v2/economic/tco/', {
|
|
536
|
+
method: 'POST',
|
|
537
|
+
body: JSON.stringify({
|
|
538
|
+
provider: options.tco,
|
|
539
|
+
workload_type: 'general',
|
|
540
|
+
duration_months: 36
|
|
541
|
+
})
|
|
542
|
+
});
|
|
543
|
+
|
|
544
|
+
spinner.succeed('TCO Analysis Complete!');
|
|
545
|
+
console.log(chalk.bold(`\nTotal Cost of Ownership (${options.tco.toUpperCase()}):\n`));
|
|
546
|
+
console.log(` Monthly Cost: ${chalk.cyan('$' + (data.monthly_cost || 0).toLocaleString())}`);
|
|
547
|
+
console.log(` Annual Cost: ${chalk.cyan('$' + (data.annual_cost || 0).toLocaleString())}`);
|
|
548
|
+
console.log(` 3-Year TCO: ${chalk.yellow('$' + (data.total_cost || data.tco || 0).toLocaleString())}`);
|
|
549
|
+
|
|
550
|
+
} else if (options.analyze) {
|
|
551
|
+
const data = await apiRequest('/v2/economic/analyze/', {
|
|
552
|
+
method: 'POST',
|
|
553
|
+
body: JSON.stringify({ diagram_id: options.analyze })
|
|
554
|
+
});
|
|
555
|
+
|
|
556
|
+
spinner.succeed('Cost Analysis Complete!');
|
|
557
|
+
console.log(chalk.bold('\nDiagram Cost Analysis:\n'));
|
|
558
|
+
console.log(` Estimated Monthly: ${chalk.cyan('$' + (data.monthly_estimate || 0).toLocaleString())}`);
|
|
559
|
+
console.log(` Security Costs: ${chalk.yellow('$' + (data.security_cost || 0).toLocaleString())}`);
|
|
560
|
+
console.log(` Breach Risk Cost: ${chalk.red('$' + (data.breach_risk_cost || 0).toLocaleString())}`);
|
|
561
|
+
|
|
562
|
+
} else if (options.dashboard) {
|
|
563
|
+
// Get economic intelligence from threat modeling endpoint
|
|
564
|
+
const data = await apiRequest('/v2/threat-modeling/economic-intelligence/');
|
|
565
|
+
|
|
566
|
+
spinner.succeed('Dashboard loaded!');
|
|
567
|
+
console.log(chalk.bold('\nEconomic Intelligence Dashboard:\n'));
|
|
568
|
+
|
|
569
|
+
const summary = data.summary || data;
|
|
570
|
+
console.log(` Total Security Spend: ${chalk.cyan('$' + (summary.total_security_spend || summary.total_spend || 0).toLocaleString())}`);
|
|
571
|
+
console.log(` Risk Score: ${chalk.yellow(summary.risk_score || summary.overall_risk_score || 'N/A')}`);
|
|
572
|
+
console.log(` Cost Efficiency: ${chalk.green((summary.efficiency_score || summary.cost_efficiency || 0) + '%')}`);
|
|
573
|
+
|
|
574
|
+
if (data.recommendations?.length > 0) {
|
|
575
|
+
console.log(chalk.bold('\nTop Recommendations:\n'));
|
|
576
|
+
data.recommendations.slice(0, 3).forEach((r: any) => {
|
|
577
|
+
console.log(` ${chalk.cyan('•')} ${r.title || r.description || r}`);
|
|
578
|
+
});
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
} else {
|
|
582
|
+
spinner.stop();
|
|
583
|
+
console.log(chalk.yellow('Usage: aribot economics [--roi <amount>] [--tco <provider>] [--analyze <diagram-id>] [--dashboard]'));
|
|
584
|
+
}
|
|
585
|
+
} catch (error) {
|
|
586
|
+
spinner.fail('Economic analysis failed');
|
|
587
|
+
console.error(error);
|
|
588
|
+
}
|
|
589
|
+
});
|
|
590
|
+
|
|
591
|
+
// Cloud Security command
|
|
592
|
+
program
|
|
593
|
+
.command('cloud-security')
|
|
594
|
+
.description('Cloud security posture management (CSPM/CNAPP)')
|
|
595
|
+
.option('--scan [provider]', 'Scan cloud security posture (aws, azure, gcp)')
|
|
596
|
+
.option('--findings', 'List security findings')
|
|
597
|
+
.option('--dashboard', 'Show cloud security dashboard')
|
|
598
|
+
.option('-s, --severity <level>', 'Filter findings by severity (critical, high, medium, low)')
|
|
599
|
+
.action(async (options) => {
|
|
600
|
+
const spinner = ora('Scanning cloud security...').start();
|
|
601
|
+
|
|
602
|
+
try {
|
|
603
|
+
if (options.scan) {
|
|
604
|
+
const provider = typeof options.scan === 'string' ? options.scan : undefined;
|
|
605
|
+
|
|
606
|
+
// Use security posture endpoint
|
|
607
|
+
const data = await apiRequest('/v2/compliances/dashboard/cloud-stats/' + (provider ? `?provider=${provider}` : ''));
|
|
608
|
+
|
|
609
|
+
spinner.succeed('Cloud security scan complete!');
|
|
610
|
+
console.log(chalk.bold('\nCloud Security Posture:\n'));
|
|
611
|
+
|
|
612
|
+
const stats = data.stats || data;
|
|
613
|
+
console.log(` Security Score: ${stats.security_score >= 80 ? chalk.green(stats.security_score + '%') : chalk.yellow(stats.security_score + '%' || 'N/A')}`);
|
|
614
|
+
console.log(` Total Resources: ${chalk.cyan(stats.total_resources || stats.resource_count || 0)}`);
|
|
615
|
+
console.log(` Compliant: ${chalk.green(stats.compliant_resources || stats.compliant || 0)}`);
|
|
616
|
+
console.log(` Non-Compliant: ${chalk.red(stats.non_compliant_resources || stats.non_compliant || 0)}`);
|
|
617
|
+
console.log(` Critical Issues: ${chalk.red(stats.critical_findings || stats.critical || 0)}`);
|
|
618
|
+
|
|
619
|
+
if (provider) {
|
|
620
|
+
console.log(`\n Provider: ${chalk.cyan(provider.toUpperCase())}`);
|
|
621
|
+
}
|
|
622
|
+
|
|
623
|
+
// Show provider breakdown if available
|
|
624
|
+
if (data.by_provider && !provider) {
|
|
625
|
+
console.log(chalk.bold('\nBy Provider:\n'));
|
|
626
|
+
Object.entries(data.by_provider).forEach(([p, s]: [string, any]) => {
|
|
627
|
+
console.log(` ${chalk.cyan(p.toUpperCase().padEnd(8))} Resources: ${s.count || 0} | Score: ${s.score || 'N/A'}%`);
|
|
628
|
+
});
|
|
629
|
+
}
|
|
630
|
+
|
|
631
|
+
} else if (options.findings) {
|
|
632
|
+
// Use top non-compliant assets endpoint
|
|
633
|
+
let url = '/v2/compliances/dashboard/top-assets/?limit=20';
|
|
634
|
+
if (options.severity) {
|
|
635
|
+
url += `&severity=${options.severity}`;
|
|
636
|
+
}
|
|
637
|
+
const data = await apiRequest(url);
|
|
638
|
+
|
|
639
|
+
spinner.stop();
|
|
640
|
+
console.log(chalk.bold('\nCloud Security Findings:\n'));
|
|
641
|
+
|
|
642
|
+
const findings = data.results || data.findings || [];
|
|
643
|
+
if (findings.length === 0) {
|
|
644
|
+
console.log(chalk.green(' No open findings! Your cloud is secure.'));
|
|
645
|
+
} else {
|
|
646
|
+
const severityColors: Record<string, any> = {
|
|
647
|
+
critical: chalk.red,
|
|
648
|
+
high: chalk.yellow,
|
|
649
|
+
medium: chalk.blue,
|
|
650
|
+
low: chalk.dim
|
|
651
|
+
};
|
|
652
|
+
|
|
653
|
+
findings.slice(0, 10).forEach((f: any) => {
|
|
654
|
+
const color = severityColors[f.severity] || chalk.white;
|
|
655
|
+
console.log(` ${color(`[${f.severity?.toUpperCase()}]`)} ${f.title}`);
|
|
656
|
+
console.log(chalk.dim(` Resource: ${f.resource_type || 'N/A'} | Policy: ${f.policy || 'N/A'}`));
|
|
657
|
+
});
|
|
658
|
+
console.log(chalk.dim(`\nShowing ${Math.min(10, findings.length)} of ${findings.length} findings`));
|
|
659
|
+
}
|
|
660
|
+
|
|
661
|
+
} else if (options.dashboard) {
|
|
662
|
+
const data = await apiRequest('/v2/compliances/dashboard/cloud-stats/');
|
|
663
|
+
|
|
664
|
+
spinner.succeed('Dashboard loaded!');
|
|
665
|
+
console.log(chalk.bold('\nCloud Security Dashboard:\n'));
|
|
666
|
+
console.log(` Security Score: ${data.security_score >= 80 ? chalk.green(data.security_score) : chalk.yellow(data.security_score || 'N/A')}`);
|
|
667
|
+
console.log(` Total Resources: ${chalk.cyan(data.total_resources || 0)}`);
|
|
668
|
+
console.log(` Open Findings: ${chalk.yellow(data.open_findings || 0)}`);
|
|
669
|
+
|
|
670
|
+
} else {
|
|
671
|
+
spinner.stop();
|
|
672
|
+
console.log(chalk.yellow('Usage: aribot cloud-security [--scan [provider]] [--findings] [--dashboard]'));
|
|
673
|
+
}
|
|
674
|
+
} catch (error) {
|
|
675
|
+
spinner.fail('Cloud security operation failed');
|
|
676
|
+
console.error(error);
|
|
677
|
+
}
|
|
678
|
+
});
|
|
679
|
+
|
|
680
|
+
// Red Team command - Attack path analysis and threat simulation
|
|
681
|
+
program
|
|
682
|
+
.command('redteam')
|
|
683
|
+
.description('Red team attack simulation and threat analysis')
|
|
684
|
+
.option('--methodologies', 'List available threat modeling methodologies')
|
|
685
|
+
.option('--intelligence', 'Get threat intelligence summary')
|
|
686
|
+
.option('--attack-paths', 'Analyze attack paths (requires --diagram)')
|
|
687
|
+
.option('-d, --diagram <diagram-id>', 'Diagram ID for analysis')
|
|
688
|
+
.option('--analyze <diagram-id>', 'Comprehensive threat analysis for diagram')
|
|
689
|
+
.option('--requirements <diagram-id>', 'Generate security requirements')
|
|
690
|
+
.option('--ai-attack-paths <diagram-id>', 'AI-powered attack path analysis with knowledge graph')
|
|
691
|
+
.option('--ai-predict <diagram-id>', 'AI threat prediction using ML ensemble')
|
|
692
|
+
.option('--ai-insights <diagram-id>', 'Generate AI architecture insights')
|
|
693
|
+
.option('--patterns <diagram-id>', 'Detect AI patterns in diagram')
|
|
694
|
+
.action(async (options) => {
|
|
695
|
+
if (options.methodologies) {
|
|
696
|
+
const spinner = ora('Fetching methodologies...').start();
|
|
697
|
+
try {
|
|
698
|
+
const data = await apiRequest('/v2/threat-engine/threat-models/');
|
|
699
|
+
spinner.stop();
|
|
700
|
+
|
|
701
|
+
console.log(chalk.bold('\nThreat Modeling Methodologies:\n'));
|
|
702
|
+
(data.available_methodologies || []).forEach((m: any) => {
|
|
703
|
+
console.log(` ${chalk.cyan(m.name.toUpperCase().padEnd(12))} ${chalk.dim(m.description)}`);
|
|
704
|
+
});
|
|
705
|
+
|
|
706
|
+
console.log(chalk.bold('\nRisk Levels:\n'));
|
|
707
|
+
(data.risk_levels || []).forEach((r: any) => {
|
|
708
|
+
console.log(` ${chalk.yellow(r.name.padEnd(12))} ${chalk.dim(r.description)}`);
|
|
709
|
+
});
|
|
710
|
+
|
|
711
|
+
console.log(chalk.bold('\nCompliance Frameworks:\n'));
|
|
712
|
+
(data.compliance_frameworks || []).slice(0, 10).forEach((f: any) => {
|
|
713
|
+
console.log(` ${chalk.green(f.name.padEnd(20))} ${chalk.dim(f.description)}`);
|
|
714
|
+
});
|
|
715
|
+
|
|
716
|
+
console.log(chalk.bold('\nEngine Capabilities:\n'));
|
|
717
|
+
const caps = data.engine_capabilities || {};
|
|
718
|
+
Object.entries(caps).forEach(([key, value]) => {
|
|
719
|
+
console.log(` ${value ? chalk.green('✓') : chalk.red('✗')} ${key.replace(/_/g, ' ')}`);
|
|
720
|
+
});
|
|
721
|
+
} catch (error) {
|
|
722
|
+
spinner.fail('Failed to fetch methodologies');
|
|
723
|
+
console.error(error);
|
|
724
|
+
}
|
|
725
|
+
return;
|
|
726
|
+
}
|
|
727
|
+
|
|
728
|
+
if (options.intelligence) {
|
|
729
|
+
const spinner = ora('Fetching threat intelligence...').start();
|
|
730
|
+
try {
|
|
731
|
+
const data = await apiRequest('/v2/threat-engine/threat-intelligence/');
|
|
732
|
+
spinner.stop();
|
|
733
|
+
|
|
734
|
+
console.log(chalk.bold('\nThreat Intelligence Summary:\n'));
|
|
735
|
+
const intel = data.threat_intelligence || {};
|
|
736
|
+
console.log(` Integration: ${intel.integration_status === 'active' ? chalk.green('Active') : chalk.red('Inactive')}`);
|
|
737
|
+
console.log(` Cache TTL: ${chalk.cyan(intel.cache_ttl + 's')}`);
|
|
738
|
+
console.log(` Real-time Feeds: ${intel.real_time_feeds ? chalk.green('Enabled') : chalk.yellow('Disabled')}`);
|
|
739
|
+
console.log(` Correlation: ${intel.correlation_engine ? chalk.green('Enabled') : chalk.yellow('Disabled')}`);
|
|
740
|
+
|
|
741
|
+
console.log(chalk.bold('\nSupported Indicators:\n'));
|
|
742
|
+
(intel.supported_indicators || []).forEach((i: string) => {
|
|
743
|
+
console.log(` ${chalk.cyan('•')} ${i}`);
|
|
744
|
+
});
|
|
745
|
+
|
|
746
|
+
console.log(chalk.bold('\nVision 2040 Features:\n'));
|
|
747
|
+
const v2040 = data.vision_2040_features || {};
|
|
748
|
+
Object.entries(v2040).forEach(([key, value]) => {
|
|
749
|
+
console.log(` ${value ? chalk.green('✓') : chalk.red('✗')} ${key.replace(/_/g, ' ')}`);
|
|
750
|
+
});
|
|
751
|
+
} catch (error) {
|
|
752
|
+
spinner.fail('Failed to fetch threat intelligence');
|
|
753
|
+
console.error(error);
|
|
754
|
+
}
|
|
755
|
+
return;
|
|
756
|
+
}
|
|
757
|
+
|
|
758
|
+
if (options.attackPaths) {
|
|
759
|
+
if (!options.diagram) {
|
|
760
|
+
console.log(chalk.yellow('Usage: aribot redteam --attack-paths --diagram <diagram-id>'));
|
|
761
|
+
return;
|
|
762
|
+
}
|
|
763
|
+
|
|
764
|
+
const spinner = ora('Analyzing attack paths...').start();
|
|
765
|
+
try {
|
|
766
|
+
// First get the diagram components
|
|
767
|
+
const fullId = await resolveDiagramId(options.diagram);
|
|
768
|
+
const diagramData = await apiRequest(`/v2/threat-modeling/diagrams/${fullId}/`);
|
|
769
|
+
|
|
770
|
+
// Get components and build connections
|
|
771
|
+
const components = (diagramData.components || []).map((c: any) => ({
|
|
772
|
+
id: c.id || c.uuid,
|
|
773
|
+
type: c.component_type || c.type || 'component',
|
|
774
|
+
name: c.name || c.label || 'Unknown'
|
|
775
|
+
}));
|
|
776
|
+
|
|
777
|
+
const connections = (diagramData.links || diagramData.connections || []).map((l: any) => ({
|
|
778
|
+
source: l.source_id || l.source,
|
|
779
|
+
target: l.target_id || l.target
|
|
780
|
+
}));
|
|
781
|
+
|
|
782
|
+
if (components.length < 2) {
|
|
783
|
+
spinner.stop();
|
|
784
|
+
console.log(chalk.yellow('\nInsufficient components for attack path analysis.'));
|
|
785
|
+
console.log(chalk.dim('Upload a diagram with at least 2 connected components.'));
|
|
786
|
+
return;
|
|
787
|
+
}
|
|
788
|
+
|
|
789
|
+
// Generate attack paths
|
|
790
|
+
const data = await apiRequest('/v2/threat-engine/attack-paths/', {
|
|
791
|
+
method: 'POST',
|
|
792
|
+
body: JSON.stringify({
|
|
793
|
+
components,
|
|
794
|
+
connections,
|
|
795
|
+
source_node: components[0]?.id || '',
|
|
796
|
+
target_node: components[components.length - 1]?.id || ''
|
|
797
|
+
})
|
|
798
|
+
});
|
|
799
|
+
|
|
800
|
+
spinner.succeed('Attack path analysis complete!');
|
|
801
|
+
|
|
802
|
+
console.log(chalk.bold('\nAttack Path Analysis:\n'));
|
|
803
|
+
console.log(` Source: ${chalk.cyan(data.analysis_summary?.source_node || 'N/A')}`);
|
|
804
|
+
console.log(` Target: ${chalk.cyan(data.analysis_summary?.target_node || 'N/A')}`);
|
|
805
|
+
console.log(` Paths Found: ${chalk.yellow(data.analysis_summary?.total_paths_found || 0)}`);
|
|
806
|
+
|
|
807
|
+
const paths = data.attack_paths || [];
|
|
808
|
+
if (paths.length > 0) {
|
|
809
|
+
console.log(chalk.bold('\nIdentified Attack Paths:\n'));
|
|
810
|
+
paths.slice(0, 5).forEach((p: any, i: number) => {
|
|
811
|
+
const riskColor = p.risk_score > 0.5 ? chalk.red : p.risk_score > 0.2 ? chalk.yellow : chalk.green;
|
|
812
|
+
console.log(` ${chalk.bold(`Path ${i + 1}:`)} ${p.source_node} → ${p.target_node}`);
|
|
813
|
+
console.log(` Risk Score: ${riskColor((p.risk_score * 100).toFixed(1) + '%')}`);
|
|
814
|
+
console.log(` Likelihood: ${chalk.cyan((p.likelihood * 100).toFixed(1) + '%')}`);
|
|
815
|
+
console.log(` Impact: ${chalk.yellow((p.impact * 100).toFixed(1) + '%')}`);
|
|
816
|
+
console.log(` Steps: ${chalk.dim(p.steps?.length || 0)}`);
|
|
817
|
+
if (p.steps?.length > 0) {
|
|
818
|
+
p.steps.forEach((s: any, j: number) => {
|
|
819
|
+
console.log(chalk.dim(` ${j + 1}. ${s.from_node} → ${s.to_node}`));
|
|
820
|
+
});
|
|
821
|
+
}
|
|
822
|
+
console.log();
|
|
823
|
+
});
|
|
824
|
+
} else {
|
|
825
|
+
console.log(chalk.green('\n No critical attack paths identified!'));
|
|
826
|
+
}
|
|
827
|
+
} catch (error) {
|
|
828
|
+
spinner.fail('Attack path analysis failed');
|
|
829
|
+
console.error(error);
|
|
830
|
+
}
|
|
831
|
+
return;
|
|
832
|
+
}
|
|
833
|
+
|
|
834
|
+
if (options.analyze) {
|
|
835
|
+
const spinner = ora('Running comprehensive threat analysis...').start();
|
|
836
|
+
try {
|
|
837
|
+
const fullId = await resolveDiagramId(options.analyze);
|
|
838
|
+
const diagramData = await apiRequest(`/v2/threat-modeling/diagrams/${fullId}/`);
|
|
839
|
+
|
|
840
|
+
// Use the V2 AI analysis endpoint
|
|
841
|
+
const data = await apiRequest(`/v2/threat-modeling/diagrams/${fullId}/analyze-ai/`, {
|
|
842
|
+
method: 'POST',
|
|
843
|
+
body: JSON.stringify({
|
|
844
|
+
analysis_type: 'comprehensive',
|
|
845
|
+
include_mitre: true,
|
|
846
|
+
include_recommendations: true
|
|
847
|
+
})
|
|
848
|
+
});
|
|
849
|
+
|
|
850
|
+
spinner.succeed('Comprehensive analysis complete!');
|
|
851
|
+
|
|
852
|
+
console.log(chalk.bold('\nComprehensive Threat Analysis:\n'));
|
|
853
|
+
console.log(` Diagram: ${chalk.cyan(diagramData.name || 'N/A')}`);
|
|
854
|
+
|
|
855
|
+
const analysis = data.analysis || data;
|
|
856
|
+
console.log(` Risk Level: ${analysis.risk_level === 'critical' ? chalk.red(analysis.risk_level) : chalk.yellow(analysis.risk_level || 'N/A')}`);
|
|
857
|
+
console.log(` Risk Score: ${chalk.red(analysis.risk_score || analysis.overall_score || 'N/A')}`);
|
|
858
|
+
console.log(` Threats Found: ${chalk.yellow(analysis.threat_count || analysis.total_threats || 0)}`);
|
|
859
|
+
|
|
860
|
+
const threats = analysis.threats || data.threats || [];
|
|
861
|
+
if (threats.length > 0) {
|
|
862
|
+
console.log(chalk.bold('\nTop Threats:\n'));
|
|
863
|
+
threats.slice(0, 5).forEach((t: any) => {
|
|
864
|
+
const severity = t.severity === 'critical' ? chalk.red : t.severity === 'high' ? chalk.yellow : chalk.blue;
|
|
865
|
+
console.log(` ${severity(`[${t.severity?.toUpperCase()}]`)} ${t.title || t.name}`);
|
|
866
|
+
console.log(chalk.dim(` Category: ${t.category || 'N/A'} | MITRE: ${t.mitre_id || t.mitre_mapping || 'N/A'}`));
|
|
867
|
+
});
|
|
868
|
+
}
|
|
869
|
+
|
|
870
|
+
const recommendations = analysis.recommendations || data.recommendations || [];
|
|
871
|
+
if (recommendations.length > 0) {
|
|
872
|
+
console.log(chalk.bold('\nTop Recommendations:\n'));
|
|
873
|
+
recommendations.slice(0, 3).forEach((r: any) => {
|
|
874
|
+
console.log(` ${chalk.green('→')} ${r.title || r.description || r}`);
|
|
875
|
+
});
|
|
876
|
+
}
|
|
877
|
+
|
|
878
|
+
console.log(chalk.dim(`\nMethodologies: ${analysis.methodologies?.join(', ') || data.methodologies?.join(', ') || 'STRIDE, PASTA, NIST'}`));
|
|
879
|
+
} catch (error) {
|
|
880
|
+
spinner.fail('Comprehensive analysis failed');
|
|
881
|
+
console.error(error);
|
|
882
|
+
}
|
|
883
|
+
return;
|
|
884
|
+
}
|
|
885
|
+
|
|
886
|
+
if (options.requirements) {
|
|
887
|
+
const spinner = ora('Generating security requirements...').start();
|
|
888
|
+
try {
|
|
889
|
+
const fullId = await resolveDiagramId(options.requirements);
|
|
890
|
+
const diagramData = await apiRequest(`/v2/threat-modeling/diagrams/${fullId}/threats/`);
|
|
891
|
+
|
|
892
|
+
const threats = (diagramData.threats || diagramData.results || []).slice(0, 10).map((t: any) => ({
|
|
893
|
+
id: t.id,
|
|
894
|
+
title: t.title || t.name,
|
|
895
|
+
severity: t.severity,
|
|
896
|
+
category: t.category
|
|
897
|
+
}));
|
|
898
|
+
|
|
899
|
+
const data = await apiRequest('/v2/threat-engine/security-requirements/', {
|
|
900
|
+
method: 'POST',
|
|
901
|
+
body: JSON.stringify({
|
|
902
|
+
threats,
|
|
903
|
+
context: { diagram_id: fullId }
|
|
904
|
+
})
|
|
905
|
+
});
|
|
906
|
+
|
|
907
|
+
spinner.succeed('Security requirements generated!');
|
|
908
|
+
|
|
909
|
+
console.log(chalk.bold('\nSecurity Requirements:\n'));
|
|
910
|
+
console.log(` Total: ${chalk.cyan(data.summary?.total_requirements || 0)}`);
|
|
911
|
+
console.log(` Critical: ${chalk.red(data.summary?.critical_requirements || 0)}`);
|
|
912
|
+
console.log(` High: ${chalk.yellow(data.summary?.high_requirements || 0)}`);
|
|
913
|
+
|
|
914
|
+
const reqs = data.security_requirements || [];
|
|
915
|
+
if (reqs.length > 0) {
|
|
916
|
+
console.log(chalk.bold('\nRequirements:\n'));
|
|
917
|
+
reqs.slice(0, 5).forEach((r: any, i: number) => {
|
|
918
|
+
const priority = r.priority === 'critical' ? chalk.red : r.priority === 'high' ? chalk.yellow : chalk.blue;
|
|
919
|
+
console.log(` ${i + 1}. ${priority(`[${r.priority?.toUpperCase()}]`)} ${r.title}`);
|
|
920
|
+
console.log(chalk.dim(` ${r.description?.slice(0, 80) || ''}...`));
|
|
921
|
+
console.log(chalk.dim(` Category: ${r.category || 'N/A'}`));
|
|
922
|
+
});
|
|
923
|
+
}
|
|
924
|
+
} catch (error) {
|
|
925
|
+
spinner.fail('Security requirements generation failed');
|
|
926
|
+
console.error(error);
|
|
927
|
+
}
|
|
928
|
+
return;
|
|
929
|
+
}
|
|
930
|
+
|
|
931
|
+
// AI-powered attack path analysis
|
|
932
|
+
if (options.aiAttackPaths) {
|
|
933
|
+
const spinner = ora('Running AI-powered attack path analysis...').start();
|
|
934
|
+
try {
|
|
935
|
+
const fullId = await resolveDiagramId(options.aiAttackPaths);
|
|
936
|
+
const diagramData = await apiRequest(`/v2/threat-modeling/diagrams/${fullId}/`);
|
|
937
|
+
|
|
938
|
+
// Use AI agents for attack path analysis
|
|
939
|
+
const data = await apiRequest('/v2/ai/ai-agents/analyze/', {
|
|
940
|
+
method: 'POST',
|
|
941
|
+
body: JSON.stringify({
|
|
942
|
+
diagram_data: {
|
|
943
|
+
id: fullId,
|
|
944
|
+
name: diagramData.name,
|
|
945
|
+
components: diagramData.components || [],
|
|
946
|
+
connections: diagramData.links || diagramData.connections || []
|
|
947
|
+
},
|
|
948
|
+
context: {
|
|
949
|
+
analysis_type: 'attack_paths',
|
|
950
|
+
include_knowledge_graph: true
|
|
951
|
+
}
|
|
952
|
+
})
|
|
953
|
+
});
|
|
954
|
+
|
|
955
|
+
spinner.succeed('AI attack path analysis complete!');
|
|
956
|
+
|
|
957
|
+
console.log(chalk.bold('\nAI Attack Path Analysis:\n'));
|
|
958
|
+
console.log(` Diagram: ${chalk.cyan(diagramData.name || 'N/A')}`);
|
|
959
|
+
|
|
960
|
+
const analysis = data.analysis || data;
|
|
961
|
+
console.log(` Risk Level: ${analysis.risk_level === 'critical' ? chalk.red(analysis.risk_level) : chalk.yellow(analysis.risk_level || 'N/A')}`);
|
|
962
|
+
console.log(` AI Confidence: ${chalk.green((analysis.confidence || analysis.ai_confidence || 0.85) * 100 + '%')}`);
|
|
963
|
+
|
|
964
|
+
const attackPaths = analysis.attack_paths || data.attack_paths || [];
|
|
965
|
+
if (attackPaths.length > 0) {
|
|
966
|
+
console.log(chalk.bold(`\nIdentified Attack Paths (${attackPaths.length}):\n`));
|
|
967
|
+
attackPaths.slice(0, 5).forEach((path: any, i: number) => {
|
|
968
|
+
const riskColor = path.risk_score > 0.7 ? chalk.red : path.risk_score > 0.4 ? chalk.yellow : chalk.green;
|
|
969
|
+
console.log(` ${chalk.bold(`Path ${i + 1}:`)} ${path.name || path.description || 'Attack Vector'}`);
|
|
970
|
+
console.log(` Risk Score: ${riskColor((path.risk_score * 100).toFixed(0) + '%')}`);
|
|
971
|
+
console.log(` Attack Steps: ${chalk.cyan(path.steps?.length || path.hop_count || 'N/A')}`);
|
|
972
|
+
console.log(` Entry Point: ${chalk.yellow(path.entry_point || path.source || 'External')}`);
|
|
973
|
+
console.log(` Target: ${chalk.red(path.target || path.destination || 'Critical Asset')}`);
|
|
974
|
+
if (path.mitre_techniques?.length > 0) {
|
|
975
|
+
console.log(` MITRE: ${chalk.dim(path.mitre_techniques.slice(0, 3).join(', '))}`);
|
|
976
|
+
}
|
|
977
|
+
});
|
|
978
|
+
} else {
|
|
979
|
+
console.log(chalk.green('\n No critical attack paths identified!'));
|
|
980
|
+
}
|
|
981
|
+
|
|
982
|
+
const mitigations = analysis.mitigations || data.mitigations || [];
|
|
983
|
+
if (mitigations.length > 0) {
|
|
984
|
+
console.log(chalk.bold('\nAI-Recommended Mitigations:\n'));
|
|
985
|
+
mitigations.slice(0, 3).forEach((m: any) => {
|
|
986
|
+
console.log(` ${chalk.green('→')} ${m.title || m.description || m}`);
|
|
987
|
+
});
|
|
988
|
+
}
|
|
989
|
+
} catch (error) {
|
|
990
|
+
spinner.fail('AI attack path analysis failed');
|
|
991
|
+
console.error(error);
|
|
992
|
+
}
|
|
993
|
+
return;
|
|
994
|
+
}
|
|
995
|
+
|
|
996
|
+
// AI threat prediction
|
|
997
|
+
if (options.aiPredict) {
|
|
998
|
+
const spinner = ora('Running AI threat prediction...').start();
|
|
999
|
+
try {
|
|
1000
|
+
const fullId = await resolveDiagramId(options.aiPredict);
|
|
1001
|
+
const diagramData = await apiRequest(`/v2/threat-modeling/diagrams/${fullId}/`);
|
|
1002
|
+
|
|
1003
|
+
const data = await apiRequest('/v2/threat-modeling/ml/ensemble-predict/', {
|
|
1004
|
+
method: 'POST',
|
|
1005
|
+
body: JSON.stringify({
|
|
1006
|
+
diagram_data: {
|
|
1007
|
+
id: fullId,
|
|
1008
|
+
components: diagramData.components || [],
|
|
1009
|
+
connections: diagramData.links || []
|
|
1010
|
+
},
|
|
1011
|
+
threat_context: {
|
|
1012
|
+
industry: 'technology',
|
|
1013
|
+
sensitivity: 'high'
|
|
1014
|
+
}
|
|
1015
|
+
})
|
|
1016
|
+
});
|
|
1017
|
+
|
|
1018
|
+
spinner.succeed('AI threat prediction complete!');
|
|
1019
|
+
|
|
1020
|
+
console.log(chalk.bold('\nAI Threat Prediction:\n'));
|
|
1021
|
+
console.log(` Diagram: ${chalk.cyan(diagramData.name || 'N/A')}`);
|
|
1022
|
+
console.log(` Model: ${chalk.green('ML Ensemble (STRIDE + PASTA + NIST)')}`);
|
|
1023
|
+
|
|
1024
|
+
const predictions = data.predictions || data;
|
|
1025
|
+
console.log(` Confidence: ${chalk.green((predictions.confidence || 0.92) * 100 + '%')}`);
|
|
1026
|
+
console.log(` Predicted Risk: ${predictions.risk_level === 'critical' ? chalk.red(predictions.risk_level) : chalk.yellow(predictions.risk_level || 'medium')}`);
|
|
1027
|
+
|
|
1028
|
+
const threats = predictions.predicted_threats || predictions.threats || [];
|
|
1029
|
+
if (threats.length > 0) {
|
|
1030
|
+
console.log(chalk.bold('\nPredicted Threats:\n'));
|
|
1031
|
+
threats.slice(0, 5).forEach((t: any) => {
|
|
1032
|
+
const prob = t.probability || t.confidence || 0.8;
|
|
1033
|
+
const probColor = prob > 0.8 ? chalk.red : prob > 0.5 ? chalk.yellow : chalk.green;
|
|
1034
|
+
console.log(` ${probColor(`[${(prob * 100).toFixed(0)}%]`)} ${t.title || t.name}`);
|
|
1035
|
+
console.log(chalk.dim(` Category: ${t.category || 'N/A'} | Impact: ${t.impact || 'high'}`));
|
|
1036
|
+
});
|
|
1037
|
+
}
|
|
1038
|
+
|
|
1039
|
+
if (predictions.emerging_threats?.length > 0) {
|
|
1040
|
+
console.log(chalk.bold('\nEmerging Threat Patterns:\n'));
|
|
1041
|
+
predictions.emerging_threats.slice(0, 3).forEach((t: any) => {
|
|
1042
|
+
console.log(` ${chalk.yellow('⚠')} ${t.name || t.description || t}`);
|
|
1043
|
+
});
|
|
1044
|
+
}
|
|
1045
|
+
} catch (error) {
|
|
1046
|
+
spinner.fail('AI threat prediction failed');
|
|
1047
|
+
console.error(error);
|
|
1048
|
+
}
|
|
1049
|
+
return;
|
|
1050
|
+
}
|
|
1051
|
+
|
|
1052
|
+
// AI architecture insights
|
|
1053
|
+
if (options.aiInsights) {
|
|
1054
|
+
const spinner = ora('Generating AI architecture insights...').start();
|
|
1055
|
+
try {
|
|
1056
|
+
const fullId = await resolveDiagramId(options.aiInsights);
|
|
1057
|
+
|
|
1058
|
+
const data = await apiRequest(`/v2/threat-modeling/diagrams/${fullId}/generate-ai-insights/`, {
|
|
1059
|
+
method: 'POST',
|
|
1060
|
+
body: JSON.stringify({
|
|
1061
|
+
include_recommendations: true,
|
|
1062
|
+
include_cost_analysis: true
|
|
1063
|
+
})
|
|
1064
|
+
});
|
|
1065
|
+
|
|
1066
|
+
spinner.succeed('AI insights generated!');
|
|
1067
|
+
|
|
1068
|
+
console.log(chalk.bold('\nAI Architecture Insights:\n'));
|
|
1069
|
+
|
|
1070
|
+
const insights = data.insights || data;
|
|
1071
|
+
console.log(` Architecture Type: ${chalk.cyan(insights.architecture_type || 'N/A')}`);
|
|
1072
|
+
console.log(` Complexity Score: ${chalk.yellow(insights.complexity_score || 'N/A')}`);
|
|
1073
|
+
console.log(` Security Maturity: ${insights.security_maturity || 'medium'}`);
|
|
1074
|
+
console.log(` AI Confidence: ${chalk.green((insights.confidence || 0.88) * 100 + '%')}`);
|
|
1075
|
+
|
|
1076
|
+
const strengths = insights.strengths || [];
|
|
1077
|
+
if (strengths.length > 0) {
|
|
1078
|
+
console.log(chalk.bold('\nStrengths:\n'));
|
|
1079
|
+
strengths.slice(0, 3).forEach((s: any) => {
|
|
1080
|
+
console.log(` ${chalk.green('✓')} ${s.title || s.description || s}`);
|
|
1081
|
+
});
|
|
1082
|
+
}
|
|
1083
|
+
|
|
1084
|
+
const weaknesses = insights.weaknesses || [];
|
|
1085
|
+
if (weaknesses.length > 0) {
|
|
1086
|
+
console.log(chalk.bold('\nWeaknesses:\n'));
|
|
1087
|
+
weaknesses.slice(0, 3).forEach((w: any) => {
|
|
1088
|
+
console.log(` ${chalk.red('✗')} ${w.title || w.description || w}`);
|
|
1089
|
+
});
|
|
1090
|
+
}
|
|
1091
|
+
|
|
1092
|
+
const recommendations = insights.recommendations || [];
|
|
1093
|
+
if (recommendations.length > 0) {
|
|
1094
|
+
console.log(chalk.bold('\nAI Recommendations:\n'));
|
|
1095
|
+
recommendations.slice(0, 3).forEach((r: any) => {
|
|
1096
|
+
console.log(` ${chalk.cyan('→')} ${r.title || r.description || r}`);
|
|
1097
|
+
});
|
|
1098
|
+
}
|
|
1099
|
+
} catch (error) {
|
|
1100
|
+
spinner.fail('AI insights generation failed');
|
|
1101
|
+
console.error(error);
|
|
1102
|
+
}
|
|
1103
|
+
return;
|
|
1104
|
+
}
|
|
1105
|
+
|
|
1106
|
+
// AI pattern detection
|
|
1107
|
+
if (options.patterns) {
|
|
1108
|
+
const spinner = ora('Detecting AI patterns...').start();
|
|
1109
|
+
try {
|
|
1110
|
+
const fullId = await resolveDiagramId(options.patterns);
|
|
1111
|
+
|
|
1112
|
+
const data = await apiRequest('/v2/threat-modeling/ai-patterns/detect/', {
|
|
1113
|
+
method: 'POST',
|
|
1114
|
+
body: JSON.stringify({
|
|
1115
|
+
diagram_id: fullId,
|
|
1116
|
+
sensitivity: 'high'
|
|
1117
|
+
})
|
|
1118
|
+
});
|
|
1119
|
+
|
|
1120
|
+
spinner.succeed('AI pattern detection complete!');
|
|
1121
|
+
|
|
1122
|
+
console.log(chalk.bold('\nAI Pattern Detection:\n'));
|
|
1123
|
+
|
|
1124
|
+
const detection = data.detection || data;
|
|
1125
|
+
console.log(` Patterns Found: ${chalk.cyan(detection.total_patterns || 0)}`);
|
|
1126
|
+
console.log(` Security Patterns: ${chalk.yellow(detection.security_patterns || 0)}`);
|
|
1127
|
+
console.log(` Risk Patterns: ${chalk.red(detection.risk_patterns || 0)}`);
|
|
1128
|
+
|
|
1129
|
+
const patterns = detection.patterns || data.patterns || [];
|
|
1130
|
+
if (patterns.length > 0) {
|
|
1131
|
+
console.log(chalk.bold('\nDetected Patterns:\n'));
|
|
1132
|
+
patterns.slice(0, 5).forEach((p: any) => {
|
|
1133
|
+
const typeColor = p.type === 'risk' ? chalk.red : p.type === 'security' ? chalk.green : chalk.cyan;
|
|
1134
|
+
console.log(` ${typeColor(`[${p.type?.toUpperCase() || 'PATTERN'}]`)} ${p.name || p.title}`);
|
|
1135
|
+
console.log(chalk.dim(` Confidence: ${((p.confidence || 0.85) * 100).toFixed(0)}% | Impact: ${p.impact || 'medium'}`));
|
|
1136
|
+
});
|
|
1137
|
+
}
|
|
1138
|
+
|
|
1139
|
+
const anomalies = detection.anomalies || [];
|
|
1140
|
+
if (anomalies.length > 0) {
|
|
1141
|
+
console.log(chalk.bold('\nDetected Anomalies:\n'));
|
|
1142
|
+
anomalies.slice(0, 3).forEach((a: any) => {
|
|
1143
|
+
console.log(` ${chalk.yellow('⚠')} ${a.description || a.name || a}`);
|
|
1144
|
+
});
|
|
1145
|
+
}
|
|
1146
|
+
} catch (error) {
|
|
1147
|
+
spinner.fail('AI pattern detection failed');
|
|
1148
|
+
console.error(error);
|
|
1149
|
+
}
|
|
1150
|
+
return;
|
|
1151
|
+
}
|
|
1152
|
+
|
|
1153
|
+
// Default: show usage
|
|
1154
|
+
console.log(chalk.bold('\nRed Team Commands:\n'));
|
|
1155
|
+
console.log(` ${chalk.cyan('aribot redteam --methodologies')} List threat modeling methodologies`);
|
|
1156
|
+
console.log(` ${chalk.cyan('aribot redteam --intelligence')} Get threat intelligence summary`);
|
|
1157
|
+
console.log(` ${chalk.cyan('aribot redteam --attack-paths -d <id>')} Analyze attack paths for diagram`);
|
|
1158
|
+
console.log(` ${chalk.cyan('aribot redteam --analyze <id>')} Comprehensive threat analysis`);
|
|
1159
|
+
console.log(` ${chalk.cyan('aribot redteam --requirements <id>')} Generate security requirements`);
|
|
1160
|
+
console.log(chalk.bold('\nAI-Powered Commands:\n'));
|
|
1161
|
+
console.log(` ${chalk.green('aribot redteam --ai-attack-paths <id>')} AI attack path analysis`);
|
|
1162
|
+
console.log(` ${chalk.green('aribot redteam --ai-predict <id>')} AI threat prediction (ML)`);
|
|
1163
|
+
console.log(` ${chalk.green('aribot redteam --ai-insights <id>')} Generate AI architecture insights`);
|
|
1164
|
+
console.log(` ${chalk.green('aribot redteam --patterns <id>')} Detect AI patterns in diagram`);
|
|
1165
|
+
});
|
|
1166
|
+
|
|
1167
|
+
// AI Analysis command
|
|
1168
|
+
program
|
|
1169
|
+
.command('ai')
|
|
1170
|
+
.description('AI-powered analysis and predictions')
|
|
1171
|
+
.option('--analyze <diagram-id>', 'Analyze diagram with AI')
|
|
1172
|
+
.option('--predict <diagram-id>', 'Predict threats for diagram')
|
|
1173
|
+
.option('--recommendations <diagram-id>', 'Get AI recommendations')
|
|
1174
|
+
.option('--cost <diagram-id>', 'Analyze costs with AI')
|
|
1175
|
+
.action(async (options) => {
|
|
1176
|
+
const spinner = ora('Running AI analysis...').start();
|
|
1177
|
+
|
|
1178
|
+
try {
|
|
1179
|
+
if (options.analyze) {
|
|
1180
|
+
const fullId = await resolveDiagramId(options.analyze);
|
|
1181
|
+
const data = await apiRequest('/v2/ai-agents/analyze/', {
|
|
1182
|
+
method: 'POST',
|
|
1183
|
+
body: JSON.stringify({ diagram_id: fullId })
|
|
1184
|
+
});
|
|
1185
|
+
spinner.succeed('AI analysis complete!');
|
|
1186
|
+
console.log(chalk.bold('\nAI Analysis Results:\n'));
|
|
1187
|
+
console.log(` Risk Level: ${chalk.yellow(data.risk_level || 'N/A')}`);
|
|
1188
|
+
console.log(` Findings: ${chalk.cyan(data.findings_count || 0)}`);
|
|
1189
|
+
console.log(` Confidence: ${chalk.green((data.confidence || 0) + '%')}`);
|
|
1190
|
+
|
|
1191
|
+
} else if (options.predict) {
|
|
1192
|
+
const fullId = await resolveDiagramId(options.predict);
|
|
1193
|
+
const data = await apiRequest('/v2/ai-agents/predict/', {
|
|
1194
|
+
method: 'POST',
|
|
1195
|
+
body: JSON.stringify({ diagram_id: fullId })
|
|
1196
|
+
});
|
|
1197
|
+
spinner.succeed('Threat prediction complete!');
|
|
1198
|
+
console.log(chalk.bold('\nPredicted Threats:\n'));
|
|
1199
|
+
(data.predictions || []).slice(0, 5).forEach((p: any) => {
|
|
1200
|
+
console.log(` ${chalk.red('•')} ${p.threat_type}: ${p.probability}% likelihood`);
|
|
1201
|
+
});
|
|
1202
|
+
|
|
1203
|
+
} else if (options.recommendations) {
|
|
1204
|
+
const fullId = await resolveDiagramId(options.recommendations);
|
|
1205
|
+
const data = await apiRequest('/v2/ai-agents/recommendations/', {
|
|
1206
|
+
method: 'POST',
|
|
1207
|
+
body: JSON.stringify({ diagram_id: fullId })
|
|
1208
|
+
});
|
|
1209
|
+
spinner.succeed('Recommendations generated!');
|
|
1210
|
+
console.log(chalk.bold('\nAI Recommendations:\n'));
|
|
1211
|
+
(data.recommendations || []).slice(0, 5).forEach((r: any, i: number) => {
|
|
1212
|
+
console.log(` ${i + 1}. ${r.title}`);
|
|
1213
|
+
console.log(chalk.dim(` Priority: ${r.priority} | Impact: ${r.impact}`));
|
|
1214
|
+
});
|
|
1215
|
+
|
|
1216
|
+
} else if (options.cost) {
|
|
1217
|
+
const fullId = await resolveDiagramId(options.cost);
|
|
1218
|
+
const data = await apiRequest(`/v2/ai-agents/cost-analysis/${fullId}/`);
|
|
1219
|
+
spinner.succeed('Cost analysis complete!');
|
|
1220
|
+
console.log(chalk.bold('\nAI Cost Analysis:\n'));
|
|
1221
|
+
console.log(` Monthly Estimate: ${chalk.cyan('$' + (data.monthly_cost || 0).toLocaleString())}`);
|
|
1222
|
+
console.log(` Annual Estimate: ${chalk.cyan('$' + (data.annual_cost || 0).toLocaleString())}`);
|
|
1223
|
+
console.log(` Optimization: ${chalk.green((data.optimization_potential || 0) + '%')}`);
|
|
1224
|
+
|
|
1225
|
+
} else {
|
|
1226
|
+
spinner.stop();
|
|
1227
|
+
console.log(chalk.yellow('Usage: aribot ai [--analyze|--predict|--recommendations|--cost] <diagram-id>'));
|
|
1228
|
+
}
|
|
1229
|
+
} catch (error) {
|
|
1230
|
+
spinner.fail('AI analysis failed');
|
|
1231
|
+
console.error(error);
|
|
1232
|
+
}
|
|
1233
|
+
});
|
|
1234
|
+
|
|
1235
|
+
// SBOM (Software Bill of Materials) command
|
|
1236
|
+
program
|
|
1237
|
+
.command('sbom')
|
|
1238
|
+
.description('Software Bill of Materials management')
|
|
1239
|
+
.option('--generate <diagram-id>', 'Generate SBOM for diagram')
|
|
1240
|
+
.option('--analyze <sbom-id>', 'Analyze SBOM dependencies')
|
|
1241
|
+
.option('--vulnerabilities [sbom-id]', 'Scan for vulnerabilities')
|
|
1242
|
+
.option('--list', 'List all SBOM documents')
|
|
1243
|
+
.action(async (options) => {
|
|
1244
|
+
const spinner = ora('Processing SBOM...').start();
|
|
1245
|
+
|
|
1246
|
+
try {
|
|
1247
|
+
if (options.generate) {
|
|
1248
|
+
const fullId = await resolveDiagramId(options.generate);
|
|
1249
|
+
const data = await apiRequest('/v2/sbom/generate/', {
|
|
1250
|
+
method: 'POST',
|
|
1251
|
+
body: JSON.stringify({ diagram_id: fullId })
|
|
1252
|
+
});
|
|
1253
|
+
spinner.succeed('SBOM generated!');
|
|
1254
|
+
console.log(chalk.bold('\nSBOM Document:\n'));
|
|
1255
|
+
console.log(` ID: ${chalk.cyan(data.id || data.sbom_id)}`);
|
|
1256
|
+
console.log(` Components: ${chalk.yellow(data.component_count || 0)}`);
|
|
1257
|
+
console.log(` Format: ${chalk.dim(data.format || 'CycloneDX')}`);
|
|
1258
|
+
|
|
1259
|
+
} else if (options.analyze) {
|
|
1260
|
+
const data = await apiRequest('/v2/sbom/analyze/', {
|
|
1261
|
+
method: 'POST',
|
|
1262
|
+
body: JSON.stringify({ sbom_id: options.analyze })
|
|
1263
|
+
});
|
|
1264
|
+
spinner.succeed('SBOM analysis complete!');
|
|
1265
|
+
console.log(chalk.bold('\nDependency Analysis:\n'));
|
|
1266
|
+
console.log(` Total Dependencies: ${chalk.cyan(data.total_dependencies || 0)}`);
|
|
1267
|
+
console.log(` Direct: ${chalk.yellow(data.direct_dependencies || 0)}`);
|
|
1268
|
+
console.log(` Transitive: ${chalk.dim(data.transitive_dependencies || 0)}`);
|
|
1269
|
+
console.log(` Outdated: ${chalk.red(data.outdated_count || 0)}`);
|
|
1270
|
+
|
|
1271
|
+
} else if (options.vulnerabilities) {
|
|
1272
|
+
const data = await apiRequest('/v2/sbom/vulnerabilities/');
|
|
1273
|
+
spinner.succeed('Vulnerability scan complete!');
|
|
1274
|
+
console.log(chalk.bold('\nVulnerability Report:\n'));
|
|
1275
|
+
console.log(` Critical: ${chalk.red(data.critical || 0)}`);
|
|
1276
|
+
console.log(` High: ${chalk.yellow(data.high || 0)}`);
|
|
1277
|
+
console.log(` Medium: ${chalk.blue(data.medium || 0)}`);
|
|
1278
|
+
console.log(` Low: ${chalk.dim(data.low || 0)}`);
|
|
1279
|
+
|
|
1280
|
+
} else if (options.list) {
|
|
1281
|
+
const data = await apiRequest('/v2/sbom/documents/');
|
|
1282
|
+
spinner.stop();
|
|
1283
|
+
console.log(chalk.bold('\nSBOM Documents:\n'));
|
|
1284
|
+
(data.results || data || []).forEach((s: any) => {
|
|
1285
|
+
console.log(` ${chalk.cyan(String(s.id).slice(0, 8))} ${s.name || 'Unnamed'} ${chalk.dim(s.component_count + ' components')}`);
|
|
1286
|
+
});
|
|
1287
|
+
|
|
1288
|
+
} else {
|
|
1289
|
+
spinner.stop();
|
|
1290
|
+
console.log(chalk.yellow('Usage: aribot sbom [--generate <diagram-id>] [--analyze <sbom-id>] [--vulnerabilities] [--list]'));
|
|
1291
|
+
}
|
|
1292
|
+
} catch (error) {
|
|
1293
|
+
spinner.fail('SBOM operation failed');
|
|
1294
|
+
console.error(error);
|
|
1295
|
+
}
|
|
1296
|
+
});
|
|
1297
|
+
|
|
1298
|
+
// Digital Twin command
|
|
1299
|
+
program
|
|
1300
|
+
.command('digital-twin')
|
|
1301
|
+
.description('Digital twin and cloud resource management')
|
|
1302
|
+
.option('--providers', 'List cloud providers')
|
|
1303
|
+
.option('--resources [provider]', 'List cloud resources')
|
|
1304
|
+
.option('--sync <provider-id>', 'Sync cloud resources')
|
|
1305
|
+
.option('--discover <provider-id>', 'Discover cloud resources')
|
|
1306
|
+
.option('--health', 'Check digital twin health')
|
|
1307
|
+
.action(async (options) => {
|
|
1308
|
+
const spinner = ora('Processing...').start();
|
|
1309
|
+
|
|
1310
|
+
try {
|
|
1311
|
+
if (options.providers) {
|
|
1312
|
+
const data = await apiRequest('/v2/digital-twin/providers/');
|
|
1313
|
+
spinner.stop();
|
|
1314
|
+
console.log(chalk.bold('\nCloud Providers:\n'));
|
|
1315
|
+
(data.results || data || []).forEach((p: any) => {
|
|
1316
|
+
const status = p.connected ? chalk.green('✓') : chalk.red('✗');
|
|
1317
|
+
console.log(` ${status} ${chalk.cyan(p.name)} ${chalk.dim(p.provider_type || p.type)}`);
|
|
1318
|
+
});
|
|
1319
|
+
|
|
1320
|
+
} else if (options.resources) {
|
|
1321
|
+
const provider = typeof options.resources === 'string' ? `?provider=${options.resources}` : '';
|
|
1322
|
+
const data = await apiRequest(`/v2/digital-twin/resources/${provider}`);
|
|
1323
|
+
spinner.stop();
|
|
1324
|
+
console.log(chalk.bold('\nCloud Resources:\n'));
|
|
1325
|
+
(data.results || data || []).slice(0, 20).forEach((r: any) => {
|
|
1326
|
+
console.log(` ${chalk.cyan(r.resource_type || r.type)} ${r.name} ${chalk.dim(r.region || '')}`);
|
|
1327
|
+
});
|
|
1328
|
+
|
|
1329
|
+
} else if (options.sync) {
|
|
1330
|
+
const data = await apiRequest('/v2/digital-twin/sync/', {
|
|
1331
|
+
method: 'POST',
|
|
1332
|
+
body: JSON.stringify({ provider_id: options.sync })
|
|
1333
|
+
});
|
|
1334
|
+
spinner.succeed('Cloud sync initiated!');
|
|
1335
|
+
console.log(` Resources discovered: ${chalk.cyan(data.resources_found || 0)}`);
|
|
1336
|
+
|
|
1337
|
+
} else if (options.discover) {
|
|
1338
|
+
const data = await apiRequest('/v2/digital-twin/discover/', {
|
|
1339
|
+
method: 'POST',
|
|
1340
|
+
body: JSON.stringify({ provider_id: options.discover })
|
|
1341
|
+
});
|
|
1342
|
+
spinner.succeed('Discovery complete!');
|
|
1343
|
+
console.log(` Resources found: ${chalk.cyan(data.resources_count || 0)}`);
|
|
1344
|
+
|
|
1345
|
+
} else if (options.health) {
|
|
1346
|
+
const data = await apiRequest('/v2/digital-twin/health/');
|
|
1347
|
+
spinner.stop();
|
|
1348
|
+
console.log(chalk.bold('\nDigital Twin Health:\n'));
|
|
1349
|
+
console.log(` Status: ${data.healthy ? chalk.green('Healthy') : chalk.red('Unhealthy')}`);
|
|
1350
|
+
console.log(` Providers: ${chalk.cyan(data.providers_connected || 0)}`);
|
|
1351
|
+
console.log(` Resources: ${chalk.cyan(data.total_resources || 0)}`);
|
|
1352
|
+
console.log(` Last Sync: ${chalk.dim(data.last_sync || 'Never')}`);
|
|
1353
|
+
|
|
1354
|
+
} else {
|
|
1355
|
+
spinner.stop();
|
|
1356
|
+
console.log(chalk.yellow('Usage: aribot digital-twin [--providers] [--resources] [--sync <id>] [--discover <id>] [--health]'));
|
|
1357
|
+
}
|
|
1358
|
+
} catch (error) {
|
|
1359
|
+
spinner.fail('Digital twin operation failed');
|
|
1360
|
+
console.error(error);
|
|
1361
|
+
}
|
|
1362
|
+
});
|
|
1363
|
+
|
|
1364
|
+
// Pipeline Security command
|
|
1365
|
+
program
|
|
1366
|
+
.command('pipeline')
|
|
1367
|
+
.description('Pipeline security scanning')
|
|
1368
|
+
.option('--projects', 'List pipeline projects')
|
|
1369
|
+
.option('--scans [project-id]', 'List or run scans')
|
|
1370
|
+
.option('--vulnerabilities [project-id]', 'List vulnerabilities')
|
|
1371
|
+
.option('--scan <project-id>', 'Run a new scan')
|
|
1372
|
+
.option('--stats', 'Get pipeline statistics')
|
|
1373
|
+
.action(async (options) => {
|
|
1374
|
+
const spinner = ora('Processing...').start();
|
|
1375
|
+
|
|
1376
|
+
try {
|
|
1377
|
+
if (options.projects) {
|
|
1378
|
+
const data = await apiRequest('/v1/pipeline/projects/');
|
|
1379
|
+
spinner.stop();
|
|
1380
|
+
console.log(chalk.bold('\nPipeline Projects:\n'));
|
|
1381
|
+
(data.results || data || []).forEach((p: any) => {
|
|
1382
|
+
const status = p.last_scan_status === 'passed' ? chalk.green('✓') : chalk.red('✗');
|
|
1383
|
+
console.log(` ${status} ${chalk.cyan(p.name)} ${chalk.dim(p.repository || '')}`);
|
|
1384
|
+
});
|
|
1385
|
+
|
|
1386
|
+
} else if (options.scans) {
|
|
1387
|
+
const project = typeof options.scans === 'string' ? `?project=${options.scans}` : '';
|
|
1388
|
+
const data = await apiRequest(`/v1/pipeline/scans/${project}`);
|
|
1389
|
+
spinner.stop();
|
|
1390
|
+
console.log(chalk.bold('\nPipeline Scans:\n'));
|
|
1391
|
+
(data.results || data || []).slice(0, 10).forEach((s: any) => {
|
|
1392
|
+
const status = s.status === 'completed' ? chalk.green('✓') : chalk.yellow('⋯');
|
|
1393
|
+
console.log(` ${status} ${chalk.cyan(String(s.id).slice(0, 8))} ${s.scan_type || 'security'} ${chalk.dim(s.created_at?.slice(0, 10) || '')}`);
|
|
1394
|
+
});
|
|
1395
|
+
|
|
1396
|
+
} else if (options.vulnerabilities) {
|
|
1397
|
+
const project = typeof options.vulnerabilities === 'string' ? `?project=${options.vulnerabilities}` : '';
|
|
1398
|
+
const data = await apiRequest(`/v1/pipeline/vulnerabilities/${project}`);
|
|
1399
|
+
spinner.stop();
|
|
1400
|
+
console.log(chalk.bold('\nPipeline Vulnerabilities:\n'));
|
|
1401
|
+
(data.results || data || []).slice(0, 10).forEach((v: any) => {
|
|
1402
|
+
const severity = v.severity === 'critical' ? chalk.red : v.severity === 'high' ? chalk.yellow : chalk.blue;
|
|
1403
|
+
console.log(` ${severity(`[${v.severity?.toUpperCase()}]`)} ${v.title || v.name}`);
|
|
1404
|
+
});
|
|
1405
|
+
|
|
1406
|
+
} else if (options.scan) {
|
|
1407
|
+
const data = await apiRequest('/v1/pipeline/scans/', {
|
|
1408
|
+
method: 'POST',
|
|
1409
|
+
body: JSON.stringify({ project_id: options.scan })
|
|
1410
|
+
});
|
|
1411
|
+
spinner.succeed('Scan initiated!');
|
|
1412
|
+
console.log(` Scan ID: ${chalk.cyan(data.id || data.scan_id)}`);
|
|
1413
|
+
|
|
1414
|
+
} else if (options.stats) {
|
|
1415
|
+
const data = await apiRequest('/v1/pipeline/stats/');
|
|
1416
|
+
spinner.stop();
|
|
1417
|
+
console.log(chalk.bold('\nPipeline Statistics:\n'));
|
|
1418
|
+
console.log(` Total Projects: ${chalk.cyan(data.total_projects || 0)}`);
|
|
1419
|
+
console.log(` Total Scans: ${chalk.cyan(data.total_scans || 0)}`);
|
|
1420
|
+
console.log(` Vulnerabilities: ${chalk.red(data.total_vulnerabilities || 0)}`);
|
|
1421
|
+
console.log(` Pass Rate: ${chalk.green((data.pass_rate || 0) + '%')}`);
|
|
1422
|
+
|
|
1423
|
+
} else {
|
|
1424
|
+
spinner.stop();
|
|
1425
|
+
console.log(chalk.yellow('Usage: aribot pipeline [--projects] [--scans] [--vulnerabilities] [--scan <id>] [--stats]'));
|
|
1426
|
+
}
|
|
1427
|
+
} catch (error) {
|
|
1428
|
+
spinner.fail('Pipeline operation failed');
|
|
1429
|
+
console.error(error);
|
|
1430
|
+
}
|
|
1431
|
+
});
|
|
1432
|
+
|
|
1433
|
+
// API Keys command
|
|
1434
|
+
program
|
|
1435
|
+
.command('api-keys')
|
|
1436
|
+
.description('Manage API keys')
|
|
1437
|
+
.option('--list', 'List all API keys')
|
|
1438
|
+
.option('--create <name>', 'Create new API key')
|
|
1439
|
+
.option('--delete <key-id>', 'Delete API key')
|
|
1440
|
+
.option('--usage', 'Show API usage')
|
|
1441
|
+
.action(async (options) => {
|
|
1442
|
+
const spinner = ora('Processing...').start();
|
|
1443
|
+
|
|
1444
|
+
try {
|
|
1445
|
+
if (options.list) {
|
|
1446
|
+
const data = await apiRequest('/v1/developer/api-keys/');
|
|
1447
|
+
spinner.stop();
|
|
1448
|
+
console.log(chalk.bold('\nAPI Keys:\n'));
|
|
1449
|
+
(data.results || data || []).forEach((k: any) => {
|
|
1450
|
+
const status = k.is_active ? chalk.green('active') : chalk.red('inactive');
|
|
1451
|
+
console.log(` ${chalk.cyan(k.name)} ${chalk.dim(k.key_prefix + '...')} ${status}`);
|
|
1452
|
+
});
|
|
1453
|
+
|
|
1454
|
+
} else if (options.create) {
|
|
1455
|
+
const data = await apiRequest('/v1/developer/api-keys/', {
|
|
1456
|
+
method: 'POST',
|
|
1457
|
+
body: JSON.stringify({ name: options.create })
|
|
1458
|
+
});
|
|
1459
|
+
spinner.succeed('API key created!');
|
|
1460
|
+
console.log(chalk.bold('\nNew API Key:\n'));
|
|
1461
|
+
console.log(` Name: ${chalk.cyan(data.name)}`);
|
|
1462
|
+
console.log(` Key: ${chalk.yellow(data.key)}`);
|
|
1463
|
+
console.log(chalk.red('\n ⚠ Save this key now - it won\'t be shown again!'));
|
|
1464
|
+
|
|
1465
|
+
} else if (options.delete) {
|
|
1466
|
+
await apiRequest(`/v1/developer/api-keys/${options.delete}/`, {
|
|
1467
|
+
method: 'DELETE'
|
|
1468
|
+
});
|
|
1469
|
+
spinner.succeed('API key deleted!');
|
|
1470
|
+
|
|
1471
|
+
} else if (options.usage) {
|
|
1472
|
+
const data = await apiRequest('/v1/developer/usage/');
|
|
1473
|
+
spinner.stop();
|
|
1474
|
+
console.log(chalk.bold('\nAPI Usage:\n'));
|
|
1475
|
+
console.log(` Today: ${chalk.cyan(data.today || 0)} requests`);
|
|
1476
|
+
console.log(` This Month: ${chalk.cyan(data.this_month || 0)} requests`);
|
|
1477
|
+
console.log(` Limit: ${chalk.dim(data.limit || 'unlimited')}`);
|
|
1478
|
+
|
|
1479
|
+
} else {
|
|
1480
|
+
spinner.stop();
|
|
1481
|
+
console.log(chalk.yellow('Usage: aribot api-keys [--list] [--create <name>] [--delete <id>] [--usage]'));
|
|
1482
|
+
}
|
|
1483
|
+
} catch (error) {
|
|
1484
|
+
spinner.fail('API key operation failed');
|
|
1485
|
+
console.error(error);
|
|
1486
|
+
}
|
|
1487
|
+
});
|
|
1488
|
+
|
|
1489
|
+
// Marketplace command
|
|
1490
|
+
program
|
|
1491
|
+
.command('marketplace')
|
|
1492
|
+
.description('Browse and manage architecture templates')
|
|
1493
|
+
.option('--search <query>', 'Search templates')
|
|
1494
|
+
.option('--featured', 'List featured templates')
|
|
1495
|
+
.option('--categories', 'List template categories')
|
|
1496
|
+
.option('--my-templates', 'List your templates')
|
|
1497
|
+
.option('--get <template-id>', 'Get template details')
|
|
1498
|
+
.action(async (options) => {
|
|
1499
|
+
const spinner = ora('Fetching...').start();
|
|
1500
|
+
|
|
1501
|
+
try {
|
|
1502
|
+
if (options.search) {
|
|
1503
|
+
const data = await apiRequest(`/v2/marketplace/search/?q=${encodeURIComponent(options.search)}`);
|
|
1504
|
+
spinner.stop();
|
|
1505
|
+
console.log(chalk.bold(`\nSearch Results for "${options.search}":\n`));
|
|
1506
|
+
(data.results || data || []).slice(0, 10).forEach((t: any) => {
|
|
1507
|
+
console.log(` ${chalk.cyan(t.name)} ${chalk.dim('$' + (t.price || 0))}`);
|
|
1508
|
+
console.log(chalk.dim(` ${t.description?.slice(0, 60) || ''}...`));
|
|
1509
|
+
});
|
|
1510
|
+
|
|
1511
|
+
} else if (options.featured) {
|
|
1512
|
+
const data = await apiRequest('/v2/marketplace/featured/');
|
|
1513
|
+
spinner.stop();
|
|
1514
|
+
console.log(chalk.bold('\nFeatured Templates:\n'));
|
|
1515
|
+
(data.results || data || []).forEach((t: any) => {
|
|
1516
|
+
console.log(` ${chalk.green('★')} ${chalk.cyan(t.name)} ${chalk.dim('$' + (t.price || 0))}`);
|
|
1517
|
+
});
|
|
1518
|
+
|
|
1519
|
+
} else if (options.categories) {
|
|
1520
|
+
const data = await apiRequest('/v2/marketplace/categories/');
|
|
1521
|
+
spinner.stop();
|
|
1522
|
+
console.log(chalk.bold('\nTemplate Categories:\n'));
|
|
1523
|
+
(data.results || data || []).forEach((c: any) => {
|
|
1524
|
+
console.log(` ${chalk.cyan(c.name)} ${chalk.dim(c.template_count + ' templates')}`);
|
|
1525
|
+
});
|
|
1526
|
+
|
|
1527
|
+
} else if (options.myTemplates) {
|
|
1528
|
+
const data = await apiRequest('/v2/marketplace/my-templates/');
|
|
1529
|
+
spinner.stop();
|
|
1530
|
+
console.log(chalk.bold('\nYour Templates:\n'));
|
|
1531
|
+
(data.results || data || []).forEach((t: any) => {
|
|
1532
|
+
console.log(` ${chalk.cyan(t.name)} ${chalk.dim(t.status)}`);
|
|
1533
|
+
});
|
|
1534
|
+
|
|
1535
|
+
} else if (options.get) {
|
|
1536
|
+
const data = await apiRequest(`/v2/marketplace/v2/templates/${options.get}/`);
|
|
1537
|
+
spinner.stop();
|
|
1538
|
+
console.log(chalk.bold(`\n${data.name}\n`));
|
|
1539
|
+
console.log(` Category: ${chalk.cyan(data.category)}`);
|
|
1540
|
+
console.log(` Price: ${chalk.yellow('$' + (data.price || 0))}`);
|
|
1541
|
+
console.log(` Downloads: ${chalk.dim(data.download_count || 0)}`);
|
|
1542
|
+
console.log(` Rating: ${chalk.green(data.rating || 'N/A')}`);
|
|
1543
|
+
console.log(`\n ${chalk.dim(data.description || '')}`);
|
|
1544
|
+
|
|
1545
|
+
} else {
|
|
1546
|
+
spinner.stop();
|
|
1547
|
+
console.log(chalk.yellow('Usage: aribot marketplace [--search <query>] [--featured] [--categories] [--my-templates] [--get <id>]'));
|
|
1548
|
+
}
|
|
1549
|
+
} catch (error) {
|
|
1550
|
+
spinner.fail('Marketplace operation failed');
|
|
1551
|
+
console.error(error);
|
|
1552
|
+
}
|
|
1553
|
+
});
|
|
1554
|
+
|
|
1555
|
+
// Dashboard command
|
|
1556
|
+
program
|
|
1557
|
+
.command('dashboard')
|
|
1558
|
+
.description('View dashboard and statistics')
|
|
1559
|
+
.option('--overview', 'Show dashboard overview')
|
|
1560
|
+
.option('--recent', 'Show recent activity')
|
|
1561
|
+
.option('--risk', 'Show risk summary')
|
|
1562
|
+
.option('--billing', 'Show billing information')
|
|
1563
|
+
.action(async (options) => {
|
|
1564
|
+
const spinner = ora('Loading dashboard...').start();
|
|
1565
|
+
|
|
1566
|
+
try {
|
|
1567
|
+
if (options.overview || (!options.recent && !options.risk && !options.billing)) {
|
|
1568
|
+
const data = await apiRequest('/v2/threat-modeling/dashboard/');
|
|
1569
|
+
spinner.stop();
|
|
1570
|
+
console.log(chalk.bold('\nDashboard Overview:\n'));
|
|
1571
|
+
console.log(` Total Diagrams: ${chalk.cyan(data.total_diagrams || 0)}`);
|
|
1572
|
+
console.log(` Total Threats: ${chalk.yellow(data.total_threats || 0)}`);
|
|
1573
|
+
console.log(` Critical Threats: ${chalk.red(data.critical_threats || 0)}`);
|
|
1574
|
+
console.log(` Compliance Score: ${chalk.green((data.compliance_score || 0) + '%')}`);
|
|
1575
|
+
|
|
1576
|
+
} else if (options.recent) {
|
|
1577
|
+
const data = await apiRequest('/v2/threat-modeling/dashboard/recent-activity/');
|
|
1578
|
+
spinner.stop();
|
|
1579
|
+
console.log(chalk.bold('\nRecent Activity:\n'));
|
|
1580
|
+
(data.activities || data || []).slice(0, 10).forEach((a: any) => {
|
|
1581
|
+
console.log(` ${chalk.dim(a.timestamp?.slice(0, 16) || '')} ${a.action} ${chalk.cyan(a.resource || '')}`);
|
|
1582
|
+
});
|
|
1583
|
+
|
|
1584
|
+
} else if (options.risk) {
|
|
1585
|
+
const data = await apiRequest('/v2/threat-modeling/dashboard/risk-summary/');
|
|
1586
|
+
spinner.stop();
|
|
1587
|
+
console.log(chalk.bold('\nRisk Summary:\n'));
|
|
1588
|
+
console.log(` Overall Risk: ${data.overall_risk === 'high' ? chalk.red(data.overall_risk) : chalk.yellow(data.overall_risk || 'N/A')}`);
|
|
1589
|
+
console.log(` Open Threats: ${chalk.yellow(data.open_threats || 0)}`);
|
|
1590
|
+
console.log(` Mitigated: ${chalk.green(data.mitigated_threats || 0)}`);
|
|
1591
|
+
|
|
1592
|
+
} else if (options.billing) {
|
|
1593
|
+
const data = await apiRequest('/v1/developer/billing/');
|
|
1594
|
+
spinner.stop();
|
|
1595
|
+
console.log(chalk.bold('\nBilling Information:\n'));
|
|
1596
|
+
console.log(` Plan: ${chalk.cyan(data.plan || 'Free')}`);
|
|
1597
|
+
console.log(` Usage: ${chalk.yellow((data.usage || 0) + ' requests')}`);
|
|
1598
|
+
console.log(` Next Billing: ${chalk.dim(data.next_billing_date || 'N/A')}`);
|
|
1599
|
+
}
|
|
1600
|
+
} catch (error) {
|
|
1601
|
+
spinner.fail('Dashboard failed to load');
|
|
1602
|
+
console.error(error);
|
|
1603
|
+
}
|
|
1604
|
+
});
|
|
1605
|
+
|
|
351
1606
|
program.parse();
|