@@ -7,14 +7,19 @@ import {getLoggerWithFilePath, logger} from "./loggerConfig";
77import * as os from "os" ;
88import CxBFL from "../bfl/CxBFL" ;
99import { CxInstaller } from "../osinstaller/CxInstaller" ;
10+ import { Semaphore } from "async-mutex" ;
1011
1112
1213type ParamTypeMap = Map < CxParamType , string > ;
1314
1415export 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 ;
1720 constructor ( cxScanConfig : CxConfig , logFilePath ?: string ) {
21+ this . cxInstaller = new CxInstaller ( process . platform ) ;
22+ this . config = new CxConfig ( ) ;
1823 getLoggerWithFilePath ( logFilePath )
1924 if ( cxScanConfig . apiKey ) {
2025 this . config . apiKey = cxScanConfig . apiKey ;
@@ -44,8 +49,54 @@ export class CxWrapper {
4449 }
4550 }
4651
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 [ ] {
49100 this . config . pathToExecutable = this . cxInstaller . getExecutablePath ( ) ;
50101
51102 const list : string [ ] = [ ] ;
@@ -87,14 +138,14 @@ export class CxWrapper {
87138
88139 async authValidate ( ) : Promise < CxCommandOutput > {
89140 const commands : string [ ] = [ CxConstants . CMD_AUTH , CxConstants . SUB_CMD_VALIDATE ] ;
90- commands . push ( ...await this . initializeCommands ( false ) ) ;
141+ commands . push ( ...this . initializeCommands ( false ) ) ;
91142 const exec = new ExecutionService ( ) ;
92143 return await exec . executeCommands ( this . config . pathToExecutable , commands ) ;
93144 }
94145
95146 async scanCreate ( params : ParamTypeMap ) : Promise < CxCommandOutput > {
96147 const commands : string [ ] = [ CxConstants . CMD_SCAN , CxConstants . SUB_CMD_CREATE ] ;
97- commands . push ( ...await this . initializeCommands ( false ) ) ;
148+ commands . push ( ...this . initializeCommands ( false ) ) ;
98149 commands . push ( CxConstants . SCAN_INFO_FORMAT ) ;
99150 commands . push ( CxConstants . FORMAT_JSON ) ;
100151
@@ -132,37 +183,37 @@ export class CxWrapper {
132183 commands . push ( '"js-wrapper"' ) ;
133184 }
134185
135- commands . push ( ...await this . initializeCommands ( false ) ) ;
186+ commands . push ( ...this . initializeCommands ( false ) ) ;
136187 const exec = new ExecutionService ( ) ;
137188 return await exec . executeCommands ( this . config . pathToExecutable , commands , CxConstants . SCAN_VORPAL ) ;
138189 }
139190
140191 async scanCancel ( id : string ) : Promise < CxCommandOutput > {
141192 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 ) ) ;
143194 const exec = new ExecutionService ( ) ;
144195 return await exec . executeCommands ( this . config . pathToExecutable , commands , CxConstants . SCAN_TYPE ) ;
145196 }
146197
147198 async scanShow ( id : string ) : Promise < CxCommandOutput > {
148199 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 ) ) ;
150201 const exec = new ExecutionService ( ) ;
151202 return await exec . executeCommands ( this . config . pathToExecutable , commands , CxConstants . SCAN_TYPE ) ;
152203 }
153204
154205 async scanList ( filters : string ) : Promise < CxCommandOutput > {
155206 const validated_filters = this . filterArguments ( filters ) ;
156207 const commands : string [ ] = [ CxConstants . CMD_SCAN , "list" ] . concat ( validated_filters ) ;
157- commands . push ( ...await this . initializeCommands ( true ) ) ;
208+ commands . push ( ...this . initializeCommands ( true ) ) ;
158209 const exec = new ExecutionService ( ) ;
159210 return await exec . executeCommands ( this . config . pathToExecutable , commands , CxConstants . SCAN_TYPE ) ;
160211 }
161212
162213 async projectList ( filters : string ) : Promise < CxCommandOutput > {
163214 const validated_filters = this . filterArguments ( filters ) ;
164215 const commands : string [ ] = [ CxConstants . CMD_PROJECT , "list" ] . concat ( validated_filters ) ;
165- commands . push ( ...await this . initializeCommands ( true ) ) ;
216+ commands . push ( ...this . initializeCommands ( true ) ) ;
166217 const exec = new ExecutionService ( ) ;
167218 return await exec . executeCommands ( this . config . pathToExecutable , commands , CxConstants . PROJECT_TYPE ) ;
168219 }
@@ -171,28 +222,28 @@ export class CxWrapper {
171222 // Verify and add possible branch filter by name
172223 const validated_filters = this . filterArguments ( CxConstants . BRANCH_NAME + filters )
173224 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 ) ) ;
175226 const exec = new ExecutionService ( ) ;
176227 return await exec . executeCommands ( this . config . pathToExecutable , commands ) ;
177228 }
178229
179230 async projectShow ( projectId : string ) : Promise < CxCommandOutput > {
180231 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 ) ) ;
182233 const exec = new ExecutionService ( ) ;
183234 return await exec . executeCommands ( this . config . pathToExecutable , commands , CxConstants . PROJECT_TYPE ) ;
184235 }
185236
186237 async triageShow ( projectId : string , similarityId : string , scanType : string ) : Promise < CxCommandOutput > {
187238 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 ) ) ;
189240 const exec = new ExecutionService ( ) ;
190241 return await exec . executeCommands ( this . config . pathToExecutable , commands , CxConstants . PREDICATE_TYPE ) ;
191242 }
192243
193244 async triageUpdate ( projectId : string , similarityId : string , scanType : string , state : string , comment : string , severity : string ) : Promise < CxCommandOutput > {
194245 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 ) ) ;
196247 const exec = new ExecutionService ( ) ;
197248 return await exec . executeCommands ( this . config . pathToExecutable , commands ) ;
198249 }
@@ -225,7 +276,7 @@ export class CxWrapper {
225276
226277 async codeBashingList ( cweId : string , language : string , queryName : string ) : Promise < CxCommandOutput > {
227278 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 ) ) ;
229280 const exec = new ExecutionService ( ) ;
230281 return await exec . executeCommands ( this . config . pathToExecutable , commands , CxConstants . CODE_BASHING_TYPE ) ;
231282 }
@@ -244,13 +295,13 @@ export class CxWrapper {
244295 commands . push ( CxConstants . AGENT ) ;
245296 commands . push ( agent ) ;
246297 }
247- commands . push ( ...await this . initializeCommands ( false ) ) ;
298+ commands . push ( ...this . initializeCommands ( false ) ) ;
248299 return commands ;
249300 }
250301
251302 async getResultsBfl ( scanId : string , queryId : string , resultNodes : any [ ] ) {
252303 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 ) ) ;
254305 const exec = new ExecutionService ( ) ;
255306 const response = await exec . executeCommands ( this . config . pathToExecutable , commands , CxConstants . BFL_TYPE ) ;
256307 if ( response ) {
@@ -265,7 +316,7 @@ export class CxWrapper {
265316 if ( engine . length > 0 ) {
266317 commands . push ( CxConstants . ENGINE , engine )
267318 }
268- commands . push ( ...await this . initializeCommands ( false ) ) ;
319+ commands . push ( ...this . initializeCommands ( false ) ) ;
269320 const exec = new ExecutionService ( ) ;
270321 return exec . executeKicsCommands ( this . config . pathToExecutable , commands , CxConstants . KICS_REALTIME_TYPE ) ;
271322 }
@@ -277,14 +328,14 @@ export class CxWrapper {
277328 */
278329 async runScaRealtimeScan ( projectDirPath : string ) : Promise < CxCommandOutput > {
279330 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 ) ) ;
281332 return new ExecutionService ( ) . executeCommands ( this . config . pathToExecutable , commands , CxConstants . SCA_REALTIME_TYPE ) ;
282333 }
283334
284335
285336 async learnMore ( queryId : string ) {
286337 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 ) )
288339 const exec = new ExecutionService ( ) ;
289340 return exec . executeCommands ( this . config . pathToExecutable , commands , CxConstants . LEARN_MORE_DESCRIPTIONS_TYPE ) ;
290341 }
@@ -297,29 +348,29 @@ export class CxWrapper {
297348 if ( similarityIds ) {
298349 commands . push ( CxConstants . KICS_REMEDIATION_SIMILARITY_IDS , similarityIds )
299350 }
300- commands . push ( ...await this . initializeCommands ( false ) ) ;
351+ commands . push ( ...this . initializeCommands ( false ) ) ;
301352 const exec = new ExecutionService ( ) ;
302353 return exec . executeKicsCommands ( this . config . pathToExecutable , commands , CxConstants . KICS_REMEDIATION_TYPE ) ;
303354 }
304355
305356 async scaRemediation ( packageFiles : string , packages : string , packageVersion : string ) : Promise < CxCommandOutput > {
306357 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 ) ) ;
308359 const exec = new ExecutionService ( ) ;
309360 return exec . executeCommands ( this . config . pathToExecutable , commands ) ;
310361 }
311362
312363 async ideScansEnabled ( ) : Promise < boolean > {
313364 const commands : string [ ] = [ CxConstants . CMD_UTILS , CxConstants . SUB_CMD_TENANT ] ;
314- commands . push ( ...await this . initializeCommands ( false ) ) ;
365+ commands . push ( ...this . initializeCommands ( false ) ) ;
315366 const exec = new ExecutionService ( ) ;
316367 const output = await exec . executeMapTenantOutputCommands ( this . config . pathToExecutable , commands ) ;
317368 return output . has ( CxConstants . IDE_SCANS_KEY ) && output . get ( CxConstants . IDE_SCANS_KEY ) . toLowerCase ( ) === " true" ;
318369 }
319370
320371 async guidedRemediationEnabled ( ) : Promise < boolean > {
321372 const commands : string [ ] = [ CxConstants . CMD_UTILS , CxConstants . SUB_CMD_TENANT ] ;
322- commands . push ( ...await this . initializeCommands ( false ) ) ;
373+ commands . push ( ...this . initializeCommands ( false ) ) ;
323374 const exec = new ExecutionService ( ) ;
324375 const output = await exec . executeMapTenantOutputCommands ( this . config . pathToExecutable , commands ) ;
325376 return output . has ( CxConstants . AI_GUIDED_REMEDIATION_KEY ) && output . get ( CxConstants . AI_GUIDED_REMEDIATION_KEY ) . toLowerCase ( ) === " true" ;
@@ -342,7 +393,7 @@ export class CxWrapper {
342393 if ( model ) {
343394 commands . push ( CxConstants . CMD_CHAT_MODEL , model )
344395 }
345- commands . push ( ...await this . initializeCommands ( false ) ) ;
396+ commands . push ( ...this . initializeCommands ( false ) ) ;
346397 return new ExecutionService ( ) . executeCommands ( this . config . pathToExecutable , commands , CxConstants . CHAT_TYPE ) ;
347398 }
348399
@@ -362,7 +413,7 @@ export class CxWrapper {
362413 if ( model ) {
363414 commands . push ( CxConstants . CMD_CHAT_MODEL , model )
364415 }
365- commands . push ( ...await this . initializeCommands ( false ) ) ;
416+ commands . push ( ...this . initializeCommands ( false ) ) ;
366417 return new ExecutionService ( ) . executeCommands ( this . config . pathToExecutable , commands , CxConstants . CHAT_TYPE ) ;
367418 }
368419
@@ -373,7 +424,7 @@ export class CxWrapper {
373424 CxConstants . CMD_CHAT_FILE , file ,
374425 ] ;
375426
376- commands . push ( ...await this . initializeCommands ( false ) ) ;
427+ commands . push ( ...this . initializeCommands ( false ) ) ;
377428 return new ExecutionService ( ) . executeCommands ( this . config . pathToExecutable , commands , CxConstants . MASK_TYPE ) ;
378429 }
379430
0 commit comments