/
model.go
304 lines (264 loc) · 9.26 KB
/
model.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
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
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
// Package model (go:generate go run -mod=mod github.com/mailru/easyjson/easyjson ./$GOFILE)
package model
import (
"regexp"
"sort"
"strings"
_ "github.com/mailru/easyjson/gen" // easyjson unmarshaler
"github.com/rs/zerolog/log"
)
// Constants to describe what kind of file refers
const (
KindTerraform FileKind = "TF"
KindJSON FileKind = "JSON"
KindYAML FileKind = "YAML"
KindYML FileKind = "YML"
KindDOCKER FileKind = "DOCKERFILE"
KindPROTO FileKind = "PROTO"
KindCOMMON FileKind = "*"
KindHELM FileKind = "HELM"
KindBUILDAH FileKind = "SH"
KindCFG FileKind = "CFG"
KindINI FileKind = "INI"
)
// Constants to describe commands given from comments
const (
IgnoreLine CommentCommand = "ignore-line"
IgnoreBlock CommentCommand = "ignore-block"
IgnoreComment CommentCommand = "ignore-comment"
)
// Constants to describe vulnerability's severity
const (
SeverityHigh = "HIGH"
SeverityMedium = "MEDIUM"
SeverityLow = "LOW"
SeverityInfo = "INFO"
SeverityTrace = "TRACE"
)
// Constants to describe issue's type
const (
IssueTypeMissingAttribute IssueType = "MissingAttribute"
IssueTypeRedundantAttribute IssueType = "RedundantAttribute"
IssueTypeIncorrectValue IssueType = "IncorrectValue"
)
// Arrays to group all constants of one type
var (
AllSeverities = []Severity{
SeverityHigh,
SeverityMedium,
SeverityLow,
SeverityInfo,
SeverityTrace,
}
AllIssueTypesAsString = []string{
string(IssueTypeMissingAttribute),
string(IssueTypeRedundantAttribute),
string(IssueTypeIncorrectValue),
}
)
var (
// KICSCommentRgxp is the regexp to identify if a comment is a KICS comment
KICSCommentRgxp = regexp.MustCompile(`(^|\n)((/{2})|#|;)*\s*kics-scan\s*`)
// KICSGetContentCommentRgxp to gets the kics comment on the hel case
KICSGetContentCommentRgxp = regexp.MustCompile(`(^|\n)((/{2})|#|;)*\s*kics-scan([^\n]*)\n`)
// KICSCommentRgxpYaml is the regexp to identify if the comment has KICS comment at the end of the comment in YAML
KICSCommentRgxpYaml = regexp.MustCompile(`((/{2})|#)*\s*kics-scan\s*(ignore-line|ignore-block)\s*\n*$`)
)
// Version - is the model for the version response
type Version struct {
Latest bool `json:"is_latest"`
LatestVersionTag string `json:"latest_version"`
}
// VulnerabilityLines is the representation of the found line for issue
type VulnerabilityLines struct {
Line int
VulnLines *[]CodeLine
LineWithVulnerability string
ResolvedFile string
}
// CommentCommand represents a command given from a comment
type CommentCommand string
// FileKind is the extension of a file
type FileKind string
// Severity of the vulnerability
type Severity string
// IssueType is the issue's type string representation
type IssueType string
// CodeLine is the lines containing and adjacent to the vulnerability line with their respective positions
type CodeLine struct {
Position int
Line string
}
// ExtractedPathObject is the struct that contains the path location of extracted source
// and a boolean to check if it is a local source
type ExtractedPathObject struct {
Path string
LocalPath bool
}
// CommentsCommands list of commands on a file that will be parsed
type CommentsCommands map[string]string
// FileMetadata is a representation of basic information and content of a file
type FileMetadata struct {
ID string `db:"id"`
ScanID string `db:"scan_id"`
Document Document
LineInfoDocument map[string]interface{}
OriginalData string `db:"orig_data"`
Kind FileKind `db:"kind"`
FilePath string `db:"file_path"`
Content string
HelmID string
IDInfo map[int]interface{}
Commands CommentsCommands
LinesIgnore []int
ResolvedFiles map[string]ResolvedFile
LinesOriginalData *[]string
IsMinified bool
}
// QueryMetadata is a representation of general information about a query
type QueryMetadata struct {
InputData string
Query string
Content string
Metadata map[string]interface{}
Platform string
CWE string
// special field for generic queries
// represents how many queries are aggregated into a single rego file
Aggregation int
Experimental bool
}
// Vulnerability is a representation of a detected vulnerability in scanned files
// after running a query
type Vulnerability struct {
ID int `json:"id"`
ScanID string `db:"scan_id" json:"-"`
SimilarityID string `db:"similarity_id" json:"similarityID"`
FileID string `db:"file_id" json:"-"`
FileName string `db:"file_name" json:"fileName"`
QueryID string `db:"query_id" json:"queryID"`
QueryName string `db:"query_name" json:"queryName"`
QueryURI string `json:"-"`
Category string `json:"category"`
Experimental bool `json:"experimental"`
Description string `json:"description"`
DescriptionID string `json:"descriptionID"`
Platform string `db:"platform" json:"platform"`
CWE string `db:"cwe" json:"cwe"`
Severity Severity `json:"severity"`
Line int `json:"line"`
VulnLines *[]CodeLine `json:"vulnLines"`
ResourceType string `db:"resource_type" json:"resourceType"`
ResourceName string `db:"resource_name" json:"resourceName"`
IssueType IssueType `db:"issue_type" json:"issueType"`
SearchKey string `db:"search_key" json:"searchKey"`
SearchLine int `db:"search_line" json:"searchLine"`
SearchValue string `db:"search_value" json:"searchValue"`
KeyExpectedValue string `db:"key_expected_value" json:"expectedValue"`
KeyActualValue string `db:"key_actual_value" json:"actualValue"`
Value *string `db:"value" json:"value"`
Output string `json:"-"`
CloudProvider string `json:"cloud_provider"`
Remediation string `db:"remediation" json:"remediation"`
RemediationType string `db:"remediation_type" json:"remediation_type"`
}
// QueryConfig is a struct that contains the fileKind and platform of the rego query
type QueryConfig struct {
FileKind []FileKind
Platform string
}
// ResolvedFiles keeps the information of all file/template resolved
type ResolvedFiles struct {
File []ResolvedHelm
Excluded []string
}
// ResolvedHelm keeps the information of a file/template resolved
type ResolvedHelm struct {
FileName string
Content []byte
OriginalData []byte
SplitID string
IDInfo map[int]interface{}
}
// Extensions represents a list of supported extensions
type Extensions map[string]struct{}
// Include returns true if an extension is included in supported extensions listed
// otherwise returns false
func (e Extensions) Include(ext string) bool {
_, b := e[ext]
return b
}
// LineObject is the struct that will hold line information for each key
type LineObject struct {
Line int `json:"_kics_line"`
Arr []map[string]*LineObject `json:"_kics_arr,omitempty"`
}
// MatchedFilesRegex returns the regex rule to identify if an extension is supported or not
func (e Extensions) MatchedFilesRegex() string {
if len(e) == 0 {
return "NO_MATCHED_FILES"
}
var parts []string
for ext := range e {
parts = append(parts, "\\"+ext)
}
sort.Strings(parts)
return "(.*)(" + strings.Join(parts, "|") + ")$"
}
// FileMetadatas is a slice of FileMetadata
type FileMetadatas []FileMetadata
// ToMap creates a map of FileMetadatas, which the key is the FileMedata ID and the value is the FileMetadata
func (m FileMetadatas) ToMap() map[string]FileMetadata {
c := make(map[string]FileMetadata, len(m))
for i := 0; i < len(m); i++ {
c[m[i].ID] = m[i]
}
return c
}
// Documents (easyjson:json)
type Documents struct {
Documents []Document `json:"document"`
}
// Document (easyjson:json)
type Document map[string]interface{}
// Combine merge documents from FileMetadatas using the ID as reference for Document ID and FileName as reference for file
func (m FileMetadatas) Combine(lineInfo bool) Documents {
documents := Documents{Documents: make([]Document, 0, len(m))}
for i := 0; i < len(m); i++ {
_, ignore := m[i].Commands["ignore"]
if len(m[i].Document) == 0 {
continue
}
if ignore {
log.Debug().Msgf("Ignoring file %s", m[i].FilePath)
continue
}
if lineInfo {
m[i].LineInfoDocument["id"] = m[i].ID
m[i].LineInfoDocument["file"] = m[i].FilePath
documents.Documents = append(documents.Documents, m[i].LineInfoDocument)
} else {
m[i].Document["id"] = m[i].ID
m[i].Document["file"] = m[i].FilePath
documents.Documents = append(documents.Documents, m[i].Document)
}
}
return documents
}
// AnalyzedPaths is a slice of types and excluded files obtained from the Analyzer
type AnalyzedPaths struct {
Types []string
Exc []string
ExpectedLOC int
}
// ResolvedFileSplit is a struct that contains the information of a resolved file, the path and the lines of the file
type ResolvedFileSplit struct {
Path string
Lines []string
}
// ResolvedFile is a struct that contains the information of a resolved file, the path and the content in bytes of the file
type ResolvedFile struct {
Path string
Content []byte
LinesContent *[]string
}