Hide keyboard shortcuts

Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

1#!/usr/bin/env python3 

2""" 

3A python module to interface with the Veracode Static Analysis APIs 

4""" 

5 

6# built-ins 

7from pathlib import Path 

8import logging 

9from typing import Optional, Dict, Any 

10from datetime import datetime 

11 

12# custom 

13from veracode import constants, __project_name__ 

14from veracode.utils import ( 

15 is_valid_attribute, 

16 http_request, 

17 get_app_id, 

18) 

19 

20LOG = logging.getLogger(__project_name__ + "." + __name__) 

21 

22 

23class VeracodeXMLAPI: 

24 """ 

25 A base Veracode XML API class to inherit from 

26 

27 For more details, see Veracode's documentation at 

28 https://help.veracode.com/reader/LMv_dtSHyb7iIxAQznC~9w/pd_p6JjB9PcDNH3GzWF5Ag 

29 """ 

30 

31 def __init__(self, *, app_name: str): 

32 # Hard code to None as it should be specified in the derived classes 

33 self._version = None 

34 

35 ## Use the setter to apply a default to ensure it is valid 

36 self.base_url = constants.API_BASE_URL 

37 

38 """ 

39 Set app name and look up ID 

40 

41 Note: App ID resolution depends on access to the Veracode upload API and 

42 the "getapplist.do" endpoint: 

43 https://help.veracode.com/reader/orRWez4I0tnZNaA_i0zn9g/Z4Ecf1fw7868vYPVgkglww 

44 """ 

45 self.app_name = app_name 

46 self.app_id = get_app_id(app_name=app_name) 

47 

48 def http_get( 

49 self, 

50 *, 

51 endpoint: str, 

52 params: Optional[Dict] = None, 

53 headers: Optional[Dict] = None, 

54 ): 

55 """ 

56 Perform a HTTP GET request to a Veracode XML API and return the 

57 response 

58 """ 

59 return http_request( 

60 verb="get", 

61 url=self.base_url + self.version[endpoint] + "/" + endpoint, 

62 params=params, 

63 headers=headers, 

64 ) 

65 

66 def http_post( 

67 self, 

68 *, 

69 endpoint: str, 

70 data: Optional[bytes] = None, 

71 params: Optional[Dict] = None, 

72 headers: Optional[Dict] = None, 

73 ): 

74 """ 

75 Perform a HTTP POST request to a Veracode XML API and return the 

76 response 

77 """ 

78 return http_request( 

79 verb="post", 

80 url=self.base_url + self.version[endpoint] + "/" + endpoint, 

81 data=data, 

82 params=params, 

83 headers=headers, 

84 ) 

85 

86 @property 

87 def base_url(self): 

88 """ 

89 Create the base_url property 

90 """ 

91 return self._base_url # pragma: no cover 

92 

93 @base_url.getter 

94 def base_url(self): 

95 """ 

96 Create a base_url getter that validates before returning 

97 """ 

98 # Validate what was already stored 

99 self._validate(key="base_url", value=self._base_url) 

100 return self._base_url 

101 

102 @base_url.setter 

103 def base_url(self, base_url): 

104 """ 

105 Create a base_url setter that validates before setting 

106 """ 

107 # Validate what was provided 

108 self._validate(key="base_url", value=base_url) 

109 self._base_url = base_url 

110 

111 @property 

112 def version(self): 

113 """ 

114 Create the version property 

115 """ 

116 return self._version # pragma: no cover 

117 

118 @version.getter 

119 def version(self): 

120 """ 

121 Create a version getter that validates before returning 

122 """ 

123 # Validate what was already stored 

124 self._validate(key="version", value=self._version) 

125 return self._version 

126 

127 @version.setter 

128 def version(self, version): 

129 """ 

130 Create a version setter that validates before setting 

131 """ 

132 # Validate what was provided 

133 self._validate(key="version", value=version) 

134 self._version = version 

135 

136 @property 

137 def app_id(self): 

138 """ 

139 Create the app_id property 

140 """ 

141 return self._app_id # pragma: no cover 

142 

143 @app_id.getter 

