@cdot65/prisma-airs-cli 3.2.0 → 3.3.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 CHANGED
@@ -10,7 +10,7 @@
10
10
  [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)
11
11
  [![Node 20+](https://img.shields.io/badge/node-%3E%3D20-brightgreen.svg)](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,6 +19,7 @@
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
23
24
  - **`airs doctor`** — one-command diagnostics for environment, credentials, and API connectivity
24
25
  - **`airs config`** — manage `~/.prisma-airs/config.json` from the CLI (`list`, `get`, `set`, `unset`, `path`)
@@ -55,6 +56,13 @@ airs runtime topics revert --profile my-profile --name "Explosives"
55
56
  airs redteam scan --target <uuid> --name "Full Scan" --type STATIC
56
57
  airs redteam report <job-id>
57
58
 
59
+ # Red team custom target adapters
60
+ airs redteam adapter list --output json
61
+
62
+ # AI Gateway workspaces and cost telemetry
63
+ airs aigateway workspace list --all --output json
64
+ airs aigateway telemetry cost --workspace <workspace-slug> --days 30
65
+
58
66
  # Model security
59
67
  airs model-security scans create --config scan-config.json
60
68
  ```
@@ -69,6 +77,7 @@ The full guides, complete CLI reference, configuration, and architecture live on
69
77
  - **[Runtime Security](https://cdot65.github.io/prisma-airs-cli/runtime/overview/)** — scanning, profiles, topics, and DLP management
70
78
  - **[Guardrail Optimization](https://cdot65.github.io/prisma-airs-cli/runtime/guardrails/overview/)** — the agent-driven `topics create/apply/eval/revert` loop
71
79
  - **[AI Red Teaming](https://cdot65.github.io/prisma-airs-cli/redteam/overview/)** — static, dynamic, and custom adversarial scans
80
+ - **[AI Gateway](https://cdot65.github.io/prisma-airs-cli/cli/aigateway/workspaces/)** — workspace CRUD, two-plane authorization, and cost telemetry
72
81
  - **[Model Security](https://cdot65.github.io/prisma-airs-cli/model-security/overview/)** — ML model supply-chain scanning
73
82
  - **[CLI Reference](https://cdot65.github.io/prisma-airs-cli/cli/)** — every command, flag, and example
74
83
 
@@ -1012,6 +1012,52 @@ function normalizeTargetDetail(raw) {
1012
1012
  metadata: sanitizeTargetMetadata(raw.target_metadata)
1013
1013
  };
1014
1014
  }
1015
+ function normalizeAdapterListItem(raw) {
1016
+ return {
1017
+ uuid: raw.uuid,
1018
+ name: raw.name,
1019
+ status: raw.status,
1020
+ createdAt: raw.created_at,
1021
+ updatedAt: raw.updated_at,
1022
+ createdByUserId: raw.created_by_user_id,
1023
+ targetCount: raw.target_count
1024
+ };
1025
+ }
1026
+ function normalizeAdapterVar(raw) {
1027
+ return {
1028
+ key: raw.key,
1029
+ value: raw.value,
1030
+ type: raw.type,
1031
+ isRedacted: raw.is_redacted
1032
+ };
1033
+ }
1034
+ function normalizeAdapterDetail(raw) {
1035
+ return {
1036
+ uuid: raw.uuid,
1037
+ tsgId: raw.tsg_id,
1038
+ name: raw.name,
1039
+ scriptB64: raw.script_b64,
1040
+ status: raw.status,
1041
+ description: raw.description,
1042
+ networkBrokerChannelUuid: raw.network_broker_channel_uuid,
1043
+ variables: (raw.variables ?? []).map(normalizeAdapterVar),
1044
+ targetCount: raw.target_count,
1045
+ createdAt: raw.created_at,
1046
+ updatedAt: raw.updated_at,
1047
+ createdByUserId: raw.created_by_user_id,
1048
+ updatedByUserId: raw.updated_by_user_id
1049
+ };
1050
+ }
1051
+ function preserveVariablesForUpdate(variables) {
1052
+ return variables.map((v) => ({
1053
+ key: v.key,
1054
+ value: v.isRedacted ? null : v.value ?? null,
1055
+ type: v.type
1056
+ }));
1057
+ }
1058
+ function toWireVariables(variables) {
1059
+ return variables.map((v) => ({ key: v.key, value: v.value, type: v.type }));
1060
+ }
1015
1061
  var SdkRedTeamService = class {
1016
1062
  client;
1017
1063
  constructor(opts) {
@@ -1180,7 +1226,12 @@ var SdkRedTeamService = class {
1180
1226
  }
1181
1227
  async createScan(request) {
1182
1228
  let jobMetadata = {};
1183
- if (request.jobType === "STATIC" && request.categories) {
1229
+ if (request.jobType === "STATIC") {
1230
+ if (!request.categories) {
1231
+ throw new Error(
1232
+ "STATIC scans require categories. Pass categories explicitly or use the CLI default."
1233
+ );
1234
+ }
1184
1235
  jobMetadata = { categories: request.categories };
1185
1236
  } else if (request.jobType === "CUSTOM" && request.customPromptSets) {
1186
1237
  jobMetadata = {
@@ -1408,6 +1459,87 @@ var SdkRedTeamService = class {
1408
1459
  totalItems: pagination?.total_items
1409
1460
  };
1410
1461
  }
1462
+ // -------------------------------------------------------------------------
1463
+ // Custom target adapters (SDK 0.16.0)
1464
+ // -------------------------------------------------------------------------
1465
+ async listAdapters(opts) {
1466
+ const sdkOpts = {};
1467
+ if (opts?.limit != null) sdkOpts.limit = opts.limit;
1468
+ if (opts?.offset != null) sdkOpts.skip = opts.offset;
1469
+ if (opts?.search) sdkOpts.search = opts.search;
1470
+ const raw = await this.client.adapters.list(sdkOpts);
1471
+ const pagination = raw.pagination;
1472
+ return {
1473
+ adapters: (raw.data ?? []).map(normalizeAdapterListItem),
1474
+ totalItems: pagination?.total_items
1475
+ };
1476
+ }
1477
+ async getAdapter(uuid) {
1478
+ const raw = await this.client.adapters.get(uuid);
1479
+ return normalizeAdapterDetail(raw);
1480
+ }
1481
+ async createAdapter(request, validate) {
1482
+ const body = {
1483
+ name: request.name,
1484
+ script_b64: request.scriptB64,
1485
+ prompt: request.prompt
1486
+ };
1487
+ if (request.description !== void 0) body.description = request.description;
1488
+ if (request.networkBrokerChannelUuid !== void 0) {
1489
+ body.network_broker_channel_uuid = request.networkBrokerChannelUuid;
1490
+ }
1491
+ if (request.variables !== void 0) body.variables = toWireVariables(request.variables);
1492
+ const raw = await this.client.adapters.create(
1493
+ // biome-ignore lint/suspicious/noExplicitAny: body is assembled dynamically; SDK validates the shape
1494
+ body,
1495
+ validate === void 0 ? void 0 : { validate }
1496
+ );
1497
+ return normalizeAdapterDetail(raw);
1498
+ }
1499
+ async updateAdapter(uuid, overrides, validate) {
1500
+ const current = await this.getAdapter(uuid);
1501
+ const body = {
1502
+ name: overrides.name ?? current.name,
1503
+ script_b64: overrides.scriptB64 ?? current.scriptB64,
1504
+ prompt: overrides.prompt,
1505
+ variables: overrides.variables ? toWireVariables(overrides.variables) : preserveVariablesForUpdate(current.variables)
1506
+ };
1507
+ const description = overrides.description ?? current.description;
1508
+ if (description != null) body.description = description;
1509
+ const channel = overrides.networkBrokerChannelUuid ?? current.networkBrokerChannelUuid;
1510
+ if (channel != null) body.network_broker_channel_uuid = channel;
1511
+ const raw = await this.client.adapters.update(
1512
+ uuid,
1513
+ // biome-ignore lint/suspicious/noExplicitAny: body is assembled dynamically; SDK validates the shape
1514
+ body,
1515
+ validate === void 0 ? void 0 : { validate }
1516
+ );
1517
+ return normalizeAdapterDetail(raw);
1518
+ }
1519
+ async deleteAdapter(uuid) {
1520
+ await this.client.adapters.delete(uuid);
1521
+ }
1522
+ async validateAdapter(request) {
1523
+ let variables = request.variables ? toWireVariables(request.variables) : void 0;
1524
+ if (variables === void 0 && request.adapterUuid) {
1525
+ const adapter = await this.getAdapter(request.adapterUuid);
1526
+ variables = preserveVariablesForUpdate(adapter.variables);
1527
+ }
1528
+ const body = {
1529
+ script_b64: request.scriptB64,
1530
+ network_broker_channel_uuid: request.networkBrokerChannelUuid,
1531
+ prompt: request.prompt
1532
+ };
1533
+ if (variables !== void 0) body.variables = variables;
1534
+ if (request.adapterUuid !== void 0) body.adapter_uuid = request.adapterUuid;
1535
+ const raw = await this.client.adapters.validate(body);
1536
+ return {
1537
+ validated: raw.validated,
1538
+ stdout: raw.stdout,
1539
+ stderr: raw.stderr,
1540
+ traceback: raw.traceback
1541
+ };
1542
+ }
1411
1543
  };
1412
1544
 
1413
1545
  // src/airs/runtime.ts
@@ -2030,6 +2162,10 @@ var ConfigSchema = z.object({
2030
2162
  modelSecDataEndpoint: z.string().optional(),
2031
2163
  modelSecMgmtEndpoint: z.string().optional(),
2032
2164
  modelSecTokenEndpoint: z.string().optional(),
2165
+ // AI Gateway (endpoints only; creds shared with mgmt*)
2166
+ aiGwDataEndpoint: z.string().optional(),
2167
+ aiGwAdminEndpoint: z.string().optional(),
2168
+ aiGwTokenEndpoint: z.string().optional(),
2033
2169
  // Tuning
2034
2170
  scanConcurrency: z.coerce.number().int().min(1).max(20).default(5),
2035
2171
  // Persistence
@@ -2060,6 +2196,9 @@ function fromEnv() {
2060
2196
  modelSecDataEndpoint: env.PANW_MODEL_SEC_DATA_ENDPOINT,
2061
2197
  modelSecMgmtEndpoint: env.PANW_MODEL_SEC_MGMT_ENDPOINT,
2062
2198
  modelSecTokenEndpoint: env.PANW_MODEL_SEC_TOKEN_ENDPOINT,
2199
+ aiGwDataEndpoint: env.PANW_AI_GW_DATA_ENDPOINT,
2200
+ aiGwAdminEndpoint: env.PANW_AI_GW_ADMIN_ENDPOINT,
2201
+ aiGwTokenEndpoint: env.PANW_AI_GW_TOKEN_ENDPOINT,
2063
2202
  scanConcurrency: env.SCAN_CONCURRENCY,
2064
2203
  dataDir: env.DATA_DIR
2065
2204
  };