@@ -10,6 +10,8 @@ import (
10
10
"github.com/open-policy-agent/opa/rego"
11
11
)
12
12
13
+ const denyMessage = "Rego policy resulted in DENY"
14
+
13
15
type regoResult struct {
14
16
Filepath string
15
17
Resource string
@@ -24,6 +26,13 @@ type regoResult struct {
24
26
Parent * regoResult
25
27
}
26
28
29
+ func messageResult (msg string ) * regoResult {
30
+ return & regoResult {
31
+ Managed : true ,
32
+ Message : msg ,
33
+ }
34
+ }
35
+
27
36
func (r regoResult ) GetMetadata () defsecTypes.Metadata {
28
37
var m defsecTypes.Metadata
29
38
if ! r .Managed {
@@ -46,102 +55,147 @@ func (r regoResult) GetRawValue() interface{} {
46
55
return nil
47
56
}
48
57
49
- func parseResult (raw interface {}) * regoResult {
50
- var result regoResult
51
- result .Managed = true
52
- switch val := raw .(type ) {
53
- case []interface {}:
54
- var msg string
55
- for _ , item := range val {
56
- switch raw := item .(type ) {
57
- case map [string ]interface {}:
58
- result = parseCause (raw )
59
- case string :
60
- msg = raw
61
- }
58
+ func (r * regoResult ) applyOffset (offset int ) {
59
+ r .StartLine += offset
60
+ r .EndLine += offset
61
+ }
62
+
63
+ func (r * regoResult ) updateMeta (raw map [string ]any ) {
64
+ for k , v := range raw {
65
+ switch k {
66
+ case "startline" , "StartLine" :
67
+ r .StartLine = parseLineNumber (v )
68
+ case "endline" , "EndLine" :
69
+ r .EndLine = parseLineNumber (v )
70
+ case "filepath" , "Path" :
71
+ r .Filepath = getString (v )
72
+ case "sourceprefix" :
73
+ r .SourcePrefix = getString (v )
74
+ case "explicit" :
75
+ r .Explicit = getBool (v )
76
+ case "managed" :
77
+ r .Managed = getBool (v )
78
+ case "fskey" :
79
+ r .FSKey = getString (v )
80
+ case "resource" :
81
+ r .Resource = getString (v )
62
82
}
63
- result .Message = msg
64
- case string :
65
- result .Message = val
66
- case map [string ]interface {}:
67
- result = parseCause (val )
68
- default :
69
- result .Message = "Rego policy resulted in DENY"
70
83
}
71
- return & result
72
84
}
73
85
74
- func parseCause (cause map [string ]interface {}) regoResult {
75
- var result regoResult
76
- result .Managed = true
77
- if msg , ok := cause ["msg" ]; ok {
78
- result .Message = fmt .Sprintf ("%s" , msg )
86
+ func getString (raw any ) string {
87
+ if str , ok := raw .(string ); ok {
88
+ return str
79
89
}
80
- if filepath , ok := cause ["filepath" ]; ok {
81
- result .Filepath = fmt .Sprintf ("%s" , filepath )
90
+ return ""
91
+ }
92
+
93
+ func getBool (raw any ) bool {
94
+ if b , ok := raw .(bool ); ok {
95
+ return b
82
96
}
83
- if msg , ok := cause ["fskey" ]; ok {
84
- result .FSKey = fmt .Sprintf ("%s" , msg )
97
+ return false
98
+ }
99
+
100
+ func newRegoResult (rawInput any ) * regoResult {
101
+ result := & regoResult {
102
+ Managed : true ,
85
103
}
86
- if msg , ok := cause ["resource" ]; ok {
87
- result .Resource = fmt .Sprintf ("%s" , msg )
104
+
105
+ input , ok := rawInput .(map [string ]any )
106
+ if ! ok {
107
+ return result
88
108
}
89
- if start , ok := cause ["startline" ]; ok {
90
- result .StartLine = parseLineNumber (start )
109
+
110
+ if rawMsg , exists := input ["msg" ]; exists {
111
+ if msg , ok := rawMsg .(string ); ok {
112
+ result .Message = msg
113
+ }
91
114
}
92
- if end , ok := cause ["endline" ]; ok {
93
- result .EndLine = parseLineNumber (end )
115
+
116
+ meta := parseMetadata (input )
117
+ result .updateMeta (meta )
118
+
119
+ if parent , ok := meta ["parent" ]; ok {
120
+ result .Parent = newRegoResult (map [string ]any {"metadata" : parent })
94
121
}
95
- if prefix , ok := cause ["sourceprefix" ]; ok {
96
- result .SourcePrefix = fmt .Sprintf ("%s" , prefix )
122
+
123
+ return result
124
+ }
125
+
126
+ func parseMetadata (input map [string ]any ) map [string ]any {
127
+ res := make (map [string ]any )
128
+ rawMetadata , exists := input ["metadata" ]
129
+ if ! exists {
130
+ // for backward compatibility
131
+ rawMetadata = input
97
132
}
98
- if explicit , ok := cause [ "explicit" ]; ok {
99
- if set , ok := explicit .( bool ); ok {
100
- result . Explicit = set
101
- }
133
+
134
+ cause , ok := rawMetadata .( map [ string ] any )
135
+ if ! ok {
136
+ return res
102
137
}
103
- if managed , ok := cause ["managed" ]; ok {
104
- if set , ok := managed .(bool ); ok {
105
- result .Managed = set
138
+
139
+ rawDefsecMeta , exists := cause ["__defsec_metadata" ]
140
+ if ! exists {
141
+ res = cause
142
+ } else {
143
+ defsecMeta , ok := rawDefsecMeta .(map [string ]any )
144
+ if ! ok {
145
+ return res
106
146
}
147
+ res = defsecMeta
107
148
}
108
- if parent , ok := cause ["parent" ]; ok {
109
- if m , ok := parent .(map [string ]interface {}); ok {
110
- parentResult := parseCause (m )
111
- result .Parent = & parentResult
149
+
150
+ return res
151
+ }
152
+
153
+ func parseResult (raw any ) * regoResult {
154
+
155
+ switch val := raw .(type ) {
156
+ case []any :
157
+ var msg string
158
+ var result * regoResult
159
+ for _ , item := range val {
160
+ switch raw := item .(type ) {
161
+ case map [string ]any :
162
+ if res := newRegoResult (raw ); res != nil {
163
+ result = res
164
+ }
165
+ case string :
166
+ msg = raw
167
+ }
168
+ }
169
+ if result != nil {
170
+ result .Message = msg
171
+ return result
112
172
}
173
+ return messageResult (msg )
174
+ case string :
175
+ return messageResult (val )
176
+ case map [string ]any :
177
+ return newRegoResult (val )
178
+ default :
179
+ return messageResult (denyMessage )
113
180
}
114
- return result
115
181
}
116
182
117
- func parseLineNumber (raw interface {}) int {
118
- str := fmt .Sprintf ("%s" , raw )
119
- n , _ := strconv .Atoi (str )
183
+ func parseLineNumber (raw any ) int {
184
+ n , _ := strconv .Atoi (fmt .Sprintf ("%s" , raw ))
120
185
return n
121
186
}
122
187
123
188
func (s * Scanner ) convertResults (set rego.ResultSet , input Input , namespace string , rule string , traces []string ) scan.Results {
124
189
var results scan.Results
125
190
126
- offset := 0
127
- if input .Contents != nil {
128
- if xx , ok := input .Contents .(map [string ]interface {}); ok {
129
- if md , ok := xx ["__defsec_metadata" ]; ok {
130
- if md2 , ok := md .(map [string ]interface {}); ok {
131
- if sl , ok := md2 ["offset" ]; ok {
132
- offset , _ = sl .(int )
133
- }
134
- }
135
- }
136
- }
137
- }
191
+ offset := input .GetOffset ()
192
+
138
193
for _ , result := range set {
139
194
for _ , expression := range result .Expressions {
140
- values , ok := expression .Value .([]interface {} )
195
+ values , ok := expression .Value .([]any )
141
196
if ! ok {
142
- values = []interface {} {expression .Value }
197
+ values = []any {expression .Value }
143
198
}
144
-
145
199
for _ , value := range values {
146
200
regoResult := parseResult (value )
147
201
regoResult .FS = input .FS
@@ -151,16 +205,10 @@ func (s *Scanner) convertResults(set rego.ResultSet, input Input, namespace stri
151
205
if regoResult .Message == "" {
152
206
regoResult .Message = fmt .Sprintf ("Rego policy rule: %s.%s" , namespace , rule )
153
207
}
154
- regoResult .StartLine += offset
155
- regoResult .EndLine += offset
208
+ regoResult .applyOffset (offset )
156
209
results .AddRego (regoResult .Message , namespace , rule , traces , regoResult )
157
210
}
158
211
}
159
212
}
160
213
return results
161
214
}
162
-
163
- func (s * Scanner ) embellishResultsWithRuleMetadata (results scan.Results , metadata StaticMetadata ) scan.Results {
164
- results .SetRule (metadata .ToRule ())
165
- return results
166
- }
0 commit comments