github.com/khulnasoft-lab/defsec@v1.0.5-0.20230827010352-5e9f46893d95/pkg/rego/result.go (about) 1 package rego 2 3 import ( 4 "fmt" 5 "io/fs" 6 "strconv" 7 8 defsecTypes "github.com/khulnasoft-lab/defsec/pkg/types" 9 10 "github.com/khulnasoft-lab/defsec/pkg/scan" 11 12 "github.com/open-policy-agent/opa/rego" 13 ) 14 15 type regoResult struct { 16 Filepath string 17 Resource string 18 StartLine int 19 EndLine int 20 SourcePrefix string 21 Message string 22 Explicit bool 23 Managed bool 24 FSKey string 25 FS fs.FS 26 Parent *regoResult 27 } 28 29 func (r regoResult) GetMetadata() defsecTypes.Metadata { 30 var m defsecTypes.Metadata 31 if !r.Managed { 32 m = defsecTypes.NewUnmanagedMetadata() 33 } else { 34 rng := defsecTypes.NewRangeWithFSKey(r.Filepath, r.StartLine, r.EndLine, r.SourcePrefix, r.FSKey, r.FS) 35 if r.Explicit { 36 m = defsecTypes.NewExplicitMetadata(rng, r.Resource) 37 } else { 38 m = defsecTypes.NewMetadata(rng, r.Resource) 39 } 40 } 41 if r.Parent != nil { 42 return m.WithParent(r.Parent.GetMetadata()) 43 } 44 return m 45 } 46 47 func (r regoResult) GetRawValue() interface{} { 48 return nil 49 } 50 51 func parseResult(raw interface{}) *regoResult { 52 var result regoResult 53 result.Managed = true 54 switch val := raw.(type) { 55 case []interface{}: 56 var msg string 57 for _, item := range val { 58 switch raw := item.(type) { 59 case map[string]interface{}: 60 result = parseCause(raw) 61 case string: 62 msg = raw 63 } 64 } 65 result.Message = msg 66 case string: 67 result.Message = val 68 case map[string]interface{}: 69 result = parseCause(val) 70 default: 71 result.Message = "Rego policy resulted in DENY" 72 } 73 return &result 74 } 75 76 func parseCause(cause map[string]interface{}) regoResult { 77 var result regoResult 78 result.Managed = true 79 if msg, ok := cause["msg"]; ok { 80 result.Message = fmt.Sprintf("%s", msg) 81 } 82 if filepath, ok := cause["filepath"]; ok { 83 result.Filepath = fmt.Sprintf("%s", filepath) 84 } 85 if msg, ok := cause["fskey"]; ok { 86 result.FSKey = fmt.Sprintf("%s", msg) 87 } 88 if msg, ok := cause["resource"]; ok { 89 result.Resource = fmt.Sprintf("%s", msg) 90 } 91 if start, ok := cause["startline"]; ok { 92 result.StartLine = parseLineNumber(start) 93 } 94 if end, ok := cause["endline"]; ok { 95 result.EndLine = parseLineNumber(end) 96 } 97 if prefix, ok := cause["sourceprefix"]; ok { 98 result.SourcePrefix = fmt.Sprintf("%s", prefix) 99 } 100 if explicit, ok := cause["explicit"]; ok { 101 if set, ok := explicit.(bool); ok { 102 result.Explicit = set 103 } 104 } 105 if managed, ok := cause["managed"]; ok { 106 if set, ok := managed.(bool); ok { 107 result.Managed = set 108 } 109 } 110 if parent, ok := cause["parent"]; ok { 111 if m, ok := parent.(map[string]interface{}); ok { 112 parentResult := parseCause(m) 113 result.Parent = &parentResult 114 } 115 } 116 return result 117 } 118 119 func parseLineNumber(raw interface{}) int { 120 str := fmt.Sprintf("%s", raw) 121 n, _ := strconv.Atoi(str) 122 return n 123 } 124 125 func (s *Scanner) convertResults(set rego.ResultSet, input Input, namespace string, rule string, traces []string) scan.Results { 126 var results scan.Results 127 128 offset := 0 129 if input.Contents != nil { 130 if xx, ok := input.Contents.(map[string]interface{}); ok { 131 if md, ok := xx["__defsec_metadata"]; ok { 132 if md2, ok := md.(map[string]interface{}); ok { 133 if sl, ok := md2["offset"]; ok { 134 offset, _ = sl.(int) 135 } 136 } 137 } 138 } 139 } 140 for _, result := range set { 141 for _, expression := range result.Expressions { 142 values, ok := expression.Value.([]interface{}) 143 if !ok { 144 values = []interface{}{expression.Value} 145 } 146 147 for _, value := range values { 148 regoResult := parseResult(value) 149 regoResult.FS = input.FS 150 if regoResult.Filepath == "" && input.Path != "" { 151 regoResult.Filepath = input.Path 152 } 153 if regoResult.Message == "" { 154 regoResult.Message = fmt.Sprintf("Rego policy rule: %s.%s", namespace, rule) 155 } 156 regoResult.StartLine += offset 157 regoResult.EndLine += offset 158 results.AddRego(regoResult.Message, namespace, rule, traces, regoResult) 159 } 160 } 161 } 162 return results 163 } 164 165 func (s *Scanner) embellishResultsWithRuleMetadata(results scan.Results, metadata StaticMetadata) scan.Results { 166 results.SetRule(metadata.ToRule()) 167 return results 168 }