@cdot65/prisma-airs-sdk 0.6.6 → 0.6.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -24,7 +24,7 @@ Requires Node.js 18+. Zero external HTTP dependencies (native `fetch` + `crypto`
24
24
  | Service | Client | Auth | Capabilities |
25
25
  | ----------------------- | --------------------- | ------- | ---------------------------------------------------------- |
26
26
  | **AI Runtime Security** | `Scanner` | API Key | Sync/async content scanning, prompt injection detection |
27
- | **Management** | `ManagementClient` | OAuth2 | Security profiles and custom topics CRUD |
27
+ | **Management** | `ManagementClient` | OAuth2 | Profiles, topics, API keys, apps, DLP, deployment, logs |
28
28
  | **Model Security** | `ModelSecurityClient` | OAuth2 | ML model scanning, security groups, rule management |
29
29
  | **AI Red Teaming** | `RedTeamClient` | OAuth2 | Automated red team scans, reports, targets, custom attacks |
30
30
 
@@ -53,28 +53,20 @@ console.log(result.action); // "allow" | "block"
53
53
 
54
54
  ### Management — Configuration CRUD (OAuth2)
55
55
 
56
- CRUD operations for all three Prisma AIRS services use OAuth2:
57
-
58
56
  ```ts
59
57
  import { ManagementClient } from '@cdot65/prisma-airs-sdk';
60
58
 
61
59
  const client = new ManagementClient(); // reads PANW_MGMT_* env vars
62
60
 
63
- // Security Profiles
64
- const profiles = await client.profiles.list();
65
- const created = await client.profiles.create({
66
- profile_name: 'my-profile',
67
- active: true,
68
- policy: {
69
- /* ... */
70
- },
71
- });
72
-
73
- // Custom Topics
74
- const topic = await client.topics.create({
75
- topic_name: 'pii-detector',
76
- examples: ['SSN: 123-45-6789'],
77
- });
61
+ // 8 sub-clients available:
62
+ client.profiles; // AI security profile CRUD
63
+ client.topics; // Custom detection topic CRUD
64
+ client.apiKeys; // API key lifecycle (create, list, regenerate, delete)
65
+ client.customerApps; // Customer application management
66
+ client.dlpProfiles; // DLP data profile listing
67
+ client.deploymentProfiles; // Deployment profile listing
68
+ client.scanLogs; // Scan activity log queries
69
+ client.oauth; // OAuth token management (get/invalidate)
78
70
  ```
79
71
 
80
72
  ### Model Security — ML Model Scanning (OAuth2)
@@ -84,6 +76,7 @@ import { ModelSecurityClient } from '@cdot65/prisma-airs-sdk';
84
76
 
85
77
  const client = new ModelSecurityClient(); // falls back to PANW_MGMT_* env vars
86
78
 
79
+ // 3 sub-clients: scans, securityGroups, securityRules
87
80
  const scans = await client.scans.list({ limit: 10 });
88
81
  const groups = await client.securityGroups.list();
89
82
  const rules = await client.securityRules.list();
@@ -96,6 +89,7 @@ import { RedTeamClient } from '@cdot65/prisma-airs-sdk';
96
89
 
97
90
  const client = new RedTeamClient(); // falls back to PANW_MGMT_* env vars
98
91
 
92
+ // 5 sub-clients: scans, reports, customAttackReports, targets, customAttacks
99
93
  const scans = await client.scans.list({ limit: 5 });
100
94
  const targets = await client.targets.list();
101
95
  const categories = await client.scans.getCategories();
@@ -118,15 +112,6 @@ export PANW_MGMT_CLIENT_SECRET=your-client-secret
118
112
  export PANW_MGMT_TSG_ID=1234567890
119
113
  ```
120
114
 
121
- ## Scanner Methods
122
-
123
- | Method | Description |
124
- | ------------------------------------- | ------------------------------------------ |
125
- | `syncScan(aiProfile, content, opts?)` | Synchronous inline scan |
126
- | `asyncScan(scanObjects)` | Batch async scan (up to 5) |
127
- | `queryByScanIds(scanIds)` | Get results by scan IDs (up to 5) |
128
- | `queryByReportIds(reportIds)` | Get threat reports by report IDs (up to 5) |
129
-
130
115
  ## Error Handling
131
116
 
132
117
  ```ts
@@ -153,7 +138,7 @@ Full documentation at **[cdot65.github.io/prisma-airs-sdk](https://cdot65.github
153
138
  ```bash
154
139
  npm install
155
140
  npm run build # tsup (CJS + ESM + .d.ts)
156
- npm run test # vitest (617 tests, 99%+ coverage)
141
+ npm run test # vitest (829 tests, 99%+ coverage)
157
142
  npm run lint # eslint
158
143
  npm run typecheck # tsc --noEmit
159
144
  ```
package/dist/index.cjs CHANGED
@@ -430,7 +430,7 @@ var MAX_NUMBER_OF_BATCH_SCAN_OBJECTS = 5;
430
430
  var MAX_CONNECTION_POOL_SIZE = 100;
431
431
  var MAX_NUMBER_OF_RETRIES = 5;
432
432
  var HTTP_FORCE_RETRY_STATUS_CODES = [500, 502, 503, 504];
433
- var SDK_VERSION = "0.6.6";
433
+ var SDK_VERSION = "0.6.8";
434
434
  var USER_AGENT = `PAN-AIRS/${SDK_VERSION}-typescript-sdk`;
435
435
  var DEFAULT_MGMT_ENDPOINT = "https://api.sase.paloaltonetworks.com/aisec";
436
436
  var DEFAULT_TOKEN_ENDPOINT = "https://auth.apps.paloaltonetworks.com/oauth2/access_token";
@@ -3248,6 +3248,49 @@ var OAuthClient = class {
3248
3248
  }
3249
3249
  };
3250
3250
 
3251
+ // src/oauth-config.ts
3252
+ function resolveOAuthConfig(opts) {
3253
+ const { primaryEnvPrefix, fallbackEnvPrefix } = opts;
3254
+ const clientId = opts.clientId ?? process.env[`${primaryEnvPrefix}_CLIENT_ID`] ?? (fallbackEnvPrefix ? process.env[`${fallbackEnvPrefix}_CLIENT_ID`] : void 0);
3255
+ const clientSecret = opts.clientSecret ?? process.env[`${primaryEnvPrefix}_CLIENT_SECRET`] ?? (fallbackEnvPrefix ? process.env[`${fallbackEnvPrefix}_CLIENT_SECRET`] : void 0);
3256
+ const tsgId = opts.tsgId ?? process.env[`${primaryEnvPrefix}_TSG_ID`] ?? (fallbackEnvPrefix ? process.env[`${fallbackEnvPrefix}_TSG_ID`] : void 0);
3257
+ const tokenEndpoint = opts.tokenEndpoint ?? process.env[`${primaryEnvPrefix}_TOKEN_ENDPOINT`] ?? (fallbackEnvPrefix ? process.env[`${fallbackEnvPrefix}_TOKEN_ENDPOINT`] : void 0);
3258
+ const numRetries = Math.min(
3259
+ Math.max(opts.numRetries ?? MAX_NUMBER_OF_RETRIES, 0),
3260
+ MAX_NUMBER_OF_RETRIES
3261
+ );
3262
+ const envHint = fallbackEnvPrefix ? `${primaryEnvPrefix}_CLIENT_ID / ${fallbackEnvPrefix}_CLIENT_ID` : `${primaryEnvPrefix}_CLIENT_ID`;
3263
+ if (!clientId) {
3264
+ throw new AISecSDKException(
3265
+ `clientId is required (option or ${envHint} env var)`,
3266
+ "AISEC_MISSING_VARIABLE" /* MISSING_VARIABLE */
3267
+ );
3268
+ }
3269
+ const secretHint = fallbackEnvPrefix ? `${primaryEnvPrefix}_CLIENT_SECRET / ${fallbackEnvPrefix}_CLIENT_SECRET` : `${primaryEnvPrefix}_CLIENT_SECRET`;
3270
+ if (!clientSecret) {
3271
+ throw new AISecSDKException(
3272
+ `clientSecret is required (option or ${secretHint} env var)`,
3273
+ "AISEC_MISSING_VARIABLE" /* MISSING_VARIABLE */
3274
+ );
3275
+ }
3276
+ const tsgHint = fallbackEnvPrefix ? `${primaryEnvPrefix}_TSG_ID / ${fallbackEnvPrefix}_TSG_ID` : `${primaryEnvPrefix}_TSG_ID`;
3277
+ if (!tsgId) {
3278
+ throw new AISecSDKException(
3279
+ `tsgId is required (option or ${tsgHint} env var)`,
3280
+ "AISEC_MISSING_VARIABLE" /* MISSING_VARIABLE */
3281
+ );
3282
+ }
3283
+ const oauthClient = new OAuthClient({
3284
+ clientId,
3285
+ clientSecret,
3286
+ tsgId,
3287
+ tokenEndpoint,
3288
+ tokenBufferMs: opts.tokenBufferMs,
3289
+ onTokenRefresh: opts.onTokenRefresh
3290
+ });
3291
+ return { baseUrl: opts.baseUrl, oauthClient, numRetries, tsgId };
3292
+ }
3293
+
3251
3294
  // src/management/management-http-client.ts
3252
3295
  async function managementHttpRequest(opts) {
3253
3296
  const { method, baseUrl, path, body, params, oauthClient, numRetries } = opts;
@@ -3342,6 +3385,40 @@ var ProfilesClient = class {
3342
3385
  });
3343
3386
  return res.data;
3344
3387
  }