144 def app_id(self): 

145 """ 

146 Create an app_id getter that validates before returning 

147 """ 

148 # Validate what was already stored 

149 self._validate(key="app_id", value=self._app_id) 

150 return self._app_id 

151 

152 @app_id.setter 

153 def app_id(self, app_id): 

154 """ 

155 Create an app_id setter that validates before setting 

156 """ 

157 # Validate what was provided 

158 self._validate(key="app_id", value=app_id) 

159 self._app_id = app_id 

160 

161 @property 

162 def app_name(self): 

163 """ 

164 Create the app_name property 

165 """ 

166 return self._app_name # pragma: no cover 

167 

168 @app_name.getter 

169 def app_name(self): 

170 """ 

171 Create an app_name getter that validates before returning 

172 """ 

173 # Validate what was already stored 

174 self._validate(key="app_name", value=self._app_name) 

175 return self._app_name 

176 

177 @app_name.setter 

178 def app_name(self, app_name): 

179 """ 

180 Create an app_name setter that validates before setting 

181 """ 

182 # Validate what was provided 

183 self._validate(key="app_name", value=app_name) 

184 self._app_name = app_name 

185 

186 @staticmethod 

187 def _validate(*, key: str, value: Any): 

188 if is_valid_attribute(key=key, value=value): 

189 return True 

190 raise ValueError(f"Invalid {key}") 

191 

192 

193class UploadAPI(VeracodeXMLAPI): # pylint: disable=too-many-instance-attributes 

194 """ 

195 A class to interact with the Upload API 

196 """ 

197 

198 def __init__(self, *, app_name: str): 

199 # Don't forget to call the init of the parent 

200 super().__init__(app_name=app_name) 

201 

202 ## Use the setter to apply a default to ensure it is valid 

203 # version information was pulled from 

204 # https://help.veracode.com/reader/LMv_dtSHyb7iIxAQznC~9w/G1Nd5yH0QSlT~vPccPhtRQ 

205 self.version = constants.UPLOAD_API_VERSIONS 

206 self.build_dir = Path("/build").absolute() 

207 self.build_id = datetime.utcnow().strftime("%F_%H-%M-%S") 

208 self.scan_all_nonfatal_top_level_modules = True 

209 self.auto_scan = True 

210 # sandbox_id is not meant to be set manually. Instead, configure using 

211 # the response of a Sandbox API query using the intended sandbox name 

212 self.sandbox_id = None 

213 

214 @property 

215 def build_dir(self): 

216 """ 

217 Create the build_dir property 

218 """ 

219 return self._build_dir # pragma: no cover 

220 

221 @build_dir.getter 

222 def build_dir(self): 

223 """ 

224 Create a build_dir getter that validates before returning 

225 """ 

226 # Validate what was already stored 

227 self._validate(key="build_dir", value=self._build_dir) 

228 return self._build_dir 

229 

230 @build_dir.setter 

231 def build_dir(self, build_dir): 

232 """ 

233 Create a build_dir setter that validates before setting 

234 """ 

235 # Validate what was provided 

236 self._validate(key="build_dir", value=build_dir) 

237 self._build_dir = build_dir 

238 

239 @property 

240 def build_id(self): 

241 """ 

242 Create the build_id property 

243 """ 

244 return self._build_id # pragma: no cover 

245 

246 @build_id.getter 

247 def build_id(self): 

248 """ 

249 Create a build_id getter that validates before returning 

250 """ 

251 # Validate what was already stored 

252 self._validate(key="build_id", value=self._build_id) 

253 return self._build_id 

254 

255 @build_id.setter 

256 def build_id(self, build_id): 

257 """ 

258 Create a build_id setter that validates before setting 

259 """ 

260 # Validate what was provided 

261 self._validate(key="build_id", value=build_id) 

262 self._build_id = build_id 

263 

264 @property 

265 def sandbox_id(self): 

266 """ 

267 Create the sandbox_id property 

268 """ 

269 return self._sandbox_id # pragma: no cover 

270 

271 @sandbox_id.getter 

272 def sandbox_id(self): 

