@@ -7,14 +7,19 @@ import {getLoggerWithFilePath, logger} from "./loggerConfig";
7
7
import * as os from "os" ;
8
8
import CxBFL from "../bfl/CxBFL" ;
9
9
import { CxInstaller } from "../osinstaller/CxInstaller" ;
10
+ import { Semaphore } from "async-mutex" ;
10
11
11
12
12
13
type ParamTypeMap = Map < CxParamType , string > ;
13
14
14
15
export class CxWrapper {
15
- config : CxConfig = new CxConfig ( ) ;
16
- cxInstaller : CxInstaller = new CxInstaller ( process . platform ) ;
16
+ private static instance : CxWrapper ;
17
+ private static semaphore = new Semaphore ( 1 ) ; // Semaphore with 1 slot
18
+ config : CxConfig ;
19
+ cxInstaller : CxInstaller ;
17
20
constructor ( cxScanConfig : CxConfig , logFilePath ?: string ) {
21
+ this . cxInstaller = new CxInstaller ( process . platform ) ;
22
+ this . config = new CxConfig ( ) ;
18
23
getLoggerWithFilePath ( logFilePath )
19
24
if ( cxScanConfig . apiKey ) {
20
25
this . config . apiKey = cxScanConfig . apiKey ;
@@ -44,8 +49,54 @@ export class CxWrapper {
44
49
}
45
50
}
46
51
47
- async initializeCommands ( formatRequired : boolean ) : Promise < string [ ] > {
48
- await this . cxInstaller . downloadIfNotInstalledCLI ( )
52
+ static async getInstance ( cxScanConfig : CxConfig , logFilePath : string ) : Promise < CxWrapper > {
53
+ const [ _ , release ] = await this . semaphore . acquire ( ) ;
54
+ if ( ! CxWrapper . instance ) {
55
+ CxWrapper . instance = new CxWrapper ( cxScanConfig , logFilePath ) ;
56
+ }
57
+ release ( ) ;
58
+
59
+ return CxWrapper . instance ;
60
+ }
61
+
62
+ setScanConfig ( cxScanConfig : CxConfig ) {
63
+ if ( cxScanConfig . apiKey ) {
64
+ this . config . apiKey = cxScanConfig . apiKey ;
65
+ } else if ( cxScanConfig . clientId && cxScanConfig . clientSecret ) {
66
+ logger . info ( "Received clientId and clientSecret" ) ;
67
+ this . config . clientId = cxScanConfig . clientId ;
68
+ this . config . clientSecret = cxScanConfig . clientSecret ;
69
+ } else {
70
+ logger . info ( "Did not receive ClientId/Secret or ApiKey from cli arguments" ) ;
71
+ }
72
+ if ( cxScanConfig . pathToExecutable ) {
73
+ this . config . pathToExecutable = cxScanConfig . pathToExecutable ;
74
+ } else {
75
+ this . config . pathToExecutable = this . cxInstaller . getExecutablePath ( ) ;
76
+ }
77
+ if ( cxScanConfig . baseUri ) {
78
+ this . config . baseUri = cxScanConfig . baseUri ;
79
+ }
80
+ if ( cxScanConfig . baseAuthUri ) {
81
+ this . config . baseAuthUri = cxScanConfig . baseAuthUri ;
82
+ }
83
+ if ( cxScanConfig . tenant ) {
84
+ this . config . tenant = cxScanConfig . tenant ;
85
+ }
86
+ if ( cxScanConfig . additionalParameters ) {
87
+ this . config . additionalParameters = cxScanConfig . additionalParameters ;
88
+ }
89
+ }
90
+
91
+ GetScanConfig ( ) : CxConfig {
92
+ return this . config ;
93
+ }
94
+
95
+ async init ( ) : Promise < void > {
96
+ return await this . cxInstaller . downloadIfNotInstalledCLI ( ) ;
97
+ }
98
+
99
+ initializeCommands ( formatRequired : boolean ) : string [ ] {
49
100
this . config . pathToExecutable = this . cxInstaller . getExecutablePath ( ) ;
50
101
51
102
const list : string [ ] = [ ] ;
@@ -87,14 +138,14 @@ export class CxWrapper {
87
138
88
139
async authValidate ( ) : Promise < CxCommandOutput > {
89
140
const commands : string [ ] = [ CxConstants . CMD_AUTH , CxConstants . SUB_CMD_VALIDATE ] ;
90
- commands . push ( ...await this . initializeCommands ( false ) ) ;
141
+ commands . push ( ...this . initializeCommands ( false ) ) ;
91
142
const exec = new ExecutionService ( ) ;
92
143
return await exec . executeCommands ( this . config . pathToExecutable , commands ) ;
93
144
}
94
145
95
146
async scanCreate ( params : ParamTypeMap ) : Promise < CxCommandOutput > {
96
147
const commands : string [ ] = [ CxConstants . CMD_SCAN , CxConstants . SUB_CMD_CREATE ] ;
97
- commands . push ( ...await this . initializeCommands ( false ) ) ;
148
+ commands . push ( ...this . initializeCommands ( false ) ) ;
98
149
commands . push ( CxConstants . SCAN_INFO_FORMAT ) ;
99
150
commands . push ( CxConstants . FORMAT_JSON ) ;
100
151
@@ -132,37 +183,37 @@ export class CxWrapper {
132
183
commands . push ( '"js-wrapper"' ) ;
133
184
}
134
185
135
- commands . push ( ...await this . initializeCommands ( false ) ) ;
186
+ commands . push ( ...this . initializeCommands ( false ) ) ;
136
187
const exec = new ExecutionService ( ) ;
137
188
return await exec . executeCommands ( this . config . pathToExecutable , commands , CxConstants . SCAN_VORPAL ) ;
138
189
}
139
190
140
191
async scanCancel ( id : string ) : Promise < CxCommandOutput > {
141
192
const commands : string [ ] = [ CxConstants . CMD_SCAN , CxConstants . SUB_CMD_CANCEL , CxConstants . SCAN_ID , id ] ;
142
- commands . push ( ...await this . initializeCommands ( false ) ) ;
193
+ commands . push ( ...this . initializeCommands ( false ) ) ;
143
194
const exec = new ExecutionService ( ) ;
144
195
return await exec . executeCommands ( this . config . pathToExecutable , commands , CxConstants . SCAN_TYPE ) ;
145
196
}
146
197
147
198
async scanShow ( id : string ) : Promise < CxCommandOutput > {
148
199
const commands : string [ ] = [ CxConstants . CMD_SCAN , CxConstants . SUB_CMD_SHOW , CxConstants . SCAN_ID , id ] ;
149
- commands . push ( ...await this . initializeCommands ( true ) ) ;
200
+ commands . push ( ...this . initializeCommands ( true ) ) ;
150
201
const exec = new ExecutionService ( ) ;
151
202
return await exec . executeCommands ( this . config . pathToExecutable , commands , CxConstants . SCAN_TYPE ) ;
152
203
}
153
204
154
205
async scanList ( filters : string ) : Promise < CxCommandOutput > {
155
206
const validated_filters = this . filterArguments ( filters ) ;
156
207
const commands : string [ ] = [ CxConstants . CMD_SCAN , "list" ] . concat ( validated_filters ) ;
157
- commands . push ( ...await this . initializeCommands ( true ) ) ;
208
+ commands . push ( ...this . initializeCommands ( true ) ) ;
158
209
const exec = new ExecutionService ( ) ;
159
210
return await exec . executeCommands ( this . config . pathToExecutable , commands , CxConstants . SCAN_TYPE ) ;
160
211
}
161
212
162
213
async projectList ( filters : string ) : Promise < CxCommandOutput > {
163
214
const validated_filters = this . filterArguments ( filters ) ;
164
215
const commands : string [ ] = [ CxConstants . CMD_PROJECT , "list" ] . concat ( validated_filters ) ;
165
- commands . push ( ...await this . initializeCommands ( true ) ) ;
216
+ commands . push ( ...this . initializeCommands ( true ) ) ;
166
217
const exec = new ExecutionService ( ) ;
167
218
return await exec . executeCommands ( this . config . pathToExecutable , commands , CxConstants . PROJECT_TYPE ) ;
168
219
}
@@ -171,28 +222,28 @@ export class CxWrapper {
171
222
// Verify and add possible branch filter by name
172
223
const validated_filters = this . filterArguments ( CxConstants . BRANCH_NAME + filters )
173
224
const commands : string [ ] = [ CxConstants . CMD_PROJECT , CxConstants . SUB_CMD_BRANCHES , CxConstants . PROJECT_ID , projectId ] . concat ( validated_filters ) ;
174
- commands . push ( ...await this . initializeCommands ( false ) ) ;
225
+ commands . push ( ...this . initializeCommands ( false ) ) ;
175
226
const exec = new ExecutionService ( ) ;
176
227
return await exec . executeCommands ( this . config . pathToExecutable , commands ) ;
177
228
}
178
229
179
230
async projectShow ( projectId : string ) : Promise < CxCommandOutput > {
180
231
const commands : string [ ] = [ CxConstants . CMD_PROJECT , CxConstants . SUB_CMD_SHOW , CxConstants . PROJECT_ID , projectId ] ;
181
- commands . push ( ...await this . initializeCommands ( true ) ) ;
232
+ commands . push ( ...this . initializeCommands ( true ) ) ;
182
233
const exec = new ExecutionService ( ) ;
183
234
return await exec . executeCommands ( this . config . pathToExecutable , commands , CxConstants . PROJECT_TYPE ) ;
184
235
}
185
236
186
237
async triageShow ( projectId : string , similarityId : string , scanType : string ) : Promise < CxCommandOutput > {
187
238
const commands : string [ ] = [ CxConstants . CMD_TRIAGE , CxConstants . SUB_CMD_SHOW , CxConstants . PROJECT_ID , projectId , CxConstants . SIMILARITY_ID , similarityId , CxConstants . SCAN_TYPES_SUB_CMD , scanType ] ;
188
- commands . push ( ...await this . initializeCommands ( true ) ) ;
239
+ commands . push ( ...this . initializeCommands ( true ) ) ;
189
240
const exec = new ExecutionService ( ) ;
190
241
return await exec . executeCommands ( this . config . pathToExecutable , commands , CxConstants . PREDICATE_TYPE ) ;
191
242
}
192
243
193
244
async triageUpdate ( projectId : string , similarityId : string , scanType : string , state : string , comment : string , severity : string ) : Promise < CxCommandOutput > {
194
245
const commands : string [ ] = [ CxConstants . CMD_TRIAGE , CxConstants . SUB_CMD_UPDATE , CxConstants . PROJECT_ID , projectId , CxConstants . SIMILARITY_ID , similarityId , CxConstants . SCAN_TYPES_SUB_CMD , scanType , CxConstants . STATE , state , CxConstants . COMMENT , comment , CxConstants . SEVERITY , severity ] ;
195
- commands . push ( ...await this . initializeCommands ( false ) ) ;
246
+ commands . push ( ...this . initializeCommands ( false ) ) ;
196
247
const exec = new ExecutionService ( ) ;
197
248
return await exec . executeCommands ( this . config . pathToExecutable , commands ) ;
198
249
}
@@ -225,7 +276,7 @@ export class CxWrapper {
225
276
226
277
async codeBashingList ( cweId : string , language : string , queryName : string ) : Promise < CxCommandOutput > {
227
278
const commands : string [ ] = [ CxConstants . CMD_RESULT , CxConstants . CMD_CODE_BASHING , CxConstants . LANGUAGE , language , CxConstants . VULNERABILITY_TYPE , queryName , CxConstants . CWE_ID , cweId ] ;
228
- commands . push ( ...await this . initializeCommands ( true ) ) ;
279
+ commands . push ( ...this . initializeCommands ( true ) ) ;
229
280
const exec = new ExecutionService ( ) ;
230
281
return await exec . executeCommands ( this . config . pathToExecutable , commands , CxConstants . CODE_BASHING_TYPE ) ;
231
282
}
@@ -244,13 +295,13 @@ export class CxWrapper {
244
295
commands . push ( CxConstants . AGENT ) ;
245
296
commands . push ( agent ) ;
246
297
}
247
- commands . push ( ...await this . initializeCommands ( false ) ) ;
298
+ commands . push ( ...this . initializeCommands ( false ) ) ;
248
299
return commands ;
249
300
}
250
301
251
302
async getResultsBfl ( scanId : string , queryId : string , resultNodes : any [ ] ) {
252
303
const commands : string [ ] = [ CxConstants . CMD_RESULT , CxConstants . SUB_CMD_BFL , CxConstants . SCAN_ID , scanId , CxConstants . QUERY_ID , queryId ] ;
253
- commands . push ( ...await this . initializeCommands ( true ) ) ;
304
+ commands . push ( ...this . initializeCommands ( true ) ) ;
254
305
const exec = new ExecutionService ( ) ;
255
306
const response = await exec . executeCommands ( this . config . pathToExecutable , commands , CxConstants . BFL_TYPE ) ;
256
307
if ( response ) {
@@ -265,7 +316,7 @@ export class CxWrapper {
265
316
if ( engine . length > 0 ) {
266
317
commands . push ( CxConstants . ENGINE , engine )
267
318
}
268
- commands . push ( ...await this . initializeCommands ( false ) ) ;
319
+ commands . push ( ...this . initializeCommands ( false ) ) ;
269
320
const exec = new ExecutionService ( ) ;
270
321
return exec . executeKicsCommands ( this . config . pathToExecutable , commands , CxConstants . KICS_REALTIME_TYPE ) ;
271
322
}
@@ -277,14 +328,14 @@ export class CxWrapper {
277
328
*/
278
329
async runScaRealtimeScan ( projectDirPath : string ) : Promise < CxCommandOutput > {
279
330
const commands : string [ ] = [ CxConstants . CMD_SCAN , CxConstants . CMD_SCA_REALTIME , CxConstants . CMD_SCA_REALTIME_PROJECT_DIR , projectDirPath ] ;
280
- commands . push ( ...await this . initializeCommands ( false ) ) ;
331
+ commands . push ( ...this . initializeCommands ( false ) ) ;
281
332
return new ExecutionService ( ) . executeCommands ( this . config . pathToExecutable , commands , CxConstants . SCA_REALTIME_TYPE ) ;
282
333
}
283
334
284
335
285
336
async learnMore ( queryId : string ) {
286
337
const commands : string [ ] = [ CxConstants . CMD_UTILS , CxConstants . CMD_LEARN_MORE , CxConstants . QUERY_ID , queryId ]
287
- commands . push ( ...await this . initializeCommands ( true ) )
338
+ commands . push ( ...this . initializeCommands ( true ) )
288
339
const exec = new ExecutionService ( ) ;
289
340
return exec . executeCommands ( this . config . pathToExecutable , commands , CxConstants . LEARN_MORE_DESCRIPTIONS_TYPE ) ;
290
341
}
@@ -297,29 +348,29 @@ export class CxWrapper {
297
348
if ( similarityIds ) {
298
349
commands . push ( CxConstants . KICS_REMEDIATION_SIMILARITY_IDS , similarityIds )
299
350
}
300
- commands . push ( ...await this . initializeCommands ( false ) ) ;
351
+ commands . push ( ...this . initializeCommands ( false ) ) ;
301
352
const exec = new ExecutionService ( ) ;
302
353
return exec . executeKicsCommands ( this . config . pathToExecutable , commands , CxConstants . KICS_REMEDIATION_TYPE ) ;
303
354
}
304
355
305
356
async scaRemediation ( packageFiles : string , packages : string , packageVersion : string ) : Promise < CxCommandOutput > {
306
357
const commands : string [ ] = [ CxConstants . CMD_UTILS , CxConstants . CMD_REMEDIATION , CxConstants . SUB_CMD_REMEDIATION_SCA , CxConstants . SCA_REMEDIATION_PACKAGE_FILES , packageFiles , CxConstants . SCA_REMEDIATION_PACKAGE , packages , CxConstants . SCA_REMEDIATION_PACKAGE_VERSION , packageVersion ] ;
307
- commands . push ( ...await this . initializeCommands ( false ) ) ;
358
+ commands . push ( ...this . initializeCommands ( false ) ) ;
308
359
const exec = new ExecutionService ( ) ;
309
360
return exec . executeCommands ( this . config . pathToExecutable , commands ) ;
310
361
}
311
362
312
363
async ideScansEnabled ( ) : Promise < boolean > {
313
364
const commands : string [ ] = [ CxConstants . CMD_UTILS , CxConstants . SUB_CMD_TENANT ] ;
314
- commands . push ( ...await this . initializeCommands ( false ) ) ;
365
+ commands . push ( ...this . initializeCommands ( false ) ) ;
315
366
const exec = new ExecutionService ( ) ;
316
367
const output = await exec . executeMapTenantOutputCommands ( this . config . pathToExecutable , commands ) ;
317
368
return output . has ( CxConstants . IDE_SCANS_KEY ) && output . get ( CxConstants . IDE_SCANS_KEY ) . toLowerCase ( ) === " true" ;
318
369
}
319
370
320
371
async guidedRemediationEnabled ( ) : Promise < boolean > {
321
372
const commands : string [ ] = [ CxConstants . CMD_UTILS , CxConstants . SUB_CMD_TENANT ] ;
322
- commands . push ( ...await this . initializeCommands ( false ) ) ;
373
+ commands . push ( ...this . initializeCommands ( false ) ) ;
323
374
const exec = new ExecutionService ( ) ;
324
375
const output = await exec . executeMapTenantOutputCommands ( this . config . pathToExecutable , commands ) ;
325
376
return output . has ( CxConstants . AI_GUIDED_REMEDIATION_KEY ) && output . get ( CxConstants . AI_GUIDED_REMEDIATION_KEY ) . toLowerCase ( ) === " true" ;
@@ -342,7 +393,7 @@ export class CxWrapper {
342
393
if ( model ) {
343
394
commands . push ( CxConstants . CMD_CHAT_MODEL , model )
344
395
}
345
- commands . push ( ...await this . initializeCommands ( false ) ) ;
396
+ commands . push ( ...this . initializeCommands ( false ) ) ;
346
397
return new ExecutionService ( ) . executeCommands ( this . config . pathToExecutable , commands , CxConstants . CHAT_TYPE ) ;
347
398
}
348
399
@@ -362,7 +413,7 @@ export class CxWrapper {
362
413
if ( model ) {
363
414
commands . push ( CxConstants . CMD_CHAT_MODEL , model )
364
415
}
365
- commands . push ( ...await this . initializeCommands ( false ) ) ;
416
+ commands . push ( ...this . initializeCommands ( false ) ) ;
366
417
return new ExecutionService ( ) . executeCommands ( this . config . pathToExecutable , commands , CxConstants . CHAT_TYPE ) ;
367
418
}
368
419
@@ -373,7 +424,7 @@ export class CxWrapper {
373
424
CxConstants . CMD_CHAT_FILE , file ,
374
425
] ;
375
426
376
- commands . push ( ...await this . initializeCommands ( false ) ) ;
427
+ commands . push ( ...this . initializeCommands ( false ) ) ;
377
428
return new ExecutionService ( ) . executeCommands ( this . config . pathToExecutable , commands , CxConstants . MASK_TYPE ) ;
378
429
}
379
430
0 commit comments