@@ -8,6 +8,20 @@ import * as tl from 'azure-pipelines-task-lib/task';
88import * as trm from 'azure-pipelines-task-lib/toolrunner' ;
99import * as path from 'path' ;
1010
11+ /**
12+ * Get Agent.TempDirectory which is a temp folder that is cleaned after each pipeline job.
13+ * This is where we will store the Veracode SCA tool so we do not take up too much disk space
14+ * on self hosted agents.
15+ */
16+ const tempPath : string = < string > tl . getVariable ( 'Agent.TempDirectory' ) ;
17+ if ( tempPath !== undefined ) {
18+ // Per https://help.veracode.com/r/c_sc_ci_script if we set
19+ // the CACHE_DIR variable, we can direct where the files are downloaded to
20+ tl . setVariable ( 'CACHE_DIR' , tempPath ) ;
21+ console . log ( `CACHE_DIR: ${ tempPath } ` ) ;
22+ }
23+
24+
1125async function run ( ) : Promise < void > {
1226 try {
1327 tl . setResourcePath ( path . join ( __dirname , 'task.json' ) ) ;
@@ -48,93 +62,54 @@ async function run(): Promise<void> {
4862
4963 //This only works on linux or MacOs Agents
5064 if ( agentPlatform === 'linux' || agentPlatform === 'darwin' ) {
51-
52- try {
53- // Is srcclr already installed?
54- const srcclrPath : string = tl . which ( 'srcclr' , true ) ;
55- console . log ( 'Found SCA Agent install here: ' + `${ srcclrPath } ` ) ;
56-
57- } catch {
58- // Install srcclr
59- const curlPath : string = tl . which ( 'curl' , true ) ;
60- const shPath : string = tl . which ( 'sh' , true ) ;
61-
62- // Install SCA Agent
63- const curl : trm . ToolRunner = tl . tool ( curlPath ) ;
64- curl . arg ( '-sSL' ) ;
65- curl . arg ( 'https://www.sourceclear.com/install' ) ;
66- const sh : trm . ToolRunner = tl . tool ( shPath ) ;
67- // On self-hosted agents this may not work if the agent is not running as root
68- const pipe : trm . ToolRunner = curl . pipeExecOutputToTool ( sh ) ;
69- const scaAgentInstall : number = await pipe . exec ( ) ;
70- tl . setResult ( tl . TaskResult . Succeeded , tl . loc ( 'curlReturnCode' , scaAgentInstall ) ) ;
71-
72- }
73-
65+
7466 // Test the environment to see which collectors are available, equivalent to 'srcclr test'
7567 if ( testAgent === true ) {
76- const scaAgentTest : trm . ToolRunner = tl . tool ( 'srcclr' ) ;
77- scaAgentTest . arg ( 'test' ) ;
78- const scaAgentTestResult : number = await scaAgentTest . exec ( ) ;
79- tl . setResult ( tl . TaskResult . Succeeded , tl . loc ( 'bashReturnCode' , scaAgentTestResult ) ) ;
68+ await testSCA ( ) ;
8069 }
70+
71+ // Run the scan
72+ await runScan ( scanType , scanTarget ) ;
73+
74+ // Find the python3 installation
75+ const pythonPath : string = tl . which ( 'python3' ) ;
8176
82- // Scan against an artifact directory
83- if ( scanType === 'directory' ) {
84- const scanDirectory : trm . ToolRunner = tl . tool ( 'srcclr' ) ;
85- scanDirectory . arg ( 'scan' ) ;
86- scanDirectory . arg ( `${ scanTarget } ` ) ;
87- scanDirectory . arg ( '--json' ) ;
88- scanDirectory . arg ( 'scaresults.json' ) ;
89- const directoryResults : number = await scanDirectory . exec ( ) ;
90- tl . setResult ( tl . TaskResult . Succeeded , tl . loc ( 'bashReturnCode' , directoryResults ) ) ;
91- // Scan against a URL - Need to make sure it begins with http(s)
92- } else if ( scanType === 'url' ) {
93- const scanUrl : trm . ToolRunner = tl . tool ( 'srcclr' ) ;
94- scanUrl . arg ( 'scan' ) ;
95- scanUrl . arg ( '--url' ) ;
96- scanUrl . arg ( `${ scanTarget } ` ) ;
97- scanUrl . arg ( '--json' ) ;
98- scanUrl . arg ( 'scaresults.json' ) ;
99- const urlResults : number = await scanUrl . exec ( ) ;
100- tl . setResult ( tl . TaskResult . Succeeded , tl . loc ( 'bashReturnCode' , urlResults ) ) ;
101- // Scan a Docker image
102- } else if ( scanType === 'image' ) {
103- const scanDockerImage : trm . ToolRunner = tl . tool ( 'srcclr' ) ;
104- scanDockerImage . arg ( 'scan' ) ;
105- scanDockerImage . arg ( '--image' ) ;
106- scanDockerImage . arg ( `${ scanTarget } ` ) ;
107- scanDockerImage . arg ( '--json' ) ;
108- scanDockerImage . arg ( 'scaresults.json' ) ;
109- const dockerResults : number = await scanDockerImage . exec ( ) ;
110- tl . setResult ( tl . TaskResult . Succeeded , tl . loc ( 'bashReturnCode' , dockerResults ) ) ;
77+ try {
78+ // Install junitparser
79+ const python3 : trm . ToolRunner = tl . tool ( pythonPath ) ;
80+ python3 . arg ( '-m' ) ;
81+ python3 . arg ( 'pip' ) ;
82+ python3 . arg ( 'install' ) ;
83+ python3 . arg ( '--upgrade' ) ;
84+ python3 . arg ( 'pip' ) ;
85+ python3 . arg ( 'junitparser' ) ;
86+ // Run the command
87+ await python3 . exec ( ) ;
88+ tl . setResult ( tl . TaskResult . Succeeded , "pip install was successful." ) ;
89+
90+ } catch ( err ) {
91+
92+ return tl . setResult ( tl . TaskResult . Failed , "pip install failed." ) ;
11193 }
11294
113- // Need error handling when selecting python for non Microsoft hosted agents
114- // Install junitparser
115- const pythonPath : string = tl . which ( 'python3' ) ;
116- const python3 : trm . ToolRunner = tl . tool ( pythonPath ) ;
117- python3 . arg ( '-m' ) ;
118- python3 . arg ( 'pip' ) ;
119- python3 . arg ( 'install' ) ;
120- python3 . arg ( '--upgrade' ) ;
121- python3 . arg ( 'junitparser' ) ;
122- const pipinstall : number = await python3 . exec ( ) ;
123- tl . setResult ( tl . TaskResult . Succeeded , tl . loc ( 'pipReturnCode' , pipinstall ) ) ;
124-
125- // Generate the results
126- const genResults : trm . ToolRunner = tl . tool ( pythonPath ) ;
127- genResults . arg ( path . join ( __dirname , 'parsescaresults.py' ) ) ;
128- genResults . arg ( '--target' ) ;
129- genResults . arg ( `${ appName } ` ) ;
130- genResults . arg ( '--mincvss' ) ;
131- genResults . arg ( `${ minCVSS } ` ) ;
132- genResults . arg ( '--failbuild' ) ;
133- genResults . arg ( `${ failBuild } ` ) ;
134- const publishResults : number = await genResults . exec ( ) ;
135- tl . setResult ( tl . TaskResult . Succeeded , tl . loc ( 'bashReturnCode' , publishResults ) ) ;
136-
137- return ;
95+ try {
96+ // Generate the results
97+ const genResults : trm . ToolRunner = tl . tool ( pythonPath ) ;
98+ genResults . arg ( path . join ( __dirname , 'parsescaresults.py' ) ) ;
99+ genResults . arg ( '--target' ) ;
100+ genResults . arg ( `${ appName } ` ) ;
101+ genResults . arg ( '--mincvss' ) ;
102+ genResults . arg ( `${ minCVSS } ` ) ;
103+ genResults . arg ( '--failbuild' ) ;
104+ genResults . arg ( `${ failBuild } ` ) ;
105+ // Run the command
106+ await genResults . exec ( ) ;
107+ return tl . setResult ( tl . TaskResult . Succeeded , "SCA result parsing and upload was successful." ) ;
108+
109+ } catch ( err ) {
110+
111+ return tl . setResult ( tl . TaskResult . Failed , "SCA result parsing and upload failed." ) ;
112+ }
138113
139114 } else {
140115 // Need to add Windows support
@@ -150,4 +125,60 @@ async function run(): Promise<void> {
150125 }
151126}
152127
128+ // Run the SCA scan
129+ async function runScan ( scanType : string ,
130+ scanTarget : string ) : Promise < void > {
131+
132+ try {
133+ const curlPath : string = tl . which ( 'curl' , true ) ;
134+ const shPath : string = tl . which ( 'sh' , true ) ;
135+ const curl : trm . ToolRunner = tl . tool ( curlPath ) ;
136+ curl . arg ( '-sSL' ) ;
137+ curl . arg ( 'https://download.sourceclear.com/ci.sh' ) ;
138+ const sh : trm . ToolRunner = tl . tool ( shPath ) ;
139+ sh . arg ( '-s' ) ;
140+ sh . arg ( '--' ) ;
141+ sh . arg ( 'scan' ) ;
142+ if ( scanType !== 'directory' ) {
143+ sh . arg ( `--${ scanType } ` ) ;
144+ }
145+ sh . arg ( `${ scanTarget } ` ) ;
146+ sh . arg ( '--recursive' ) ;
147+ sh . arg ( '--json' ) ;
148+ sh . arg ( 'scaresults.json' ) ;
149+ const pipe : trm . ToolRunner = curl . pipeExecOutputToTool ( sh ) ;
150+ await pipe . exec ( ) ;
151+
152+ return tl . setResult ( tl . TaskResult . Succeeded , "SCA scan completed." ) ;
153+
154+ } catch ( err ) {
155+ throw new Error ( err ) ;
156+
157+ }
158+ }
159+
160+ // Test the SCA scan environment
161+ async function testSCA ( ) : Promise < void > {
162+
163+ try {
164+ const curlPath : string = tl . which ( 'curl' , true ) ;
165+ const shPath : string = tl . which ( 'sh' , true ) ;
166+ const curl : trm . ToolRunner = tl . tool ( curlPath ) ;
167+ curl . arg ( '-sSL' ) ;
168+ curl . arg ( 'https://download.sourceclear.com/ci.sh' ) ;
169+ const sh : trm . ToolRunner = tl . tool ( shPath ) ;
170+ sh . arg ( '-s' ) ;
171+ sh . arg ( '--' ) ;
172+ sh . arg ( 'test' ) ;
173+ const pipe : trm . ToolRunner = curl . pipeExecOutputToTool ( sh ) ;
174+ await pipe . exec ( ) ;
175+
176+ return tl . setResult ( tl . TaskResult . Succeeded , "SCA test completed." ) ;
177+
178+ } catch ( err ) {
179+ throw new Error ( err ) ;
180+
181+ }
182+ }
183+
153184run ( ) ;
0 commit comments