273 """ 

274 Create a sandbox_id getter that validates before returning 

275 

276 This should only be set using the response of a Sandbox API query using 

277 the intended sandbox name 

278 """ 

279 # Validate what was already stored 

280 self._validate(key="sandbox_id", value=self._sandbox_id) 

281 return self._sandbox_id 

282 

283 @sandbox_id.setter 

284 def sandbox_id(self, sandbox_id): 

285 """ 

286 Create a sandbox_id setter that validates before setting 

287 """ 

288 # Validate what was provided 

289 self._validate(key="sandbox_id", value=sandbox_id) 

290 self._sandbox_id = sandbox_id 

291 

292 @property 

293 def scan_all_nonfatal_top_level_modules(self): 

294 """ 

295 Create the scan_all_nonfatal_top_level_modules property 

296 """ 

297 return self._scan_all_nonfatal_top_level_modules # pragma: no cover 

298 

299 @scan_all_nonfatal_top_level_modules.getter 

300 def scan_all_nonfatal_top_level_modules(self): 

301 """ 

302 Create a scan_all_nonfatal_top_level_modules getter that validates 

303 before returning 

304 """ 

305 # Validate what was already stored 

306 self._validate( 

307 key="scan_all_nonfatal_top_level_modules", 

308 value=self._scan_all_nonfatal_top_level_modules, 

309 ) 

310 return self._scan_all_nonfatal_top_level_modules 

311 

312 @scan_all_nonfatal_top_level_modules.setter 

313 def scan_all_nonfatal_top_level_modules(self, scan_all_nonfatal_top_level_modules): 

314 """ 

315 Create a scan_all_nonfatal_top_level_modules setter that validates before setting 

316 """ 

317 # Validate what was provided 

318 self._validate( 

319 key="scan_all_nonfatal_top_level_modules", 

320 value=scan_all_nonfatal_top_level_modules, 

321 ) 

322 self._scan_all_nonfatal_top_level_modules = scan_all_nonfatal_top_level_modules 

323 

324 @property 

325 def auto_scan(self): 

326 """ 

327 Create the auto_scan property 

328 """ 

329 return self._auto_scan # pragma: no cover 

330 

331 @auto_scan.getter 

332 def auto_scan(self): 

333 """ 

334 Create an auto_scan getter that validates before returning 

335 """ 

336 # Validate what was already stored 

337 self._validate(key="auto_scan", value=self._auto_scan) 

338 return self._auto_scan 

339 

340 @auto_scan.setter 

341 def auto_scan(self, auto_scan): 

342 """ 

343 Create an auto_scan setter that validates before setting 

344 """ 

345 # Validate what was provided 

346 self._validate(key="auto_scan", value=auto_scan) 

347 self._auto_scan = auto_scan 

348 

349 

350# pylint: disable=too-many-instance-attributes 

351class ResultsAPI(VeracodeXMLAPI): 

352 """ 

353 A class to interact with the Results API 

354 

355 Note: App ID resolution depends on access to the Veracode upload API and 

356 the "getapplist.do" endpoint: 

357 https://help.veracode.com/reader/orRWez4I0tnZNaA_i0zn9g/Z4Ecf1fw7868vYPVgkglww 

358 """ 

359 

360 def __init__(self, *, app_name: str): 

361 # Don't forget to call the init of the parent 

362 super().__init__(app_name=app_name) 

363 

364 ## Use the setter to apply a default to ensure it is valid 

365 self.ignore_compliance_status = False 

366 # version information was pulled from 

367 # https://help.veracode.com/reader/LMv_dtSHyb7iIxAQznC~9w/Mp2BEkLx6rD87k465BWqQg 

368 self.version = constants.RESULTS_API_VERSIONS 

369 

370 @property 

371 def ignore_compliance_status(self): 

372 """ 

373 Specify whether or not to ignore the app compliance status 

374 """ 

375 return self._ignore_compliance_status # pragma: no cover 

376 

377 @ignore_compliance_status.getter 

378 def ignore_compliance_status(self): 

379 """ 

380 Create an ignore_compliance_status getter that validates before returning 

381 """ 

