@cdot65/prisma-airs-cli 2.11.0 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +27 -169
- package/dist/chunk-JXHYQFEK.js +1752 -0
- package/dist/cli/index.js +6511 -4
- package/dist/dlp-5XKWITZX.js +710 -0
- package/dist/index.d.ts +1396 -26
- package/dist/index.js +40 -37
- package/package.json +22 -25
- package/dist/airs/dlp/data-filtering-profiles.d.ts +0 -10
- package/dist/airs/dlp/data-filtering-profiles.d.ts.map +0 -1
- package/dist/airs/dlp/data-filtering-profiles.js +0 -17
- package/dist/airs/dlp/data-filtering-profiles.js.map +0 -1
- package/dist/airs/dlp/data-patterns.d.ts +0 -13
- package/dist/airs/dlp/data-patterns.d.ts.map +0 -1
- package/dist/airs/dlp/data-patterns.js +0 -26
- package/dist/airs/dlp/data-patterns.js.map +0 -1
- package/dist/airs/dlp/data-profiles.d.ts +0 -12
- package/dist/airs/dlp/data-profiles.d.ts.map +0 -1
- package/dist/airs/dlp/data-profiles.js +0 -23
- package/dist/airs/dlp/data-profiles.js.map +0 -1
- package/dist/airs/dlp/dictionaries.d.ts +0 -13
- package/dist/airs/dlp/dictionaries.d.ts.map +0 -1
- package/dist/airs/dlp/dictionaries.js +0 -34
- package/dist/airs/dlp/dictionaries.js.map +0 -1
- package/dist/airs/dlp/index.d.ts +0 -6
- package/dist/airs/dlp/index.d.ts.map +0 -1
- package/dist/airs/dlp/index.js +0 -6
- package/dist/airs/dlp/index.js.map +0 -1
- package/dist/airs/dlp/types.d.ts +0 -36
- package/dist/airs/dlp/types.d.ts.map +0 -1
- package/dist/airs/dlp/types.js +0 -2
- package/dist/airs/dlp/types.js.map +0 -1
- package/dist/airs/management.d.ts +0 -68
- package/dist/airs/management.d.ts.map +0 -1
- package/dist/airs/management.js +0 -317
- package/dist/airs/management.js.map +0 -1
- package/dist/airs/modelsecurity.d.ts +0 -74
- package/dist/airs/modelsecurity.d.ts.map +0 -1
- package/dist/airs/modelsecurity.js +0 -337
- package/dist/airs/modelsecurity.js.map +0 -1
- package/dist/airs/promptsets.d.ts +0 -50
- package/dist/airs/promptsets.d.ts.map +0 -1
- package/dist/airs/promptsets.js +0 -120
- package/dist/airs/promptsets.js.map +0 -1
- package/dist/airs/redteam.d.ts +0 -74
- package/dist/airs/redteam.d.ts.map +0 -1
- package/dist/airs/redteam.js +0 -406
- package/dist/airs/redteam.js.map +0 -1
- package/dist/airs/runtime.d.ts +0 -27
- package/dist/airs/runtime.d.ts.map +0 -1
- package/dist/airs/runtime.js +0 -158
- package/dist/airs/runtime.js.map +0 -1
- package/dist/airs/scanner.d.ts +0 -36
- package/dist/airs/scanner.d.ts.map +0 -1
- package/dist/airs/scanner.js +0 -101
- package/dist/airs/scanner.js.map +0 -1
- package/dist/airs/types.d.ts +0 -780
- package/dist/airs/types.d.ts.map +0 -1
- package/dist/airs/types.js +0 -6
- package/dist/airs/types.js.map +0 -1
- package/dist/audit/evaluator.d.ts +0 -17
- package/dist/audit/evaluator.d.ts.map +0 -1
- package/dist/audit/evaluator.js +0 -82
- package/dist/audit/evaluator.js.map +0 -1
- package/dist/audit/report.d.ts +0 -38
- package/dist/audit/report.d.ts.map +0 -1
- package/dist/audit/report.js +0 -141
- package/dist/audit/report.js.map +0 -1
- package/dist/audit/runner.d.ts +0 -18
- package/dist/audit/runner.d.ts.map +0 -1
- package/dist/audit/runner.js +0 -60
- package/dist/audit/runner.js.map +0 -1
- package/dist/audit/types.d.ts +0 -53
- package/dist/audit/types.d.ts.map +0 -1
- package/dist/audit/types.js +0 -5
- package/dist/audit/types.js.map +0 -1
- package/dist/backup/index.d.ts +0 -3
- package/dist/backup/index.d.ts.map +0 -1
- package/dist/backup/index.js +0 -3
- package/dist/backup/index.js.map +0 -1
- package/dist/backup/io.d.ts +0 -15
- package/dist/backup/io.d.ts.map +0 -1
- package/dist/backup/io.js +0 -67
- package/dist/backup/io.js.map +0 -1
- package/dist/backup/types.d.ts +0 -25
- package/dist/backup/types.d.ts.map +0 -1
- package/dist/backup/types.js +0 -2
- package/dist/backup/types.js.map +0 -1
- package/dist/cli/builders/profile-builder.d.ts +0 -45
- package/dist/cli/builders/profile-builder.d.ts.map +0 -1
- package/dist/cli/builders/profile-builder.js +0 -308
- package/dist/cli/builders/profile-builder.js.map +0 -1
- package/dist/cli/bulk-scan-state.d.ts +0 -15
- package/dist/cli/bulk-scan-state.d.ts.map +0 -1
- package/dist/cli/bulk-scan-state.js +0 -20
- package/dist/cli/bulk-scan-state.js.map +0 -1
- package/dist/cli/commands/audit.d.ts +0 -4
- package/dist/cli/commands/audit.d.ts.map +0 -1
- package/dist/cli/commands/audit.js +0 -113
- package/dist/cli/commands/audit.js.map +0 -1
- package/dist/cli/commands/backup.d.ts +0 -10
- package/dist/cli/commands/backup.d.ts.map +0 -1
- package/dist/cli/commands/backup.js +0 -102
- package/dist/cli/commands/backup.js.map +0 -1
- package/dist/cli/commands/dlp/build-body.d.ts +0 -28
- package/dist/cli/commands/dlp/build-body.d.ts.map +0 -1
- package/dist/cli/commands/dlp/build-body.js +0 -174
- package/dist/cli/commands/dlp/build-body.js.map +0 -1
- package/dist/cli/commands/dlp/dictionaries.d.ts +0 -3
- package/dist/cli/commands/dlp/dictionaries.d.ts.map +0 -1
- package/dist/cli/commands/dlp/dictionaries.js +0 -167
- package/dist/cli/commands/dlp/dictionaries.js.map +0 -1
- package/dist/cli/commands/dlp/filtering-profiles.d.ts +0 -3
- package/dist/cli/commands/dlp/filtering-profiles.d.ts.map +0 -1
- package/dist/cli/commands/dlp/filtering-profiles.js +0 -82
- package/dist/cli/commands/dlp/filtering-profiles.js.map +0 -1
- package/dist/cli/commands/dlp/generate.d.ts +0 -3
- package/dist/cli/commands/dlp/generate.d.ts.map +0 -1
- package/dist/cli/commands/dlp/generate.js +0 -51
- package/dist/cli/commands/dlp/generate.js.map +0 -1
- package/dist/cli/commands/dlp/index.d.ts +0 -3
- package/dist/cli/commands/dlp/index.d.ts.map +0 -1
- package/dist/cli/commands/dlp/index.js +0 -16
- package/dist/cli/commands/dlp/index.js.map +0 -1
- package/dist/cli/commands/dlp/patch.d.ts +0 -15
- package/dist/cli/commands/dlp/patch.d.ts.map +0 -1
- package/dist/cli/commands/dlp/patch.js +0 -70
- package/dist/cli/commands/dlp/patch.js.map +0 -1
- package/dist/cli/commands/dlp/patterns.d.ts +0 -3
- package/dist/cli/commands/dlp/patterns.d.ts.map +0 -1
- package/dist/cli/commands/dlp/patterns.js +0 -127
- package/dist/cli/commands/dlp/patterns.js.map +0 -1
- package/dist/cli/commands/dlp/profiles.d.ts +0 -3
- package/dist/cli/commands/dlp/profiles.d.ts.map +0 -1
- package/dist/cli/commands/dlp/profiles.js +0 -126
- package/dist/cli/commands/dlp/profiles.js.map +0 -1
- package/dist/cli/commands/modelsecurity.d.ts +0 -4
- package/dist/cli/commands/modelsecurity.d.ts.map +0 -1
- package/dist/cli/commands/modelsecurity.js +0 -605
- package/dist/cli/commands/modelsecurity.js.map +0 -1
- package/dist/cli/commands/profiles-cleanup.d.ts +0 -26
- package/dist/cli/commands/profiles-cleanup.d.ts.map +0 -1
- package/dist/cli/commands/profiles-cleanup.js +0 -113
- package/dist/cli/commands/profiles-cleanup.js.map +0 -1
- package/dist/cli/commands/redteam.d.ts +0 -12
- package/dist/cli/commands/redteam.d.ts.map +0 -1
- package/dist/cli/commands/redteam.js +0 -1071
- package/dist/cli/commands/redteam.js.map +0 -1
- package/dist/cli/commands/restore.d.ts +0 -11
- package/dist/cli/commands/restore.d.ts.map +0 -1
- package/dist/cli/commands/restore.js +0 -109
- package/dist/cli/commands/restore.js.map +0 -1
- package/dist/cli/commands/runtime.d.ts +0 -6
- package/dist/cli/commands/runtime.d.ts.map +0 -1
- package/dist/cli/commands/runtime.js +0 -822
- package/dist/cli/commands/runtime.js.map +0 -1
- package/dist/cli/commands/topics-apply.d.ts +0 -16
- package/dist/cli/commands/topics-apply.d.ts.map +0 -1
- package/dist/cli/commands/topics-apply.js +0 -69
- package/dist/cli/commands/topics-apply.js.map +0 -1
- package/dist/cli/commands/topics-create.d.ts +0 -16
- package/dist/cli/commands/topics-create.d.ts.map +0 -1
- package/dist/cli/commands/topics-create.js +0 -71
- package/dist/cli/commands/topics-create.js.map +0 -1
- package/dist/cli/commands/topics-eval.d.ts +0 -7
- package/dist/cli/commands/topics-eval.d.ts.map +0 -1
- package/dist/cli/commands/topics-eval.js +0 -65
- package/dist/cli/commands/topics-eval.js.map +0 -1
- package/dist/cli/commands/topics-revert.d.ts +0 -9
- package/dist/cli/commands/topics-revert.d.ts.map +0 -1
- package/dist/cli/commands/topics-revert.js +0 -52
- package/dist/cli/commands/topics-revert.js.map +0 -1
- package/dist/cli/commands/topics-sample.d.ts +0 -4
- package/dist/cli/commands/topics-sample.d.ts.map +0 -1
- package/dist/cli/commands/topics-sample.js +0 -27
- package/dist/cli/commands/topics-sample.js.map +0 -1
- package/dist/cli/debug-logger.d.ts +0 -11
- package/dist/cli/debug-logger.d.ts.map +0 -1
- package/dist/cli/debug-logger.js +0 -137
- package/dist/cli/debug-logger.js.map +0 -1
- package/dist/cli/index.d.ts +0 -3
- package/dist/cli/index.d.ts.map +0 -1
- package/dist/cli/index.js.map +0 -1
- package/dist/cli/parse-input.d.ts +0 -9
- package/dist/cli/parse-input.d.ts.map +0 -1
- package/dist/cli/parse-input.js +0 -109
- package/dist/cli/parse-input.js.map +0 -1
- package/dist/cli/program.d.ts +0 -3
- package/dist/cli/program.d.ts.map +0 -1
- package/dist/cli/program.js +0 -32
- package/dist/cli/program.js.map +0 -1
- package/dist/cli/renderer/audit.d.ts +0 -11
- package/dist/cli/renderer/audit.d.ts.map +0 -1
- package/dist/cli/renderer/audit.js +0 -58
- package/dist/cli/renderer/audit.js.map +0 -1
- package/dist/cli/renderer/backup.d.ts +0 -8
- package/dist/cli/renderer/backup.d.ts.map +0 -1
- package/dist/cli/renderer/backup.js +0 -50
- package/dist/cli/renderer/backup.js.map +0 -1
- package/dist/cli/renderer/common.d.ts +0 -14
- package/dist/cli/renderer/common.d.ts.map +0 -1
- package/dist/cli/renderer/common.js +0 -50
- package/dist/cli/renderer/common.js.map +0 -1
- package/dist/cli/renderer/dlp.d.ts +0 -34
- package/dist/cli/renderer/dlp.d.ts.map +0 -1
- package/dist/cli/renderer/dlp.js +0 -348
- package/dist/cli/renderer/dlp.js.map +0 -1
- package/dist/cli/renderer/eval.d.ts +0 -30
- package/dist/cli/renderer/eval.d.ts.map +0 -1
- package/dist/cli/renderer/eval.js +0 -61
- package/dist/cli/renderer/eval.js.map +0 -1
- package/dist/cli/renderer/index.d.ts +0 -9
- package/dist/cli/renderer/index.d.ts.map +0 -1
- package/dist/cli/renderer/index.js +0 -9
- package/dist/cli/renderer/index.js.map +0 -1
- package/dist/cli/renderer/modelsecurity.d.ts +0 -35
- package/dist/cli/renderer/modelsecurity.d.ts.map +0 -1
- package/dist/cli/renderer/modelsecurity.js +0 -339
- package/dist/cli/renderer/modelsecurity.js.map +0 -1
- package/dist/cli/renderer/redteam.d.ts +0 -216
- package/dist/cli/renderer/redteam.d.ts.map +0 -1
- package/dist/cli/renderer/redteam.js +0 -471
- package/dist/cli/renderer/redteam.js.map +0 -1
- package/dist/cli/renderer/runtime.d.ts +0 -107
- package/dist/cli/renderer/runtime.d.ts.map +0 -1
- package/dist/cli/renderer/runtime.js +0 -359
- package/dist/cli/renderer/runtime.js.map +0 -1
- package/dist/config/loader.d.ts +0 -3
- package/dist/config/loader.d.ts.map +0 -1
- package/dist/config/loader.js +0 -59
- package/dist/config/loader.js.map +0 -1
- package/dist/config/schema.d.ts +0 -63
- package/dist/config/schema.d.ts.map +0 -1
- package/dist/config/schema.js +0 -38
- package/dist/config/schema.js.map +0 -1
- package/dist/core/constraints.d.ts +0 -19
- package/dist/core/constraints.d.ts.map +0 -1
- package/dist/core/constraints.js +0 -82
- package/dist/core/constraints.js.map +0 -1
- package/dist/core/metrics.d.ts +0 -13
- package/dist/core/metrics.d.ts.map +0 -1
- package/dist/core/metrics.js +0 -73
- package/dist/core/metrics.js.map +0 -1
- package/dist/core/prompt-loader.d.ts +0 -14
- package/dist/core/prompt-loader.d.ts.map +0 -1
- package/dist/core/prompt-loader.js +0 -122
- package/dist/core/prompt-loader.js.map +0 -1
- package/dist/core/types.d.ts +0 -96
- package/dist/core/types.d.ts.map +0 -1
- package/dist/core/types.js +0 -5
- package/dist/core/types.js.map +0 -1
- package/dist/dlp/embed/docx.d.ts +0 -3
- package/dist/dlp/embed/docx.d.ts.map +0 -1
- package/dist/dlp/embed/docx.js +0 -54
- package/dist/dlp/embed/docx.js.map +0 -1
- package/dist/dlp/embed/index.d.ts +0 -6
- package/dist/dlp/embed/index.d.ts.map +0 -1
- package/dist/dlp/embed/index.js +0 -20
- package/dist/dlp/embed/index.js.map +0 -1
- package/dist/dlp/embed/jpeg.d.ts +0 -5
- package/dist/dlp/embed/jpeg.d.ts.map +0 -1
- package/dist/dlp/embed/jpeg.js +0 -60
- package/dist/dlp/embed/jpeg.js.map +0 -1
- package/dist/dlp/embed/pdf.d.ts +0 -7
- package/dist/dlp/embed/pdf.d.ts.map +0 -1
- package/dist/dlp/embed/pdf.js +0 -92
- package/dist/dlp/embed/pdf.js.map +0 -1
- package/dist/dlp/embed/png-chunks.d.ts +0 -12
- package/dist/dlp/embed/png-chunks.d.ts.map +0 -1
- package/dist/dlp/embed/png-chunks.js +0 -85
- package/dist/dlp/embed/png-chunks.js.map +0 -1
- package/dist/dlp/embed/png.d.ts +0 -5
- package/dist/dlp/embed/png.d.ts.map +0 -1
- package/dist/dlp/embed/png.js +0 -68
- package/dist/dlp/embed/png.js.map +0 -1
- package/dist/dlp/embed/svg.d.ts +0 -3
- package/dist/dlp/embed/svg.d.ts.map +0 -1
- package/dist/dlp/embed/svg.js +0 -28
- package/dist/dlp/embed/svg.js.map +0 -1
- package/dist/dlp/embed/zip.d.ts +0 -3
- package/dist/dlp/embed/zip.d.ts.map +0 -1
- package/dist/dlp/embed/zip.js +0 -25
- package/dist/dlp/embed/zip.js.map +0 -1
- package/dist/dlp/generate/docx.d.ts +0 -3
- package/dist/dlp/generate/docx.d.ts.map +0 -1
- package/dist/dlp/generate/docx.js +0 -24
- package/dist/dlp/generate/docx.js.map +0 -1
- package/dist/dlp/generate/index.d.ts +0 -5
- package/dist/dlp/generate/index.d.ts.map +0 -1
- package/dist/dlp/generate/index.js +0 -21
- package/dist/dlp/generate/index.js.map +0 -1
- package/dist/dlp/generate/jpeg.d.ts +0 -3
- package/dist/dlp/generate/jpeg.d.ts.map +0 -1
- package/dist/dlp/generate/jpeg.js +0 -8
- package/dist/dlp/generate/jpeg.js.map +0 -1
- package/dist/dlp/generate/pdf.d.ts +0 -3
- package/dist/dlp/generate/pdf.d.ts.map +0 -1
- package/dist/dlp/generate/pdf.js +0 -19
- package/dist/dlp/generate/pdf.js.map +0 -1
- package/dist/dlp/generate/png.d.ts +0 -3
- package/dist/dlp/generate/png.d.ts.map +0 -1
- package/dist/dlp/generate/png.js +0 -8
- package/dist/dlp/generate/png.js.map +0 -1
- package/dist/dlp/generate/raster.d.ts +0 -9
- package/dist/dlp/generate/raster.d.ts.map +0 -1
- package/dist/dlp/generate/raster.js +0 -20
- package/dist/dlp/generate/raster.js.map +0 -1
- package/dist/dlp/generate/svg.d.ts +0 -3
- package/dist/dlp/generate/svg.d.ts.map +0 -1
- package/dist/dlp/generate/svg.js +0 -17
- package/dist/dlp/generate/svg.js.map +0 -1
- package/dist/dlp/index.d.ts +0 -15
- package/dist/dlp/index.d.ts.map +0 -1
- package/dist/dlp/index.js +0 -54
- package/dist/dlp/index.js.map +0 -1
- package/dist/dlp/lorem.d.ts +0 -3
- package/dist/dlp/lorem.d.ts.map +0 -1
- package/dist/dlp/lorem.js +0 -65
- package/dist/dlp/lorem.js.map +0 -1
- package/dist/dlp/manifest.d.ts +0 -11
- package/dist/dlp/manifest.d.ts.map +0 -1
- package/dist/dlp/manifest.js +0 -14
- package/dist/dlp/manifest.js.map +0 -1
- package/dist/dlp/payload.d.ts +0 -6
- package/dist/dlp/payload.d.ts.map +0 -1
- package/dist/dlp/payload.js +0 -62
- package/dist/dlp/payload.js.map +0 -1
- package/dist/dlp/rng.d.ts +0 -9
- package/dist/dlp/rng.d.ts.map +0 -1
- package/dist/dlp/rng.js +0 -28
- package/dist/dlp/rng.js.map +0 -1
- package/dist/dlp/types.d.ts +0 -26
- package/dist/dlp/types.d.ts.map +0 -1
- package/dist/dlp/types.js +0 -2
- package/dist/dlp/types.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/llm/prompts/analyze-results.d.ts +0 -3
- package/dist/llm/prompts/analyze-results.d.ts.map +0 -1
- package/dist/llm/prompts/analyze-results.js +0 -52
- package/dist/llm/prompts/analyze-results.js.map +0 -1
- package/dist/llm/prompts/generate-companion.d.ts +0 -3
- package/dist/llm/prompts/generate-companion.d.ts.map +0 -1
- package/dist/llm/prompts/generate-companion.js +0 -42
- package/dist/llm/prompts/generate-companion.js.map +0 -1
- package/dist/llm/prompts/generate-tests.d.ts +0 -3
- package/dist/llm/prompts/generate-tests.d.ts.map +0 -1
- package/dist/llm/prompts/generate-tests.js +0 -46
- package/dist/llm/prompts/generate-tests.js.map +0 -1
- package/dist/llm/prompts/generate-topic.d.ts +0 -4
- package/dist/llm/prompts/generate-topic.d.ts.map +0 -1
- package/dist/llm/prompts/generate-topic.js +0 -41
- package/dist/llm/prompts/generate-topic.js.map +0 -1
- package/dist/llm/prompts/improve-topic.d.ts +0 -3
- package/dist/llm/prompts/improve-topic.d.ts.map +0 -1
- package/dist/llm/prompts/improve-topic.js +0 -77
- package/dist/llm/prompts/improve-topic.js.map +0 -1
- package/dist/llm/prompts/simplify-topic.d.ts +0 -3
- package/dist/llm/prompts/simplify-topic.d.ts.map +0 -1
- package/dist/llm/prompts/simplify-topic.js +0 -50
- package/dist/llm/prompts/simplify-topic.js.map +0 -1
- package/dist/llm/provider.d.ts +0 -21
- package/dist/llm/provider.d.ts.map +0 -1
- package/dist/llm/provider.js +0 -76
- package/dist/llm/provider.js.map +0 -1
- package/dist/llm/schemas.d.ts +0 -97
- package/dist/llm/schemas.d.ts.map +0 -1
- package/dist/llm/schemas.js +0 -24
- package/dist/llm/schemas.js.map +0 -1
- package/dist/llm/service.d.ts +0 -34
- package/dist/llm/service.d.ts.map +0 -1
- package/dist/llm/service.js +0 -268
- package/dist/llm/service.js.map +0 -1
- package/dist/llm/types.d.ts +0 -18
- package/dist/llm/types.d.ts.map +0 -1
- package/dist/llm/types.js +0 -2
- package/dist/llm/types.js.map +0 -1
- package/dist/report/html.d.ts +0 -6
- package/dist/report/html.d.ts.map +0 -1
- package/dist/report/html.js +0 -200
- package/dist/report/html.js.map +0 -1
- package/dist/report/json.d.ts +0 -11
- package/dist/report/json.d.ts.map +0 -1
- package/dist/report/json.js +0 -74
- package/dist/report/json.js.map +0 -1
- package/dist/report/types.d.ts +0 -58
- package/dist/report/types.d.ts.map +0 -1
- package/dist/report/types.js +0 -5
- package/dist/report/types.js.map +0 -1
|
@@ -1,1071 +0,0 @@
|
|
|
1
|
-
import * as fs from 'node:fs';
|
|
2
|
-
import * as path from 'node:path';
|
|
3
|
-
import chalk from 'chalk';
|
|
4
|
-
import { SdkPromptSetService } from '../../airs/promptsets.js';
|
|
5
|
-
import { SdkRedTeamService } from '../../airs/redteam.js';
|
|
6
|
-
import { resolveOutputDir } from '../../backup/io.js';
|
|
7
|
-
import { loadConfig } from '../../config/loader.js';
|
|
8
|
-
import { buildAttackListFootnote, renderAttackList, renderAuthValidation, renderBackupHeader, renderBackupSummary, renderCategories, renderCustomAttackList, renderCustomReport, renderError, renderEulaContent, renderEulaStatus, renderInstanceDetail, renderInstanceResponse, renderPromptDetail, renderPromptList, renderPromptSetDetail, renderPromptSetList, renderPropertyNames, renderPropertyValues, renderRedteamHeader, renderRegistryCredentials, renderRestoreSummary, renderScanList, renderScanProgress, renderScanStatus, renderStaticReport, renderTargetDetail, renderTargetList, renderTargetTemplates, renderVersionInfo, } from '../renderer/index.js';
|
|
9
|
-
import { backupTargets } from './backup.js';
|
|
10
|
-
import { restoreTargets } from './restore.js';
|
|
11
|
-
/** Create an SdkRedTeamService from config. */
|
|
12
|
-
async function createService() {
|
|
13
|
-
const config = await loadConfig();
|
|
14
|
-
return new SdkRedTeamService({
|
|
15
|
-
clientId: config.mgmtClientId,
|
|
16
|
-
clientSecret: config.mgmtClientSecret,
|
|
17
|
-
tsgId: config.mgmtTsgId,
|
|
18
|
-
tokenEndpoint: config.mgmtTokenEndpoint,
|
|
19
|
-
});
|
|
20
|
-
}
|
|
21
|
-
/** Create an SdkPromptSetService from config. */
|
|
22
|
-
async function createPromptSetService() {
|
|
23
|
-
const config = await loadConfig();
|
|
24
|
-
return new SdkPromptSetService({
|
|
25
|
-
clientId: config.mgmtClientId,
|
|
26
|
-
clientSecret: config.mgmtClientSecret,
|
|
27
|
-
tsgId: config.mgmtTsgId,
|
|
28
|
-
tokenEndpoint: config.mgmtTokenEndpoint,
|
|
29
|
-
});
|
|
30
|
-
}
|
|
31
|
-
/** Parse `--goals` arg as inline JSON array (starts with `[`) or path to a JSON file. */
|
|
32
|
-
export function parseAttackGoals(input) {
|
|
33
|
-
const trimmed = input.trim();
|
|
34
|
-
const raw = trimmed.startsWith('[') ? trimmed : fs.readFileSync(trimmed, 'utf-8');
|
|
35
|
-
let parsed;
|
|
36
|
-
try {
|
|
37
|
-
parsed = JSON.parse(raw);
|
|
38
|
-
}
|
|
39
|
-
catch (err) {
|
|
40
|
-
throw new Error(`--goals: invalid JSON (${err instanceof Error ? err.message : err})`);
|
|
41
|
-
}
|
|
42
|
-
if (!Array.isArray(parsed) || !parsed.every((g) => typeof g === 'string' && g.length > 0)) {
|
|
43
|
-
throw new Error('--goals: expected a JSON array of non-empty strings');
|
|
44
|
-
}
|
|
45
|
-
return parsed;
|
|
46
|
-
}
|
|
47
|
-
/** Parse a string flag as a positive integer. */
|
|
48
|
-
export function parsePositiveInt(input, flag) {
|
|
49
|
-
const n = Number.parseInt(input, 10);
|
|
50
|
-
if (!Number.isFinite(n) || n <= 0) {
|
|
51
|
-
throw new Error(`${flag}: expected a positive integer, got "${input}"`);
|
|
52
|
-
}
|
|
53
|
-
return n;
|
|
54
|
-
}
|
|
55
|
-
/** Valid provider names for target init templates. */
|
|
56
|
-
export const VALID_TARGET_PROVIDERS = [
|
|
57
|
-
'OPENAI',
|
|
58
|
-
'HUGGING_FACE',
|
|
59
|
-
'DATABRICKS',
|
|
60
|
-
'BEDROCK',
|
|
61
|
-
'REST',
|
|
62
|
-
'STREAMING',
|
|
63
|
-
];
|
|
64
|
-
/** Build a target config scaffold from a provider template. */
|
|
65
|
-
export function buildTargetScaffold(provider, templates) {
|
|
66
|
-
const key = provider.toUpperCase();
|
|
67
|
-
if (!VALID_TARGET_PROVIDERS.includes(key)) {
|
|
68
|
-
throw new Error(`Unknown provider "${provider}". Valid providers: ${VALID_TARGET_PROVIDERS.join(', ')}`);
|
|
69
|
-
}
|
|
70
|
-
return {
|
|
71
|
-
name: '',
|
|
72
|
-
target_type: 'APPLICATION',
|
|
73
|
-
connection_params: templates[key] ?? {},
|
|
74
|
-
target_background: {},
|
|
75
|
-
additional_context: {},
|
|
76
|
-
target_metadata: {},
|
|
77
|
-
};
|
|
78
|
-
}
|
|
79
|
-
/** Register the `redteam` command group. */
|
|
80
|
-
export function registerRedteamCommand(program) {
|
|
81
|
-
const redteam = program.command('redteam').description('AI Red Team scan operations');
|
|
82
|
-
// -----------------------------------------------------------------------
|
|
83
|
-
// redteam abort — abort a running scan
|
|
84
|
-
// -----------------------------------------------------------------------
|
|
85
|
-
redteam
|
|
86
|
-
.command('abort <jobId>')
|
|
87
|
-
.description('Abort a running scan')
|
|
88
|
-
.action(async (jobId) => {
|
|
89
|
-
try {
|
|
90
|
-
renderRedteamHeader();
|
|
91
|
-
const service = await createService();
|
|
92
|
-
await service.abortScan(jobId);
|
|
93
|
-
console.log(` Scan ${jobId} aborted.\n`);
|
|
94
|
-
}
|
|
95
|
-
catch (err) {
|
|
96
|
-
renderError(err instanceof Error ? err.message : String(err));
|
|
97
|
-
process.exit(1);
|
|
98
|
-
}
|
|
99
|
-
});
|
|
100
|
-
// -----------------------------------------------------------------------
|
|
101
|
-
// redteam categories — list attack categories
|
|
102
|
-
// -----------------------------------------------------------------------
|
|
103
|
-
redteam
|
|
104
|
-
.command('categories')
|
|
105
|
-
.description('List available attack categories')
|
|
106
|
-
.action(async () => {
|
|
107
|
-
try {
|
|
108
|
-
renderRedteamHeader();
|
|
109
|
-
const service = await createService();
|
|
110
|
-
const categories = await service.getCategories();
|
|
111
|
-
renderCategories(categories);
|
|
112
|
-
}
|
|
113
|
-
catch (err) {
|
|
114
|
-
renderError(err instanceof Error ? err.message : String(err));
|
|
115
|
-
process.exit(1);
|
|
116
|
-
}
|
|
117
|
-
});
|
|
118
|
-
// -----------------------------------------------------------------------
|
|
119
|
-
// redteam eula — EULA management subcommands
|
|
120
|
-
// -----------------------------------------------------------------------
|
|
121
|
-
const eula = redteam.command('eula').description('Manage Red Team EULA');
|
|
122
|
-
eula
|
|
123
|
-
.command('status')
|
|
124
|
-
.description('Check EULA acceptance status')
|
|
125
|
-
.action(async () => {
|
|
126
|
-
try {
|
|
127
|
-
renderRedteamHeader();
|
|
128
|
-
const service = await createService();
|
|
129
|
-
const status = await service.getEulaStatus();
|
|
130
|
-
renderEulaStatus(status);
|
|
131
|
-
}
|
|
132
|
-
catch (err) {
|
|
133
|
-
renderError(err instanceof Error ? err.message : String(err));
|
|
134
|
-
process.exit(1);
|
|
135
|
-
}
|
|
136
|
-
});
|
|
137
|
-
eula
|
|
138
|
-
.command('content')
|
|
139
|
-
.description('Display EULA content')
|
|
140
|
-
.action(async () => {
|
|
141
|
-
try {
|
|
142
|
-
renderRedteamHeader();
|
|
143
|
-
const service = await createService();
|
|
144
|
-
const content = await service.getEulaContent();
|
|
145
|
-
renderEulaContent(content);
|
|
146
|
-
}
|
|
147
|
-
catch (err) {
|
|
148
|
-
renderError(err instanceof Error ? err.message : String(err));
|
|
149
|
-
process.exit(1);
|
|
150
|
-
}
|
|
151
|
-
});
|
|
152
|
-
eula
|
|
153
|
-
.command('accept')
|
|
154
|
-
.description('Accept the EULA')
|
|
155
|
-
.option('--confirm', 'Skip confirmation prompt')
|
|
156
|
-
.action(async (opts) => {
|
|
157
|
-
try {
|
|
158
|
-
renderRedteamHeader();
|
|
159
|
-
const service = await createService();
|
|
160
|
-
const content = await service.getEulaContent();
|
|
161
|
-
if (!opts.confirm) {
|
|
162
|
-
renderEulaContent(content);
|
|
163
|
-
console.log(' Pass --confirm to accept.\n');
|
|
164
|
-
return;
|
|
165
|
-
}
|
|
166
|
-
const result = await service.acceptEula(content.content);
|
|
167
|
-
renderEulaStatus(result);
|
|
168
|
-
console.log(' EULA accepted.\n');
|
|
169
|
-
}
|
|
170
|
-
catch (err) {
|
|
171
|
-
renderError(err instanceof Error ? err.message : String(err));
|
|
172
|
-
process.exit(1);
|
|
173
|
-
}
|
|
174
|
-
});
|
|
175
|
-
// -----------------------------------------------------------------------
|
|
176
|
-
// redteam instances — instance CRUD subcommands
|
|
177
|
-
// -----------------------------------------------------------------------
|
|
178
|
-
const instances = redteam.command('instances').description('Manage Red Team instances');
|
|
179
|
-
instances
|
|
180
|
-
.command('create')
|
|
181
|
-
.description('Create an instance')
|
|
182
|
-
.requiredOption('--tsg-id <id>', 'TSG ID')
|
|
183
|
-
.requiredOption('--tenant-id <id>', 'Tenant ID')
|
|
184
|
-
.requiredOption('--app-id <id>', 'App ID')
|
|
185
|
-
.requiredOption('--region <region>', 'Region')
|
|
186
|
-
.action(async (opts) => {
|
|
187
|
-
try {
|
|
188
|
-
renderRedteamHeader();
|
|
189
|
-
const service = await createService();
|
|
190
|
-
const result = await service.createInstance({
|
|
191
|
-
tsgId: opts.tsgId,
|
|
192
|
-
tenantId: opts.tenantId,
|
|
193
|
-
appId: opts.appId,
|
|
194
|
-
region: opts.region,
|
|
195
|
-
});
|
|
196
|
-
renderInstanceResponse(result);
|
|
197
|
-
}
|
|
198
|
-
catch (err) {
|
|
199
|
-
renderError(err instanceof Error ? err.message : String(err));
|
|
200
|
-
process.exit(1);
|
|
201
|
-
}
|
|
202
|
-
});
|
|
203
|
-
instances
|
|
204
|
-
.command('get <tenantId>')
|
|
205
|
-
.description('Get instance details')
|
|
206
|
-
.action(async (tenantId) => {
|
|
207
|
-
try {
|
|
208
|
-
renderRedteamHeader();
|
|
209
|
-
const service = await createService();
|
|
210
|
-
const result = await service.getInstance(tenantId);
|
|
211
|
-
renderInstanceDetail(result);
|
|
212
|
-
}
|
|
213
|
-
catch (err) {
|
|
214
|
-
renderError(err instanceof Error ? err.message : String(err));
|
|
215
|
-
process.exit(1);
|
|
216
|
-
}
|
|
217
|
-
});
|
|
218
|
-
instances
|
|
219
|
-
.command('update <tenantId>')
|
|
220
|
-
.description('Update an instance')
|
|
221
|
-
.requiredOption('--tsg-id <id>', 'TSG ID')
|
|
222
|
-
.requiredOption('--app-id <id>', 'App ID')
|
|
223
|
-
.requiredOption('--region <region>', 'Region')
|
|
224
|
-
.action(async (tenantId, opts) => {
|
|
225
|
-
try {
|
|
226
|
-
renderRedteamHeader();
|
|
227
|
-
const service = await createService();
|
|
228
|
-
const result = await service.updateInstance(tenantId, {
|
|
229
|
-
tsgId: opts.tsgId,
|
|
230
|
-
tenantId,
|
|
231
|
-
appId: opts.appId,
|
|
232
|
-
region: opts.region,
|
|
233
|
-
});
|
|
234
|
-
renderInstanceResponse(result);
|
|
235
|
-
}
|
|
236
|
-
catch (err) {
|
|
237
|
-
renderError(err instanceof Error ? err.message : String(err));
|
|
238
|
-
process.exit(1);
|
|
239
|
-
}
|
|
240
|
-
});
|
|
241
|
-
instances
|
|
242
|
-
.command('delete <tenantId>')
|
|
243
|
-
.description('Delete an instance')
|
|
244
|
-
.action(async (tenantId) => {
|
|
245
|
-
try {
|
|
246
|
-
renderRedteamHeader();
|
|
247
|
-
const service = await createService();
|
|
248
|
-
const result = await service.deleteInstance(tenantId);
|
|
249
|
-
renderInstanceResponse(result);
|
|
250
|
-
console.log(` Instance ${tenantId} deleted.\n`);
|
|
251
|
-
}
|
|
252
|
-
catch (err) {
|
|
253
|
-
renderError(err instanceof Error ? err.message : String(err));
|
|
254
|
-
process.exit(1);
|
|
255
|
-
}
|
|
256
|
-
});
|
|
257
|
-
// -----------------------------------------------------------------------
|
|
258
|
-
// redteam devices — device management subcommands
|
|
259
|
-
// -----------------------------------------------------------------------
|
|
260
|
-
const devices = redteam.command('devices').description('Manage Red Team devices');
|
|
261
|
-
devices
|
|
262
|
-
.command('create <tenantId>')
|
|
263
|
-
.description('Create devices for an instance')
|
|
264
|
-
.requiredOption('--config <path>', 'JSON file with device request')
|
|
265
|
-
.action(async (tenantId, opts) => {
|
|
266
|
-
try {
|
|
267
|
-
renderRedteamHeader();
|
|
268
|
-
const service = await createService();
|
|
269
|
-
const config = JSON.parse(fs.readFileSync(opts.config, 'utf-8'));
|
|
270
|
-
const result = await service.createDevices(tenantId, config);
|
|
271
|
-
console.log(' Devices created:');
|
|
272
|
-
console.log(` ${JSON.stringify(result, null, 2)}\n`);
|
|
273
|
-
}
|
|
274
|
-
catch (err) {
|
|
275
|
-
renderError(err instanceof Error ? err.message : String(err));
|
|
276
|
-
process.exit(1);
|
|
277
|
-
}
|
|
278
|
-
});
|
|
279
|
-
devices
|
|
280
|
-
.command('update <tenantId>')
|
|
281
|
-
.description('Update devices for an instance (PATCH)')
|
|
282
|
-
.requiredOption('--config <path>', 'JSON file with device request')
|
|
283
|
-
.action(async (tenantId, opts) => {
|
|
284
|
-
try {
|
|
285
|
-
renderRedteamHeader();
|
|
286
|
-
const service = await createService();
|
|
287
|
-
const config = JSON.parse(fs.readFileSync(opts.config, 'utf-8'));
|
|
288
|
-
const result = await service.updateDevices(tenantId, config);
|
|
289
|
-
console.log(' Devices updated:');
|
|
290
|
-
console.log(` ${JSON.stringify(result, null, 2)}\n`);
|
|
291
|
-
}
|
|
292
|
-
catch (err) {
|
|
293
|
-
renderError(err instanceof Error ? err.message : String(err));
|
|
294
|
-
process.exit(1);
|
|
295
|
-
}
|
|
296
|
-
});
|
|
297
|
-
devices
|
|
298
|
-
.command('delete <tenantId>')
|
|
299
|
-
.description('Delete devices by serial numbers')
|
|
300
|
-
.requiredOption('--serial-numbers <list>', 'Comma-separated serial numbers')
|
|
301
|
-
.action(async (tenantId, opts) => {
|
|
302
|
-
try {
|
|
303
|
-
renderRedteamHeader();
|
|
304
|
-
const service = await createService();
|
|
305
|
-
const result = await service.deleteDevices(tenantId, opts.serialNumbers);
|
|
306
|
-
console.log(' Devices deleted:');
|
|
307
|
-
console.log(` ${JSON.stringify(result, null, 2)}\n`);
|
|
308
|
-
}
|
|
309
|
-
catch (err) {
|
|
310
|
-
renderError(err instanceof Error ? err.message : String(err));
|
|
311
|
-
process.exit(1);
|
|
312
|
-
}
|
|
313
|
-
});
|
|
314
|
-
// -----------------------------------------------------------------------
|
|
315
|
-
// redteam registry-credentials — registry credentials
|
|
316
|
-
// -----------------------------------------------------------------------
|
|
317
|
-
redteam
|
|
318
|
-
.command('registry-credentials')
|
|
319
|
-
.description('Get or create registry credentials')
|
|
320
|
-
.action(async () => {
|
|
321
|
-
try {
|
|
322
|
-
renderRedteamHeader();
|
|
323
|
-
const service = await createService();
|
|
324
|
-
const creds = await service.getRegistryCredentials();
|
|
325
|
-
renderRegistryCredentials(creds);
|
|
326
|
-
}
|
|
327
|
-
catch (err) {
|
|
328
|
-
renderError(err instanceof Error ? err.message : String(err));
|
|
329
|
-
process.exit(1);
|
|
330
|
-
}
|
|
331
|
-
});
|
|
332
|
-
// -----------------------------------------------------------------------
|
|
333
|
-
// redteam list — list recent scans
|
|
334
|
-
// -----------------------------------------------------------------------
|
|
335
|
-
redteam
|
|
336
|
-
.command('list')
|
|
337
|
-
.description('List recent scans')
|
|
338
|
-
.option('--status <status>', 'Filter by status (QUEUED, RUNNING, COMPLETED, FAILED, ABORTED)')
|
|
339
|
-
.option('--type <type>', 'Filter by job type (STATIC, DYNAMIC, CUSTOM)')
|
|
340
|
-
.option('--target <uuid>', 'Filter by target UUID')
|
|
341
|
-
.option('--limit <n>', 'Max results', '10')
|
|
342
|
-
.option('--output <format>', 'Output format: pretty, table, csv, json, yaml', 'pretty')
|
|
343
|
-
.action(async (opts) => {
|
|
344
|
-
try {
|
|
345
|
-
const fmt = opts.output;
|
|
346
|
-
if (fmt === 'pretty')
|
|
347
|
-
renderRedteamHeader();
|
|
348
|
-
const service = await createService();
|
|
349
|
-
const scans = await service.listScans({
|
|
350
|
-
status: opts.status,
|
|
351
|
-
jobType: opts.type,
|
|
352
|
-
targetId: opts.target,
|
|
353
|
-
limit: Number.parseInt(opts.limit, 10),
|
|
354
|
-
});
|
|
355
|
-
renderScanList(scans, fmt);
|
|
356
|
-
}
|
|
357
|
-
catch (err) {
|
|
358
|
-
renderError(err instanceof Error ? err.message : String(err));
|
|
359
|
-
process.exit(1);
|
|
360
|
-
}
|
|
361
|
-
});
|
|
362
|
-
// -----------------------------------------------------------------------
|
|
363
|
-
// redteam prompt-sets — prompt set CRUD subcommands
|
|
364
|
-
// -----------------------------------------------------------------------
|
|
365
|
-
const promptSets = redteam.command('prompt-sets').description('Manage custom prompt sets');
|
|
366
|
-
promptSets
|
|
367
|
-
.command('list')
|
|
368
|
-
.description('List custom prompt sets')
|
|
369
|
-
.option('--output <format>', 'Output format: pretty, table, csv, json, yaml', 'pretty')
|
|
370
|
-
.action(async (opts) => {
|
|
371
|
-
try {
|
|
372
|
-
const fmt = opts.output;
|
|
373
|
-
if (fmt === 'pretty')
|
|
374
|
-
renderRedteamHeader();
|
|
375
|
-
const service = await createPromptSetService();
|
|
376
|
-
const sets = await service.listPromptSets();
|
|
377
|
-
renderPromptSetList(sets, fmt);
|
|
378
|
-
}
|
|
379
|
-
catch (err) {
|
|
380
|
-
renderError(err instanceof Error ? err.message : String(err));
|
|
381
|
-
process.exit(1);
|
|
382
|
-
}
|
|
383
|
-
});
|
|
384
|
-
promptSets
|
|
385
|
-
.command('get <uuid>')
|
|
386
|
-
.description('Get prompt set details')
|
|
387
|
-
.option('--output <format>', 'Output format: pretty, json, yaml', 'pretty')
|
|
388
|
-
.action(async (uuid, opts) => {
|
|
389
|
-
try {
|
|
390
|
-
const fmt = opts.output;
|
|
391
|
-
if (fmt === 'pretty')
|
|
392
|
-
renderRedteamHeader();
|
|
393
|
-
const service = await createPromptSetService();
|
|
394
|
-
const ps = await service.getPromptSet(uuid);
|
|
395
|
-
const info = await service.getPromptSetVersionInfo(uuid);
|
|
396
|
-
if (fmt === 'pretty') {
|
|
397
|
-
renderPromptSetDetail(ps);
|
|
398
|
-
renderVersionInfo(info);
|
|
399
|
-
}
|
|
400
|
-
else {
|
|
401
|
-
renderPromptSetDetail(ps, fmt, info);
|
|
402
|
-
}
|
|
403
|
-
}
|
|
404
|
-
catch (err) {
|
|
405
|
-
renderError(err instanceof Error ? err.message : String(err));
|
|
406
|
-
process.exit(1);
|
|
407
|
-
}
|
|
408
|
-
});
|
|
409
|
-
promptSets
|
|
410
|
-
.command('create')
|
|
411
|
-
.description('Create a new prompt set')
|
|
412
|
-
.requiredOption('--name <name>', 'Prompt set name')
|
|
413
|
-
.option('--description <desc>', 'Prompt set description')
|
|
414
|
-
.action(async (opts) => {
|
|
415
|
-
try {
|
|
416
|
-
renderRedteamHeader();
|
|
417
|
-
const service = await createPromptSetService();
|
|
418
|
-
const result = await service.createPromptSet(opts.name, opts.description);
|
|
419
|
-
console.log(` Prompt set created: ${result.uuid}\n`);
|
|
420
|
-
console.log(` Name: ${result.name}\n`);
|
|
421
|
-
}
|
|
422
|
-
catch (err) {
|
|
423
|
-
renderError(err instanceof Error ? err.message : String(err));
|
|
424
|
-
process.exit(1);
|
|
425
|
-
}
|
|
426
|
-
});
|
|
427
|
-
promptSets
|
|
428
|
-
.command('update <uuid>')
|
|
429
|
-
.description('Update a prompt set')
|
|
430
|
-
.option('--name <name>', 'New name')
|
|
431
|
-
.option('--description <desc>', 'New description')
|
|
432
|
-
.action(async (uuid, opts) => {
|
|
433
|
-
try {
|
|
434
|
-
renderRedteamHeader();
|
|
435
|
-
const service = await createPromptSetService();
|
|
436
|
-
const request = {};
|
|
437
|
-
if (opts.name)
|
|
438
|
-
request.name = opts.name;
|
|
439
|
-
if (opts.description)
|
|
440
|
-
request.description = opts.description;
|
|
441
|
-
const result = await service.updatePromptSet(uuid, request);
|
|
442
|
-
renderPromptSetDetail(result);
|
|
443
|
-
}
|
|
444
|
-
catch (err) {
|
|
445
|
-
renderError(err instanceof Error ? err.message : String(err));
|
|
446
|
-
process.exit(1);
|
|
447
|
-
}
|
|
448
|
-
});
|
|
449
|
-
promptSets
|
|
450
|
-
.command('archive <uuid>')
|
|
451
|
-
.description('Archive a prompt set')
|
|
452
|
-
.option('--unarchive', 'Unarchive instead')
|
|
453
|
-
.action(async (uuid, opts) => {
|
|
454
|
-
try {
|
|
455
|
-
renderRedteamHeader();
|
|
456
|
-
const service = await createPromptSetService();
|
|
457
|
-
const archive = !opts.unarchive;
|
|
458
|
-
await service.archivePromptSet(uuid, archive);
|
|
459
|
-
console.log(` Prompt set ${uuid} ${archive ? 'archived' : 'unarchived'}.\n`);
|
|
460
|
-
}
|
|
461
|
-
catch (err) {
|
|
462
|
-
renderError(err instanceof Error ? err.message : String(err));
|
|
463
|
-
process.exit(1);
|
|
464
|
-
}
|
|
465
|
-
});
|
|
466
|
-
promptSets
|
|
467
|
-
.command('download <uuid>')
|
|
468
|
-
.description('Download CSV template for a prompt set')
|
|
469
|
-
.option('--output <path>', 'Output file path')
|
|
470
|
-
.action(async (uuid, opts) => {
|
|
471
|
-
try {
|
|
472
|
-
renderRedteamHeader();
|
|
473
|
-
const service = await createPromptSetService();
|
|
474
|
-
const csv = await service.downloadTemplate(uuid);
|
|
475
|
-
const outPath = opts.output || `${uuid}-template.csv`;
|
|
476
|
-
fs.writeFileSync(outPath, csv, 'utf-8');
|
|
477
|
-
console.log(` Template saved to ${outPath}\n`);
|
|
478
|
-
}
|
|
479
|
-
catch (err) {
|
|
480
|
-
renderError(err instanceof Error ? err.message : String(err));
|
|
481
|
-
process.exit(1);
|
|
482
|
-
}
|
|
483
|
-
});
|
|
484
|
-
promptSets
|
|
485
|
-
.command('upload <uuid> <file>')
|
|
486
|
-
.description('Upload CSV prompts to a prompt set')
|
|
487
|
-
.action(async (uuid, file) => {
|
|
488
|
-
try {
|
|
489
|
-
renderRedteamHeader();
|
|
490
|
-
const service = await createPromptSetService();
|
|
491
|
-
const content = fs.readFileSync(file);
|
|
492
|
-
const filename = path.basename(file);
|
|
493
|
-
const blob = new File([content], filename, { type: 'text/csv' });
|
|
494
|
-
const result = await service.uploadPromptsCsv(uuid, blob);
|
|
495
|
-
console.log(` ${result.message}\n`);
|
|
496
|
-
}
|
|
497
|
-
catch (err) {
|
|
498
|
-
renderError(err instanceof Error ? err.message : String(err));
|
|
499
|
-
process.exit(1);
|
|
500
|
-
}
|
|
501
|
-
});
|
|
502
|
-
// -----------------------------------------------------------------------
|
|
503
|
-
// redteam prompts — individual prompt CRUD subcommands
|
|
504
|
-
// -----------------------------------------------------------------------
|
|
505
|
-
const prompts = redteam.command('prompts').description('Manage prompts within prompt sets');
|
|
506
|
-
prompts
|
|
507
|
-
.command('list <setUuid>')
|
|
508
|
-
.description('List prompts in a prompt set')
|
|
509
|
-
.option('--limit <n>', 'Max results', '50')
|
|
510
|
-
.action(async (setUuid, opts) => {
|
|
511
|
-
try {
|
|
512
|
-
renderRedteamHeader();
|
|
513
|
-
const service = await createPromptSetService();
|
|
514
|
-
const list = await service.listPrompts(setUuid, {
|
|
515
|
-
limit: Number.parseInt(opts.limit, 10),
|
|
516
|
-
});
|
|
517
|
-
renderPromptList(list);
|
|
518
|
-
}
|
|
519
|
-
catch (err) {
|
|
520
|
-
renderError(err instanceof Error ? err.message : String(err));
|
|
521
|
-
process.exit(1);
|
|
522
|
-
}
|
|
523
|
-
});
|
|
524
|
-
prompts
|
|
525
|
-
.command('get <setUuid> <promptUuid>')
|
|
526
|
-
.description('Get prompt details')
|
|
527
|
-
.action(async (setUuid, promptUuid) => {
|
|
528
|
-
try {
|
|
529
|
-
renderRedteamHeader();
|
|
530
|
-
const service = await createPromptSetService();
|
|
531
|
-
const prompt = await service.getPrompt(setUuid, promptUuid);
|
|
532
|
-
renderPromptDetail(prompt);
|
|
533
|
-
}
|
|
534
|
-
catch (err) {
|
|
535
|
-
renderError(err instanceof Error ? err.message : String(err));
|
|
536
|
-
process.exit(1);
|
|
537
|
-
}
|
|
538
|
-
});
|
|
539
|
-
prompts
|
|
540
|
-
.command('add <setUuid>')
|
|
541
|
-
.description('Add a prompt to a prompt set')
|
|
542
|
-
.requiredOption('--prompt <text>', 'Prompt text')
|
|
543
|
-
.option('--goal <text>', 'Prompt goal')
|
|
544
|
-
.action(async (setUuid, opts) => {
|
|
545
|
-
try {
|
|
546
|
-
renderRedteamHeader();
|
|
547
|
-
const service = await createPromptSetService();
|
|
548
|
-
const result = await service.addPrompt(setUuid, opts.prompt, opts.goal);
|
|
549
|
-
console.log(` Prompt added: ${result.uuid}\n`);
|
|
550
|
-
}
|
|
551
|
-
catch (err) {
|
|
552
|
-
renderError(err instanceof Error ? err.message : String(err));
|
|
553
|
-
process.exit(1);
|
|
554
|
-
}
|
|
555
|
-
});
|
|
556
|
-
prompts
|
|
557
|
-
.command('update <setUuid> <promptUuid>')
|
|
558
|
-
.description('Update a prompt')
|
|
559
|
-
.option('--prompt <text>', 'New prompt text')
|
|
560
|
-
.option('--goal <text>', 'New goal')
|
|
561
|
-
.action(async (setUuid, promptUuid, opts) => {
|
|
562
|
-
try {
|
|
563
|
-
renderRedteamHeader();
|
|
564
|
-
const service = await createPromptSetService();
|
|
565
|
-
const request = {};
|
|
566
|
-
if (opts.prompt)
|
|
567
|
-
request.prompt = opts.prompt;
|
|
568
|
-
if (opts.goal)
|
|
569
|
-
request.goal = opts.goal;
|
|
570
|
-
const result = await service.updatePrompt(setUuid, promptUuid, request);
|
|
571
|
-
renderPromptDetail(result);
|
|
572
|
-
}
|
|
573
|
-
catch (err) {
|
|
574
|
-
renderError(err instanceof Error ? err.message : String(err));
|
|
575
|
-
process.exit(1);
|
|
576
|
-
}
|
|
577
|
-
});
|
|
578
|
-
prompts
|
|
579
|
-
.command('delete <setUuid> <promptUuid>')
|
|
580
|
-
.description('Delete a prompt')
|
|
581
|
-
.action(async (setUuid, promptUuid) => {
|
|
582
|
-
try {
|
|
583
|
-
renderRedteamHeader();
|
|
584
|
-
const service = await createPromptSetService();
|
|
585
|
-
await service.deletePrompt(setUuid, promptUuid);
|
|
586
|
-
console.log(` Prompt ${promptUuid} deleted.\n`);
|
|
587
|
-
}
|
|
588
|
-
catch (err) {
|
|
589
|
-
renderError(err instanceof Error ? err.message : String(err));
|
|
590
|
-
process.exit(1);
|
|
591
|
-
}
|
|
592
|
-
});
|
|
593
|
-
// -----------------------------------------------------------------------
|
|
594
|
-
// redteam properties — property name/value management
|
|
595
|
-
// -----------------------------------------------------------------------
|
|
596
|
-
const properties = redteam.command('properties').description('Manage custom attack properties');
|
|
597
|
-
properties
|
|
598
|
-
.command('list')
|
|
599
|
-
.description('List property names')
|
|
600
|
-
.option('--output <format>', 'Output format: pretty, table, csv, json, yaml', 'pretty')
|
|
601
|
-
.action(async (opts) => {
|
|
602
|
-
try {
|
|
603
|
-
const fmt = opts.output;
|
|
604
|
-
if (fmt === 'pretty')
|
|
605
|
-
renderRedteamHeader();
|
|
606
|
-
const service = await createPromptSetService();
|
|
607
|
-
const names = await service.getPropertyNames();
|
|
608
|
-
renderPropertyNames(names, fmt);
|
|
609
|
-
}
|
|
610
|
-
catch (err) {
|
|
611
|
-
renderError(err instanceof Error ? err.message : String(err));
|
|
612
|
-
process.exit(1);
|
|
613
|
-
}
|
|
614
|
-
});
|
|
615
|
-
properties
|
|
616
|
-
.command('create')
|
|
617
|
-
.description('Create a property name')
|
|
618
|
-
.requiredOption('--name <name>', 'Property name')
|
|
619
|
-
.action(async (opts) => {
|
|
620
|
-
try {
|
|
621
|
-
renderRedteamHeader();
|
|
622
|
-
const service = await createPromptSetService();
|
|
623
|
-
const result = await service.createPropertyName(opts.name);
|
|
624
|
-
console.log(` Property created: ${result.name}\n`);
|
|
625
|
-
}
|
|
626
|
-
catch (err) {
|
|
627
|
-
renderError(err instanceof Error ? err.message : String(err));
|
|
628
|
-
process.exit(1);
|
|
629
|
-
}
|
|
630
|
-
});
|
|
631
|
-
properties
|
|
632
|
-
.command('values <name>')
|
|
633
|
-
.description('List values for a property')
|
|
634
|
-
.option('--output <format>', 'Output format: pretty, json, yaml', 'pretty')
|
|
635
|
-
.action(async (name, opts) => {
|
|
636
|
-
try {
|
|
637
|
-
const fmt = opts.output;
|
|
638
|
-
if (fmt === 'pretty')
|
|
639
|
-
renderRedteamHeader();
|
|
640
|
-
const service = await createPromptSetService();
|
|
641
|
-
const values = await service.getPropertyValues(name);
|
|
642
|
-
renderPropertyValues(values, fmt);
|
|
643
|
-
}
|
|
644
|
-
catch (err) {
|
|
645
|
-
renderError(err instanceof Error ? err.message : String(err));
|
|
646
|
-
process.exit(1);
|
|
647
|
-
}
|
|
648
|
-
});
|
|
649
|
-
properties
|
|
650
|
-
.command('add-value')
|
|
651
|
-
.description('Create a property value')
|
|
652
|
-
.requiredOption('--name <name>', 'Property name')
|
|
653
|
-
.requiredOption('--value <value>', 'Property value')
|
|
654
|
-
.action(async (opts) => {
|
|
655
|
-
try {
|
|
656
|
-
renderRedteamHeader();
|
|
657
|
-
const service = await createPromptSetService();
|
|
658
|
-
const result = await service.createPropertyValue(opts.name, opts.value);
|
|
659
|
-
console.log(` Value created: ${result.name}=${result.value}\n`);
|
|
660
|
-
}
|
|
661
|
-
catch (err) {
|
|
662
|
-
renderError(err instanceof Error ? err.message : String(err));
|
|
663
|
-
process.exit(1);
|
|
664
|
-
}
|
|
665
|
-
});
|
|
666
|
-
// -----------------------------------------------------------------------
|
|
667
|
-
// redteam report — view scan report
|
|
668
|
-
// -----------------------------------------------------------------------
|
|
669
|
-
redteam
|
|
670
|
-
.command('report <jobId>')
|
|
671
|
-
.description('View scan report')
|
|
672
|
-
.option('--attacks', 'Include attack list', false)
|
|
673
|
-
.option('--severity <level>', 'Filter attacks by severity')
|
|
674
|
-
.option('--limit <n>', 'Max attacks to show', '20')
|
|
675
|
-
.action(async (jobId, opts) => {
|
|
676
|
-
try {
|
|
677
|
-
renderRedteamHeader();
|
|
678
|
-
const service = await createService();
|
|
679
|
-
const job = await service.getScan(jobId);
|
|
680
|
-
renderScanStatus(job);
|
|
681
|
-
if (job.jobType === 'CUSTOM') {
|
|
682
|
-
const report = await service.getCustomReport(jobId);
|
|
683
|
-
renderCustomReport(report);
|
|
684
|
-
if (opts.attacks) {
|
|
685
|
-
const attacks = await service.listCustomAttacks(jobId, {
|
|
686
|
-
limit: Number.parseInt(opts.limit, 10),
|
|
687
|
-
});
|
|
688
|
-
renderCustomAttackList(attacks);
|
|
689
|
-
}
|
|
690
|
-
}
|
|
691
|
-
else {
|
|
692
|
-
const report = await service.getStaticReport(jobId);
|
|
693
|
-
renderStaticReport(report);
|
|
694
|
-
if (opts.attacks) {
|
|
695
|
-
const { attacks, totalItems } = await service.listAttacks(jobId, {
|
|
696
|
-
severity: opts.severity,
|
|
697
|
-
limit: Number.parseInt(opts.limit, 10),
|
|
698
|
-
});
|
|
699
|
-
const footnote = buildAttackListFootnote({
|
|
700
|
-
severity: opts.severity,
|
|
701
|
-
totalItems,
|
|
702
|
-
severityBreakdown: report.severityBreakdown,
|
|
703
|
-
});
|
|
704
|
-
renderAttackList(attacks, { footnote });
|
|
705
|
-
}
|
|
706
|
-
}
|
|
707
|
-
}
|
|
708
|
-
catch (err) {
|
|
709
|
-
renderError(err instanceof Error ? err.message : String(err));
|
|
710
|
-
process.exit(1);
|
|
711
|
-
}
|
|
712
|
-
});
|
|
713
|
-
// -----------------------------------------------------------------------
|
|
714
|
-
// redteam scan — execute a red team scan
|
|
715
|
-
// -----------------------------------------------------------------------
|
|
716
|
-
redteam
|
|
717
|
-
.command('scan')
|
|
718
|
-
.description('Execute a red team scan against a target')
|
|
719
|
-
.requiredOption('--target <uuid>', 'Target UUID')
|
|
720
|
-
.requiredOption('--name <name>', 'Scan name')
|
|
721
|
-
.option('--type <type>', 'Job type: STATIC, DYNAMIC, or CUSTOM', 'STATIC')
|
|
722
|
-
.option('--categories <json>', 'Category filter JSON (STATIC scans)')
|
|
723
|
-
.option('--prompt-sets <uuids>', 'Comma-separated prompt set UUIDs (CUSTOM scans)')
|
|
724
|
-
.option('--goals <file>', 'JSON file or inline JSON array of attack goals (DYNAMIC scans)')
|
|
725
|
-
.option('--depth <number>', 'Max conversation turns per goal (DYNAMIC scans)', '10')
|
|
726
|
-
.option('--breadth <number>', 'Parallel agents per goal (DYNAMIC scans)', '6')
|
|
727
|
-
.option('--no-wait', 'Submit scan without waiting for completion')
|
|
728
|
-
.action(async (opts) => {
|
|
729
|
-
try {
|
|
730
|
-
renderRedteamHeader();
|
|
731
|
-
const service = await createService();
|
|
732
|
-
let categories;
|
|
733
|
-
if (opts.categories) {
|
|
734
|
-
categories = JSON.parse(opts.categories);
|
|
735
|
-
}
|
|
736
|
-
const customPromptSets = opts.promptSets
|
|
737
|
-
? opts.promptSets.split(',').map((s) => s.trim())
|
|
738
|
-
: undefined;
|
|
739
|
-
const attackGoals = opts.goals ? parseAttackGoals(opts.goals) : undefined;
|
|
740
|
-
const streamDepth = parsePositiveInt(opts.depth, '--depth');
|
|
741
|
-
const streamBreadth = parsePositiveInt(opts.breadth, '--breadth');
|
|
742
|
-
console.log(` Creating ${opts.type} scan "${opts.name}"...`);
|
|
743
|
-
const job = await service.createScan({
|
|
744
|
-
name: opts.name,
|
|
745
|
-
targetUuid: opts.target,
|
|
746
|
-
jobType: opts.type,
|
|
747
|
-
categories,
|
|
748
|
-
customPromptSets,
|
|
749
|
-
attackGoals,
|
|
750
|
-
streamDepth,
|
|
751
|
-
streamBreadth,
|
|
752
|
-
});
|
|
753
|
-
renderScanStatus(job);
|
|
754
|
-
if (opts.wait !== false) {
|
|
755
|
-
console.log(' Waiting for completion...\n');
|
|
756
|
-
const completed = await service.waitForCompletion(job.uuid, (progress) => renderScanProgress(progress));
|
|
757
|
-
console.log('\n');
|
|
758
|
-
renderScanStatus(completed);
|
|
759
|
-
console.log(` Job ID: ${completed.uuid}`);
|
|
760
|
-
console.log(' Run `airs redteam report <jobId>` to view results.\n');
|
|
761
|
-
}
|
|
762
|
-
else {
|
|
763
|
-
console.log(` Job ID: ${job.uuid}`);
|
|
764
|
-
console.log(' Run `airs redteam status <jobId>` to check progress.\n');
|
|
765
|
-
}
|
|
766
|
-
}
|
|
767
|
-
catch (err) {
|
|
768
|
-
renderError(err instanceof Error ? err.message : String(err));
|
|
769
|
-
process.exit(1);
|
|
770
|
-
}
|
|
771
|
-
});
|
|
772
|
-
// -----------------------------------------------------------------------
|
|
773
|
-
// redteam status — check scan status
|
|
774
|
-
// -----------------------------------------------------------------------
|
|
775
|
-
redteam
|
|
776
|
-
.command('status <jobId>')
|
|
777
|
-
.description('Check scan status')
|
|
778
|
-
.action(async (jobId) => {
|
|
779
|
-
try {
|
|
780
|
-
renderRedteamHeader();
|
|
781
|
-
const service = await createService();
|
|
782
|
-
const job = await service.getScan(jobId);
|
|
783
|
-
renderScanStatus(job);
|
|
784
|
-
}
|
|
785
|
-
catch (err) {
|
|
786
|
-
renderError(err instanceof Error ? err.message : String(err));
|
|
787
|
-
process.exit(1);
|
|
788
|
-
}
|
|
789
|
-
});
|
|
790
|
-
// -----------------------------------------------------------------------
|
|
791
|
-
// redteam targets — target CRUD subcommands
|
|
792
|
-
// -----------------------------------------------------------------------
|
|
793
|
-
const targets = redteam.command('targets').description('Manage red team targets');
|
|
794
|
-
targets
|
|
795
|
-
.command('list')
|
|
796
|
-
.description('List configured red team targets')
|
|
797
|
-
.option('--output <format>', 'Output format: pretty, table, csv, json, yaml', 'pretty')
|
|
798
|
-
.action(async (opts) => {
|
|
799
|
-
try {
|
|
800
|
-
const fmt = opts.output;
|
|
801
|
-
if (fmt === 'pretty')
|
|
802
|
-
renderRedteamHeader();
|
|
803
|
-
const service = await createService();
|
|
804
|
-
const list = await service.listTargets();
|
|
805
|
-
renderTargetList(list, fmt);
|
|
806
|
-
}
|
|
807
|
-
catch (err) {
|
|
808
|
-
renderError(err instanceof Error ? err.message : String(err));
|
|
809
|
-
process.exit(1);
|
|
810
|
-
}
|
|
811
|
-
});
|
|
812
|
-
targets
|
|
813
|
-
.command('get <uuid>')
|
|
814
|
-
.description('Get target details')
|
|
815
|
-
.option('--output <format>', 'Output format: pretty, json, yaml', 'pretty')
|
|
816
|
-
.action(async (uuid, opts) => {
|
|
817
|
-
try {
|
|
818
|
-
const fmt = opts.output;
|
|
819
|
-
if (fmt === 'pretty')
|
|
820
|
-
renderRedteamHeader();
|
|
821
|
-
const service = await createService();
|
|
822
|
-
const target = await service.getTarget(uuid);
|
|
823
|
-
renderTargetDetail(target, fmt);
|
|
824
|
-
}
|
|
825
|
-
catch (err) {
|
|
826
|
-
renderError(err instanceof Error ? err.message : String(err));
|
|
827
|
-
process.exit(1);
|
|
828
|
-
}
|
|
829
|
-
});
|
|
830
|
-
targets
|
|
831
|
-
.command('create')
|
|
832
|
-
.description('Create a new red team target')
|
|
833
|
-
.requiredOption('--config <path>', 'JSON file with target configuration')
|
|
834
|
-
.option('--validate', 'Validate target connection before saving')
|
|
835
|
-
.action(async (opts) => {
|
|
836
|
-
try {
|
|
837
|
-
renderRedteamHeader();
|
|
838
|
-
const service = await createService();
|
|
839
|
-
const config = JSON.parse(fs.readFileSync(opts.config, 'utf-8'));
|
|
840
|
-
const target = await service.createTarget(config, opts.validate ? { validate: true } : undefined);
|
|
841
|
-
console.log(` Target created: ${target.uuid}\n`);
|
|
842
|
-
renderTargetDetail(target);
|
|
843
|
-
}
|
|
844
|
-
catch (err) {
|
|
845
|
-
renderError(err instanceof Error ? err.message : String(err));
|
|
846
|
-
process.exit(1);
|
|
847
|
-
}
|
|
848
|
-
});
|
|
849
|
-
targets
|
|
850
|
-
.command('update <uuid>')
|
|
851
|
-
.description('Update a red team target')
|
|
852
|
-
.requiredOption('--config <path>', 'JSON file with target updates')
|
|
853
|
-
.option('--validate', 'Validate target connection before saving')
|
|
854
|
-
.action(async (uuid, opts) => {
|
|
855
|
-
try {
|
|
856
|
-
renderRedteamHeader();
|
|
857
|
-
const service = await createService();
|
|
858
|
-
const config = JSON.parse(fs.readFileSync(opts.config, 'utf-8'));
|
|
859
|
-
const target = await service.updateTarget(uuid, config, opts.validate ? { validate: true } : undefined);
|
|
860
|
-
console.log(` Target updated: ${target.uuid}\n`);
|
|
861
|
-
renderTargetDetail(target);
|
|
862
|
-
}
|
|
863
|
-
catch (err) {
|
|
864
|
-
renderError(err instanceof Error ? err.message : String(err));
|
|
865
|
-
process.exit(1);
|
|
866
|
-
}
|
|
867
|
-
});
|
|
868
|
-
targets
|
|
869
|
-
.command('delete <uuid>')
|
|
870
|
-
.description('Delete a red team target')
|
|
871
|
-
.action(async (uuid) => {
|
|
872
|
-
try {
|
|
873
|
-
renderRedteamHeader();
|
|
874
|
-
const service = await createService();
|
|
875
|
-
await service.deleteTarget(uuid);
|
|
876
|
-
console.log(` Target ${uuid} deleted.\n`);
|
|
877
|
-
}
|
|
878
|
-
catch (err) {
|
|
879
|
-
renderError(err instanceof Error ? err.message : String(err));
|
|
880
|
-
process.exit(1);
|
|
881
|
-
}
|
|
882
|
-
});
|
|
883
|
-
targets
|
|
884
|
-
.command('probe')
|
|
885
|
-
.description('Test target connection without saving')
|
|
886
|
-
.requiredOption('--config <path>', 'JSON file with connection params')
|
|
887
|
-
.action(async (opts) => {
|
|
888
|
-
try {
|
|
889
|
-
renderRedteamHeader();
|
|
890
|
-
const service = await createService();
|
|
891
|
-
const config = JSON.parse(fs.readFileSync(opts.config, 'utf-8'));
|
|
892
|
-
const result = await service.probeTarget(config);
|
|
893
|
-
console.log(' Probe result:');
|
|
894
|
-
console.log(` ${JSON.stringify(result, null, 2)}\n`);
|
|
895
|
-
}
|
|
896
|
-
catch (err) {
|
|
897
|
-
renderError(err instanceof Error ? err.message : String(err));
|
|
898
|
-
process.exit(1);
|
|
899
|
-
}
|
|
900
|
-
});
|
|
901
|
-
targets
|
|
902
|
-
.command('profile <uuid>')
|
|
903
|
-
.description('View target profile')
|
|
904
|
-
.action(async (uuid) => {
|
|
905
|
-
try {
|
|
906
|
-
renderRedteamHeader();
|
|
907
|
-
const service = await createService();
|
|
908
|
-
const profile = await service.getTargetProfile(uuid);
|
|
909
|
-
console.log(' Target Profile:');
|
|
910
|
-
console.log(` ${JSON.stringify(profile, null, 2)}\n`);
|
|
911
|
-
}
|
|
912
|
-
catch (err) {
|
|
913
|
-
renderError(err instanceof Error ? err.message : String(err));
|
|
914
|
-
process.exit(1);
|
|
915
|
-
}
|
|
916
|
-
});
|
|
917
|
-
targets
|
|
918
|
-
.command('update-profile <uuid>')
|
|
919
|
-
.description('Update target profile')
|
|
920
|
-
.requiredOption('--config <path>', 'JSON file with profile updates')
|
|
921
|
-
.action(async (uuid, opts) => {
|
|
922
|
-
try {
|
|
923
|
-
renderRedteamHeader();
|
|
924
|
-
const service = await createService();
|
|
925
|
-
const config = JSON.parse(fs.readFileSync(opts.config, 'utf-8'));
|
|
926
|
-
const result = await service.updateTargetProfile(uuid, config);
|
|
927
|
-
console.log(' Profile updated:');
|
|
928
|
-
console.log(` ${JSON.stringify(result, null, 2)}\n`);
|
|
929
|
-
}
|
|
930
|
-
catch (err) {
|
|
931
|
-
renderError(err instanceof Error ? err.message : String(err));
|
|
932
|
-
process.exit(1);
|
|
933
|
-
}
|
|
934
|
-
});
|
|
935
|
-
targets
|
|
936
|
-
.command('validate-auth')
|
|
937
|
-
.description('Validate target auth credentials')
|
|
938
|
-
.requiredOption('--auth-type <type>', 'Auth type: HEADERS, BASIC_AUTH, OAUTH2')
|
|
939
|
-
.requiredOption('--config <path>', 'JSON file with auth_config')
|
|
940
|
-
.option('--target-id <uuid>', 'Existing target UUID')
|
|
941
|
-
.action(async (opts) => {
|
|
942
|
-
try {
|
|
943
|
-
renderRedteamHeader();
|
|
944
|
-
const service = await createService();
|
|
945
|
-
const authConfig = JSON.parse(fs.readFileSync(opts.config, 'utf-8'));
|
|
946
|
-
const result = await service.validateTargetAuth({
|
|
947
|
-
authType: opts.authType,
|
|
948
|
-
authConfig,
|
|
949
|
-
targetId: opts.targetId,
|
|
950
|
-
});
|
|
951
|
-
renderAuthValidation(result);
|
|
952
|
-
}
|
|
953
|
-
catch (err) {
|
|
954
|
-
renderError(err instanceof Error ? err.message : String(err));
|
|
955
|
-
process.exit(1);
|
|
956
|
-
}
|
|
957
|
-
});
|
|
958
|
-
targets
|
|
959
|
-
.command('metadata')
|
|
960
|
-
.description('Get target field metadata')
|
|
961
|
-
.action(async () => {
|
|
962
|
-
try {
|
|
963
|
-
renderRedteamHeader();
|
|
964
|
-
const service = await createService();
|
|
965
|
-
const metadata = await service.getTargetMetadata();
|
|
966
|
-
console.log(JSON.stringify(metadata, null, 2));
|
|
967
|
-
}
|
|
968
|
-
catch (err) {
|
|
969
|
-
renderError(err instanceof Error ? err.message : String(err));
|
|
970
|
-
process.exit(1);
|
|
971
|
-
}
|
|
972
|
-
});
|
|
973
|
-
targets
|
|
974
|
-
.command('init <provider>')
|
|
975
|
-
.description('Scaffold a target config JSON from a provider template')
|
|
976
|
-
.option('--output <file>', 'Output file path')
|
|
977
|
-
.action(async (provider, opts) => {
|
|
978
|
-
try {
|
|
979
|
-
renderRedteamHeader();
|
|
980
|
-
const service = await createService();
|
|
981
|
-
const templates = await service.getTargetTemplates();
|
|
982
|
-
const scaffold = buildTargetScaffold(provider, templates);
|
|
983
|
-
const filename = opts.output ?? `${provider.toLowerCase()}-target.json`;
|
|
984
|
-
const outputPath = path.resolve(filename);
|
|
985
|
-
if (fs.existsSync(outputPath)) {
|
|
986
|
-
renderError(`File already exists: ${outputPath} (use --output to specify a different path)`);
|
|
987
|
-
process.exit(1);
|
|
988
|
-
}
|
|
989
|
-
fs.writeFileSync(outputPath, `${JSON.stringify(scaffold, null, 2)}\n`);
|
|
990
|
-
console.log(chalk.bold('\n Target config scaffolded:\n'));
|
|
991
|
-
console.log(` File: ${chalk.cyan(outputPath)}`);
|
|
992
|
-
console.log(` Provider: ${chalk.dim(provider.toUpperCase())}`);
|
|
993
|
-
console.log(`\n ${chalk.yellow('Next steps:')} Edit the file to fill in ${chalk.bold('name')} and credentials, then run:`);
|
|
994
|
-
console.log(` ${chalk.cyan(`airs redteam targets create --config ${filename} --validate`)}\n`);
|
|
995
|
-
}
|
|
996
|
-
catch (err) {
|
|
997
|
-
renderError(err instanceof Error ? err.message : String(err));
|
|
998
|
-
process.exit(1);
|
|
999
|
-
}
|
|
1000
|
-
});
|
|
1001
|
-
targets
|
|
1002
|
-
.command('templates')
|
|
1003
|
-
.description('Get provider-specific target templates')
|
|
1004
|
-
.action(async () => {
|
|
1005
|
-
try {
|
|
1006
|
-
renderRedteamHeader();
|
|
1007
|
-
const service = await createService();
|
|
1008
|
-
const templates = await service.getTargetTemplates();
|
|
1009
|
-
renderTargetTemplates(templates);
|
|
1010
|
-
}
|
|
1011
|
-
catch (err) {
|
|
1012
|
-
renderError(err instanceof Error ? err.message : String(err));
|
|
1013
|
-
process.exit(1);
|
|
1014
|
-
}
|
|
1015
|
-
});
|
|
1016
|
-
targets
|
|
1017
|
-
.command('backup')
|
|
1018
|
-
.description('Backup red team targets to local JSON/YAML files')
|
|
1019
|
-
.option('--output-dir <path>', 'Output directory')
|
|
1020
|
-
.option('--format <format>', 'Output format: json or yaml', 'json')
|
|
1021
|
-
.option('--name <targetName>', 'Backup a single target by name')
|
|
1022
|
-
.action(async (opts) => {
|
|
1023
|
-
try {
|
|
1024
|
-
renderBackupHeader();
|
|
1025
|
-
const outputDir = resolveOutputDir(opts.outputDir, 'targets');
|
|
1026
|
-
const results = await backupTargets({
|
|
1027
|
-
outputDir,
|
|
1028
|
-
format: (opts.format ?? 'json'),
|
|
1029
|
-
name: opts.name,
|
|
1030
|
-
});
|
|
1031
|
-
renderBackupSummary(results, outputDir);
|
|
1032
|
-
const failed = results.filter((r) => r.status === 'failed').length;
|
|
1033
|
-
if (failed > 0)
|
|
1034
|
-
process.exit(1);
|
|
1035
|
-
}
|
|
1036
|
-
catch (err) {
|
|
1037
|
-
renderError(err instanceof Error ? err.message : String(err));
|
|
1038
|
-
process.exit(1);
|
|
1039
|
-
}
|
|
1040
|
-
});
|
|
1041
|
-
targets
|
|
1042
|
-
.command('restore')
|
|
1043
|
-
.description('Restore red team targets from local JSON/YAML backup files')
|
|
1044
|
-
.option('--input-dir <path>', 'Directory containing backup files')
|
|
1045
|
-
.option('--file <path>', 'Single backup file to restore')
|
|
1046
|
-
.option('--overwrite', 'Update existing targets with same name (default: skip)')
|
|
1047
|
-
.option('--validate', 'Validate target connection before saving')
|
|
1048
|
-
.action(async (opts) => {
|
|
1049
|
-
try {
|
|
1050
|
-
renderBackupHeader();
|
|
1051
|
-
if (!opts.file && !opts.inputDir) {
|
|
1052
|
-
throw new Error('Specify --file <path> or --input-dir <path>');
|
|
1053
|
-
}
|
|
1054
|
-
const results = await restoreTargets({
|
|
1055
|
-
file: opts.file,
|
|
1056
|
-
inputDir: opts.inputDir,
|
|
1057
|
-
overwrite: opts.overwrite,
|
|
1058
|
-
validate: opts.validate,
|
|
1059
|
-
});
|
|
1060
|
-
renderRestoreSummary(results);
|
|
1061
|
-
const failed = results.filter((r) => r.action === 'failed').length;
|
|
1062
|
-
if (failed > 0)
|
|
1063
|
-
process.exit(1);
|
|
1064
|
-
}
|
|
1065
|
-
catch (err) {
|
|
1066
|
-
renderError(err instanceof Error ? err.message : String(err));
|
|
1067
|
-
process.exit(1);
|
|
1068
|
-
}
|
|
1069
|
-
});
|
|
1070
|
-
}
|
|
1071
|
-
//# sourceMappingURL=redteam.js.map
|