blob: b79ab85138bfc78b1d8f06c67efa2666699190db [file] [log] [blame]
Ivan Udovichenko894fd8a2020-04-13 17:24:50 +03001#!groovy
2
Ivan Udovichenko314a0732020-04-13 22:47:26 +03003package com.mirantis.mk
4
Ivan Udovichenko894fd8a2020-04-13 17:24:50 +03005import groovy.json.JsonSlurper
Ivan Udovichenko6c337562020-08-06 16:22:26 +03006import groovy.json.JsonOutput
Ivan Udovichenko894fd8a2020-04-13 17:24:50 +03007
Ivan Udovichenko9110aed2021-10-14 19:12:39 +03008def callREST(String uri, String auth,
Ivan Udovichenko45252252020-04-14 22:45:53 +03009 String method = 'GET', String message = null) {
10 String authEnc = auth.bytes.encodeBase64()
11 def req = new URL(uri).openConnection()
12 req.setRequestMethod(method)
13 req.setRequestProperty('Content-Type', 'application/json')
14 req.setRequestProperty('Authorization', "Basic ${authEnc}")
15 if (message) {
16 req.setDoOutput(true)
17 req.getOutputStream().write(message.getBytes('UTF-8'))
18 }
19 Integer responseCode = req.getResponseCode()
20 String responseText = ''
21 if (responseCode == 200 || responseCode == 201) {
22 responseText = req.getInputStream().getText()
23 }
24 req = null
25 return [ 'responseCode': responseCode, 'responseText': responseText ]
Ivan Udovichenko894fd8a2020-04-13 17:24:50 +030026}
27
Ivan Udovichenko9110aed2021-10-14 19:12:39 +030028def getTeam(String image = '') {
Ivan Udovichenko894fd8a2020-04-13 17:24:50 +030029 def team_assignee = ''
30 switch(image) {
Ivan Udovichenko4fbf5792021-10-13 13:50:06 +030031 case ~/^openstack\/extra\/xrally-openstack\/.*$/:
32 team_assignee = 'Scale'
33 break
Ivan Udovichenko894fd8a2020-04-13 17:24:50 +030034 case ~/^(tungsten|tungsten-operator)\/.*$/:
35 team_assignee = 'OpenContrail'
36 break
Ivan Udovichenko6f47e7d2021-10-11 23:49:48 +030037 case ~/^(openstack|general\/mariadb|general\/general\/rabbitmq|general\/general\/rabbitmq-management)\/.*$/:
Ivan Udovichenko894fd8a2020-04-13 17:24:50 +030038 team_assignee = 'OpenStack hardening'
39 break
40 case ~/^stacklight\/.*$/:
41 team_assignee = 'Stacklight LMA'
42 break
43 case ~/^ceph\/.*$/:
44 team_assignee = 'Storage'
45 break
Ivan Udovichenko6f47e7d2021-10-11 23:49:48 +030046 case ~/^(core|iam|lcm|general\/external\/docker.io\/library\/nginx)\/.*$/:
Ivan Udovichenko894fd8a2020-04-13 17:24:50 +030047 team_assignee = 'KaaS'
48 break
Ivan Udovichenko6f47e7d2021-10-11 23:49:48 +030049 case ~/^(bm|general)\/.*$/:
50 team_assignee = 'BM/OS (KaaS BM)'
51 break
Ivan Udovichenko894fd8a2020-04-13 17:24:50 +030052 default:
53 team_assignee = 'Release Engineering'
54 break
55 }
56
57 return team_assignee
58}
59
Ivan Udovichenko9110aed2021-10-14 19:12:39 +030060def updateDictionary(String jira_issue_key, Map dict, String uri, String auth, String jira_user_id) {
Ivan Udovichenko894fd8a2020-04-13 17:24:50 +030061 def response = callREST("${uri}/${jira_issue_key}", auth)
62 if ( response['responseCode'] == 200 ) {
63 def issueJSON = new JsonSlurper().parseText(response["responseText"])
64 if (issueJSON.containsKey('fields')) {
65 if (!dict.containsKey(jira_issue_key)) {
66 dict[jira_issue_key] = [
67 summary : '',
68 description: '',
69 comments: []
70 ]
71 }
72 if (issueJSON['fields'].containsKey('summary')){
73 dict[jira_issue_key].summary = issueJSON['fields']['summary']
74 }
75 if (issueJSON['fields'].containsKey('description')) {
76 dict[jira_issue_key].description = issueJSON['fields']['description']
77 }
78 if (issueJSON['fields'].containsKey('comment') && issueJSON['fields']['comment']['comments']) {
79 issueJSON['fields']['comment']['comments'].each {
80 if (it.containsKey('author') && it['author'].containsKey('accountId') && it['author']['accountId'] == jira_user_id) {
81 dict[jira_issue_key]['comments'].add(it['body'])
82 }
83 }
84 }
85 }
86 }
87 return dict
88}
89
90def cacheLookUp(Map dict, String image_short_name, String image_full_name = '', String cve_id = '' ) {
91 def found_key = ['','']
92 if (!found_key[0] && dict && image_short_name) {
93 dict.each { issue_key_name ->
94 if (!found_key[0]) {
Ivan Udovichenkodd63d662021-09-23 19:35:38 +030095 def s
96 if (image_short_name =~ /^mirantis(eng)?\//) {
97 def tmp_image_short_name = image_short_name.replaceAll(/^mirantis(eng)?\//, '')
98 s = dict[issue_key_name.key]['summary'] =~ /^\[mirantis(eng)?\/${tmp_image_short_name}(?=\])/
99 } else {
100 s = dict[issue_key_name.key]['summary'] =~ /(?<=[\/\[])${image_short_name}(?=\])/
101 }
Ivan Udovichenko894fd8a2020-04-13 17:24:50 +0300102 if (s) {
103 if (image_full_name) {
104 def d = dict[issue_key_name.key]['description'] =~ /(?m)\b${image_full_name}\b/
Ivan Udovichenko894fd8a2020-04-13 17:24:50 +0300105 if (d) {
106 found_key = [issue_key_name.key,'']
107 } else {
108 if (dict[issue_key_name.key]['comments']) {
109 def comment_match = false
110 dict[issue_key_name.key]['comments'].each{ comment ->
111 if (!comment_match) {
112 def c = comment =~ /(?m)\b${image_full_name}\b/
113 if (c) {
114 comment_match = true
115 }
116 }
117 }
118 if (!comment_match) {
119 found_key = [issue_key_name.key,'na']
120 } else {
121 found_key = [issue_key_name.key,'']
122 }
123 } else {
124 found_key = [issue_key_name.key,'na']
125 }
126 }
127 }
128 }
129 }
130 }
131 }
132 return found_key
133}
134
Ivan Udovichenko67398552020-12-25 20:13:35 +0300135def getLatestAffectedVersion(cred, productName, defaultJiraAffectedVersion = 'Backlog') {
136 def filterName = ''
137 if (productName == 'mosk') {
138 filterName = 'MOSK'
139 } else if (productName == 'kaas') {
140 filterName = 'KaaS'
141 } else {
142 return defaultJiraAffectedVersion
143 }
144
Ivan Udovichenko4c08b8d2021-01-20 22:15:49 +0000145 def search_api_url = "${cred.description}/rest/api/2/issue/createmeta?projectKeys=PRODX&issuetypeNames=Bug&expand=projects.issuetypes.fields"
Ivan Udovichenko67398552020-12-25 20:13:35 +0300146 def response = callREST("${search_api_url}", "${cred.username}:${cred.password}", 'GET')
147 def InputJSON = new JsonSlurper().parseText(response["responseText"])
148 def AffectedVersions = InputJSON['projects'][0]['issuetypes'][0]['fields']['versions']['allowedValues']
149
150 def versions = []
151 AffectedVersions.each{
Ivan Udovichenko14e87f62021-06-01 17:20:39 +0300152 // 'MOSK' doesn not contain 'released' field
153 if (productName != 'mosk' && it.containsKey('released') && it['released']) {
154 return
155 }
156 if (it.containsKey('name') && it['name'].startsWith(filterName)) {
157 def justVersion = it['name'].replaceAll(/.*_/, '')
158 justVersion = justVersion.replaceAll(/([0-9]+\.)([0-9])$/, '$10$2')
159 versions.add("${justVersion}`${it['name']}")
Ivan Udovichenko67398552020-12-25 20:13:35 +0300160 }
161 }
162 if (versions) {
Ivan Udovichenko14e87f62021-06-01 17:20:39 +0300163 return versions.sort()[0].split('`')[-1]
Ivan Udovichenko67398552020-12-25 20:13:35 +0300164 }
165 return defaultJiraAffectedVersion
166}
167
Ivan Udovichenkodd63d662021-09-23 19:35:38 +0300168def getNvdInfo(nvdApiUrl, cve, requestDelay = 1, requestRetryNum = 5, sleepTimeOnBan = 60) {
Ivan Udovichenko31631232021-09-22 13:54:02 +0300169 def cveArr = []
Ivan Udovichenkodd63d662021-09-23 19:35:38 +0300170 sleep requestDelay
171 def response = callREST("${nvdApiUrl}/${cve}", '')
172 for (i = 0; i < requestRetryNum; i++) {
173 if (response['responseCode'] == 429) {
174 sleep sleepTimeOnBan
175 response = callREST("${nvdApiUrl}/${cve}", '')
176 } else {
Ivan Udovichenko46439352021-09-30 22:21:32 +0300177 break
Ivan Udovichenkodd63d662021-09-23 19:35:38 +0300178 }
179 }
Ivan Udovichenko31631232021-09-22 13:54:02 +0300180 if (response['responseCode'] == 200) {
181 def InputJSON = new JsonSlurper().parseText(response["responseText"])
Ivan Udovichenko681f35f2021-10-06 12:40:56 +0300182 if (InputJSON && InputJSON.containsKey('impact')) {
Ivan Udovichenko31631232021-09-22 13:54:02 +0300183 def cveImpact = InputJSON['impact']
184 ['V3','V2'].each {
185 if (cveImpact.containsKey('baseMetric' + it)) {
186 if (cveImpact['baseMetric' + it].containsKey('cvss' + it)) {
187 if (cveImpact['baseMetric' + it]['cvss' + it].containsKey('baseScore')) {
188 def cveBaseSeverity = ''
189 if (cveImpact['baseMetric' + it]['cvss' + it].containsKey('baseSeverity')) {
190 cveBaseSeverity = cveImpact['baseMetric'+it]['cvss'+it]['baseSeverity']
191 }
192 cveArr.add([it, cveImpact['baseMetric'+it]['cvss'+it]['baseScore'],cveBaseSeverity])
193 }
Ivan Udovichenko16568a62021-09-16 12:50:59 +0300194
Ivan Udovichenko31631232021-09-22 13:54:02 +0300195 }
196 }
197 }
198 }
199 }
200 return cveArr
201}
202
Ivan Udovichenko9110aed2021-10-14 19:12:39 +0300203def nvdCacheLookUp(Map dict, String cveId) {
204 if (dict.containsKey(cveId)) {
205 return dict[cveId]
206 }
207 return false
208}
209
210def nvdUpdateDictionary(Map dict, String cveId, List cveArr) {
211 if (!dict.containsKey(cveId)) {
212 dict[cveId] = cveArr
213 }
214 return dict
215}
216
Ivan Udovichenko11e006a2021-10-21 00:23:43 +0300217def logInfo(String infoText, String infoLogFile) {
218 if (infoLogFile) {
219 sh """#!/bin/bash -e
220 mkdir -p `dirname $infoLogFile`
221 echo "[`date +'%Y-%m-%d %H:%M:%S'`] ${errorText}" >> $infoLogFile
222 """
223 }
224}
Ivan Udovichenko31631232021-09-22 13:54:02 +0300225
Ivan Udovichenko11e006a2021-10-21 00:23:43 +0300226def reportJiraTickets(String reportFileContents, String jiraCredentialsID, String jiraUserID, String productName = '', String ignoreImageListFileContents = '[]', Integer retryTry = 0, String nvdApiUrl = '', String reportsDirLoc = '', jiraNamespace = 'PRODX', nvdNistGovCveUrl = 'https://nvd.nist.gov/vuln/detail/') {
Ivan Udovichenko894fd8a2020-04-13 17:24:50 +0300227
228 def dict = [:]
Ivan Udovichenko9110aed2021-10-14 19:12:39 +0300229 def nvdDict = [:]
Ivan Udovichenko894fd8a2020-04-13 17:24:50 +0300230
Ivan Udovichenko6c870b72020-04-14 11:31:51 +0300231 def common = new com.mirantis.mk.Common()
Ivan Udovichenko894fd8a2020-04-13 17:24:50 +0300232 def cred = common.getCredentialsById(jiraCredentialsID)
233 def auth = "${cred.username}:${cred.password}"
234 def uri = "${cred.description}/rest/api/2/issue"
235
236 def search_api_url = "${cred.description}/rest/api/2/search"
237
Ivan Udovichenko11e006a2021-10-21 00:23:43 +0300238 def jiraLog = ''
239 if (reportsDirLoc) {
240 jiraLog = "${reportsDirLoc}/jira.log"
241 }
Ivan Udovichenko16568a62021-09-16 12:50:59 +0300242
243 def jqlStartAt = 0
244 def jqlStep = 100
245 def jqlProcessedItems = 0
246 def jqlUnfinishedProcess = true
247 def jqlTotalItems = 0
248 while (jqlUnfinishedProcess) {
249 def search_json = """
Ivan Udovichenko894fd8a2020-04-13 17:24:50 +0300250{
Ivan Udovichenkodd63d662021-09-23 19:35:38 +0300251 "jql": "reporter = ${jiraUserID} and (labels = cve and labels = security) and (status = 'To Do' or status = 'For Triage' or status = Open or status = 'In Progress' or status = New or status = 'Input Required')", "maxResults":-1, "startAt": ${jqlStartAt}
Ivan Udovichenko894fd8a2020-04-13 17:24:50 +0300252}
253"""
254
Ivan Udovichenko16568a62021-09-16 12:50:59 +0300255 def response = callREST("${search_api_url}", auth, 'POST', search_json)
256 def InputJSON = new JsonSlurper().parseText(response["responseText"])
257 if (InputJSON.containsKey('maxResults')){
258 if (jqlStep > InputJSON['maxResults']) {
259 jqlStep = InputJSON['maxResults']
260 }
261 }
Ivan Udovichenko894fd8a2020-04-13 17:24:50 +0300262
Ivan Udovichenko16568a62021-09-16 12:50:59 +0300263 jqlStartAt = jqlStartAt + jqlStep
Ivan Udovichenko894fd8a2020-04-13 17:24:50 +0300264
Ivan Udovichenko16568a62021-09-16 12:50:59 +0300265 if (InputJSON.containsKey('total')){
266 jqlTotalItems = InputJSON['total']
267 }
Ivan Udovichenko894fd8a2020-04-13 17:24:50 +0300268
Ivan Udovichenko77fd79e2021-09-20 13:15:28 +0300269 if (InputJSON.containsKey('issues')){
Ivan Udovichenko16568a62021-09-16 12:50:59 +0300270 if (!InputJSON['issues'] && retryTry != 0) {
271 throw new Exception('"issues" list is empty')
272 }
273 } else {
274 throw new Exception('Returned JSON from jql does not contain "issues" section')
275 }
Ivan Udovichenko11e006a2021-10-21 00:23:43 +0300276// print 'Temporal debug information:'
277// InputJSON['issues'].each {
278// print it['key'] + ' -> ' + it['fields']['summary']
279// }
Ivan Udovichenko16568a62021-09-16 12:50:59 +0300280
281 InputJSON['issues'].each {
282 dict[it['key']] = [
283 summary : '',
284 description: '',
285 comments: []
286 ]
287 }
288
289 InputJSON['issues'].each { jira_issue ->
290 dict = updateDictionary(jira_issue['key'], dict, uri, auth, jiraUserID)
291 jqlProcessedItems = jqlProcessedItems + 1
292 }
293 if (jqlProcessedItems >= jqlTotalItems) {
294 jqlUnfinishedProcess = false
295 }
Ivan Udovichenko894fd8a2020-04-13 17:24:50 +0300296 }
297
Ivan Udovichenko6c870b72020-04-14 11:31:51 +0300298 def reportJSON = new JsonSlurper().parseText(reportFileContents)
Ivan Udovichenko894fd8a2020-04-13 17:24:50 +0300299 def imageDict = [:]
Ivan Udovichenko894fd8a2020-04-13 17:24:50 +0300300 reportJSON.each{
301 image ->
302 if ("${image.value}".contains('issues')) { return }
303 image.value.each{
304 pkg ->
Ivan Udovichenko894fd8a2020-04-13 17:24:50 +0300305 pkg.value.each{
306 cve ->
307 if (cve[2] && (cve[1].contains('High') || cve[1].contains('Critical'))) {
Ivan Udovichenkoc774c6e2020-04-15 01:55:41 +0300308 if (!imageDict.containsKey(image.key)) {
Ivan Udovichenko894fd8a2020-04-13 17:24:50 +0300309 imageDict.put(image.key, [:])
310 }
311 if (!imageDict[image.key].containsKey(pkg.key)) {
312 imageDict[image.key].put(pkg.key, [])
313 }
Ivan Udovichenko5c60cde2021-08-12 23:52:58 +0300314 imageDict[image.key][pkg.key].add("[${cve[0]}|${cve[4]}] (${cve[2]}) (${cve[3]}) | ${cve[5]}")
Ivan Udovichenko894fd8a2020-04-13 17:24:50 +0300315 }
316 }
Ivan Udovichenko894fd8a2020-04-13 17:24:50 +0300317 }
318 }
319
Ivan Udovichenko5e4ae9c2020-12-26 10:56:48 +0300320 def affectedVersion = ''
321 if (jiraNamespace == 'PRODX') {
322 affectedVersion = getLatestAffectedVersion(cred, productName)
323 }
324
Ivan Udovichenko83b7ffc2021-05-07 12:50:16 +0300325 def ignoreImageList = new JsonSlurper().parseText(ignoreImageListFileContents)
326
Ivan Udovichenko894fd8a2020-04-13 17:24:50 +0300327 def jira_summary = ''
328 def jira_description = ''
Ivan Udovichenko31631232021-09-22 13:54:02 +0300329 def jira_description_nvd_scoring = []
Ivan Udovichenko894fd8a2020-04-13 17:24:50 +0300330 imageDict.each{
331 image ->
332 def image_key = image.key.replaceAll(/(^[a-z0-9-.]+.mirantis.(net|com)\/|:.*$)/, '')
Ivan Udovichenko83b7ffc2021-05-07 12:50:16 +0300333
334 // Ignore images listed
335 if ((image.key in ignoreImageList) || (image.key.replaceAll(/:.*$/, '') in ignoreImageList)) {
336 print "\n\nIgnoring ${image.key} as it has been found in Docker image ignore list\n"
Ivan Udovichenko11e006a2021-10-21 00:23:43 +0300337 logInfo("Ignoring ${image.key} as it has been found in Docker image ignore list", jiraLog)
Ivan Udovichenko83b7ffc2021-05-07 12:50:16 +0300338 return
339 }
340
Ivan Udovichenko6c337562020-08-06 16:22:26 +0300341 // Below change was produced due to other workflow for UCP Docker images (RE-274)
Ivan Udovichenko9721c312020-10-01 23:50:38 +0300342 if (image_key.startsWith('lcm/docker/ucp')) {
343 return
Ivan Udovichenko6bc5e182020-10-30 02:57:56 +0300344 } else if (image_key.startsWith('mirantis/ucp') || image_key.startsWith('mirantiseng/ucp')) {
Ivan Udovichenko31631232021-09-22 13:54:02 +0300345 jiraNamespace = 'MKE'
Ivan Udovichenkoe0ea4942021-02-18 17:50:20 +0300346 } else if (image_key.startsWith('mirantis/dtr') || image_key.startsWith('mirantiseng/dtr')) {
347 jiraNamespace = 'ENGDTR'
Ivan Udovichenkofe3f11e2020-09-29 17:31:38 +0300348 } else {
349 jiraNamespace = 'PRODX'
350 }
Ivan Udovichenko894fd8a2020-04-13 17:24:50 +0300351 jira_summary = "[${image_key}] Found CVEs in Docker image"
Ivan Udovichenko62563612020-10-31 03:46:23 +0300352 jira_description = "${image.key}\n"
Ivan Udovichenko31631232021-09-22 13:54:02 +0300353 def filter_mke_severity = false
Ivan Udovichenko894fd8a2020-04-13 17:24:50 +0300354 image.value.each{
355 pkg ->
Ivan Udovichenko62563612020-10-31 03:46:23 +0300356 jira_description += "__* ${pkg.key}\n"
Ivan Udovichenko894fd8a2020-04-13 17:24:50 +0300357 pkg.value.each{
358 cve ->
Ivan Udovichenko62563612020-10-31 03:46:23 +0300359 jira_description += "________${cve}\n"
Ivan Udovichenkodd63d662021-09-23 19:35:38 +0300360 if (nvdApiUrl) {
361 def cveId = cve.replaceAll(/(^\[|\|.*$)/, '')
362 if (cveId.startsWith('CVE-')) {
Ivan Udovichenko9110aed2021-10-14 19:12:39 +0300363 jira_description_nvd_scoring = nvdCacheLookUp(nvdDict, cveId)
364 if (!jira_description_nvd_scoring) {
365 jira_description_nvd_scoring = getNvdInfo(nvdApiUrl, cveId)
366 if (jira_description_nvd_scoring) {
367 nvdDict = nvdUpdateDictionary(nvdDict, cveId, jira_description_nvd_scoring)
368 }
369 }
Ivan Udovichenkodd63d662021-09-23 19:35:38 +0300370 jira_description_nvd_scoring.each {
371 jira_description += 'CVSS ' + it.join(' ') + '\n'
372 // According to Vikram there will be no fixes for
373 // CVEs with CVSS base score below 7
374 if (jiraNamespace == 'MKE' && it[0] == 'V3' && it[1].toInteger() >= 7) {
375 filter_mke_severity = true
376 }
Ivan Udovichenko31631232021-09-22 13:54:02 +0300377 }
Ivan Udovichenkob3fc9f72021-09-23 21:41:43 +0300378 if (filter_mke_severity) {
379 jira_description += nvdNistGovCveUrl + cveId + '\n'
380 }
Ivan Udovichenko46439352021-09-30 22:21:32 +0300381 } else {
382 print "No info about ${cveId} item from NVD API server"
Ivan Udovichenko31631232021-09-22 13:54:02 +0300383 }
384 } else {
Ivan Udovichenkodd63d662021-09-23 19:35:38 +0300385 print 'nvdApiUrl var is not specified.'
Ivan Udovichenko31631232021-09-22 13:54:02 +0300386 }
Ivan Udovichenko894fd8a2020-04-13 17:24:50 +0300387 }
388 }
Ivan Udovichenko894fd8a2020-04-13 17:24:50 +0300389
Ivan Udovichenko31631232021-09-22 13:54:02 +0300390 if (filter_mke_severity) {
391 print "\n\nIgnoring ${image.key} as it does not have CVEs with CVSS base score >7\n"
Ivan Udovichenko11e006a2021-10-21 00:23:43 +0300392 logInfo("Ignoring ${image.key} as it does not have CVEs with CVSS base score >7", jiraLog)
Ivan Udovichenko31631232021-09-22 13:54:02 +0300393 return
394 }
395
Ivan Udovichenko894fd8a2020-04-13 17:24:50 +0300396 def team_assignee = getTeam(image_key)
397
Ivan Udovichenkoadee8b52020-08-06 17:07:28 +0300398 def basicIssueJSON = new JsonSlurper().parseText('{"fields": {}}')
Ivan Udovichenko6c337562020-08-06 16:22:26 +0300399
Ivan Udovichenkoadee8b52020-08-06 17:07:28 +0300400 basicIssueJSON['fields'] = [
Ivan Udovichenkofe3f11e2020-09-29 17:31:38 +0300401 project:[
402 key:"${jiraNamespace}"
403 ],
Ivan Udovichenko6c337562020-08-06 16:22:26 +0300404 summary:"${jira_summary}",
405 description:"${jira_description}",
406 issuetype:[
Ivan Udovichenkofe3f11e2020-09-29 17:31:38 +0300407 name:'Bug'
Ivan Udovichenko6c337562020-08-06 16:22:26 +0300408 ],
409 labels:[
410 'security',
411 'cve'
412 ]
413 ]
414 if (jiraNamespace == 'PRODX') {
Ivan Udovichenkoadee8b52020-08-06 17:07:28 +0300415 basicIssueJSON['fields']['customfield_19000'] = [value:"${team_assignee}"]
Ivan Udovichenko67398552020-12-25 20:13:35 +0300416 basicIssueJSON['fields']['versions'] = [["name": affectedVersion]]
Ivan Udovichenko49955b22021-08-19 23:22:47 +0300417 if (image_key.startsWith('lcm/')) {
418 basicIssueJSON['fields']['components'] = [["name": 'KaaS: LCM']]
419 }
Ivan Udovichenko894fd8a2020-04-13 17:24:50 +0300420 }
Ivan Udovichenko31631232021-09-22 13:54:02 +0300421
422 if (jiraNamespace == 'MKE') {
423 // Assign issues by default to Vikram bir Singh, as it was asked by him
424 basicIssueJSON['fields']['assignee'] = ['accountId': '5ddd4d67b95b180d17cecc67']
425 }
426
Ivan Udovichenkoadee8b52020-08-06 17:07:28 +0300427 def post_issue_json = JsonOutput.toJson(basicIssueJSON)
Ivan Udovichenko62563612020-10-31 03:46:23 +0300428 def jira_comment = jira_description.replaceAll(/\n/, '\\\\n')
Ivan Udovichenko894fd8a2020-04-13 17:24:50 +0300429 def post_comment_json = """
430{
Ivan Udovichenko62563612020-10-31 03:46:23 +0300431 "body": "${jira_comment}"
Ivan Udovichenko894fd8a2020-04-13 17:24:50 +0300432}
433"""
434 def jira_key = cacheLookUp(dict, image_key, image.key)
435 if (jira_key[0] && jira_key[1] == 'na') {
436 def post_comment_response = callREST("${uri}/${jira_key[0]}/comment", auth, 'POST', post_comment_json)
437 if ( post_comment_response['responseCode'] == 201 ) {
438 def issueCommentJSON = new JsonSlurper().parseText(post_comment_response["responseText"])
Ivan Udovichenko67398552020-12-25 20:13:35 +0300439 print "\n\nComment was posted to ${jira_key[0]} ${affectedVersion} for ${image_key} and ${image.key}"
Ivan Udovichenko11e006a2021-10-21 00:23:43 +0300440 logInfo("Comment was posted to ${jira_key[0]} ${affectedVersion} for ${image_key} and ${image.key}", jiraLog)
Ivan Udovichenko894fd8a2020-04-13 17:24:50 +0300441 } else {
442 print "\nComment to ${jira_key[0]} Jira issue was not posted"
Ivan Udovichenko11e006a2021-10-21 00:23:43 +0300443 logInfo("Comment to ${jira_key[0]} Jira issue was not posted", jiraLog)
Ivan Udovichenko894fd8a2020-04-13 17:24:50 +0300444 }
445 } else if (!jira_key[0]) {
446 def post_issue_response = callREST("${uri}/", auth, 'POST', post_issue_json)
447 if (post_issue_response['responseCode'] == 201) {
448 def issueJSON = new JsonSlurper().parseText(post_issue_response["responseText"])
449 dict = updateDictionary(issueJSON['key'], dict, uri, auth, jiraUserID)
Ivan Udovichenko67398552020-12-25 20:13:35 +0300450 print "\n\nJira issue was created ${issueJSON['key']} ${affectedVersion} for ${image_key} and ${image.key}"
Ivan Udovichenko11e006a2021-10-21 00:23:43 +0300451 logInfo("Ignoring ${image.key} as it has been found in Docker image ignore list", jiraLog)
Ivan Udovichenko894fd8a2020-04-13 17:24:50 +0300452 } else {
453 print "\n${image.key} CVE issues were not published\n"
Ivan Udovichenko11e006a2021-10-21 00:23:43 +0300454 logInfo("Ignoring ${image.key} as it has been found in Docker image ignore list", jiraLog)
Ivan Udovichenko894fd8a2020-04-13 17:24:50 +0300455 }
456 } else {
Ivan Udovichenko99467752020-04-21 02:28:06 +0300457 print "\n\nNothing to process for ${image_key} and ${image.key}"
Ivan Udovichenko11e006a2021-10-21 00:23:43 +0300458 logInfo("Nothing to process for ${image_key} and ${image.key}", jiraLog)
Ivan Udovichenko894fd8a2020-04-13 17:24:50 +0300459 }
Ivan Udovichenko894fd8a2020-04-13 17:24:50 +0300460 }
Ivan Udovichenko314a0732020-04-13 22:47:26 +0300461}
Ivan Udovichenko45252252020-04-14 22:45:53 +0300462
463def find_cves_by_severity(String reportJsonContent, String Severity) {
464 def cves = []
465 def reportJSON = new JsonSlurper().parseText(reportJsonContent)
466 reportJSON.each{
467 image ->
468 image.value.each{
469 pkg ->
470 pkg.value.each{
471 cve ->
472 if (cve[2]) {
473 if (cve[1].contains(Severity)) {
474 cves.add("${pkg.key} ${cve[0]} (${cve[2]})")
475 }
476 }
477 }
478 }
479 }
480 return cves
481}