forked from snyk-tech-services/jira-tickets-for-new-vulns
-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathsnyk_utils.go
222 lines (187 loc) · 9.09 KB
/
snyk_utils.go
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
package main
import (
"bytes"
"errors"
"fmt"
"io/ioutil"
"net/http"
"strings"
"time"
"github.com/michael-go/go-jsn/jsn"
)
func makeSnykAPIRequest(verb string, endpointURL string, snykToken string, body []byte, customDebug debug) ([]byte, error) {
bodyBuffer := bytes.NewBuffer(nil)
if verb == "POST" && body != nil {
bodyBuffer = bytes.NewBuffer(body)
}
request, err := http.NewRequest(verb, endpointURL, bodyBuffer)
if err != nil {
customDebug.Debugf("*** ERROR *** could not create requests to '%s' failed with error %s\n", endpointURL, err.Error())
return nil, err
}
request.Header.Add("Content-Type", "application/json")
request.Header.Add("Authorization", "token "+snykToken)
request.Header.Set("User-Agent", "tech-services/snyk-jira-tickets-for-new-vulns")
client := &http.Client{}
response, err := client.Do(request)
if err != nil {
customDebug.Debugf("*** ERROR *** Request on endpoint '%s' failed with error %s\n", endpointURL, err.Error())
}
customDebug.Debugf("*** INFO *** Sending %s request to %s", verb, endpointURL)
if body != nil {
customDebug.Debug("*** INFO *** Body : ", string(body))
}
var responseData []byte
if response != nil {
var er error
responseData, er = ioutil.ReadAll(response.Body)
if er != nil {
customDebug.Debugf("*** ERROR *** could not read response from request to endpoint %s with error %s\n", endpointURL, err.Error())
}
}
if err != nil || response == nil || response.StatusCode >= 300 {
count := 0
for {
customDebug.Debugf("*** INFO *** Sending %s request to %s", verb, endpointURL)
customDebug.Debugf("*** INFO *** retry number %d\n", count)
response, err = client.Do(request)
if err != nil {
customDebug.Debugf("*** ERROR *** Request on endpoint '%s' failed with error %s, Retrying\n", endpointURL, err.Error())
}
// requests fails but we want to retry
if response != nil {
if response.StatusCode < 500 {
if response.Body != nil {
responseData, err = ioutil.ReadAll(response.Body)
if err != nil {
customDebug.Debugf("*** ERROR *** could not read response from request to endpoint %s with error %s\n", endpointURL, err.Error())
}
}
break
}
if response.Body != nil {
responseData, err = ioutil.ReadAll(response.Body)
if err != nil {
customDebug.Debugf("*** ERROR *** could not read response from request to endpoint %s with error %s\n", endpointURL, err.Error())
}
}
}
// Allow 2 retries with other error type then fail properly
if count >= 2 {
customDebug.Debugf("*** ERROR *** Request on endpoint '%s' failed too many times\n", endpointURL)
customDebug.Debugf("*** ERROR *** Ticket for this issue cannot be created. Skipping\n")
errorMessage := fmt.Sprintf("*** ERROR *** Request on endpoint %s failed too many times with 50x error\n *** ERROR *** Ticket for this issue cannot be created. Skipping\n", endpointURL)
// writing into the file
writeErrorFile("makeSnykAPIRequest", errorMessage, customDebug)
return nil, errors.New("Failed too many times with 50x errors") // skipping this
}
count = count + 1
time.Sleep(1)
}
}
if response.StatusCode == 404 {
customDebug.Debugf("*** INFO *** Request on endpoint '%s' failed with error %s\n", endpointURL, response.Status)
errorMessage := fmt.Sprintf("*** INFO *** Request on endpoint '%s' failed with error %s\n", endpointURL, response.Status)
writeErrorFile("makeSnykAPIRequest", errorMessage, customDebug)
return nil, errors.New("Not found, Request failed")
} else if response.StatusCode == 422 {
customDebug.Debugf("*** INFO *** Request on endpoint '%s' failed with error %s\n", endpointURL, response.Status)
customDebug.Debugf("*** INFO *** Please check that all expected fields are present in the config file\n")
customDebug.Debugf("*** INFO *** Details : %s\n", string(responseData))
errorMessage := fmt.Sprintf("*** INFO *** Request on endpoint '%s' failed with error %s\n", endpointURL, response.Status)
writeErrorFile("makeSnykAPIRequest", errorMessage, customDebug)
return nil, errors.New("Unprocessable Entity, Request failed")
} else if response.StatusCode > 400 {
customDebug.Debugf("*** INFO *** Request on endpoint '%s' failed with error %s\n", endpointURL, response.Status)
customDebug.Debugf("*** INFO *** Please check that all expected fields are present in the config file\n")
customDebug.Debugf("*** INFO *** Details : %s\n", string(responseData))
errorMessage := fmt.Sprintf("*** INFO *** Request on endpoint '%s' failed with error %s\n", endpointURL, response.Status)
writeErrorFile("makeSnykAPIRequest", errorMessage, customDebug)
return nil, errors.New("Request failed")
}
if err != nil {
if strings.Contains(strings.ToLower(string(responseData)), "error") {
customDebug.Debug(err)
errorMessage := fmt.Sprintf("*** INFO *** Retrying without the priority field\n")
writeErrorFile("makeSnykAPIRequest", errorMessage, customDebug)
customDebug.Debug("*** INFO *** Retrying without the priority field")
}
return nil, errors.New("Request failed")
}
time.Sleep(1)
return responseData, err
}
// This does not have general testing or capabilities at present.
// So far, is being tested only with GET https://api.snyk.io/rest/orgs/[OrgID]/projects
// Need to investigate and update error handling TODO
// currently no retry logic TODO
func makeSnykAPIRequest_REST(verb string, baseURL string, endpointURL string, snykToken string, body []byte, customDebug debug) ([]jsn.Json, error) {
var err error
allData := []jsn.Json{}
bodyBuffer := bytes.NewBuffer(nil)
url := baseURL + endpointURL
client := &http.Client{}
for url != "" {
if verb == "POST" && body != nil {
bodyBuffer = bytes.NewBuffer(body)
}
request, err := http.NewRequest(verb, url, bodyBuffer)
if err != nil {
customDebug.Debugf("*** ERROR *** could not create requests to '%s' failed with error %s\n", url, err.Error())
return []jsn.Json{}, err
}
request.Header.Add("Accept", "application/vnd.api+json")
request.Header.Add("Authorization", snykToken)
request.Header.Set("User-Agent", "tech-services/snyk-jira-tickets-for-new-vulns")
response, err := client.Do(request)
if err != nil {
customDebug.Debugf("*** ERROR *** Request on endpoint '%s' failed with error %s\n", url, err.Error())
return []jsn.Json{}, err
}
defer response.Body.Close()
// fmt.Println("Response Status Code:", response.StatusCode)
customDebug.Debugf("*** INFO *** Sending %s request to %s", verb, url)
jsonResponse, err := jsn.NewJson(response.Body)
if err != nil {
customDebug.Debugf("*** ERROR *** failed to load load json from response from endpoint %s with error %s\n", url, err.Error())
}
if response.StatusCode == 404 {
customDebug.Debugf("*** INFO *** Request on endpoint '%s' failed with error %s\n", endpointURL, response.Status)
errorMessage := fmt.Sprintf("*** INFO *** Request on endpoint '%s' failed with error %s\n", endpointURL, response.Status)
writeErrorFile("makeSnykAPIRequest", errorMessage, customDebug)
return nil, errors.New("Not found, Request failed")
} else if response.StatusCode == 400 {
customDebug.Debugf("*** INFO *** Request on endpoint '%s' failed with error %s\n", endpointURL, response.Status)
customDebug.Debugf("*** INFO *** Please check that all expected fields are present in the config file\n")
customDebug.Debugf("*** INFO *** Details : %s\n", jsonResponse.Pretty())
errorMessage := fmt.Sprintf("*** INFO *** Request on endpoint '%s' failed with error %s\n", endpointURL, response.Status)
writeErrorFile("makeSnykAPIRequest", errorMessage, customDebug)
return nil, errors.New("Unprocessable Entity, Request failed")
} else if response.StatusCode == 401 || response.StatusCode == 403 {
customDebug.Debugf("*** INFO *** Request on endpoint '%s' failed with error %s\n", endpointURL, response.Status)
customDebug.Debugf("*** INFO *** Please valid API token and permissions\n")
customDebug.Debugf("*** INFO *** Details : %s\n", jsonResponse.Pretty())
errorMessage := fmt.Sprintf("*** INFO *** Request on endpoint '%s' failed with error %s\n", endpointURL, response.Status)
writeErrorFile("makeSnykAPIRequest", errorMessage, customDebug)
return nil, errors.New("Authentication or permission error, Request failed")
} else if response.StatusCode > 400 {
customDebug.Debugf("*** INFO *** Request on endpoint '%s' failed with error %s\n", endpointURL, response.Status)
customDebug.Debugf("*** INFO *** Please check that all expected fields are present in the config file\n")
customDebug.Debugf("*** INFO *** Details : %s\n", jsonResponse.Pretty())
errorMessage := fmt.Sprintf("*** INFO *** Request on endpoint '%s' failed with error %s\n", endpointURL, response.Status)
writeErrorFile("makeSnykAPIRequest", errorMessage, customDebug)
return nil, errors.New("Request failed")
}
data := jsonResponse.K("data").Array()
allData = append(allData, data.Elements()...)
// Check if there is a next link, if not empty string ends the loop
next := jsonResponse.K("links").K("next").String()
if !next.IsValid {
url = ""
} else {
url = baseURL + next.Value
}
}
time.Sleep(1)
return allData, err
}