3388
+ /**
3389
+ * Get a security profile by UUID.
3390
+ * Fetches all profiles and filters — no dedicated API endpoint exists.
3391
+ * @param profileId - UUID of the profile to retrieve.
3392
+ * @returns The matching security profile.
3393
+ */
3394
+ async get(profileId) {
3395
+ const { ai_profiles } = await this.list();
3396
+ const profile = ai_profiles.find((p) => p.profile_id === profileId);
3397
+ if (!profile) {
3398
+ throw new AISecSDKException(
3399
+ `Profile not found: ${profileId}`,
3400
+ "AISEC_USER_REQUEST_PAYLOAD_ERROR" /* USER_REQUEST_PAYLOAD_ERROR */
3401
+ );
3402
+ }
3403
+ return profile;
3404
+ }
3405
+ /**
3406
+ * Get a security profile by name.
3407
+ * Returns the highest-revision match (latest version).
3408
+ * @param profileName - Name of the profile to retrieve.
3409
+ * @returns The matching security profile with the highest revision.
3410
+ */
3411
+ async getByName(profileName) {
3412
+ const { ai_profiles } = await this.list();
3413
+ const matches = ai_profiles.filter((p) => p.profile_name === profileName);
3414
+ if (matches.length === 0) {
3415
+ throw new AISecSDKException(
3416
+ `Profile not found: ${profileName}`,
3417
+ "AISEC_USER_REQUEST_PAYLOAD_ERROR" /* USER_REQUEST_PAYLOAD_ERROR */
3418
+ );
3419
+ }
3420
+ return matches.reduce((best, p) => (p.revision ?? 0) > (best.revision ?? 0) ? p : best);
3421
+ }
3345
3422
  /**
3346
3423
  * Update an existing security profile.
3347
3424
  * @param profileId - UUID of the profile to update.
@@ -3853,80 +3930,57 @@ var ManagementClient = class {
3853
3930
  scanLogs;
3854
3931
  oauth;
3855
3932
  constructor(opts = {}) {
3856
- const clientId = opts.clientId ?? process.env[MGMT_CLIENT_ID];
3857
- const clientSecret = opts.clientSecret ?? process.env[MGMT_CLIENT_SECRET];
3858
- const tsgId = opts.tsgId ?? process.env[MGMT_TSG_ID];
3859
3933
  const apiEndpoint = opts.apiEndpoint ?? process.env[MGMT_ENDPOINT] ?? DEFAULT_MGMT_ENDPOINT;
3860
- const tokenEndpoint = opts.tokenEndpoint ?? process.env[MGMT_TOKEN_ENDPOINT];
3861
- const numRetries = Math.min(
3862
- Math.max(opts.numRetries ?? MAX_NUMBER_OF_RETRIES, 0),
3863
- MAX_NUMBER_OF_RETRIES
3864
- );
3865
- if (!clientId) {
3866
- throw new AISecSDKException(
3867
- "clientId is required (option or PANW_MGMT_CLIENT_ID env var)",
3868
- "AISEC_MISSING_VARIABLE" /* MISSING_VARIABLE */
3869
- );
3870
- }
3871
- if (!clientSecret) {
3872
- throw new AISecSDKException(
3873
- "clientSecret is required (option or PANW_MGMT_CLIENT_SECRET env var)",
3874
- "AISEC_MISSING_VARIABLE" /* MISSING_VARIABLE */
3875
- );
3876
- }
3877
- if (!tsgId) {
3878
- throw new AISecSDKException(
3879
- "tsgId is required (option or PANW_MGMT_TSG_ID env var)",
3880
- "AISEC_MISSING_VARIABLE" /* MISSING_VARIABLE */
3881
- );
3882
- }
3883
- const oauthClient = new OAuthClient({
3884
- clientId,
3885
- clientSecret,
3886
- tsgId,
3887
- tokenEndpoint
3934
+ const { baseUrl, oauthClient, numRetries, tsgId } = resolveOAuthConfig({
3935
+ clientId: opts.clientId,
3936
+ clientSecret: opts.clientSecret,
3937
+ tsgId: opts.tsgId,
3938
+ baseUrl: apiEndpoint,
3939
+ numRetries: opts.numRetries,
3940
+ tokenEndpoint: opts.tokenEndpoint,
3941
+ primaryEnvPrefix: "PANW_MGMT"
3888
3942
  });
3889
3943
  this.profiles = new ProfilesClient({
3890
- baseUrl: apiEndpoint,
3944
+ baseUrl,
3891
3945
  oauthClient,
3892
3946
  tsgId,
3893
3947
  numRetries
3894
3948
  });
3895
3949
  this.topics = new TopicsClient({
3896
- baseUrl: apiEndpoint,
3950
+ baseUrl,
3897
3951
  oauthClient,
3898
3952
  tsgId,
3899
3953
  numRetries
3900
3954
  });
3901
3955
  this.apiKeys = new ApiKeysClient({
3902
- baseUrl: apiEndpoint,
3956
+ baseUrl,
3903
3957
  oauthClient,
3904
3958
  tsgId,
3905
3959
  numRetries
3906
3960
  });
3907
3961
  this.customerApps = new CustomerAppsClient({
3908
- baseUrl: apiEndpoint,
3962
+ baseUrl,
3909
3963
  oauthClient,
3910
3964
  tsgId,
3911
3965
  numRetries
3912
3966
  });
3913
3967
  this.dlpProfiles = new DlpProfilesClient({
3914
- baseUrl: apiEndpoint,
3968
+ baseUrl,
3915
3969
  oauthClient,
3916
3970
  numRetries
3917
3971
  });
3918
3972
  this.deploymentProfiles = new DeploymentProfilesClient({
3919
- baseUrl: apiEndpoint,
3973
+ baseUrl,
3920
3974
  oauthClient,
3921
3975
  numRetries
3922
3976
  });
3923
3977
  this.scanLogs = new ScanLogsClient({
3924
- baseUrl: apiEndpoint,
3978
+ baseUrl,
3925
3979
  oauthClient,
3926
3980
  numRetries
3927
3981
  });
3928
3982
  this.oauth = new OAuthManagementClient({
3929
- baseUrl: apiEndpoint,
3983
+ baseUrl,
3930
3984
  oauthClient,
3931
3985
  numRetries
3932
3986
  });
@@ -4542,55 +4596,34 @@ var ModelSecurityClient = class {
4542
4596
  oauthClient;
4543
4597
  numRetries;
4544
4598
  constructor(opts = {}) {
4545
- const clientId = opts.clientId ?? process.env[MODEL_SEC_CLIENT_ID] ?? process.env[MGMT_CLIENT_ID];
4546
- const clientSecret = opts.clientSecret ?? process.env[MODEL_SEC_CLIENT_SECRET] ?? process.env[MGMT_CLIENT_SECRET];
4547
- const tsgId = opts.tsgId ?? process.env[MODEL_SEC_TSG_ID] ?? process.env[MGMT_TSG_ID];
4548
4599
  const dataEndpoint = opts.dataEndpoint ?? process.env[MODEL_SEC_DATA_ENDPOINT] ?? DEFAULT_MODEL_SEC_DATA_ENDPOINT;
4549
4600
  const mgmtEndpoint = opts.mgmtEndpoint ?? process.env[MODEL_SEC_MGMT_ENDPOINT] ?? DEFAULT_MODEL_SEC_MGMT_ENDPOINT;
4550
- const tokenEndpoint = opts.tokenEndpoint ?? process.env[MODEL_SEC_TOKEN_ENDPOINT] ?? process.env[MGMT_TOKEN_ENDPOINT];
4551
- const numRetries = Math.min(
4552
- Math.max(opts.numRetries ?? MAX_NUMBER_OF_RETRIES, 0),
4553
- MAX_NUMBER_OF_RETRIES
4554
- );
4555
- if (!clientId) {
4556
- throw new AISecSDKException(
4557
- "clientId is required (option or PANW_MODEL_SEC_CLIENT_ID / PANW_MGMT_CLIENT_ID env var)",
4558
- "AISEC_MISSING_VARIABLE" /* MISSING_VARIABLE */
4559
- );
4560
- }
4561
- if (!clientSecret) {
4562
- throw new AISecSDKException(
4563
- "clientSecret is required (option or PANW_MODEL_SEC_CLIENT_SECRET / PANW_MGMT_CLIENT_SECRET env var)",
4564
- "AISEC_MISSING_VARIABLE" /* MISSING_VARIABLE */
4565
- );
4566
- }
4567
- if (!tsgId) {
4568
- throw new AISecSDKException(
4569
- "tsgId is required (option or PANW_MODEL_SEC_TSG_ID / PANW_MGMT_TSG_ID env var)",
4570
- "AISEC_MISSING_VARIABLE" /* MISSING_VARIABLE */
4571
- );
4572
- }
4573
- this.oauthClient = new OAuthClient({
4574
- clientId,
4575
- clientSecret,
4576
- tsgId,
4577
- tokenEndpoint
4601
+ const { oauthClient, numRetries } = resolveOAuthConfig({
4602
+ clientId: opts.clientId,
4603
+ clientSecret: opts.clientSecret,
4604
+ tsgId: opts.tsgId,
4605
+ baseUrl: mgmtEndpoint,
4606
+ numRetries: opts.numRetries,
4607
+ tokenEndpoint: opts.tokenEndpoint,
4608
+ primaryEnvPrefix: "PANW_MODEL_SEC",
4609
+ fallbackEnvPrefix: "PANW_MGMT"
4578
4610
  });
4611
+ this.oauthClient = oauthClient;
4579
4612
  this.mgmtEndpoint = mgmtEndpoint;
4580
4613
  this.numRetries = numRetries;
4581
4614
  this.scans = new ModelSecurityScansClient({
4582
4615
  baseUrl: dataEndpoint,
4583
- oauthClient: this.oauthClient,
4616
+ oauthClient,
4584
4617
  numRetries
4585
4618
  });
4586
4619
  this.securityGroups = new ModelSecurityGroupsClient({
4587
4620
  baseUrl: mgmtEndpoint,
4588
- oauthClient: this.oauthClient,
4621
+ oauthClient,
4589
4622
  numRetries
4590
4623
  });
4591
4624
  this.securityRules = new ModelSecurityRulesClient({
4592
4625
  baseUrl: mgmtEndpoint,
4593
- oauthClient: this.oauthClient,
4626
+ oauthClient,
4594
4627
  numRetries
4595
4628
  });
4596
4629
  }
@@ -5742,61 +5775,45 @@ var RedTeamClient = class {
5742
5775
  oauthClient;
5743
5776
  numRetries;
5744
5777
  constructor(opts = {}) {
5745
- const clientId = opts.clientId ?? process.env[RED_TEAM_CLIENT_ID] ?? process.env[MGMT_CLIENT_ID];
5746
- const clientSecret = opts.clientSecret ?? process.env[RED_TEAM_CLIENT_SECRET] ?? process.env[MGMT_CLIENT_SECRET];
5747
- const tsgId = opts.tsgId ?? process.env[RED_TEAM_TSG_ID] ?? process.env[MGMT_TSG_ID];
5748
5778
  const dataEndpoint = opts.dataEndpoint ?? process.env[RED_TEAM_DATA_ENDPOINT] ?? DEFAULT_RED_TEAM_DATA_ENDPOINT;
5749
5779
  const mgmtEndpoint = opts.mgmtEndpoint ?? process.env[RED_TEAM_MGMT_ENDPOINT] ?? DEFAULT_RED_TEAM_MGMT_ENDPOINT;
5750
- const tokenEndpoint = opts.tokenEndpoint ?? process.env[RED_TEAM_TOKEN_ENDPOINT] ?? process.env[MGMT_TOKEN_ENDPOINT];
5751
- const numRetries = Math.min(
5752
- Math.max(opts.numRetries ?? MAX_NUMBER_OF_RETRIES, 0),
5753
- MAX_NUMBER_OF_RETRIES
5754
- );
5755
- if (!clientId) {
5756
- throw new AISecSDKException(
5757
- "clientId is required (option or PANW_RED_TEAM_CLIENT_ID / PANW_MGMT_CLIENT_ID env var)",
5758
- "AISEC_MISSING_VARIABLE" /* MISSING_VARIABLE */
5759
- );
5760
- }
5761
- if (!clientSecret) {
5762
- throw new AISecSDKException(
5763
- "clientSecret is required (option or PANW_RED_TEAM_CLIENT_SECRET / PANW_MGMT_CLIENT_SECRET env var)",
5764
- "AISEC_MISSING_VARIABLE" /* MISSING_VARIABLE */
5765
- );
5766
- }
5767
- if (!tsgId) {
5768
- throw new AISecSDKException(
5769
- "tsgId is required (option or PANW_RED_TEAM_TSG_ID / PANW_MGMT_TSG_ID env var)",
5770
- "AISEC_MISSING_VARIABLE" /* MISSING_VARIABLE */
5771
- );
5772
- }
5773
- this.oauthClient = new OAuthClient({ clientId, clientSecret, tsgId, tokenEndpoint });
5780
+ const { oauthClient, numRetries } = resolveOAuthConfig({
5781
+ clientId: opts.clientId,
5782
+ clientSecret: opts.clientSecret,
5783
+ tsgId: opts.tsgId,
5784
+ baseUrl: dataEndpoint,
5785
+ numRetries: opts.numRetries,
5786
+ tokenEndpoint: opts.tokenEndpoint,
5787
+ primaryEnvPrefix: "PANW_RED_TEAM",
5788
+ fallbackEnvPrefix: "PANW_MGMT"
5789
+ });
5790
+ this.oauthClient = oauthClient;
5774
5791
  this.dataEndpoint = dataEndpoint;
5775
5792
  this.mgmtEndpoint = mgmtEndpoint;
5776
5793
  this.numRetries = numRetries;
5777
5794
  this.scans = new RedTeamScansClient({
5778
5795
  baseUrl: dataEndpoint,
5779
- oauthClient: this.oauthClient,
5796
+ oauthClient,
5780
5797
  numRetries
5781
5798
  });
5782
5799
  this.reports = new RedTeamReportsClient({
5783
5800
  baseUrl: dataEndpoint,
5784
- oauthClient: this.oauthClient,
5801
+ oauthClient,
5785
5802
  numRetries
5786
5803
  });
5787
5804
  this.customAttackReports = new RedTeamCustomAttackReportsClient({
5788
5805
  baseUrl: dataEndpoint,
5789
- oauthClient: this.oauthClient,
5806
+ oauthClient,
5790
5807
  numRetries
5791
5808
  });
5792
5809
  this.targets = new RedTeamTargetsClient({
5793
5810
  baseUrl: mgmtEndpoint,
5794
- oauthClient: this.oauthClient,
5811
+ oauthClient,
5795
5812
  numRetries
5796
5813
  });
5797
5814
  this.customAttacks = new RedTeamCustomAttacksClient({
5798
5815
  baseUrl: mgmtEndpoint,
5799
- oauthClient: this.oauthClient,
5816
+ oauthClient,
5800
5817
  numRetries
5801
5818
  });
5802
5819
  }