1
0
Fork 0
mirror of https://github.com/kyverno/kyverno.git synced 2025-03-06 07:57:07 +00:00
kyverno/pkg/engine/context/context.go
Shivkumar Dudhani 3cf9141f4d
593 feature (#594)
* 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
2020-01-07 15:13:57 -08:00

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
}