@optimizely-opal/opal-tool-ocp-sdk 1.0.0-OCP-1442.1 → 1.0.0-OCP-1442.3
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 +72 -0
- package/dist/function/GlobalToolFunction.js +1 -1
- package/dist/function/GlobalToolFunction.js.map +1 -1
- package/dist/function/ToolFunction.js +1 -1
- package/dist/function/ToolFunction.js.map +1 -1
- package/dist/logging/ToolLogger.d.ts.map +1 -1
- package/dist/logging/ToolLogger.js +54 -19
- package/dist/logging/ToolLogger.js.map +1 -1
- package/dist/logging/ToolLogger.test.js +110 -50
- package/dist/logging/ToolLogger.test.js.map +1 -1
- package/package.json +1 -1
- package/src/function/GlobalToolFunction.ts +1 -1
- package/src/function/ToolFunction.ts +1 -1
- package/src/logging/ToolLogger.test.ts +219 -213
- package/src/logging/ToolLogger.ts +58 -20
|
@@ -21,6 +21,14 @@ describe('ToolLogger', () => {
|
|
|
21
21
|
jest.clearAllMocks();
|
|
22
22
|
});
|
|
23
23
|
|
|
24
|
+
// Helper function to check JSON string logs
|
|
25
|
+
const expectJsonLog = (expectedData: any) => {
|
|
26
|
+
expect(mockLogger.info).toHaveBeenCalledWith(
|
|
27
|
+
LogVisibility.Zaius,
|
|
28
|
+
JSON.stringify(expectedData)
|
|
29
|
+
);
|
|
30
|
+
};
|
|
31
|
+
|
|
24
32
|
const createMockRequest = (overrides: any = {}): App.Request => {
|
|
25
33
|
const defaultRequest = {
|
|
26
34
|
path: '/test-tool',
|
|
@@ -59,16 +67,18 @@ describe('ToolLogger', () => {
|
|
|
59
67
|
|
|
60
68
|
ToolLogger.logRequest(req);
|
|
61
69
|
|
|
70
|
+
const expectedLog = {
|
|
71
|
+
event: 'opal_tool_request',
|
|
72
|
+
path: '/test-tool',
|
|
73
|
+
parameters: {
|
|
74
|
+
name: 'test',
|
|
75
|
+
value: 'data'
|
|
76
|
+
}
|
|
77
|
+
};
|
|
78
|
+
|
|
62
79
|
expect(mockLogger.info).toHaveBeenCalledWith(
|
|
63
80
|
LogVisibility.Zaius,
|
|
64
|
-
|
|
65
|
-
event: 'opal_tool_request',
|
|
66
|
-
path: '/test-tool',
|
|
67
|
-
parameters: {
|
|
68
|
-
name: 'test',
|
|
69
|
-
value: 'data'
|
|
70
|
-
}
|
|
71
|
-
})
|
|
81
|
+
JSON.stringify(expectedLog)
|
|
72
82
|
);
|
|
73
83
|
});
|
|
74
84
|
|
|
@@ -79,14 +89,11 @@ describe('ToolLogger', () => {
|
|
|
79
89
|
|
|
80
90
|
ToolLogger.logRequest(req);
|
|
81
91
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
parameters: null
|
|
88
|
-
})
|
|
89
|
-
);
|
|
92
|
+
expectJsonLog({
|
|
93
|
+
event: 'opal_tool_request',
|
|
94
|
+
path: '/test-tool',
|
|
95
|
+
parameters: null
|
|
96
|
+
});
|
|
90
97
|
});
|
|
91
98
|
|
|
92
99
|
it('should use bodyJSON as parameters when no parameters field exists', () => {
|
|
@@ -99,15 +106,14 @@ describe('ToolLogger', () => {
|
|
|
99
106
|
|
|
100
107
|
ToolLogger.logRequest(req);
|
|
101
108
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
);
|
|
109
|
+
expectJsonLog({
|
|
110
|
+
event: 'opal_tool_request',
|
|
111
|
+
path: '/test-tool',
|
|
112
|
+
parameters: {
|
|
113
|
+
name: 'direct',
|
|
114
|
+
action: 'test'
|
|
115
|
+
}
|
|
116
|
+
});
|
|
111
117
|
});
|
|
112
118
|
|
|
113
119
|
it('should redact all sensitive field variations', () => {
|
|
@@ -132,25 +138,24 @@ describe('ToolLogger', () => {
|
|
|
132
138
|
|
|
133
139
|
ToolLogger.logRequest(req);
|
|
134
140
|
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
);
|
|
141
|
+
expectJsonLog({
|
|
142
|
+
event: 'opal_tool_request',
|
|
143
|
+
path: '/test-tool',
|
|
144
|
+
parameters: {
|
|
145
|
+
username: 'john',
|
|
146
|
+
password: '[REDACTED]',
|
|
147
|
+
api_key: '[REDACTED]',
|
|
148
|
+
secret: '[REDACTED]',
|
|
149
|
+
token: '[REDACTED]',
|
|
150
|
+
auth: '[REDACTED]',
|
|
151
|
+
credentials: '[REDACTED]',
|
|
152
|
+
access_token: '[REDACTED]',
|
|
153
|
+
refresh_token: '[REDACTED]',
|
|
154
|
+
private_key: '[REDACTED]',
|
|
155
|
+
client_secret: '[REDACTED]',
|
|
156
|
+
normal_field: 'visible'
|
|
157
|
+
}
|
|
158
|
+
});
|
|
154
159
|
});
|
|
155
160
|
|
|
156
161
|
it('should redact sensitive fields with case variations', () => {
|
|
@@ -170,20 +175,19 @@ describe('ToolLogger', () => {
|
|
|
170
175
|
|
|
171
176
|
ToolLogger.logRequest(req);
|
|
172
177
|
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
);
|
|
178
|
+
expectJsonLog({
|
|
179
|
+
event: 'opal_tool_request',
|
|
180
|
+
path: '/test-tool',
|
|
181
|
+
parameters: {
|
|
182
|
+
PASSWORD: '[REDACTED]',
|
|
183
|
+
API_KEY: '[REDACTED]',
|
|
184
|
+
clientSecret: '[REDACTED]',
|
|
185
|
+
user_password: '[REDACTED]',
|
|
186
|
+
oauth_token: '[REDACTED]',
|
|
187
|
+
ssh_key: '[REDACTED]',
|
|
188
|
+
normal_field: 'visible'
|
|
189
|
+
}
|
|
190
|
+
});
|
|
187
191
|
});
|
|
188
192
|
|
|
189
193
|
it('should truncate long string values', () => {
|
|
@@ -199,15 +203,14 @@ describe('ToolLogger', () => {
|
|
|
199
203
|
|
|
200
204
|
ToolLogger.logRequest(req);
|
|
201
205
|
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
);
|
|
206
|
+
expectJsonLog({
|
|
207
|
+
event: 'opal_tool_request',
|
|
208
|
+
path: '/test-tool',
|
|
209
|
+
parameters: {
|
|
210
|
+
description: `${'a'.repeat(100)}... (truncated, 150 chars total)`,
|
|
211
|
+
short_field: 'normal'
|
|
212
|
+
}
|
|
213
|
+
});
|
|
211
214
|
});
|
|
212
215
|
|
|
213
216
|
it('should truncate large arrays', () => {
|
|
@@ -223,18 +226,17 @@ describe('ToolLogger', () => {
|
|
|
223
226
|
|
|
224
227
|
ToolLogger.logRequest(req);
|
|
225
228
|
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
);
|
|
229
|
+
expectJsonLog({
|
|
230
|
+
event: 'opal_tool_request',
|
|
231
|
+
path: '/test-tool',
|
|
232
|
+
parameters: {
|
|
233
|
+
items: [
|
|
234
|
+
...largeArray.slice(0, 10),
|
|
235
|
+
'... (5 more items truncated)'
|
|
236
|
+
],
|
|
237
|
+
small_array: ['a', 'b']
|
|
238
|
+
}
|
|
239
|
+
});
|
|
238
240
|
});
|
|
239
241
|
|
|
240
242
|
it('should handle nested objects with sensitive fields', () => {
|
|
@@ -260,26 +262,25 @@ describe('ToolLogger', () => {
|
|
|
260
262
|
|
|
261
263
|
ToolLogger.logRequest(req);
|
|
262
264
|
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
265
|
+
expectJsonLog({
|
|
266
|
+
event: 'opal_tool_request',
|
|
267
|
+
path: '/test-tool',
|
|
268
|
+
parameters: {
|
|
269
|
+
user: {
|
|
270
|
+
name: 'John',
|
|
271
|
+
email: '[REDACTED]',
|
|
272
|
+
password: '[REDACTED]'
|
|
273
|
+
},
|
|
274
|
+
config: {
|
|
275
|
+
database: {
|
|
276
|
+
host: 'localhost',
|
|
277
|
+
port: 5432,
|
|
270
278
|
password: '[REDACTED]'
|
|
271
279
|
},
|
|
272
|
-
|
|
273
|
-
database: {
|
|
274
|
-
host: 'localhost',
|
|
275
|
-
port: 5432,
|
|
276
|
-
password: '[REDACTED]'
|
|
277
|
-
},
|
|
278
|
-
api_key: '[REDACTED]'
|
|
279
|
-
}
|
|
280
|
+
api_key: '[REDACTED]'
|
|
280
281
|
}
|
|
281
|
-
}
|
|
282
|
-
);
|
|
282
|
+
}
|
|
283
|
+
});
|
|
283
284
|
});
|
|
284
285
|
|
|
285
286
|
it('should handle null and undefined values', () => {
|
|
@@ -298,19 +299,17 @@ describe('ToolLogger', () => {
|
|
|
298
299
|
|
|
299
300
|
ToolLogger.logRequest(req);
|
|
300
301
|
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
})
|
|
313
|
-
);
|
|
302
|
+
expectJsonLog({
|
|
303
|
+
event: 'opal_tool_request',
|
|
304
|
+
path: '/test-tool',
|
|
305
|
+
parameters: {
|
|
306
|
+
nullValue: null,
|
|
307
|
+
emptyString: '',
|
|
308
|
+
zero: 0,
|
|
309
|
+
false: false,
|
|
310
|
+
password: '[REDACTED]'
|
|
311
|
+
}
|
|
312
|
+
});
|
|
314
313
|
});
|
|
315
314
|
|
|
316
315
|
it('should handle arrays in sensitive fields', () => {
|
|
@@ -325,15 +324,14 @@ describe('ToolLogger', () => {
|
|
|
325
324
|
|
|
326
325
|
ToolLogger.logRequest(req);
|
|
327
326
|
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
);
|
|
327
|
+
expectJsonLog({
|
|
328
|
+
event: 'opal_tool_request',
|
|
329
|
+
path: '/test-tool',
|
|
330
|
+
parameters: {
|
|
331
|
+
credentials: '[REDACTED]',
|
|
332
|
+
public_list: ['item1', 'item2']
|
|
333
|
+
}
|
|
334
|
+
});
|
|
337
335
|
});
|
|
338
336
|
|
|
339
337
|
it('should handle objects in sensitive fields', () => {
|
|
@@ -354,18 +352,17 @@ describe('ToolLogger', () => {
|
|
|
354
352
|
|
|
355
353
|
ToolLogger.logRequest(req);
|
|
356
354
|
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
}
|
|
355
|
+
expectJsonLog({
|
|
356
|
+
event: 'opal_tool_request',
|
|
357
|
+
path: '/test-tool',
|
|
358
|
+
parameters: {
|
|
359
|
+
auth: '[REDACTED]',
|
|
360
|
+
public_config: {
|
|
361
|
+
timeout: 30,
|
|
362
|
+
retries: 3
|
|
366
363
|
}
|
|
367
|
-
}
|
|
368
|
-
);
|
|
364
|
+
}
|
|
365
|
+
});
|
|
369
366
|
});
|
|
370
367
|
|
|
371
368
|
it('should respect max depth to prevent infinite recursion', () => {
|
|
@@ -395,17 +392,19 @@ describe('ToolLogger', () => {
|
|
|
395
392
|
|
|
396
393
|
ToolLogger.logResponse(req, response, 150);
|
|
397
394
|
|
|
395
|
+
const expectedLog = {
|
|
396
|
+
event: 'opal_tool_response',
|
|
397
|
+
path: '/test-tool',
|
|
398
|
+
duration: '150ms',
|
|
399
|
+
status: 200,
|
|
400
|
+
contentType: 'application/json',
|
|
401
|
+
contentLength: 34, // JSON.stringify({ result: 'success', data: 'test' }).length
|
|
402
|
+
success: true
|
|
403
|
+
};
|
|
404
|
+
|
|
398
405
|
expect(mockLogger.info).toHaveBeenCalledWith(
|
|
399
406
|
LogVisibility.Zaius,
|
|
400
|
-
|
|
401
|
-
event: 'opal_tool_response',
|
|
402
|
-
path: '/test-tool',
|
|
403
|
-
duration: '150ms',
|
|
404
|
-
status: 200,
|
|
405
|
-
contentType: 'application/json',
|
|
406
|
-
contentLength: 34, // JSON.stringify({ result: 'success', data: 'test' }).length
|
|
407
|
-
success: true
|
|
408
|
-
})
|
|
407
|
+
JSON.stringify(expectedLog)
|
|
409
408
|
);
|
|
410
409
|
});
|
|
411
410
|
|
|
@@ -415,16 +414,15 @@ describe('ToolLogger', () => {
|
|
|
415
414
|
|
|
416
415
|
ToolLogger.logResponse(req, response, 75);
|
|
417
416
|
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
);
|
|
417
|
+
expectJsonLog({
|
|
418
|
+
event: 'opal_tool_response',
|
|
419
|
+
path: '/test-tool',
|
|
420
|
+
duration: '75ms',
|
|
421
|
+
status: 400,
|
|
422
|
+
contentType: 'application/json',
|
|
423
|
+
contentLength: 23,
|
|
424
|
+
success: false
|
|
425
|
+
});
|
|
428
426
|
});
|
|
429
427
|
|
|
430
428
|
it('should handle response without bodyJSON', () => {
|
|
@@ -434,13 +432,14 @@ describe('ToolLogger', () => {
|
|
|
434
432
|
|
|
435
433
|
ToolLogger.logResponse(req, response);
|
|
436
434
|
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
435
|
+
expectJsonLog({
|
|
436
|
+
event: 'opal_tool_response',
|
|
437
|
+
path: '/test-tool',
|
|
438
|
+
status: 204,
|
|
439
|
+
contentType: 'application/json',
|
|
440
|
+
contentLength: 0,
|
|
441
|
+
success: true
|
|
442
|
+
});
|
|
444
443
|
});
|
|
445
444
|
|
|
446
445
|
it('should handle response without processing time', () => {
|
|
@@ -449,12 +448,14 @@ describe('ToolLogger', () => {
|
|
|
449
448
|
|
|
450
449
|
ToolLogger.logResponse(req, response);
|
|
451
450
|
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
451
|
+
expectJsonLog({
|
|
452
|
+
event: 'opal_tool_response',
|
|
453
|
+
path: '/test-tool',
|
|
454
|
+
status: 200,
|
|
455
|
+
contentType: 'application/json',
|
|
456
|
+
contentLength: 15,
|
|
457
|
+
success: true
|
|
458
|
+
});
|
|
458
459
|
});
|
|
459
460
|
|
|
460
461
|
it('should handle unknown content type', () => {
|
|
@@ -464,12 +465,14 @@ describe('ToolLogger', () => {
|
|
|
464
465
|
|
|
465
466
|
ToolLogger.logResponse(req, response);
|
|
466
467
|
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
468
|
+
expectJsonLog({
|
|
469
|
+
event: 'opal_tool_response',
|
|
470
|
+
path: '/test-tool',
|
|
471
|
+
status: 200,
|
|
472
|
+
contentType: 'unknown',
|
|
473
|
+
contentLength: 15,
|
|
474
|
+
success: true
|
|
475
|
+
});
|
|
473
476
|
});
|
|
474
477
|
|
|
475
478
|
it('should handle content length calculation error', () => {
|
|
@@ -481,12 +484,14 @@ describe('ToolLogger', () => {
|
|
|
481
484
|
|
|
482
485
|
ToolLogger.logResponse(req, response);
|
|
483
486
|
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
487
|
+
expectJsonLog({
|
|
488
|
+
event: 'opal_tool_response',
|
|
489
|
+
path: '/test-tool',
|
|
490
|
+
status: 200,
|
|
491
|
+
contentType: 'application/json',
|
|
492
|
+
contentLength: 'unknown',
|
|
493
|
+
success: true
|
|
494
|
+
});
|
|
490
495
|
});
|
|
491
496
|
|
|
492
497
|
it('should correctly identify success status codes', () => {
|
|
@@ -508,12 +513,14 @@ describe('ToolLogger', () => {
|
|
|
508
513
|
const response = createMockResponse(status);
|
|
509
514
|
ToolLogger.logResponse(req, response);
|
|
510
515
|
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
516
|
+
expectJsonLog({
|
|
517
|
+
event: 'opal_tool_response',
|
|
518
|
+
path: '/test-tool',
|
|
519
|
+
status,
|
|
520
|
+
contentType: 'application/json',
|
|
521
|
+
contentLength: 2,
|
|
522
|
+
success: expected
|
|
523
|
+
});
|
|
517
524
|
});
|
|
518
525
|
});
|
|
519
526
|
|
|
@@ -534,12 +541,14 @@ describe('ToolLogger', () => {
|
|
|
534
541
|
|
|
535
542
|
ToolLogger.logResponse(req, response);
|
|
536
543
|
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
544
|
+
expectJsonLog({
|
|
545
|
+
event: 'opal_tool_response',
|
|
546
|
+
path: '/test-tool',
|
|
547
|
+
status: 200,
|
|
548
|
+
contentType,
|
|
549
|
+
contentLength: 15,
|
|
550
|
+
success: true
|
|
551
|
+
});
|
|
543
552
|
});
|
|
544
553
|
});
|
|
545
554
|
});
|
|
@@ -552,12 +561,11 @@ describe('ToolLogger', () => {
|
|
|
552
561
|
|
|
553
562
|
ToolLogger.logRequest(req);
|
|
554
563
|
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
);
|
|
564
|
+
expectJsonLog({
|
|
565
|
+
event: 'opal_tool_request',
|
|
566
|
+
path: '/test-tool',
|
|
567
|
+
parameters: {}
|
|
568
|
+
});
|
|
561
569
|
});
|
|
562
570
|
|
|
563
571
|
it('should handle request with only parameters field', () => {
|
|
@@ -571,14 +579,13 @@ describe('ToolLogger', () => {
|
|
|
571
579
|
|
|
572
580
|
ToolLogger.logRequest(req);
|
|
573
581
|
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
);
|
|
582
|
+
expectJsonLog({
|
|
583
|
+
event: 'opal_tool_request',
|
|
584
|
+
path: '/test-tool',
|
|
585
|
+
parameters: {
|
|
586
|
+
field: 'value'
|
|
587
|
+
}
|
|
588
|
+
});
|
|
582
589
|
});
|
|
583
590
|
|
|
584
591
|
it('should handle mixed data types in parameters', () => {
|
|
@@ -598,20 +605,19 @@ describe('ToolLogger', () => {
|
|
|
598
605
|
|
|
599
606
|
ToolLogger.logRequest(req);
|
|
600
607
|
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
);
|
|
608
|
+
expectJsonLog({
|
|
609
|
+
event: 'opal_tool_request',
|
|
610
|
+
path: '/test-tool',
|
|
611
|
+
parameters: {
|
|
612
|
+
string: 'text',
|
|
613
|
+
number: 42,
|
|
614
|
+
boolean: true,
|
|
615
|
+
array: [1, 2, 3],
|
|
616
|
+
object: { nested: 'value' },
|
|
617
|
+
nullValue: null,
|
|
618
|
+
password: '[REDACTED]'
|
|
619
|
+
}
|
|
620
|
+
});
|
|
615
621
|
});
|
|
616
622
|
});
|
|
617
623
|
});
|