382 # Validate what was already stored 

383 self._validate( 

384 key="ignore_compliance_status", value=self._ignore_compliance_status 

385 ) 

386 return self._ignore_compliance_status 

387 

388 @ignore_compliance_status.setter 

389 def ignore_compliance_status(self, ignore_compliance_status): 

390 """ 

391 Create an ignore_compliance_status setter that validates before setting 

392 """ 

393 # Validate what was provided 

394 self._validate(key="ignore_compliance_status", value=ignore_compliance_status) 

395 self._ignore_compliance_status = ignore_compliance_status 

396 

397 

398class SandboxAPI(VeracodeXMLAPI): 

399 """ 

400 A class to interact with the Sandbox API 

401 

402 Note: App ID resolution depends on access to the Veracode upload API and 

403 the "getapplist.do" endpoint: 

404 https://help.veracode.com/reader/orRWez4I0tnZNaA_i0zn9g/Z4Ecf1fw7868vYPVgkglww 

405 """ 

406 

407 def __init__(self, *, app_name: str, sandbox_name: str): 

408 # Don't forget to call the init of the parent 

409 super().__init__(app_name=app_name) 

410 

411 # version information was pulled from 

412 # https://help.veracode.com/reader/LMv_dtSHyb7iIxAQznC~9w/KusbW5J7EG8jEr64JEiBzw 

413 self.version = constants.SANDBOX_API_VERSIONS 

414 self.build_id = datetime.utcnow().strftime("%F_%H-%M-%S") 

415 self.sandbox_name = sandbox_name 

416 # sandbox_id is not meant to be set manually. Instead, configure using 

417 # the response of a Sandbox API query using the intended sandbox name 

418 self.sandbox_id = None 

419 

420 @property 

421 def build_id(self): 

422 """ 

423 Create the build_id property 

424 """ 

425 return self._build_id # pragma: no cover 

426 

427 @build_id.getter 

428 def build_id(self): 

429 """ 

430 Create a build_id getter that validates before returning 

431 """ 

432 # Validate what was already stored 

433 self._validate(key="build_id", value=self._build_id) 

434 return self._build_id 

435 

436 @build_id.setter 

437 def build_id(self, build_id): 

438 """ 

439 Create a build_id setter that validates before setting 

440 """ 

441 # Validate what was provided 

442 self._validate(key="build_id", value=build_id) 

443 self._build_id = build_id 

444 

445 @property 

446 def sandbox_id(self): 

447 """ 

448 Create the sandbox_id property 

449 """ 

450 return self._sandbox_id # pragma: no cover 

451 

452 @sandbox_id.getter 

453 def sandbox_id(self): 

454 """ 

455 Create a sandbox_id getter that validates before returning 

456 """ 

457 # Validate what was already stored 

458 self._validate(key="sandbox_id", value=self._sandbox_id) 

459 return self._sandbox_id 

460 

461 @sandbox_id.setter 

462 def sandbox_id(self, sandbox_id): 

463 """ 

464 Create a sandbox_id setter that validates before setting 

465 

466 This should only be set using the response of a Sandbox API query using 

467 the intended sandbox name 

468 """ 

469 # Validate what was provided 

470 self._validate(key="sandbox_id", value=sandbox_id) 

471 self._sandbox_id = sandbox_id 

472 

473 @property 

474 def sandbox_name(self): 

475 """ 

476 Create the sandbox_name property 

477 """ 

478 return self._sandbox_name # pragma: no cover 

479 

480 @sandbox_name.getter 

481 def sandbox_name(self): 

482 """ 

483 Create a sandbox_name getter that validates before returning 

484 """ 

485 # Validate what was already stored 

486 self._validate(key="sandbox_name", value=self._sandbox_name) 

487 return self._sandbox_name 

488 

489 @sandbox_name.setter 

490 def sandbox_name(self, sandbox_name): 

491 """ 

492 Create a sandbox_name setter that validates before setting 

493 """ 

494 # Validate what was provided 

495 self._validate(key="sandbox_name", value=sandbox_name) 

496 self._sandbox_name = sandbox_name