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

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

185

186

187

188

189

190

191

192

193

194

195

196

197

198

199

200

201

202

203

204

205

206

207

208

209

210

211

212

213

214

215

216

217

218

219

220

221

222

223

224

225

226

227

228

229

230

231

232

233

234

235

236

237

238

239

240

241

242

243

244

245

246

247

248

#!/usr/bin/env python3 

""" 

Integrate with Veracode's SAST APIs to submit artifacts for scanning and check 

compliance 

""" 

 

# built-ins 

from argparse import ArgumentParser 

import logging 

import os 

import sys 

from pathlib import Path 

 

# custom 

import check_compliance 

import submit_artifacts 

from utils import validate_environment 

 

__maintainer__ = "Seiso" 

__author__ = "Jon Zeolla" 

__copyright__ = "(c) 2019 Seiso, LLC" 

__license__ = "MIT" 

__version__ = "0.1.0" 

 

 

@validate_environment 

def create_parser() -> ArgumentParser: 

"""Parse the arguments""" 

parser = ArgumentParser( 

description="Parse arguments to construct Veracode API environmental dicts" 

) 

parser.add_argument( 

"--app-id", 

type=str, 

help="Application ID as provided by Veracode", 

default=os.environ.get("VERACODE_APP_ID", None), 

) 

parser.add_argument( 

"--build-dir", 

type=lambda p: Path(p).absolute(), 

help="A Path where the build artifacts exist, defaults to /build", 

default=Path("/build").absolute(), 

) 

parser.add_argument( 

"--build-id", 

type=str, 

help="Application build id", 

default=os.environ.get("VERACODE_BUILD_ID", None), 

) 

parser.add_argument( 

"--disable-auto-scan", action="store_true", help="Disable auto_scan" 

) 

parser.add_argument( 

"--disable-scan-nonfatal-modules", 

action="store_true", 

help="Disable scan_all_nonfatal_top_level_modules", 

) 

parser.add_argument( 

"--version", action="version", version=__version__ 

) 

parser.add_argument( 

"--api-key-id", 

type=str, 

default=os.environ.get("VERACODE_API_KEY_ID", None), 

help="Veracode API Key ID", 

) 

parser.add_argument( 

"--api-key-secret", 

type=str, 

default=os.environ.get("VERACODE_API_KEY_SECRET", None), 

help="Veracode API Key Secret", 

) 

 

group = parser.add_mutually_exclusive_group() 

group.add_argument( 

"--debug", 

action="store_const", 

dest="loglevel", 

const=logging.DEBUG, 

default=logging.WARNING, 

help="Enable debug level logging", 

) 

group.add_argument( 

"--verbose", 

action="store_const", 

dest="loglevel", 

const=logging.INFO, 

default=logging.WARNING, 

help="Enable info level logging", 

) 

return parser 

 

 

@validate_environment 

def _build_results_vapi(*, app_id: str, api_key_id: str, api_key_secret: str) -> dict: 

"""Build the results_vapi dict""" 

results_vapi = {} 

results_vapi["api_name"] = "Results" 

results_vapi["base_url"] = "https://analysiscenter.veracode.com/api/" 

# Last updated on 2019-10-22: 

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

results_vapi["version"] = { 

"detailedreport.do": "5.0", 

"detailedreportpdf.do": "4.0", 

"getaccountcustomfieldlist.do": "5.0", 

"getappbuilds.do": "4.0", 

"getcallstacks.do": "5.0", 

"summaryreport.do": "4.0", 

"summaryreportpdf.do": "4.0", 

"thirdpartyreportpdf.do": "4.0", 

} 

results_vapi["app_id"] = app_id 

results_vapi["api_key_id"] = api_key_id 

results_vapi["api_key_secret"] = api_key_secret 

 

return results_vapi 

 

 

@validate_environment 

def _build_upload_vapi( 

*, 

app_id: str, 

build_dir: Path, 

build_id: str, 

auto_scan: bool, 

scan_all_nonfatal_top_level_modules: bool, 

api_key_id: str, 

api_key_secret: str 

) -> dict: 

""" 

Build the upload_vapi dict 

""" 

upload_vapi = {} 

