forked from kyverno/kyverno
-
Notifications
You must be signed in to change notification settings - Fork 0
/
context.go
155 lines (138 loc) · 3.53 KB
/
context.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
package context
import (
"encoding/json"
"strings"
"sync"
jsonpatch "github.com/evanphx/json-patch"
"github.com/golang/glog"
kyverno "github.com/nirmata/kyverno/pkg/api/kyverno/v1"
)
//Interface ... normal functions
type Interface interface {
// merges the json with context
AddJSON(dataRaw []byte) error
// merges resource json under request.object
AddResource(dataRaw []byte) error
// merges userInfo json under kyverno.userInfo
AddUserInfo(userInfo kyverno.UserInfo) error
// merges serrviceaccount
AddSA(userName string) error
EvalInterface
}
//EvalInterface ... to evaluate
type EvalInterface interface {
Query(query string) (interface{}, error)
}
//Context stores the data resources as JSON
type Context struct {
mu sync.RWMutex
// data map[string]interface{}
jsonRaw []byte
}
//NewContext returns a new context
func NewContext() *Context {
ctx := Context{
// data: map[string]interface{}{},
jsonRaw: []byte(`{}`), // empty json struct
}
return &ctx
}
// AddJSON merges json data
func (ctx *Context) AddJSON(dataRaw []byte) error {
var err error
ctx.mu.Lock()
defer ctx.mu.Unlock()
// merge json
ctx.jsonRaw, err = jsonpatch.MergePatch(ctx.jsonRaw, dataRaw)
if err != nil {
glog.V(4).Infof("failed to merge JSON data: %v", err)
return err
}
return nil
}
//Add data at path: request.object
func (ctx *Context) AddResource(dataRaw []byte) error {
// unmarshall the resource struct
var data interface{}
if err := json.Unmarshal(dataRaw, &data); err != nil {
glog.V(4).Infof("failed to unmarshall the context data: %v", err)
return err
}
modifiedResource := struct {
Request interface{} `json:"request"`
}{
Request: struct {
Object interface{} `json:"object"`
}{
Object: data,
},
}
objRaw, err := json.Marshal(modifiedResource)
if err != nil {
glog.V(4).Infof("failed to marshall the updated context data")
return err
}
return ctx.AddJSON(objRaw)
}
func (ctx *Context) AddUserInfo(userRequestInfo kyverno.RequestInfo) error {
modifiedResource := struct {
Request interface{} `json:"request"`
}{
Request: userRequestInfo,
}
objRaw, err := json.Marshal(modifiedResource)
if err != nil {
glog.V(4).Infof("failed to marshall the updated context data")
return err
}
return ctx.AddJSON(objRaw)
}
// removes prefix 'system:serviceaccount:' and namespace, then loads only username
func (ctx *Context) AddSA(userName string) error {
saPrefix := "system:serviceaccount:"
var sa string
saName := ""
saNamespace := ""
if len(userName) <= len(saPrefix) {
sa = ""
} else {
sa = userName[len(saPrefix):]
}
// filter namespace
groups := strings.Split(sa, ":")
if len(groups) >= 2 {
glog.V(4).Infof("serviceAccount namespace: %s", groups[0])
glog.V(4).Infof("serviceAccount name: %s", groups[1])
saName = groups[1]
saNamespace = groups[0]
}
glog.Infof("Loading variable serviceAccountName with value: %s", saName)
saNameObj := struct {
SA string `json:"serviceAccountName"`
}{
SA: saName,
}
saNameRaw, err := json.Marshal(saNameObj)
if err != nil {
glog.V(4).Infof("failed to marshall the updated context data")
return err
}
if err := ctx.AddJSON(saNameRaw); err != nil {
return err
}
glog.Infof("Loading variable serviceAccountNamespace with value: %s", saNamespace)
saNsObj := struct {
SA string `json:"serviceAccountNamespace"`
}{
SA: saNamespace,
}
saNsRaw, err := json.Marshal(saNsObj)
if err != nil {
glog.V(4).Infof("failed to marshall the updated context data")
return err
}
if err := ctx.AddJSON(saNsRaw); err != nil {
return err
}
return nil
}