github.com/devseccon/trivy@v0.47.1-0.20231123133102-bd902a0bd996/pkg/fanal/types/misconf.go (about) 1 package types 2 3 import ( 4 "fmt" 5 "sort" 6 7 "github.com/samber/lo" 8 ) 9 10 type Misconfiguration struct { 11 FileType ConfigType `json:",omitempty"` 12 FilePath string `json:",omitempty"` 13 Successes MisconfResults `json:",omitempty"` 14 Warnings MisconfResults `json:",omitempty"` 15 Failures MisconfResults `json:",omitempty"` 16 Exceptions MisconfResults `json:",omitempty"` 17 Layer Layer `json:",omitempty"` 18 } 19 20 type MisconfResult struct { 21 Namespace string `json:",omitempty"` 22 Query string `json:",omitempty"` 23 Message string `json:",omitempty"` 24 PolicyMetadata `json:",omitempty"` 25 CauseMetadata `json:",omitempty"` 26 27 // For debugging 28 Traces []string `json:",omitempty"` 29 } 30 31 type MisconfResults []MisconfResult 32 33 type CauseMetadata struct { 34 Resource string `json:",omitempty"` 35 Provider string `json:",omitempty"` 36 Service string `json:",omitempty"` 37 StartLine int `json:",omitempty"` 38 EndLine int `json:",omitempty"` 39 Code Code `json:",omitempty"` 40 Occurrences []Occurrence `json:",omitempty"` 41 } 42 43 type Occurrence struct { 44 Resource string `json:",omitempty"` 45 Filename string `json:",omitempty"` 46 Location Location 47 } 48 49 type Code struct { 50 Lines []Line 51 } 52 53 type Line struct { 54 Number int `json:"Number"` 55 Content string `json:"Content"` 56 IsCause bool `json:"IsCause"` 57 Annotation string `json:"Annotation"` 58 Truncated bool `json:"Truncated"` 59 Highlighted string `json:"Highlighted,omitempty"` 60 FirstCause bool `json:"FirstCause"` 61 LastCause bool `json:"LastCause"` 62 } 63 64 type PolicyMetadata struct { 65 ID string `json:",omitempty"` 66 AVDID string `json:",omitempty"` 67 Type string `json:",omitempty"` 68 Title string `json:",omitempty"` 69 Description string `json:",omitempty"` 70 Severity string `json:",omitempty"` 71 RecommendedActions string `json:",omitempty" mapstructure:"recommended_actions"` 72 References []string `json:",omitempty"` 73 } 74 75 type PolicyInputOption struct { 76 Combine bool `mapstructure:"combine"` 77 Selectors []PolicyInputSelector `mapstructure:"selector"` 78 } 79 80 type PolicyInputSelector struct { 81 Type string `mapstructure:"type"` 82 } 83 84 func (r MisconfResults) Len() int { 85 return len(r) 86 } 87 88 func (r MisconfResults) Swap(i, j int) { 89 r[i], r[j] = r[j], r[i] 90 } 91 92 func (r MisconfResults) Less(i, j int) bool { 93 switch { 94 case r[i].Type != r[j].Type: 95 return r[i].Type < r[j].Type 96 case r[i].AVDID != r[j].AVDID: 97 return r[i].AVDID < r[j].AVDID 98 case r[i].ID != r[j].ID: 99 return r[i].ID < r[j].ID 100 case r[i].Severity != r[j].Severity: 101 return r[i].Severity < r[j].Severity 102 case r[i].Resource != r[j].Resource: 103 return r[i].Resource < r[j].Resource 104 } 105 return r[i].Message < r[j].Message 106 } 107 108 func ToMisconfigurations(misconfs map[string]Misconfiguration) []Misconfiguration { 109 var results []Misconfiguration 110 for _, misconf := range misconfs { 111 // Remove duplicates 112 misconf.Successes = uniqueResults(misconf.Successes) 113 misconf.Warnings = uniqueResults(misconf.Warnings) 114 misconf.Failures = uniqueResults(misconf.Failures) 115 116 // Sort results 117 sort.Sort(misconf.Successes) 118 sort.Sort(misconf.Warnings) 119 sort.Sort(misconf.Failures) 120 sort.Sort(misconf.Exceptions) 121 122 results = append(results, misconf) 123 } 124 125 // Sort misconfigurations 126 sort.Slice(results, func(i, j int) bool { 127 if results[i].FileType != results[j].FileType { 128 return results[i].FileType < results[j].FileType 129 } 130 return results[i].FilePath < results[j].FilePath 131 }) 132 133 return results 134 } 135 136 func uniqueResults(results []MisconfResult) []MisconfResult { 137 if len(results) == 0 { 138 return results 139 } 140 return lo.UniqBy(results, func(result MisconfResult) string { 141 return fmt.Sprintf("ID: %s, Namespace: %s, Messsage: %s, Cause: %v", 142 result.ID, result.Namespace, result.Message, result.CauseMetadata) 143 }) 144 }