upload_vapi["api_name"] = "Upload" 

upload_vapi["base_url"] = "https://analysiscenter.veracode.com/api/" 

# Last updated on 2019-10-22: 

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

upload_vapi["version"] = { 

"beginprescan.do": "5.0", 

"beginscan.do": "5.0", 

"createapp.do": "5.0", 

"createbuild.do": "5.0", 

"deleteapp.do": "5.0", 

"deletebuild.do": "5.0", 

"getappinfo.do": "5.0", 

"getapplist.do": "5.0", 

"getbuildinfo.do": "5.0", 

"getbuildlist.do": "5.0", 

"getfilelist.do": "5.0", 

"getpolicylist.do": "5.0", 

"getprescanresults.do": "5.0", 

"getvendorlist.do": "5.0", 

"removefile.do": "5.0", 

"updateapp.do": "5.0", 

"updatebuild.do": "5.0", 

"uploadfile.do": "5.0", 

"uploadlargefile.do": "5.0", 

} 

upload_vapi["app_id"] = app_id 

upload_vapi["build_dir"] = build_dir 

upload_vapi["build_id"] = build_id 

upload_vapi[ 

"scan_all_nonfatal_top_level_modules" 

] = scan_all_nonfatal_top_level_modules 

upload_vapi["auto_scan"] = auto_scan 

upload_vapi["api_key_id"] = api_key_id 

upload_vapi["api_key_secret"] = api_key_secret 

 

return upload_vapi 

 

 

@validate_environment 

def main() -> None: 

""" 

CI/CD integration with Veracode for SAST 

""" 

# Parse the provided arguments 

parser = create_parser() 

args = parser.parse_args() 

 

# Extract variables from the provided arguments 

app_id = args.app_id 

build_dir = args.build_dir 

build_id = args.build_id 

auto_scan = not args.disable_auto_scan 

scan_all_nonfatal_top_level_modules = not args.disable_scan_nonfatal_modules 

loglevel = args.loglevel 

api_key_id = args.api_key_id 

api_key_secret = args.api_key_secret 

 

# Setup the root logger 

logging.getLogger() 

formatting = "%(asctime)s - %(name)s - %(levelname)s - %(message)s" 

logging.basicConfig(level=loglevel, format=formatting) 

logging.raiseExceptions = True 

log = logging.getLogger(__name__) 

 

# Ensure that the required information was somehow set 

if not args.app_id: 

log.error( 

"An application ID must be provided via the VERACODE_APP_ID environment variable or --app-id command line argument" 

) 

sys.exit(1) 

if not args.build_id: 

log.error( 

"A build ID must be provided via the VERACODE_BUILD_ID environment variable or --build-id command line argument" 

) 

sys.exit(1) 

if not args.api_key_id: 

log.error( 

"An API key ID must be provided via the VERACODE_API_KEY_ID environment variable or --api-key-id command line argument" 

) 

sys.exit(1) 

if not args.api_key_secret: 

log.error( 

"An API key secret must be provided via the VERACODE_API_KEY_SECRET environment variable or --api-key-secret command line argument" 

) 

sys.exit(1) 

 

# Build the environmental dicts 

results_vapi = _build_results_vapi( 

app_id=app_id, api_key_id=api_key_id, api_key_secret=api_key_secret 

) 

upload_vapi = _build_upload_vapi( 

app_id=app_id, 

build_dir=build_dir, 

build_id=build_id, 

auto_scan=auto_scan, 

scan_all_nonfatal_top_level_modules=scan_all_nonfatal_top_level_modules, 

api_key_id=api_key_id, 

api_key_secret=api_key_secret, 

) 

 

if submit_artifacts.submit_artifacts(upload_vapi=upload_vapi): 

log.debug("Successfully submit build artifacts for scanning") 

else: 

log.error("Failed to submit build artifacts for scanning") 

sys.exit(1) 

 

if check_compliance.check_compliance(results_vapi=results_vapi): 

log.debug("Successfully validated that the latest build was in compliance") 

else: 

log.error("Unable to determine that the latest build was in compliance") 

sys.exit(1) 

 

 

if __name__ == "__main__": 

main()