mirror of
https://github.com/kyverno/kyverno.git
synced 2025-03-06 16:06:56 +00:00
* initial commit * background policy validation * correct message * skip non-background policy process for add/update * add Generate Request CR * generate Request Generator Initial * test generate request CR generation * initial commit gr generator * generate controller initial framework * add crd for generate request * gr cleanup controller initial commit * cleanup controller initial * generate mid-commit * generate rule processing * create PV on generate error * embed resource type * testing phase 1- generate resources with variable substitution * fix tests * comment broken test #586 * add printer column for state * return if existing resource for clone * set resync time to 2 mins & remove resource version check in update handler for gr * generate events for reporting * fix logs * initial commit * fix trailing quote in patch * remove comments * initial condition (equal & notequal) * initial support for conditions * initial support fo conditions in generate * support precondition checks * cleanup * re-evaluate GR on namespace update using dynamic informers * add status for generated resources * display loaded variable SA * support delete cleanup of generate request main resources * fix log * remove namespace from SA username * support multiple variables per statement for scalar values * fix fail variables * add check for userInfo * validation checks for conditions * update policy * refactor logs * code review * add openapispec for clusterpolicy preconditions * Update documentation * CR fixes * documentation * CR fixes * update variable * fix logs * update policy * pre-defined variables (serviceAccountName & serviceAccountNamespace) * update test
155 lines
3.5 KiB
Go
155 lines
3.5 KiB
Go
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
|
|
}
|