Skip to content
This repository was archived by the owner on Jan 23, 2025. It is now read-only.

Commit 3a22d37

Browse files
committed
refactor: migrate REGO functions to Go
1 parent c2d65f4 commit 3a22d37

File tree

6 files changed

+199
-198
lines changed

6 files changed

+199
-198
lines changed

go.mod

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,3 +85,5 @@ require (
8585
gopkg.in/yaml.v2 v2.4.0 // indirect
8686
sigs.k8s.io/yaml v1.4.0 // indirect
8787
)
88+
89+
replace github.com/aquasecurity/trivy-policies => github.com/nikpivkin/trivy-policies v0.0.0-20240122112512-4cefa920d85c

go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,6 @@ github.com/apparentlymart/go-textseg/v13 v13.0.0 h1:Y+KvPE1NYz0xl601PVImeQfFyEy6
2222
github.com/apparentlymart/go-textseg/v13 v13.0.0/go.mod h1:ZK2fH7c4NqDTLtiYLvIkEghdlcqw7yxLeM89kiTRPUo=
2323
github.com/apparentlymart/go-textseg/v15 v15.0.0 h1:uYvfpb3DyLSCGWnctWKGj857c6ew1u1fNQOlOtuGxQY=
2424
github.com/apparentlymart/go-textseg/v15 v15.0.0/go.mod h1:K8XmNZdhEBkdlyDdvbmmsvpAG721bKi0joRfFdHIWJ4=
25-
github.com/aquasecurity/trivy-policies v0.8.0 h1:LvmIdw/DfTF72Lc8L+CKLYzfb5BFYzLBGFFR95PKC74=
26-
github.com/aquasecurity/trivy-policies v0.8.0/go.mod h1:qF/t59pgK/0JTV6tXaeA3Iw3opzoMgzGCDcTDBmqb30=
2725
github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0 h1:jfIu9sQUG6Ig+0+Ap1h4unLjW6YQJpKZVmUzxsD4E/Q=
2826
github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0/go.mod h1:t2tdKJDJF9BV14lnkjHmOQgcvEKgtqs5a1N3LNdJhGE=
2927
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=
@@ -122,6 +120,8 @@ github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQ
122120
github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0=
123121
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
124122
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
123+
github.com/nikpivkin/trivy-policies v0.0.0-20240122112512-4cefa920d85c h1:haHvIlIYDbyg3FcFrsPWcaEwBGBAkuPwPQ6GegoWXUE=
124+
github.com/nikpivkin/trivy-policies v0.0.0-20240122112512-4cefa920d85c/go.mod h1:I8cjIJ/PzMkhIY+2DVT2Vco0USiOqXjw04HzSEZXp9c=
125125
github.com/onsi/gomega v1.27.10 h1:naR28SdDFlqrG6kScpT8VWpu1xWY5nJRCF3XaYyBjhI=
126126
github.com/open-policy-agent/opa v0.60.0 h1:ZPoPt4yeNs5UXCpd/P/btpSyR8CR0wfhVoh9BOwgJNs=
127127
github.com/open-policy-agent/opa v0.60.0/go.mod h1:aD5IK6AiLNYBjNXn7E02++yC8l4Z+bRDvgM6Ss0bBzA=

pkg/rego/custom.go

Lines changed: 0 additions & 109 deletions
This file was deleted.

pkg/rego/result.go

Lines changed: 123 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ import (
1010
"github.com/open-policy-agent/opa/rego"
1111
)
1212

13+
const denyMessage = "Rego policy resulted in DENY"
14+
1315
type regoResult struct {
1416
Filepath string
1517
Resource string
@@ -24,6 +26,13 @@ type regoResult struct {
2426
Parent *regoResult
2527
}
2628

29+
func messageResult(msg string) *regoResult {
30+
return &regoResult{
31+
Managed: true,
32+
Message: msg,
33+
}
34+
}
35+
2736
func (r regoResult) GetMetadata() defsecTypes.Metadata {
2837
var m defsecTypes.Metadata
2938
if !r.Managed {
@@ -46,102 +55,147 @@ func (r regoResult) GetRawValue() interface{} {
4655
return nil
4756
}
4857

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)
6282
}
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"
7083
}
71-
return &result
7284
}
7385

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
7989
}
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
8296
}
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,
85103
}
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
88108
}
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+
}
91114
}
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})
94121
}
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
97132
}
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
102137
}
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
106146
}
147+
res = defsecMeta
107148
}
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
112172
}
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)
113180
}
114-
return result
115181
}
116182

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))
120185
return n
121186
}
122187

123188
func (s *Scanner) convertResults(set rego.ResultSet, input Input, namespace string, rule string, traces []string) scan.Results {
124189
var results scan.Results
125190

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+
138193
for _, result := range set {
139194
for _, expression := range result.Expressions {
140-
values, ok := expression.Value.([]interface{})
195+
values, ok := expression.Value.([]any)
141196
if !ok {
142-
values = []interface{}{expression.Value}
197+
values = []any{expression.Value}
143198
}
144-
145199
for _, value := range values {
146200
regoResult := parseResult(value)
147201
regoResult.FS = input.FS
@@ -151,16 +205,10 @@ func (s *Scanner) convertResults(set rego.ResultSet, input Input, namespace stri
151205
if regoResult.Message == "" {
152206
regoResult.Message = fmt.Sprintf("Rego policy rule: %s.%s", namespace, rule)
153207
}
154-
regoResult.StartLine += offset
155-
regoResult.EndLine += offset
208+
regoResult.applyOffset(offset)
156209
results.AddRego(regoResult.Message, namespace, rule, traces, regoResult)
157210
}
158211
}
159212
}
160213
return results
161214
}
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

Comments
 (0)