@cdot65/prisma-airs-cli 3.2.0 → 4.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 +36 -3
- package/dist/{chunk-TTBN7YHC.js → chunk-W5YDJS7H.js} +264 -35
- package/dist/cli/index.js +1923 -690
- package/dist/index.d.ts +189 -5
- package/dist/index.js +1 -1
- package/package.json +15 -3
package/README.md
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
[](https://opensource.org/licenses/MIT)
|
|
11
11
|
[](https://nodejs.org/)
|
|
12
12
|
|
|
13
|
-
**Full operational coverage over Palo Alto Prisma AIRS AI security — guardrail refinement, runtime scanning, AI red teaming, and model security.**
|
|
13
|
+
**Full operational coverage over Palo Alto Prisma AIRS AI security — guardrail refinement, runtime scanning, AI red teaming, AI Gateway, and model security.**
|
|
14
14
|
|
|
15
15
|
> **[Read the full documentation](https://cdot65.github.io/prisma-airs-cli/)** — installation, configuration, architecture, CLI reference, and examples.
|
|
16
16
|
|
|
@@ -19,7 +19,10 @@
|
|
|
19
19
|
- **Runtime Scanning** — scan prompts and responses against AIRS security profiles, single or bulk with CSV export
|
|
20
20
|
- **Guardrail Optimization** — atomic CLI commands (`create`, `apply`, `eval`, `revert`) for custom topic guardrails, designed for autonomous agent loops (see [`AGENTS.md`](AGENTS.md))
|
|
21
21
|
- **AI Red Teaming** — adversarial scanning with static, dynamic, and custom prompt set attack modes
|
|
22
|
+
- **[AI Gateway](https://cdot65.github.io/prisma-airs-cli/cli/aigateway/workspaces/)** — scoped/admin workspace management and workspace cost telemetry
|
|
22
23
|
- **Model Security** — ML model supply chain scanning with security groups, rules, and violation tracking
|
|
24
|
+
- **Unified automation output** — every read command supports `pretty`, `table`, `markdown`, `csv`, `json`, and `yaml`, with pipe-safe stdout
|
|
25
|
+
- **Complete pagination** — consistent `--limit`, `--offset`, and `--all` traversal with a configurable safety cap
|
|
23
26
|
- **`airs doctor`** — one-command diagnostics for environment, credentials, and API connectivity
|
|
24
27
|
- **`airs config`** — manage `~/.prisma-airs/config.json` from the CLI (`list`, `get`, `set`, `unset`, `path`)
|
|
25
28
|
|
|
@@ -55,11 +58,40 @@ airs runtime topics revert --profile my-profile --name "Explosives"
|
|
|
55
58
|
airs redteam scan --target <uuid> --name "Full Scan" --type STATIC
|
|
56
59
|
airs redteam report <job-id>
|
|
57
60
|
|
|
61
|
+
# Red team custom target adapters
|
|
62
|
+
airs redteam adapter list --output json
|
|
63
|
+
|
|
64
|
+
# AI Gateway workspaces and cost telemetry
|
|
65
|
+
airs aigateway workspace list --all --output json
|
|
66
|
+
airs aigateway telemetry cost --workspace <workspace-slug> --days 30
|
|
67
|
+
|
|
58
68
|
# Model security
|
|
59
69
|
airs model-security scans create --config scan-config.json
|
|
70
|
+
|
|
71
|
+
# Pipe-safe read output and complete traversal
|
|
72
|
+
airs runtime profiles list --all --output json | jq '.[].profileName'
|
|
73
|
+
airs runtime topics list --all-versions --output markdown
|
|
60
74
|
```
|
|
61
75
|
|
|
62
|
-
Bulk scans preserve one output row per input prompt in input order, including all eight runtime detector flags. Work is processed as sequential logical batches (`--batch-size 25` by default), with SDK requests capped at 20 prompts. Item-level state makes accepted and pending work resumable without duplicating CSV rows, and active jobs are locked against overlapping resumes. Runtime actions are exactly `allow`, `block`, or `failed`; failed or timed-out prompts make the command exit 1.
|
|
76
|
+
Bulk scans preserve one output row per input prompt in input order, including all eight runtime detector flags. Work is processed as sequential logical batches (`--batch-size 25` by default), with SDK requests capped at 20 prompts. Item-level state makes accepted and pending work resumable without duplicating CSV rows, and active jobs are locked against overlapping resumes. Runtime actions are exactly `allow`, `block`, or `failed`; failed or timed-out prompts make the command exit 1. Version 4 uses `@cdot65/prisma-airs-sdk` 0.18.0 or later.
|
|
77
|
+
|
|
78
|
+
## Read Output and Pagination
|
|
79
|
+
|
|
80
|
+
Read commands share one contract:
|
|
81
|
+
|
|
82
|
+
- Formats: `pretty`, `table`, `markdown`, `csv`, `json`, and `yaml`.
|
|
83
|
+
- JSON/YAML lists are bare arrays of complete normalized records; detail reads are complete objects.
|
|
84
|
+
- Table, Markdown, and CSV are stable human-oriented projections. CSV uses RFC 4180 quoting.
|
|
85
|
+
- Data is written to stdout; status, paging hints, warnings, and errors are written to stderr.
|
|
86
|
+
- Output precedence is command `--output`, global `--output`, `defaultOutput`/`PANW_CLI_OUTPUT`, then `pretty`.
|
|
87
|
+
- Paginated lists use `--limit`, `--offset`, and `--all`. Complete traversal is capped at 10,000 records by default; change it with `--max`, or use `--max 0` for no cap.
|
|
88
|
+
- Profile and topic lists return only the latest revision by default. Use `--all-versions` or `--revision` when historical revisions are needed.
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
airs --output json runtime profiles list --all | jq '.[].profileName'
|
|
92
|
+
PANW_CLI_OUTPUT=yaml airs runtime topics get "My Topic"
|
|
93
|
+
airs model-security scans list --all --max 25000 --output csv > scans.csv
|
|
94
|
+
```
|
|
63
95
|
|
|
64
96
|
## Documentation
|
|
65
97
|
|
|
@@ -69,12 +101,13 @@ The full guides, complete CLI reference, configuration, and architecture live on
|
|
|
69
101
|
- **[Runtime Security](https://cdot65.github.io/prisma-airs-cli/runtime/overview/)** — scanning, profiles, topics, and DLP management
|
|
70
102
|
- **[Guardrail Optimization](https://cdot65.github.io/prisma-airs-cli/runtime/guardrails/overview/)** — the agent-driven `topics create/apply/eval/revert` loop
|
|
71
103
|
- **[AI Red Teaming](https://cdot65.github.io/prisma-airs-cli/redteam/overview/)** — static, dynamic, and custom adversarial scans
|
|
104
|
+
- **[AI Gateway](https://cdot65.github.io/prisma-airs-cli/cli/aigateway/workspaces/)** — workspace CRUD, two-plane authorization, and cost telemetry
|
|
72
105
|
- **[Model Security](https://cdot65.github.io/prisma-airs-cli/model-security/overview/)** — ML model supply-chain scanning
|
|
73
106
|
- **[CLI Reference](https://cdot65.github.io/prisma-airs-cli/cli/)** — every command, flag, and example
|
|
74
107
|
|
|
75
108
|
## Configuration
|
|
76
109
|
|
|
77
|
-
Credentials come from environment variables or `~/.prisma-airs/config.json`. At minimum: `PANW_AI_SEC_API_KEY` (scanning) and `PANW_MGMT_CLIENT_ID` / `PANW_MGMT_CLIENT_SECRET` / `PANW_MGMT_TSG_ID` (management). See [`.env.example`](.env.example) and the [configuration guide](https://cdot65.github.io/prisma-airs-cli/getting-started/configuration/) for the full list.
|
|
110
|
+
Credentials come from environment variables or `~/.prisma-airs/config.json`. At minimum: `PANW_AI_SEC_API_KEY` (scanning) and `PANW_MGMT_CLIENT_ID` / `PANW_MGMT_CLIENT_SECRET` / `PANW_MGMT_TSG_ID` (management). Set `defaultOutput` in the config file or `PANW_CLI_OUTPUT` in the environment to choose a default read format. See [`.env.example`](.env.example) and the [configuration guide](https://cdot65.github.io/prisma-airs-cli/getting-started/configuration/) for the full list.
|
|
78
111
|
|
|
79
112
|
## License
|
|
80
113
|
|
|
@@ -21,7 +21,14 @@ var SdkManagementService = class {
|
|
|
21
21
|
return { message: response.message };
|
|
22
22
|
}
|
|
23
23
|
async listTopics() {
|
|
24
|
-
|
|
24
|
+
return this.client.topics.listAll();
|
|
25
|
+
}
|
|
26
|
+
async listLatestTopics(opts) {
|
|
27
|
+
const response = await this.client.topics.list({
|
|
28
|
+
latestOnly: true,
|
|
29
|
+
limit: opts?.limit,
|
|
30
|
+
offset: opts?.offset
|
|
31
|
+
});
|
|
25
32
|
return response.custom_topics;
|
|
26
33
|
}
|
|
27
34
|
async getTopic(topicId) {
|
|
@@ -32,9 +39,9 @@ var SdkManagementService = class {
|
|
|
32
39
|
}
|
|
33
40
|
async getTopicByName(topicName) {
|
|
34
41
|
const topics = await this.listTopics();
|
|
35
|
-
const
|
|
36
|
-
if (
|
|
37
|
-
return topic;
|
|
42
|
+
const matches = topics.filter((topic) => topic.topic_name === topicName);
|
|
43
|
+
if (matches.length === 0) throw new Error(`Topic "${topicName}" not found`);
|
|
44
|
+
return matches.reduce((latest, topic) => topic.revision > latest.revision ? topic : latest);
|
|
38
45
|
}
|
|
39
46
|
/**
|
|
40
47
|
* Sets a single custom topic on a profile's topic-guardrails config.
|
|
@@ -53,7 +60,7 @@ var SdkManagementService = class {
|
|
|
53
60
|
* it defaults to revision 0 (original content), not the latest.
|
|
54
61
|
*/
|
|
55
62
|
async assignTopicsToProfile(profileName, topics, guardrailAction) {
|
|
56
|
-
const
|
|
63
|
+
const ai_profiles = await this.client.profiles.listAll();
|
|
57
64
|
const profile = ai_profiles.find((p) => p.profile_name === profileName);
|
|
58
65
|
if (!profile?.profile_id) {
|
|
59
66
|
throw new Error(`Profile "${profileName}" not found`);
|
|
@@ -102,7 +109,7 @@ var SdkManagementService = class {
|
|
|
102
109
|
});
|
|
103
110
|
}
|
|
104
111
|
async getProfileTopics(profileName) {
|
|
105
|
-
const
|
|
112
|
+
const ai_profiles = await this.client.profiles.listAll();
|
|
106
113
|
const profile = ai_profiles.find((p) => p.profile_name === profileName);
|
|
107
114
|
if (!profile?.profile_id) {
|
|
108
115
|
throw new Error(`Profile "${profileName}" not found`);
|
|
@@ -170,6 +177,12 @@ var SdkManagementService = class {
|
|
|
170
177
|
nextOffset: response.next_offset
|
|
171
178
|
};
|
|
172
179
|
}
|
|
180
|
+
async listAllProfiles(opts) {
|
|
181
|
+
const profiles = await this.client.profiles.listAll(opts);
|
|
182
|
+
return profiles.map(
|
|
183
|
+
(profile) => this.normalizeProfile(profile)
|
|
184
|
+
);
|
|
185
|
+
}
|
|
173
186
|
async createProfile(request) {
|
|
174
187
|
const response = await this.client.profiles.create(request);
|
|
175
188
|
return this.normalizeProfile(response);
|
|
@@ -208,6 +221,11 @@ var SdkManagementService = class {
|
|
|
208
221
|
nextOffset: raw.next_offset
|
|
209
222
|
};
|
|
210
223
|
}
|
|
224
|
+
async listAllApiKeys(opts) {
|
|
225
|
+
return (await this.client.apiKeys.listAll(opts)).map(
|
|
226
|
+
(key) => this.normalizeApiKey(key)
|
|
227
|
+
);
|
|
228
|
+
}
|
|
211
229
|
async createApiKey(request) {
|
|
212
230
|
const response = await this.client.apiKeys.create(request);
|
|
213
231
|
return this.normalizeApiKey(response);
|
|
@@ -240,6 +258,11 @@ var SdkManagementService = class {
|
|
|
240
258
|
nextOffset: raw.next_offset
|
|
241
259
|
};
|
|
242
260
|
}
|
|
261
|
+
async listAllCustomerApps(opts) {
|
|
262
|
+
return (await this.client.customerApps.listAll(opts)).map(
|
|
263
|
+
(app) => this.normalizeCustomerApp(app)
|
|
264
|
+
);
|
|
265
|
+
}
|
|
243
266
|
async getCustomerApp(appName) {
|
|
244
267
|
const response = await this.client.customerApps.get(appName);
|
|
245
268
|
return this.normalizeCustomerApp(response);
|
|
@@ -253,11 +276,18 @@ var SdkManagementService = class {
|
|
|
253
276
|
return this.normalizeCustomerApp(response);
|
|
254
277
|
}
|
|
255
278
|
async listConsumptionApps(opts) {
|
|
256
|
-
const
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
279
|
+
const limit = opts?.limit ?? 100;
|
|
280
|
+
let offset = opts?.offset ?? 0;
|
|
281
|
+
const items = [];
|
|
282
|
+
for (; ; ) {
|
|
283
|
+
const response = await this.client.dashboard.applicationsOverview({ limit, offset });
|
|
284
|
+
const page = response.items ?? [];
|
|
285
|
+
items.push(...page);
|
|
286
|
+
const total = response.pagination?.total_items;
|
|
287
|
+
offset += page.length;
|
|
288
|
+
if (page.length === 0 || page.length < limit || total != null && offset >= total) break;
|
|
289
|
+
}
|
|
290
|
+
return items.filter(
|
|
261
291
|
(item) => typeof item.id === "string" && typeof item.name === "string"
|
|
262
292
|
).map((item) => ({
|
|
263
293
|
appId: item.id,
|
|
@@ -525,6 +555,18 @@ var SdkModelSecurityService = class {
|
|
|
525
555
|
groups: raw.security_groups.map(normalizeGroup)
|
|
526
556
|
};
|
|
527
557
|
}
|
|
558
|
+
async listAllGroups(opts = {}) {
|
|
559
|
+
const rows = await this.client.securityGroups.listAll({
|
|
560
|
+
source_types: opts.sourceTypes,
|
|
561
|
+
search_query: opts.searchQuery,
|
|
562
|
+
sort_field: opts.sortField,
|
|
563
|
+
sort_dir: opts.sortDir,
|
|
564
|
+
enabled_rules: opts.enabledRules,
|
|
565
|
+
limit: opts.limit,
|
|
566
|
+
max: opts.max
|
|
567
|
+
});
|
|
568
|
+
return rows.map((row) => normalizeGroup(row));
|
|
569
|
+
}
|
|
528
570
|
async getGroup(uuid) {
|
|
529
571
|
const response = await this.client.securityGroups.get(uuid);
|
|
530
572
|
return normalizeGroup(response);
|
|
@@ -615,6 +657,15 @@ var SdkModelSecurityService = class {
|
|
|
615
657
|
rules: raw.rules.map(normalizeRule)
|
|
616
658
|
};
|
|
617
659
|
}
|
|
660
|
+
async listAllRules(opts = {}) {
|
|
661
|
+
const rows = await this.client.securityRules.listAll({
|
|
662
|
+
source_type: opts.sourceType,
|
|
663
|
+
search_query: opts.searchQuery,
|
|
664
|
+
limit: opts.limit,
|
|
665
|
+
max: opts.max
|
|
666
|
+
});
|
|
667
|
+
return rows.map((row) => normalizeRule(row));
|
|
668
|
+
}
|
|
618
669
|
async getRule(uuid) {
|
|
619
670
|
const response = await this.client.securityRules.get(uuid);
|
|
620
671
|
return normalizeRule(response);
|
|
@@ -641,6 +692,16 @@ var SdkModelSecurityService = class {
|
|
|
641
692
|
scans: raw.scans.map(normalizeScan)
|
|
642
693
|
};
|
|
643
694
|
}
|
|
695
|
+
async listAllScans(opts = {}) {
|
|
696
|
+
const rows = await this.client.scans.listAll({
|
|
697
|
+
eval_outcomes: opts.evalOutcome === void 0 ? void 0 : [opts.evalOutcome],
|
|
698
|
+
source_types: opts.sourceType === void 0 ? void 0 : [opts.sourceType],
|
|
699
|
+
search_query: opts.search,
|
|
700
|
+
limit: opts.limit,
|
|
701
|
+
max: opts.max
|
|
702
|
+
});
|
|
703
|
+
return rows.map((row) => normalizeScan(row));
|
|
704
|
+
}
|
|
644
705
|
async getScan(uuid) {
|
|
645
706
|
const response = await this.client.scans.get(uuid);
|
|
646
707
|
return normalizeScan(response);
|
|
@@ -743,6 +804,17 @@ var SdkModelSecurityService = class {
|
|
|
743
804
|
models: raw.models.map(normalizeModel)
|
|
744
805
|
};
|
|
745
806
|
}
|
|
807
|
+
async listAllModels(opts = {}) {
|
|
808
|
+
const rows = await this.client.models.listAllModels({
|
|
809
|
+
search: opts.search,
|
|
810
|
+
search_query: opts.searchQuery,
|
|
811
|
+
sort_field: opts.sortField,
|
|
812
|
+
sort_order: opts.sortOrder,
|
|
813
|
+
limit: opts.limit,
|
|
814
|
+
max: opts.max
|
|
815
|
+
});
|
|
816
|
+
return rows.map((row) => normalizeModel(row));
|
|
817
|
+
}
|
|
746
818
|
async getModel(uuid) {
|
|
747
819
|
const response = await this.client.models.getModel(uuid);
|
|
748
820
|
return normalizeModel(response);
|
|
@@ -1012,6 +1084,52 @@ function normalizeTargetDetail(raw) {
|
|
|
1012
1084
|
metadata: sanitizeTargetMetadata(raw.target_metadata)
|
|
1013
1085
|
};
|
|
1014
1086
|
}
|
|
1087
|
+
function normalizeAdapterListItem(raw) {
|
|
1088
|
+
return {
|
|
1089
|
+
uuid: raw.uuid,
|
|
1090
|
+
name: raw.name,
|
|
1091
|
+
status: raw.status,
|
|
1092
|
+
createdAt: raw.created_at,
|
|
1093
|
+
updatedAt: raw.updated_at,
|
|
1094
|
+
createdByUserId: raw.created_by_user_id,
|
|
1095
|
+
targetCount: raw.target_count
|
|
1096
|
+
};
|
|
1097
|
+
}
|
|
1098
|
+
function normalizeAdapterVar(raw) {
|
|
1099
|
+
return {
|
|
1100
|
+
key: raw.key,
|
|
1101
|
+
value: raw.value,
|
|
1102
|
+
type: raw.type,
|
|
1103
|
+
isRedacted: raw.is_redacted
|
|
1104
|
+
};
|
|
1105
|
+
}
|
|
1106
|
+
function normalizeAdapterDetail(raw) {
|
|
1107
|
+
return {
|
|
1108
|
+
uuid: raw.uuid,
|
|
1109
|
+
tsgId: raw.tsg_id,
|
|
1110
|
+
name: raw.name,
|
|
1111
|
+
scriptB64: raw.script_b64,
|
|
1112
|
+
status: raw.status,
|
|
1113
|
+
description: raw.description,
|
|
1114
|
+
networkBrokerChannelUuid: raw.network_broker_channel_uuid,
|
|
1115
|
+
variables: (raw.variables ?? []).map(normalizeAdapterVar),
|
|
1116
|
+
targetCount: raw.target_count,
|
|
1117
|
+
createdAt: raw.created_at,
|
|
1118
|
+
updatedAt: raw.updated_at,
|
|
1119
|
+
createdByUserId: raw.created_by_user_id,
|
|
1120
|
+
updatedByUserId: raw.updated_by_user_id
|
|
1121
|
+
};
|
|
1122
|
+
}
|
|
1123
|
+
function preserveVariablesForUpdate(variables) {
|
|
1124
|
+
return variables.map((v) => ({
|
|
1125
|
+
key: v.key,
|
|
1126
|
+
value: v.isRedacted ? null : v.value ?? null,
|
|
1127
|
+
type: v.type
|
|
1128
|
+
}));
|
|
1129
|
+
}
|
|
1130
|
+
function toWireVariables(variables) {
|
|
1131
|
+
return variables.map((v) => ({ key: v.key, value: v.value, type: v.type }));
|
|
1132
|
+
}
|
|
1015
1133
|
var SdkRedTeamService = class {
|
|
1016
1134
|
client;
|
|
1017
1135
|
constructor(opts) {
|
|
@@ -1122,29 +1240,14 @@ var SdkRedTeamService = class {
|
|
|
1122
1240
|
return await this.client.targets.getTargetTemplates();
|
|
1123
1241
|
}
|
|
1124
1242
|
async listTargets() {
|
|
1125
|
-
const
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
all.push({
|
|
1134
|
-
uuid: t.uuid,
|
|
1135
|
-
name: t.name,
|
|
1136
|
-
status: t.status,
|
|
1137
|
-
targetType: t.target_type,
|
|
1138
|
-
active: t.active
|
|
1139
|
-
});
|
|
1140
|
-
}
|
|
1141
|
-
const pagination = body.pagination;
|
|
1142
|
-
if (!pagination || all.length >= (pagination.total ?? data.length) || data.length < limit) {
|
|
1143
|
-
break;
|
|
1144
|
-
}
|
|
1145
|
-
skip += limit;
|
|
1146
|
-
}
|
|
1147
|
-
return all;
|
|
1243
|
+
const targets = await this.client.targets.listAll({ limit: 100 });
|
|
1244
|
+
return targets.map((target) => ({
|
|
1245
|
+
uuid: target.uuid,
|
|
1246
|
+
name: target.name,
|
|
1247
|
+
status: String(target.status ?? ""),
|
|
1248
|
+
targetType: target.target_type == null ? void 0 : String(target.target_type),
|
|
1249
|
+
active: target.active
|
|
1250
|
+
}));
|
|
1148
1251
|
}
|
|
1149
1252
|
async getTarget(uuid) {
|
|
1150
1253
|
const response = await this.client.targets.get(uuid);
|
|
@@ -1180,7 +1283,12 @@ var SdkRedTeamService = class {
|
|
|
1180
1283
|
}
|
|
1181
1284
|
async createScan(request) {
|
|
1182
1285
|
let jobMetadata = {};
|
|
1183
|
-
if (request.jobType === "STATIC"
|
|
1286
|
+
if (request.jobType === "STATIC") {
|
|
1287
|
+
if (!request.categories) {
|
|
1288
|
+
throw new Error(
|
|
1289
|
+
"STATIC scans require categories. Pass categories explicitly or use the CLI default."
|
|
1290
|
+
);
|
|
1291
|
+
}
|
|
1184
1292
|
jobMetadata = { categories: request.categories };
|
|
1185
1293
|
} else if (request.jobType === "CUSTOM" && request.customPromptSets) {
|
|
1186
1294
|
jobMetadata = {
|
|
@@ -1211,11 +1319,22 @@ var SdkRedTeamService = class {
|
|
|
1211
1319
|
if (opts?.jobType) sdkOpts.job_type = opts.jobType;
|
|
1212
1320
|
if (opts?.targetId) sdkOpts.target_id = opts.targetId;
|
|
1213
1321
|
if (opts?.limit) sdkOpts.limit = opts.limit;
|
|
1322
|
+
if (opts?.offset !== void 0) sdkOpts.skip = opts.offset;
|
|
1214
1323
|
const response = await this.client.scans.list(sdkOpts);
|
|
1215
1324
|
return response.data.map(
|
|
1216
1325
|
normalizeJob
|
|
1217
1326
|
);
|
|
1218
1327
|
}
|
|
1328
|
+
async listAllScans(opts) {
|
|
1329
|
+
const sdkOpts = {};
|
|
1330
|
+
if (opts?.status) sdkOpts.status = opts.status;
|
|
1331
|
+
if (opts?.jobType) sdkOpts.job_type = opts.jobType;
|
|
1332
|
+
if (opts?.targetId) sdkOpts.target_id = opts.targetId;
|
|
1333
|
+
if (opts?.limit) sdkOpts.limit = opts.limit;
|
|
1334
|
+
if (opts?.max !== void 0) sdkOpts.max = opts.max;
|
|
1335
|
+
const rows = await this.client.scans.listAll(sdkOpts);
|
|
1336
|
+
return rows.map((row) => normalizeJob(row));
|
|
1337
|
+
}
|
|
1219
1338
|
async abortScan(jobId) {
|
|
1220
1339
|
await this.client.scans.abort(jobId);
|
|
1221
1340
|
}
|
|
@@ -1351,6 +1470,18 @@ var SdkRedTeamService = class {
|
|
|
1351
1470
|
totalItems: pagination?.total_items
|
|
1352
1471
|
};
|
|
1353
1472
|
}
|
|
1473
|
+
async listAllChannels(opts = {}) {
|
|
1474
|
+
const limit = opts.limit ?? 100;
|
|
1475
|
+
const cap = opts.max === 0 ? Number.POSITIVE_INFINITY : opts.max ?? 1e4;
|
|
1476
|
+
const rows = [];
|
|
1477
|
+
for (let offset = 0; rows.length < cap; offset += limit) {
|
|
1478
|
+
const page = await this.listChannels({ ...opts, limit, offset });
|
|
1479
|
+
rows.push(...page.channels.slice(0, cap - rows.length));
|
|
1480
|
+
if (page.channels.length < limit || rows.length >= (page.totalItems ?? Number.POSITIVE_INFINITY))
|
|
1481
|
+
break;
|
|
1482
|
+
}
|
|
1483
|
+
return rows;
|
|
1484
|
+
}
|
|
1354
1485
|
async getChannel(channelId) {
|
|
1355
1486
|
const raw = await this.client.networkBroker.getChannel(channelId);
|
|
1356
1487
|
return normalizeChannel(raw);
|
|
@@ -1408,6 +1539,95 @@ var SdkRedTeamService = class {
|
|
|
1408
1539
|
totalItems: pagination?.total_items
|
|
1409
1540
|
};
|
|
1410
1541
|
}
|
|
1542
|
+
// -------------------------------------------------------------------------
|
|
1543
|
+
// Custom target adapters (SDK 0.16.0)
|
|
1544
|
+
// -------------------------------------------------------------------------
|
|
1545
|
+
async listAdapters(opts) {
|
|
1546
|
+
const sdkOpts = {};
|
|
1547
|
+
if (opts?.limit != null) sdkOpts.limit = opts.limit;
|
|
1548
|
+
if (opts?.offset != null) sdkOpts.skip = opts.offset;
|
|
1549
|
+
if (opts?.search) sdkOpts.search = opts.search;
|
|
1550
|
+
const raw = await this.client.adapters.list(sdkOpts);
|
|
1551
|
+
const pagination = raw.pagination;
|
|
1552
|
+
return {
|
|
1553
|
+
adapters: (raw.data ?? []).map(normalizeAdapterListItem),
|
|
1554
|
+
totalItems: pagination?.total_items
|
|
1555
|
+
};
|
|
1556
|
+
}
|
|
1557
|
+
async listAllAdapters(opts = {}) {
|
|
1558
|
+
const sdkOpts = {};
|
|
1559
|
+
if (opts.limit != null) sdkOpts.limit = opts.limit;
|
|
1560
|
+
if (opts.search) sdkOpts.search = opts.search;
|
|
1561
|
+
if (opts.max !== void 0) sdkOpts.max = opts.max;
|
|
1562
|
+
const rows = await this.client.adapters.listAll(sdkOpts);
|
|
1563
|
+
return rows.map((row) => normalizeAdapterListItem(row));
|
|
1564
|
+
}
|
|
1565
|
+
async getAdapter(uuid) {
|
|
1566
|
+
const raw = await this.client.adapters.get(uuid);
|
|
1567
|
+
return normalizeAdapterDetail(raw);
|
|
1568
|
+
}
|
|
1569
|
+
async createAdapter(request, validate) {
|
|
1570
|
+
const body = {
|
|
1571
|
+
name: request.name,
|
|
1572
|
+
script_b64: request.scriptB64,
|
|
1573
|
+
prompt: request.prompt
|
|
1574
|
+
};
|
|
1575
|
+
if (request.description !== void 0) body.description = request.description;
|
|
1576
|
+
if (request.networkBrokerChannelUuid !== void 0) {
|
|
1577
|
+
body.network_broker_channel_uuid = request.networkBrokerChannelUuid;
|
|
1578
|
+
}
|
|
1579
|
+
if (request.variables !== void 0) body.variables = toWireVariables(request.variables);
|
|
1580
|
+
const raw = await this.client.adapters.create(
|
|
1581
|
+
// biome-ignore lint/suspicious/noExplicitAny: body is assembled dynamically; SDK validates the shape
|
|
1582
|
+
body,
|
|
1583
|
+
validate === void 0 ? void 0 : { validate }
|
|
1584
|
+
);
|
|
1585
|
+
return normalizeAdapterDetail(raw);
|
|
1586
|
+
}
|
|
1587
|
+
async updateAdapter(uuid, overrides, validate) {
|
|
1588
|
+
const current = await this.getAdapter(uuid);
|
|
1589
|
+
const body = {
|
|
1590
|
+
name: overrides.name ?? current.name,
|
|
1591
|
+
script_b64: overrides.scriptB64 ?? current.scriptB64,
|
|
1592
|
+
prompt: overrides.prompt,
|
|
1593
|
+
variables: overrides.variables ? toWireVariables(overrides.variables) : preserveVariablesForUpdate(current.variables)
|
|
1594
|
+
};
|
|
1595
|
+
const description = overrides.description ?? current.description;
|
|
1596
|
+
if (description != null) body.description = description;
|
|
1597
|
+
const channel = overrides.networkBrokerChannelUuid ?? current.networkBrokerChannelUuid;
|
|
1598
|
+
if (channel != null) body.network_broker_channel_uuid = channel;
|
|
1599
|
+
const raw = await this.client.adapters.update(
|
|
1600
|
+
uuid,
|
|
1601
|
+
// biome-ignore lint/suspicious/noExplicitAny: body is assembled dynamically; SDK validates the shape
|
|
1602
|
+
body,
|
|
1603
|
+
validate === void 0 ? void 0 : { validate }
|
|
1604
|
+
);
|
|
1605
|
+
return normalizeAdapterDetail(raw);
|
|
1606
|
+
}
|
|
1607
|
+
async deleteAdapter(uuid) {
|
|
1608
|
+
await this.client.adapters.delete(uuid);
|
|
1609
|
+
}
|
|
1610
|
+
async validateAdapter(request) {
|
|
1611
|
+
let variables = request.variables ? toWireVariables(request.variables) : void 0;
|
|
1612
|
+
if (variables === void 0 && request.adapterUuid) {
|
|
1613
|
+
const adapter = await this.getAdapter(request.adapterUuid);
|
|
1614
|
+
variables = preserveVariablesForUpdate(adapter.variables);
|
|
1615
|
+
}
|
|
1616
|
+
const body = {
|
|
1617
|
+
script_b64: request.scriptB64,
|
|
1618
|
+
network_broker_channel_uuid: request.networkBrokerChannelUuid,
|
|
1619
|
+
prompt: request.prompt
|
|
1620
|
+
};
|
|
1621
|
+
if (variables !== void 0) body.variables = variables;
|
|
1622
|
+
if (request.adapterUuid !== void 0) body.adapter_uuid = request.adapterUuid;
|
|
1623
|
+
const raw = await this.client.adapters.validate(body);
|
|
1624
|
+
return {
|
|
1625
|
+
validated: raw.validated,
|
|
1626
|
+
stdout: raw.stdout,
|
|
1627
|
+
stderr: raw.stderr,
|
|
1628
|
+
traceback: raw.traceback
|
|
1629
|
+
};
|
|
1630
|
+
}
|
|
1411
1631
|
};
|
|
1412
1632
|
|
|
1413
1633
|
// src/airs/runtime.ts
|
|
@@ -2030,8 +2250,13 @@ var ConfigSchema = z.object({
|
|
|
2030
2250
|
modelSecDataEndpoint: z.string().optional(),
|
|
2031
2251
|
modelSecMgmtEndpoint: z.string().optional(),
|
|
2032
2252
|
modelSecTokenEndpoint: z.string().optional(),
|
|
2253
|
+
// AI Gateway (endpoints only; creds shared with mgmt*)
|
|
2254
|
+
aiGwDataEndpoint: z.string().optional(),
|
|
2255
|
+
aiGwAdminEndpoint: z.string().optional(),
|
|
2256
|
+
aiGwTokenEndpoint: z.string().optional(),
|
|
2033
2257
|
// Tuning
|
|
2034
2258
|
scanConcurrency: z.coerce.number().int().min(1).max(20).default(5),
|
|
2259
|
+
defaultOutput: z.enum(["pretty", "table", "markdown", "csv", "json", "yaml"]).optional(),
|
|
2035
2260
|
// Persistence
|
|
2036
2261
|
dataDir: z.string().default("~/.prisma-airs/runs")
|
|
2037
2262
|
});
|
|
@@ -2060,7 +2285,11 @@ function fromEnv() {
|
|
|
2060
2285
|
modelSecDataEndpoint: env.PANW_MODEL_SEC_DATA_ENDPOINT,
|
|
2061
2286
|
modelSecMgmtEndpoint: env.PANW_MODEL_SEC_MGMT_ENDPOINT,
|
|
2062
2287
|
modelSecTokenEndpoint: env.PANW_MODEL_SEC_TOKEN_ENDPOINT,
|
|
2288
|
+
aiGwDataEndpoint: env.PANW_AI_GW_DATA_ENDPOINT,
|
|
2289
|
+
aiGwAdminEndpoint: env.PANW_AI_GW_ADMIN_ENDPOINT,
|
|
2290
|
+
aiGwTokenEndpoint: env.PANW_AI_GW_TOKEN_ENDPOINT,
|
|
2063
2291
|
scanConcurrency: env.SCAN_CONCURRENCY,
|
|
2292
|
+
defaultOutput: env.PANW_CLI_OUTPUT,
|
|
2064
2293
|
dataDir: env.DATA_DIR
|
|
2065
2294
|
};
|
|
2066
2295
|
}
|