@cdot65/prisma-airs-cli 1.0.2 → 1.0.4
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/dist/cli/commands/modelsecurity.d.ts.map +1 -1
- package/dist/cli/commands/modelsecurity.js +218 -128
- package/dist/cli/commands/modelsecurity.js.map +1 -1
- package/dist/cli/commands/redteam.js +249 -249
- package/dist/cli/commands/redteam.js.map +1 -1
- package/dist/cli/commands/runtime.d.ts.map +1 -1
- package/dist/cli/commands/runtime.js +310 -301
- package/dist/cli/commands/runtime.js.map +1 -1
- package/package.json +1 -1
|
@@ -30,34 +30,104 @@ function renderScanResult(result) {
|
|
|
30
30
|
}
|
|
31
31
|
console.log();
|
|
32
32
|
}
|
|
33
|
+
/** Create a management service from config. */
|
|
34
|
+
async function createMgmtService() {
|
|
35
|
+
const config = await loadConfig();
|
|
36
|
+
return new SdkManagementService({
|
|
37
|
+
clientId: config.mgmtClientId,
|
|
38
|
+
clientSecret: config.mgmtClientSecret,
|
|
39
|
+
tsgId: config.mgmtTsgId,
|
|
40
|
+
tokenEndpoint: config.mgmtTokenEndpoint,
|
|
41
|
+
});
|
|
42
|
+
}
|
|
33
43
|
export function registerRuntimeCommand(program) {
|
|
34
44
|
const runtime = program
|
|
35
45
|
.command('runtime')
|
|
36
46
|
.description('Runtime prompt scanning against AIRS profiles');
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
.
|
|
47
|
+
// -----------------------------------------------------------------------
|
|
48
|
+
// runtime api-keys — API key management subcommands
|
|
49
|
+
// -----------------------------------------------------------------------
|
|
50
|
+
const apiKeys = runtime.command('api-keys').description('Manage AIRS API keys');
|
|
51
|
+
apiKeys
|
|
52
|
+
.command('list')
|
|
53
|
+
.description('List API keys')
|
|
54
|
+
.option('--limit <n>', 'Max results', '100')
|
|
55
|
+
.action(async (opts) => {
|
|
43
56
|
try {
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
57
|
+
renderRuntimeConfigHeader();
|
|
58
|
+
const service = await createMgmtService();
|
|
59
|
+
const result = await service.listApiKeys({
|
|
60
|
+
limit: Number.parseInt(opts.limit, 10),
|
|
61
|
+
});
|
|
62
|
+
renderApiKeyList(result.apiKeys);
|
|
63
|
+
}
|
|
64
|
+
catch (err) {
|
|
65
|
+
renderError(err instanceof Error ? err.message : String(err));
|
|
66
|
+
process.exit(1);
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
apiKeys
|
|
70
|
+
.command('create')
|
|
71
|
+
.description('Create a new API key')
|
|
72
|
+
.requiredOption('--config <path>', 'JSON file with API key configuration')
|
|
73
|
+
.action(async (opts) => {
|
|
74
|
+
try {
|
|
75
|
+
renderRuntimeConfigHeader();
|
|
76
|
+
const service = await createMgmtService();
|
|
77
|
+
const config = JSON.parse(fs.readFileSync(opts.config, 'utf-8'));
|
|
78
|
+
const key = await service.createApiKey(config);
|
|
79
|
+
console.log(` API key created: ${key.id}\n`);
|
|
80
|
+
renderApiKeyDetail(key);
|
|
81
|
+
}
|
|
82
|
+
catch (err) {
|
|
83
|
+
renderError(err instanceof Error ? err.message : String(err));
|
|
84
|
+
process.exit(1);
|
|
85
|
+
}
|
|
86
|
+
});
|
|
87
|
+
apiKeys
|
|
88
|
+
.command('regenerate <apiKeyId>')
|
|
89
|
+
.description('Regenerate an API key')
|
|
90
|
+
.requiredOption('--interval <n>', 'Rotation time interval')
|
|
91
|
+
.requiredOption('--unit <unit>', 'Rotation time unit (hours, days, months)')
|
|
92
|
+
.option('--updated-by <email>', 'Email of user performing regeneration')
|
|
93
|
+
.action(async (apiKeyId, opts) => {
|
|
94
|
+
try {
|
|
95
|
+
renderRuntimeConfigHeader();
|
|
96
|
+
const service = await createMgmtService();
|
|
97
|
+
const request = {
|
|
98
|
+
rotation_time_interval: Number.parseInt(opts.interval, 10),
|
|
99
|
+
rotation_time_unit: opts.unit,
|
|
100
|
+
};
|
|
101
|
+
if (opts.updatedBy)
|
|
102
|
+
request.updated_by = opts.updatedBy;
|
|
103
|
+
const key = await service.regenerateApiKey(apiKeyId, request);
|
|
104
|
+
console.log(` API key regenerated: ${key.id}\n`);
|
|
105
|
+
renderApiKeyDetail(key);
|
|
106
|
+
}
|
|
107
|
+
catch (err) {
|
|
108
|
+
renderError(err instanceof Error ? err.message : String(err));
|
|
109
|
+
process.exit(1);
|
|
110
|
+
}
|
|
111
|
+
});
|
|
112
|
+
apiKeys
|
|
113
|
+
.command('delete <apiKeyName>')
|
|
114
|
+
.description('Delete an API key')
|
|
115
|
+
.requiredOption('--updated-by <email>', 'Email of user performing deletion')
|
|
116
|
+
.action(async (apiKeyName, opts) => {
|
|
117
|
+
try {
|
|
118
|
+
renderRuntimeConfigHeader();
|
|
119
|
+
const service = await createMgmtService();
|
|
120
|
+
const result = await service.deleteApiKey(apiKeyName, opts.updatedBy);
|
|
121
|
+
console.log(` ${result.message}\n`);
|
|
55
122
|
}
|
|
56
123
|
catch (err) {
|
|
57
124
|
renderError(err instanceof Error ? err.message : String(err));
|
|
58
125
|
process.exit(1);
|
|
59
126
|
}
|
|
60
127
|
});
|
|
128
|
+
// -----------------------------------------------------------------------
|
|
129
|
+
// runtime bulk-scan — async bulk scanning
|
|
130
|
+
// -----------------------------------------------------------------------
|
|
61
131
|
runtime
|
|
62
132
|
.command('bulk-scan')
|
|
63
133
|
.description('Scan multiple prompts via the async AIRS API')
|
|
@@ -117,40 +187,114 @@ export function registerRuntimeCommand(program) {
|
|
|
117
187
|
process.exit(1);
|
|
118
188
|
}
|
|
119
189
|
});
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
190
|
+
// -----------------------------------------------------------------------
|
|
191
|
+
// runtime customer-apps — customer app management subcommands
|
|
192
|
+
// -----------------------------------------------------------------------
|
|
193
|
+
const customerApps = runtime.command('customer-apps').description('Manage AIRS customer apps');
|
|
194
|
+
customerApps
|
|
195
|
+
.command('list')
|
|
196
|
+
.description('List customer apps')
|
|
197
|
+
.option('--limit <n>', 'Max results', '100')
|
|
198
|
+
.action(async (opts) => {
|
|
125
199
|
try {
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
}
|
|
131
|
-
const state = await loadBulkScanState(stateFile);
|
|
132
|
-
const service = new SdkRuntimeService(config.airsApiKey);
|
|
133
|
-
console.log(chalk.bold.cyan('\n Prisma AIRS Resume Poll'));
|
|
134
|
-
console.log(chalk.dim(` Profile: ${state.profile}`));
|
|
135
|
-
console.log(chalk.dim(` Scan IDs: ${state.scanIds.length}`));
|
|
136
|
-
console.log(chalk.dim(` Prompts: ${state.promptCount}\n`));
|
|
137
|
-
console.log(chalk.dim(' Polling for results...'));
|
|
138
|
-
const results = await service.pollResults(state.scanIds, undefined, {
|
|
139
|
-
onRetry: (attempt, delayMs) => {
|
|
140
|
-
console.log(chalk.yellow(` ⚠ Rate limited — retry ${attempt} in ${(delayMs / 1000).toFixed(0)}s...`));
|
|
141
|
-
},
|
|
200
|
+
renderRuntimeConfigHeader();
|
|
201
|
+
const service = await createMgmtService();
|
|
202
|
+
const result = await service.listCustomerApps({
|
|
203
|
+
limit: Number.parseInt(opts.limit, 10),
|
|
142
204
|
});
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
205
|
+
renderCustomerAppList(result.apps);
|
|
206
|
+
}
|
|
207
|
+
catch (err) {
|
|
208
|
+
renderError(err instanceof Error ? err.message : String(err));
|
|
209
|
+
process.exit(1);
|
|
210
|
+
}
|
|
211
|
+
});
|
|
212
|
+
customerApps
|
|
213
|
+
.command('get <appName>')
|
|
214
|
+
.description('Get customer app details')
|
|
215
|
+
.action(async (appName) => {
|
|
216
|
+
try {
|
|
217
|
+
renderRuntimeConfigHeader();
|
|
218
|
+
const service = await createMgmtService();
|
|
219
|
+
const app = await service.getCustomerApp(appName);
|
|
220
|
+
renderCustomerAppDetail(app);
|
|
221
|
+
}
|
|
222
|
+
catch (err) {
|
|
223
|
+
renderError(err instanceof Error ? err.message : String(err));
|
|
224
|
+
process.exit(1);
|
|
225
|
+
}
|
|
226
|
+
});
|
|
227
|
+
customerApps
|
|
228
|
+
.command('update <appId>')
|
|
229
|
+
.description('Update a customer app')
|
|
230
|
+
.requiredOption('--config <path>', 'JSON file with app updates')
|
|
231
|
+
.action(async (appId, opts) => {
|
|
232
|
+
try {
|
|
233
|
+
renderRuntimeConfigHeader();
|
|
234
|
+
const service = await createMgmtService();
|
|
235
|
+
const config = JSON.parse(fs.readFileSync(opts.config, 'utf-8'));
|
|
236
|
+
const app = await service.updateCustomerApp(appId, config);
|
|
237
|
+
console.log(` Customer app updated: ${app.name}\n`);
|
|
238
|
+
renderCustomerAppDetail(app);
|
|
239
|
+
}
|
|
240
|
+
catch (err) {
|
|
241
|
+
renderError(err instanceof Error ? err.message : String(err));
|
|
242
|
+
process.exit(1);
|
|
243
|
+
}
|
|
244
|
+
});
|
|
245
|
+
customerApps
|
|
246
|
+
.command('delete <appName>')
|
|
247
|
+
.description('Delete a customer app')
|
|
248
|
+
.requiredOption('--updated-by <email>', 'Email of user performing deletion')
|
|
249
|
+
.action(async (appName, opts) => {
|
|
250
|
+
try {
|
|
251
|
+
renderRuntimeConfigHeader();
|
|
252
|
+
const service = await createMgmtService();
|
|
253
|
+
const app = await service.deleteCustomerApp(appName, opts.updatedBy);
|
|
254
|
+
console.log(` Customer app "${app.name}" deleted.\n`);
|
|
255
|
+
}
|
|
256
|
+
catch (err) {
|
|
257
|
+
renderError(err instanceof Error ? err.message : String(err));
|
|
258
|
+
process.exit(1);
|
|
259
|
+
}
|
|
260
|
+
});
|
|
261
|
+
// -----------------------------------------------------------------------
|
|
262
|
+
// runtime deployment-profiles — read-only listing
|
|
263
|
+
// -----------------------------------------------------------------------
|
|
264
|
+
const deploymentProfiles = runtime
|
|
265
|
+
.command('deployment-profiles')
|
|
266
|
+
.description('List AIRS deployment profiles');
|
|
267
|
+
deploymentProfiles
|
|
268
|
+
.command('list')
|
|
269
|
+
.description('List deployment profiles')
|
|
270
|
+
.option('--unactivated', 'Include unactivated profiles')
|
|
271
|
+
.action(async (opts) => {
|
|
272
|
+
try {
|
|
273
|
+
renderRuntimeConfigHeader();
|
|
274
|
+
const service = await createMgmtService();
|
|
275
|
+
const profiles = await service.listDeploymentProfiles({
|
|
276
|
+
unactivated: opts.unactivated,
|
|
277
|
+
});
|
|
278
|
+
renderDeploymentProfileList(profiles);
|
|
279
|
+
}
|
|
280
|
+
catch (err) {
|
|
281
|
+
renderError(err instanceof Error ? err.message : String(err));
|
|
282
|
+
process.exit(1);
|
|
283
|
+
}
|
|
284
|
+
});
|
|
285
|
+
// -----------------------------------------------------------------------
|
|
286
|
+
// runtime dlp-profiles — read-only listing
|
|
287
|
+
// -----------------------------------------------------------------------
|
|
288
|
+
const dlpProfiles = runtime.command('dlp-profiles').description('List AIRS DLP profiles');
|
|
289
|
+
dlpProfiles
|
|
290
|
+
.command('list')
|
|
291
|
+
.description('List DLP profiles')
|
|
292
|
+
.action(async () => {
|
|
293
|
+
try {
|
|
294
|
+
renderRuntimeConfigHeader();
|
|
295
|
+
const service = await createMgmtService();
|
|
296
|
+
const profiles = await service.listDlpProfiles();
|
|
297
|
+
renderDlpProfileList(profiles);
|
|
154
298
|
}
|
|
155
299
|
catch (err) {
|
|
156
300
|
renderError(err instanceof Error ? err.message : String(err));
|
|
@@ -161,16 +305,6 @@ export function registerRuntimeCommand(program) {
|
|
|
161
305
|
// runtime profiles — security profile CRUD subcommands
|
|
162
306
|
// -----------------------------------------------------------------------
|
|
163
307
|
const profiles = runtime.command('profiles').description('Manage AIRS security profiles');
|
|
164
|
-
/** Create a management service from config. */
|
|
165
|
-
async function createMgmtService() {
|
|
166
|
-
const config = await loadConfig();
|
|
167
|
-
return new SdkManagementService({
|
|
168
|
-
clientId: config.mgmtClientId,
|
|
169
|
-
clientSecret: config.mgmtClientSecret,
|
|
170
|
-
tsgId: config.mgmtTsgId,
|
|
171
|
-
tokenEndpoint: config.mgmtTokenEndpoint,
|
|
172
|
-
});
|
|
173
|
-
}
|
|
174
308
|
profiles
|
|
175
309
|
.command('list')
|
|
176
310
|
.description('List security profiles')
|
|
@@ -260,25 +394,125 @@ export function registerRuntimeCommand(program) {
|
|
|
260
394
|
// Register audit under profiles
|
|
261
395
|
registerAuditCommand(profiles);
|
|
262
396
|
// -----------------------------------------------------------------------
|
|
263
|
-
// runtime
|
|
397
|
+
// runtime resume-poll — resume polling for bulk scans
|
|
264
398
|
// -----------------------------------------------------------------------
|
|
265
|
-
|
|
266
|
-
.command('
|
|
267
|
-
.description('
|
|
268
|
-
|
|
269
|
-
.
|
|
270
|
-
.description('List custom topics')
|
|
271
|
-
.option('--limit <n>', 'Max results', '100')
|
|
272
|
-
.option('--offset <n>', 'Starting offset', '0')
|
|
273
|
-
.action(async (opts) => {
|
|
399
|
+
runtime
|
|
400
|
+
.command('resume-poll <stateFile>')
|
|
401
|
+
.description('Resume polling for a previously submitted bulk scan')
|
|
402
|
+
.option('--output <file>', 'Output CSV file path')
|
|
403
|
+
.action(async (stateFile, opts) => {
|
|
274
404
|
try {
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
const
|
|
281
|
-
const
|
|
405
|
+
const config = await loadConfig({});
|
|
406
|
+
if (!config.airsApiKey) {
|
|
407
|
+
renderError('PANW_AI_SEC_API_KEY is required');
|
|
408
|
+
process.exit(1);
|
|
409
|
+
}
|
|
410
|
+
const state = await loadBulkScanState(stateFile);
|
|
411
|
+
const service = new SdkRuntimeService(config.airsApiKey);
|
|
412
|
+
console.log(chalk.bold.cyan('\n Prisma AIRS Resume Poll'));
|
|
413
|
+
console.log(chalk.dim(` Profile: ${state.profile}`));
|
|
414
|
+
console.log(chalk.dim(` Scan IDs: ${state.scanIds.length}`));
|
|
415
|
+
console.log(chalk.dim(` Prompts: ${state.promptCount}\n`));
|
|
416
|
+
console.log(chalk.dim(' Polling for results...'));
|
|
417
|
+
const results = await service.pollResults(state.scanIds, undefined, {
|
|
418
|
+
onRetry: (attempt, delayMs) => {
|
|
419
|
+
console.log(chalk.yellow(` ⚠ Rate limited — retry ${attempt} in ${(delayMs / 1000).toFixed(0)}s...`));
|
|
420
|
+
},
|
|
421
|
+
});
|
|
422
|
+
const outputPath = opts.output ?? `${state.profile.replace(/\s+/g, '-')}-bulk-scan.csv`;
|
|
423
|
+
const csv = SdkRuntimeService.formatResultsCsv(results);
|
|
424
|
+
await writeFile(outputPath, csv, 'utf-8');
|
|
425
|
+
const blocked = results.filter((r) => r.action === 'block').length;
|
|
426
|
+
const allowed = results.filter((r) => r.action === 'allow').length;
|
|
427
|
+
console.log(chalk.bold('\n Resume Poll Complete'));
|
|
428
|
+
console.log(chalk.dim(' ─────────────────────────'));
|
|
429
|
+
console.log(` Total: ${results.length}`);
|
|
430
|
+
console.log(` Blocked: ${chalk.red(String(blocked))}`);
|
|
431
|
+
console.log(` Allowed: ${chalk.green(String(allowed))}`);
|
|
432
|
+
console.log(` Output: ${chalk.cyan(outputPath)}\n`);
|
|
433
|
+
}
|
|
434
|
+
catch (err) {
|
|
435
|
+
renderError(err instanceof Error ? err.message : String(err));
|
|
436
|
+
process.exit(1);
|
|
437
|
+
}
|
|
438
|
+
});
|
|
439
|
+
// -----------------------------------------------------------------------
|
|
440
|
+
// runtime scan — single prompt scanning
|
|
441
|
+
// -----------------------------------------------------------------------
|
|
442
|
+
runtime
|
|
443
|
+
.command('scan <prompt>')
|
|
444
|
+
.description('Scan a single prompt against an AIRS security profile')
|
|
445
|
+
.requiredOption('--profile <name>', 'Security profile name')
|
|
446
|
+
.option('--response <text>', 'Response text to scan alongside the prompt')
|
|
447
|
+
.action(async (prompt, opts) => {
|
|
448
|
+
try {
|
|
449
|
+
const config = await loadConfig({});
|
|
450
|
+
if (!config.airsApiKey) {
|
|
451
|
+
renderError('PANW_AI_SEC_API_KEY is required');
|
|
452
|
+
process.exit(1);
|
|
453
|
+
}
|
|
454
|
+
const service = new SdkRuntimeService(config.airsApiKey);
|
|
455
|
+
console.log(chalk.bold.cyan('\n Prisma AIRS Runtime Scan'));
|
|
456
|
+
console.log(chalk.dim(` Profile: ${opts.profile}`));
|
|
457
|
+
console.log(chalk.dim(` Prompt: "${prompt.slice(0, 80)}${prompt.length > 80 ? '...' : ''}"`));
|
|
458
|
+
const result = await service.scanPrompt(opts.profile, prompt, opts.response);
|
|
459
|
+
renderScanResult(result);
|
|
460
|
+
}
|
|
461
|
+
catch (err) {
|
|
462
|
+
renderError(err instanceof Error ? err.message : String(err));
|
|
463
|
+
process.exit(1);
|
|
464
|
+
}
|
|
465
|
+
});
|
|
466
|
+
// -----------------------------------------------------------------------
|
|
467
|
+
// runtime scan-logs — scan log query
|
|
468
|
+
// -----------------------------------------------------------------------
|
|
469
|
+
const scanLogs = runtime.command('scan-logs').description('Query AIRS scan logs');
|
|
470
|
+
scanLogs
|
|
471
|
+
.command('query')
|
|
472
|
+
.description('Query scan logs')
|
|
473
|
+
.requiredOption('--interval <n>', 'Time interval')
|
|
474
|
+
.requiredOption('--unit <unit>', 'Time unit (hours)')
|
|
475
|
+
.option('--filter <filter>', 'Filter: all, benign, threat', 'all')
|
|
476
|
+
.option('--page <n>', 'Page number', '1')
|
|
477
|
+
.option('--page-size <n>', 'Page size', '50')
|
|
478
|
+
.action(async (opts) => {
|
|
479
|
+
try {
|
|
480
|
+
renderRuntimeConfigHeader();
|
|
481
|
+
const service = await createMgmtService();
|
|
482
|
+
const result = await service.queryScanLogs({
|
|
483
|
+
timeInterval: Number.parseInt(opts.interval, 10),
|
|
484
|
+
timeUnit: opts.unit,
|
|
485
|
+
pageNumber: Number.parseInt(opts.page, 10),
|
|
486
|
+
pageSize: Number.parseInt(opts.pageSize, 10),
|
|
487
|
+
filter: opts.filter,
|
|
488
|
+
});
|
|
489
|
+
renderScanLogList(result.results, result.pageToken);
|
|
490
|
+
}
|
|
491
|
+
catch (err) {
|
|
492
|
+
renderError(err instanceof Error ? err.message : String(err));
|
|
493
|
+
process.exit(1);
|
|
494
|
+
}
|
|
495
|
+
});
|
|
496
|
+
// -----------------------------------------------------------------------
|
|
497
|
+
// runtime topics — custom topic CRUD + guardrail generation subcommands
|
|
498
|
+
// -----------------------------------------------------------------------
|
|
499
|
+
const topics = runtime
|
|
500
|
+
.command('topics')
|
|
501
|
+
.description('Manage AIRS custom topics and guardrail generation');
|
|
502
|
+
topics
|
|
503
|
+
.command('list')
|
|
504
|
+
.description('List custom topics')
|
|
505
|
+
.option('--limit <n>', 'Max results', '100')
|
|
506
|
+
.option('--offset <n>', 'Starting offset', '0')
|
|
507
|
+
.action(async (opts) => {
|
|
508
|
+
try {
|
|
509
|
+
renderRuntimeConfigHeader();
|
|
510
|
+
const service = await createMgmtService();
|
|
511
|
+
const allTopics = await service.listTopics();
|
|
512
|
+
// Client-side pagination since SDK returns all
|
|
513
|
+
const offset = Number.parseInt(opts.offset, 10);
|
|
514
|
+
const limit = Number.parseInt(opts.limit, 10);
|
|
515
|
+
const page = allTopics.slice(offset, offset + limit);
|
|
282
516
|
renderTopicList(page);
|
|
283
517
|
if (offset + limit < allTopics.length) {
|
|
284
518
|
console.log(chalk.dim(` Showing ${page.length} of ${allTopics.length} topics\n`));
|
|
@@ -353,230 +587,5 @@ export function registerRuntimeCommand(program) {
|
|
|
353
587
|
registerResumeCommand(topics);
|
|
354
588
|
registerReportCommand(topics);
|
|
355
589
|
registerListCommand(topics, 'runs');
|
|
356
|
-
// -----------------------------------------------------------------------
|
|
357
|
-
// runtime api-keys — API key management subcommands
|
|
358
|
-
// -----------------------------------------------------------------------
|
|
359
|
-
const apiKeys = runtime.command('api-keys').description('Manage AIRS API keys');
|
|
360
|
-
apiKeys
|
|
361
|
-
.command('list')
|
|
362
|
-
.description('List API keys')
|
|
363
|
-
.option('--limit <n>', 'Max results', '100')
|
|
364
|
-
.action(async (opts) => {
|
|
365
|
-
try {
|
|
366
|
-
renderRuntimeConfigHeader();
|
|
367
|
-
const service = await createMgmtService();
|
|
368
|
-
const result = await service.listApiKeys({
|
|
369
|
-
limit: Number.parseInt(opts.limit, 10),
|
|
370
|
-
});
|
|
371
|
-
renderApiKeyList(result.apiKeys);
|
|
372
|
-
}
|
|
373
|
-
catch (err) {
|
|
374
|
-
renderError(err instanceof Error ? err.message : String(err));
|
|
375
|
-
process.exit(1);
|
|
376
|
-
}
|
|
377
|
-
});
|
|
378
|
-
apiKeys
|
|
379
|
-
.command('create')
|
|
380
|
-
.description('Create a new API key')
|
|
381
|
-
.requiredOption('--config <path>', 'JSON file with API key configuration')
|
|
382
|
-
.action(async (opts) => {
|
|
383
|
-
try {
|
|
384
|
-
renderRuntimeConfigHeader();
|
|
385
|
-
const service = await createMgmtService();
|
|
386
|
-
const config = JSON.parse(fs.readFileSync(opts.config, 'utf-8'));
|
|
387
|
-
const key = await service.createApiKey(config);
|
|
388
|
-
console.log(` API key created: ${key.id}\n`);
|
|
389
|
-
renderApiKeyDetail(key);
|
|
390
|
-
}
|
|
391
|
-
catch (err) {
|
|
392
|
-
renderError(err instanceof Error ? err.message : String(err));
|
|
393
|
-
process.exit(1);
|
|
394
|
-
}
|
|
395
|
-
});
|
|
396
|
-
apiKeys
|
|
397
|
-
.command('regenerate <apiKeyId>')
|
|
398
|
-
.description('Regenerate an API key')
|
|
399
|
-
.requiredOption('--interval <n>', 'Rotation time interval')
|
|
400
|
-
.requiredOption('--unit <unit>', 'Rotation time unit (hours, days, months)')
|
|
401
|
-
.option('--updated-by <email>', 'Email of user performing regeneration')
|
|
402
|
-
.action(async (apiKeyId, opts) => {
|
|
403
|
-
try {
|
|
404
|
-
renderRuntimeConfigHeader();
|
|
405
|
-
const service = await createMgmtService();
|
|
406
|
-
const request = {
|
|
407
|
-
rotation_time_interval: Number.parseInt(opts.interval, 10),
|
|
408
|
-
rotation_time_unit: opts.unit,
|
|
409
|
-
};
|
|
410
|
-
if (opts.updatedBy)
|
|
411
|
-
request.updated_by = opts.updatedBy;
|
|
412
|
-
const key = await service.regenerateApiKey(apiKeyId, request);
|
|
413
|
-
console.log(` API key regenerated: ${key.id}\n`);
|
|
414
|
-
renderApiKeyDetail(key);
|
|
415
|
-
}
|
|
416
|
-
catch (err) {
|
|
417
|
-
renderError(err instanceof Error ? err.message : String(err));
|
|
418
|
-
process.exit(1);
|
|
419
|
-
}
|
|
420
|
-
});
|
|
421
|
-
apiKeys
|
|
422
|
-
.command('delete <apiKeyName>')
|
|
423
|
-
.description('Delete an API key')
|
|
424
|
-
.requiredOption('--updated-by <email>', 'Email of user performing deletion')
|
|
425
|
-
.action(async (apiKeyName, opts) => {
|
|
426
|
-
try {
|
|
427
|
-
renderRuntimeConfigHeader();
|
|
428
|
-
const service = await createMgmtService();
|
|
429
|
-
const result = await service.deleteApiKey(apiKeyName, opts.updatedBy);
|
|
430
|
-
console.log(` ${result.message}\n`);
|
|
431
|
-
}
|
|
432
|
-
catch (err) {
|
|
433
|
-
renderError(err instanceof Error ? err.message : String(err));
|
|
434
|
-
process.exit(1);
|
|
435
|
-
}
|
|
436
|
-
});
|
|
437
|
-
// -----------------------------------------------------------------------
|
|
438
|
-
// runtime customer-apps — customer app management subcommands
|
|
439
|
-
// -----------------------------------------------------------------------
|
|
440
|
-
const customerApps = runtime.command('customer-apps').description('Manage AIRS customer apps');
|
|
441
|
-
customerApps
|
|
442
|
-
.command('list')
|
|
443
|
-
.description('List customer apps')
|
|
444
|
-
.option('--limit <n>', 'Max results', '100')
|
|
445
|
-
.action(async (opts) => {
|
|
446
|
-
try {
|
|
447
|
-
renderRuntimeConfigHeader();
|
|
448
|
-
const service = await createMgmtService();
|
|
449
|
-
const result = await service.listCustomerApps({
|
|
450
|
-
limit: Number.parseInt(opts.limit, 10),
|
|
451
|
-
});
|
|
452
|
-
renderCustomerAppList(result.apps);
|
|
453
|
-
}
|
|
454
|
-
catch (err) {
|
|
455
|
-
renderError(err instanceof Error ? err.message : String(err));
|
|
456
|
-
process.exit(1);
|
|
457
|
-
}
|
|
458
|
-
});
|
|
459
|
-
customerApps
|
|
460
|
-
.command('get <appName>')
|
|
461
|
-
.description('Get customer app details')
|
|
462
|
-
.action(async (appName) => {
|
|
463
|
-
try {
|
|
464
|
-
renderRuntimeConfigHeader();
|
|
465
|
-
const service = await createMgmtService();
|
|
466
|
-
const app = await service.getCustomerApp(appName);
|
|
467
|
-
renderCustomerAppDetail(app);
|
|
468
|
-
}
|
|
469
|
-
catch (err) {
|
|
470
|
-
renderError(err instanceof Error ? err.message : String(err));
|
|
471
|
-
process.exit(1);
|
|
472
|
-
}
|
|
473
|
-
});
|
|
474
|
-
customerApps
|
|
475
|
-
.command('update <appId>')
|
|
476
|
-
.description('Update a customer app')
|
|
477
|
-
.requiredOption('--config <path>', 'JSON file with app updates')
|
|
478
|
-
.action(async (appId, opts) => {
|
|
479
|
-
try {
|
|
480
|
-
renderRuntimeConfigHeader();
|
|
481
|
-
const service = await createMgmtService();
|
|
482
|
-
const config = JSON.parse(fs.readFileSync(opts.config, 'utf-8'));
|
|
483
|
-
const app = await service.updateCustomerApp(appId, config);
|
|
484
|
-
console.log(` Customer app updated: ${app.name}\n`);
|
|
485
|
-
renderCustomerAppDetail(app);
|
|
486
|
-
}
|
|
487
|
-
catch (err) {
|
|
488
|
-
renderError(err instanceof Error ? err.message : String(err));
|
|
489
|
-
process.exit(1);
|
|
490
|
-
}
|
|
491
|
-
});
|
|
492
|
-
customerApps
|
|
493
|
-
.command('delete <appName>')
|
|
494
|
-
.description('Delete a customer app')
|
|
495
|
-
.requiredOption('--updated-by <email>', 'Email of user performing deletion')
|
|
496
|
-
.action(async (appName, opts) => {
|
|
497
|
-
try {
|
|
498
|
-
renderRuntimeConfigHeader();
|
|
499
|
-
const service = await createMgmtService();
|
|
500
|
-
const app = await service.deleteCustomerApp(appName, opts.updatedBy);
|
|
501
|
-
console.log(` Customer app "${app.name}" deleted.\n`);
|
|
502
|
-
}
|
|
503
|
-
catch (err) {
|
|
504
|
-
renderError(err instanceof Error ? err.message : String(err));
|
|
505
|
-
process.exit(1);
|
|
506
|
-
}
|
|
507
|
-
});
|
|
508
|
-
// -----------------------------------------------------------------------
|
|
509
|
-
// runtime deployment-profiles — read-only listing
|
|
510
|
-
// -----------------------------------------------------------------------
|
|
511
|
-
const deploymentProfiles = runtime
|
|
512
|
-
.command('deployment-profiles')
|
|
513
|
-
.description('List AIRS deployment profiles');
|
|
514
|
-
deploymentProfiles
|
|
515
|
-
.command('list')
|
|
516
|
-
.description('List deployment profiles')
|
|
517
|
-
.option('--unactivated', 'Include unactivated profiles')
|
|
518
|
-
.action(async (opts) => {
|
|
519
|
-
try {
|
|
520
|
-
renderRuntimeConfigHeader();
|
|
521
|
-
const service = await createMgmtService();
|
|
522
|
-
const profiles = await service.listDeploymentProfiles({
|
|
523
|
-
unactivated: opts.unactivated,
|
|
524
|
-
});
|
|
525
|
-
renderDeploymentProfileList(profiles);
|
|
526
|
-
}
|
|
527
|
-
catch (err) {
|
|
528
|
-
renderError(err instanceof Error ? err.message : String(err));
|
|
529
|
-
process.exit(1);
|
|
530
|
-
}
|
|
531
|
-
});
|
|
532
|
-
// -----------------------------------------------------------------------
|
|
533
|
-
// runtime dlp-profiles — read-only listing
|
|
534
|
-
// -----------------------------------------------------------------------
|
|
535
|
-
const dlpProfiles = runtime.command('dlp-profiles').description('List AIRS DLP profiles');
|
|
536
|
-
dlpProfiles
|
|
537
|
-
.command('list')
|
|
538
|
-
.description('List DLP profiles')
|
|
539
|
-
.action(async () => {
|
|
540
|
-
try {
|
|
541
|
-
renderRuntimeConfigHeader();
|
|
542
|
-
const service = await createMgmtService();
|
|
543
|
-
const profiles = await service.listDlpProfiles();
|
|
544
|
-
renderDlpProfileList(profiles);
|
|
545
|
-
}
|
|
546
|
-
catch (err) {
|
|
547
|
-
renderError(err instanceof Error ? err.message : String(err));
|
|
548
|
-
process.exit(1);
|
|
549
|
-
}
|
|
550
|
-
});
|
|
551
|
-
// -----------------------------------------------------------------------
|
|
552
|
-
// runtime scan-logs — scan log query
|
|
553
|
-
// -----------------------------------------------------------------------
|
|
554
|
-
const scanLogs = runtime.command('scan-logs').description('Query AIRS scan logs');
|
|
555
|
-
scanLogs
|
|
556
|
-
.command('query')
|
|
557
|
-
.description('Query scan logs')
|
|
558
|
-
.requiredOption('--interval <n>', 'Time interval')
|
|
559
|
-
.requiredOption('--unit <unit>', 'Time unit (hours)')
|
|
560
|
-
.option('--filter <filter>', 'Filter: all, benign, threat', 'all')
|
|
561
|
-
.option('--page <n>', 'Page number', '1')
|
|
562
|
-
.option('--page-size <n>', 'Page size', '50')
|
|
563
|
-
.action(async (opts) => {
|
|
564
|
-
try {
|
|
565
|
-
renderRuntimeConfigHeader();
|
|
566
|
-
const service = await createMgmtService();
|
|
567
|
-
const result = await service.queryScanLogs({
|
|
568
|
-
timeInterval: Number.parseInt(opts.interval, 10),
|
|
569
|
-
timeUnit: opts.unit,
|
|
570
|
-
pageNumber: Number.parseInt(opts.page, 10),
|
|
571
|
-
pageSize: Number.parseInt(opts.pageSize, 10),
|
|
572
|
-
filter: opts.filter,
|
|
573
|
-
});
|
|
574
|
-
renderScanLogList(result.results, result.pageToken);
|
|
575
|
-
}
|
|
576
|
-
catch (err) {
|
|
577
|
-
renderError(err instanceof Error ? err.message : String(err));
|
|
578
|
-
process.exit(1);
|
|
579
|
-
}
|
|
580
|
-
});
|
|
581
590
|
}
|
|
582
591
|
//# sourceMappingURL=runtime.js.map
|