1
0
Fork 0
mirror of https://github.com/kyverno/kyverno.git synced 2025-03-31 03:45:17 +00:00

refactor: engine context (#3563)

Co-authored-by: Jim Bugwadia <jim@nirmata.com>
Co-authored-by: shuting <shuting@nirmata.com>
This commit is contained in:
Charles-Edouard Brétéché 2022-04-09 13:52:50 +02:00 committed by GitHub
parent 944bf1728e
commit 3d554ce53b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
30 changed files with 375 additions and 495 deletions

View file

@ -5,43 +5,19 @@ import (
"strings"
"sync"
"github.com/pkg/errors"
jsonpatch "github.com/evanphx/json-patch/v5"
"github.com/go-logr/logr"
kyverno "github.com/kyverno/kyverno/api/kyverno/v1"
pkgcommon "github.com/kyverno/kyverno/pkg/common"
"github.com/pkg/errors"
admissionv1 "k8s.io/api/admission/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"sigs.k8s.io/controller-runtime/pkg/log"
)
//Interface to manage context operations
type Interface interface {
var logger = log.Log.WithName("context")
// AddRequest marshals and adds the admission request to the context
AddRequest(request *admissionv1.AdmissionRequest) error
// AddJSON merges the json with context
AddJSON(dataRaw []byte) error
// AddResource merges resource json under request.object
AddResource(dataRaw []byte) error
// AddUserInfo merges userInfo json under kyverno.userInfo
AddUserInfo(userInfo kyverno.UserInfo) error
// AddServiceAccount merges ServiceAccount types
AddServiceAccount(userName string) error
// AddNamespace merges resource json under request.namespace
AddNamespace(namespace string) error
EvalInterface
}
//EvalInterface is used to query and inspect context data
// EvalInterface is used to query and inspect context data
type EvalInterface interface {
// Query accepts a JMESPath expression and returns matching data
Query(query string) (interface{}, error)
@ -52,178 +28,128 @@ type EvalInterface interface {
HasChanged(jmespath string) (bool, error)
}
//Context stores the data resources as JSON
type Context struct {
// Interface to manage context operations
type Interface interface {
// AddRequest marshals and adds the admission request to the context
AddRequest(request *admissionv1.AdmissionRequest) error
// AddVariable adds a variable to the context
AddVariable(key, value string) error
// AddContextEntry adds a context entry to the context
AddContextEntry(name string, dataRaw []byte) error
// AddResource merges resource json under request.object
AddResource(data map[string]interface{}) error
// AddOldResource merges resource json under request.oldObject
AddOldResource(data map[string]interface{}) error
// AddUserInfo merges userInfo json under kyverno.userInfo
AddUserInfo(userInfo kyverno.RequestInfo) error
// AddServiceAccount merges ServiceAccount types
AddServiceAccount(userName string) error
// AddNamespace merges resource json under request.namespace
AddNamespace(namespace string) error
// AddElement adds element info to the context
AddElement(data map[string]interface{}, index int) error
// AddImageInfo adds image info to the context
AddImageInfo(info *ImageInfo) error
// AddImageInfos adds image infos to the context
AddImageInfos(resource *unstructured.Unstructured) error
// ImageInfo returns image infos present in the context
ImageInfo() *Images
// Checkpoint creates a copy of the current internal state and pushes it into a stack of stored states.
Checkpoint()
// Restore sets the internal state to the last checkpoint, and removes the checkpoint.
Restore()
// Reset sets the internal state to the last checkpoint, but does not remove the checkpoint.
Reset()
EvalInterface
// AddJSON merges the json with context
addJSON(dataRaw []byte) error
}
// Context stores the data resources as JSON
type context struct {
mutex sync.RWMutex
jsonRaw []byte
jsonRawCheckpoints [][]byte
images *Images
log logr.Logger
}
//NewContext returns a new context
func NewContext() *Context {
ctx := Context{
jsonRaw: []byte(`{}`), // empty json struct
log: log.Log.WithName("context"),
// NewContext returns a new context
func NewContext() Interface {
return NewContextFromRaw([]byte(`{}`))
}
// NewContextFromRaw returns a new context initialized with raw data
func NewContextFromRaw(raw []byte) Interface {
ctx := context{
jsonRaw: raw,
jsonRawCheckpoints: make([][]byte, 0),
}
return &ctx
}
// AddJSON merges json data
func (ctx *Context) AddJSON(dataRaw []byte) error {
var err error
// addJSON merges json data
func (ctx *context) addJSON(dataRaw []byte) error {
ctx.mutex.Lock()
defer ctx.mutex.Unlock()
ctx.jsonRaw, err = jsonpatch.MergeMergePatches(ctx.jsonRaw, dataRaw)
json, err := jsonpatch.MergeMergePatches(ctx.jsonRaw, dataRaw)
if err != nil {
return errors.Wrap(err, "failed to merge JSON data")
}
ctx.jsonRaw = json
return nil
}
// AddJSONObject merges json data
func (ctx *Context) AddJSONObject(jsonData interface{}) error {
jsonBytes, err := json.Marshal(jsonData)
if err != nil {
return err
}
return ctx.AddJSON(jsonBytes)
}
// AddRequest adds an admission request to context
func (ctx *Context) AddRequest(request *admissionv1.AdmissionRequest) error {
modifiedResource := struct {
Request interface{} `json:"request"`
}{
Request: request,
}
objRaw, err := json.Marshal(modifiedResource)
if err != nil {
ctx.log.Error(err, "failed to marshal the request")
return err
}
return ctx.AddJSON(objRaw)
func (ctx *context) AddRequest(request *admissionv1.AdmissionRequest) error {
return addToContext(ctx, request, "request")
}
//AddResource data at path: request.object
func (ctx *Context) AddResource(dataRaw []byte) error {
func (ctx *context) AddVariable(key, value string) error {
return ctx.addJSON(pkgcommon.VariableToJSON(key, value))
}
// unmarshal the resource struct
func (ctx *context) AddContextEntry(name string, dataRaw []byte) error {
var data interface{}
if err := json.Unmarshal(dataRaw, &data); err != nil {
ctx.log.Error(err, "failed to unmarshal the resource")
logger.Error(err, "failed to unmarshal the resource")
return err
}
modifiedResource := struct {
Request interface{} `json:"request"`
}{
Request: struct {
Object interface{} `json:"object"`
}{
Object: data,
},
}
objRaw, err := json.Marshal(modifiedResource)
if err != nil {
ctx.log.Error(err, "failed to marshal the resource")
return err
}
return ctx.AddJSON(objRaw)
return addToContext(ctx, data, name)
}
//AddResourceInOldObject data at path: request.oldObject
func (ctx *Context) AddResourceInOldObject(dataRaw []byte) error {
// unmarshal the resource struct
var data interface{}
if err := json.Unmarshal(dataRaw, &data); err != nil {
ctx.log.Error(err, "failed to unmarshal the resource")
return err
}
modifiedResource := struct {
Request interface{} `json:"request"`
}{
Request: struct {
OldObject interface{} `json:"oldObject"`
}{
OldObject: data,
},
}
objRaw, err := json.Marshal(modifiedResource)
if err != nil {
ctx.log.Error(err, "failed to marshal the resource")
return err
}
return ctx.AddJSON(objRaw)
// AddResource data at path: request.object
func (ctx *context) AddResource(data map[string]interface{}) error {
return addToContext(ctx, data, "request", "object")
}
func (ctx *Context) AddResourceAsObject(data interface{}) error {
return ctx.addToRequest(data, "object")
// AddOldResource data at path: request.oldObject
func (ctx *context) AddOldResource(data map[string]interface{}) error {
return addToContext(ctx, data, "request", "oldObject")
}
func (ctx *Context) ReplaceResourceAsObject(data interface{}) error {
if err := ctx.addToRequest(nil, "object"); err != nil {
return err
}
return ctx.addToRequest(data, "object")
// AddUserInfo adds userInfo at path request.userInfo
func (ctx *context) AddUserInfo(userRequestInfo kyverno.RequestInfo) error {
return addToContext(ctx, userRequestInfo, "request")
}
func (ctx *Context) ReplaceResourceAsOldObject(data interface{}) error {
if err := ctx.addToRequest(nil, "oldObject"); err != nil {
return err
}
return ctx.addToRequest(data, "oldObject")
}
func (ctx *Context) addToRequest(data interface{}, tag string) error {
requestData := make(map[string]interface{})
requestData[tag] = data
request := map[string]interface{}{
"request": requestData,
}
objRaw, err := json.Marshal(request)
if err != nil {
ctx.log.Error(err, "failed to marshal the resource")
return err
}
return ctx.AddJSON(objRaw)
}
//AddUserInfo adds userInfo at path request.userInfo
func (ctx *Context) AddUserInfo(userRequestInfo kyverno.RequestInfo) error {
modifiedResource := struct {
Request interface{} `json:"request"`
}{
Request: userRequestInfo,
}
objRaw, err := json.Marshal(modifiedResource)
if err != nil {
ctx.log.Error(err, "failed to marshal the UserInfo")
return err
}
ctx.log.V(4).Info("Adding user info logs", "userRequestInfo", userRequestInfo)
return ctx.AddJSON(objRaw)
}
//AddServiceAccount removes prefix 'system:serviceaccount:' and namespace, then loads only SA name and SA namespace
func (ctx *Context) AddServiceAccount(userName string) error {
// AddServiceAccount removes prefix 'system:serviceaccount:' and namespace, then loads only SA name and SA namespace
func (ctx *context) AddServiceAccount(userName string) error {
saPrefix := "system:serviceaccount:"
var sa string
saName := ""
@ -239,7 +165,6 @@ func (ctx *Context) AddServiceAccount(userName string) error {
saName = groups[1]
saNamespace = groups[0]
}
saNameObj := struct {
SA string `json:"serviceAccountName"`
}{
@ -247,10 +172,10 @@ func (ctx *Context) AddServiceAccount(userName string) error {
}
saNameRaw, err := json.Marshal(saNameObj)
if err != nil {
ctx.log.Error(err, "failed to marshal the SA")
logger.Error(err, "failed to marshal the SA")
return err
}
if err := ctx.AddJSON(saNameRaw); err != nil {
if err := ctx.addJSON(saNameRaw); err != nil {
return err
}
@ -261,103 +186,85 @@ func (ctx *Context) AddServiceAccount(userName string) error {
}
saNsRaw, err := json.Marshal(saNsObj)
if err != nil {
ctx.log.Error(err, "failed to marshal the SA namespace")
logger.Error(err, "failed to marshal the SA namespace")
return err
}
if err := ctx.AddJSON(saNsRaw); err != nil {
if err := ctx.addJSON(saNsRaw); err != nil {
return err
}
ctx.log.V(4).Info("Adding service account", "service account name", saName, "service account namespace", saNamespace)
logger.V(4).Info("Adding service account", "service account name", saName, "service account namespace", saNamespace)
return nil
}
// AddNamespace merges resource json under request.namespace
func (ctx *Context) AddNamespace(namespace string) error {
modifiedResource := struct {
Request interface{} `json:"request"`
}{
Request: struct {
Namespace string `json:"namespace"`
}{
Namespace: namespace,
},
}
objRaw, err := json.Marshal(modifiedResource)
if err != nil {
ctx.log.Error(err, "failed to marshal the resource")
return err
}
return ctx.AddJSON(objRaw)
func (ctx *context) AddNamespace(namespace string) error {
return addToContext(ctx, namespace, "request", "namespace")
}
func (ctx *Context) AddImageInfo(resource *unstructured.Unstructured) error {
initContainersImgs, containersImgs, ephemeralContainersImgs := extractImageInfo(resource, ctx.log)
func (ctx *context) AddElement(data map[string]interface{}, index int) error {
data = map[string]interface{}{
"element": data,
"elementIndex": index,
}
return addToContext(ctx, data)
}
func (ctx *context) AddImageInfo(info *ImageInfo) error {
data := map[string]interface{}{
"image": info.String(),
"registry": info.Registry,
"path": info.Path,
"name": info.Name,
"tag": info.Tag,
"digest": info.Digest,
}
return addToContext(ctx, data, "image")
}
func (ctx *context) AddImageInfos(resource *unstructured.Unstructured) error {
initContainersImgs, containersImgs, ephemeralContainersImgs := extractImageInfo(resource, logger)
if len(initContainersImgs) == 0 && len(containersImgs) == 0 && len(ephemeralContainersImgs) == 0 {
return nil
}
images := newImages(initContainersImgs, containersImgs, ephemeralContainersImgs)
if images == nil {
return nil
}
ctx.images = images
imagesTag := struct {
Images interface{} `json:"images"`
}{
Images: images,
}
objRaw, err := json.Marshal(imagesTag)
if err != nil {
return err
}
return ctx.AddJSON(objRaw)
ctx.images = &images
return addToContext(ctx, images, "images")
}
func (ctx *Context) ImageInfo() *Images {
func (ctx *context) ImageInfo() *Images {
return ctx.images
}
// Checkpoint creates a copy of the current internal state and
// pushes it into a stack of stored states.
func (ctx *Context) Checkpoint() {
func (ctx *context) Checkpoint() {
ctx.mutex.Lock()
defer ctx.mutex.Unlock()
jsonRawCheckpoint := make([]byte, len(ctx.jsonRaw))
copy(jsonRawCheckpoint, ctx.jsonRaw)
ctx.jsonRawCheckpoints = append(ctx.jsonRawCheckpoints, jsonRawCheckpoint)
}
// Restore sets the internal state to the last checkpoint, and removes the checkpoint.
func (ctx *Context) Restore() {
func (ctx *context) Restore() {
ctx.reset(true)
}
// Reset sets the internal state to the last checkpoint, but does not remove the checkpoint.
func (ctx *Context) Reset() {
func (ctx *context) Reset() {
ctx.reset(false)
}
func (ctx *Context) reset(remove bool) {
func (ctx *context) reset(remove bool) {
ctx.mutex.Lock()
defer ctx.mutex.Unlock()
if len(ctx.jsonRawCheckpoints) == 0 {
return
}
n := len(ctx.jsonRawCheckpoints) - 1
jsonRawCheckpoint := ctx.jsonRawCheckpoints[n]
ctx.jsonRaw = make([]byte, len(jsonRawCheckpoint))
copy(ctx.jsonRaw, jsonRawCheckpoint)
if remove {
ctx.jsonRawCheckpoints = ctx.jsonRawCheckpoints[:n]
}

View file

@ -55,7 +55,7 @@ func Test_addResourceAndUserContext(t *testing.T) {
var expectedResult string
ctx := NewContext()
err = ctx.AddResource(rawResource)
err = AddResource(ctx, rawResource)
if err != nil {
t.Error(err)
}

View file

@ -11,61 +11,46 @@ import (
jmespath "github.com/kyverno/kyverno/pkg/engine/jmespath"
)
//Query the JSON context with JMESPATH search path
func (ctx *Context) Query(query string) (interface{}, error) {
// Query the JSON context with JMESPATH search path
func (ctx *context) Query(query string) (interface{}, error) {
query = strings.TrimSpace(query)
if query == "" {
return nil, fmt.Errorf("invalid query (nil)")
}
var emptyResult interface{}
// compile the query
queryPath, err := jmespath.New(query)
if err != nil {
ctx.log.Error(err, "incorrect query", "query", query)
return emptyResult, fmt.Errorf("incorrect query %s: %v", query, err)
logger.Error(err, "incorrect query", "query", query)
return nil, fmt.Errorf("incorrect query %s: %v", query, err)
}
// search
ctx.mutex.RLock()
defer ctx.mutex.RUnlock()
var data interface{}
if err := json.Unmarshal(ctx.jsonRaw, &data); err != nil {
return emptyResult, errors.Wrap(err, "failed to unmarshal context")
return nil, errors.Wrap(err, "failed to unmarshal context")
}
result, err := queryPath.Search(data)
if err != nil {
return emptyResult, errors.Wrap(err, "JMESPath query failed")
return nil, errors.Wrap(err, "JMESPath query failed")
}
return result, nil
}
func (ctx *Context) HasChanged(jmespath string) (bool, error) {
func (ctx *context) HasChanged(jmespath string) (bool, error) {
objData, err := ctx.Query("request.object." + jmespath)
if err != nil {
return false, errors.Wrap(err, "failed to query request.object")
}
if objData == nil {
return false, fmt.Errorf("request.object.%s not found", jmespath)
}
oldObjData, err := ctx.Query("request.oldObject." + jmespath)
if err != nil {
return false, errors.Wrap(err, "failed to query request.object")
}
if oldObjData == nil {
return false, fmt.Errorf("request.oldObject.%s not found", jmespath)
}
if reflect.DeepEqual(objData, oldObjData) {
return false, nil
}
return true, nil
return !reflect.DeepEqual(objData, oldObjData), nil
}

View file

@ -55,7 +55,7 @@ func TestMissingObject(t *testing.T) {
assert.Error(t, err)
}
func createTestContext(obj, oldObj string) *Context {
func createTestContext(obj, oldObj string) Interface {
request := &admissionv1.AdmissionRequest{}
request.Operation = "UPDATE"
request.Object.Raw = []byte(obj)

View file

@ -13,7 +13,6 @@ import (
)
type ImageInfo struct {
// Registry is the URL address of the image registry e.g. `docker.io`
Registry string `json:"registry,omitempty"`
@ -43,124 +42,96 @@ func (i *ImageInfo) String() string {
}
type ContainerImage struct {
Name string
Image *ImageInfo
ImageInfo
Name string
}
type Images struct {
InitContainers map[string]*ImageInfo `json:"initContainers,omitempty"`
Containers map[string]*ImageInfo `json:"containers"`
EphemeralContainers map[string]*ImageInfo `json:"ephemeralContainers"`
InitContainers map[string]ImageInfo `json:"initContainers,omitempty"`
Containers map[string]ImageInfo `json:"containers"`
EphemeralContainers map[string]ImageInfo `json:"ephemeralContainers"`
}
func newImages(initContainersImgs, containersImgs, ephemeralContainersImgs []*ContainerImage) *Images {
initContainers := make(map[string]*ImageInfo)
func newImages(initContainersImgs, containersImgs, ephemeralContainersImgs []ContainerImage) Images {
initContainers := make(map[string]ImageInfo)
for _, resource := range initContainersImgs {
initContainers[resource.Name] = resource.Image
initContainers[resource.Name] = resource.ImageInfo
}
containers := make(map[string]*ImageInfo)
containers := make(map[string]ImageInfo)
for _, resource := range containersImgs {
containers[resource.Name] = resource.Image
containers[resource.Name] = resource.ImageInfo
}
ephemeralContainers := make(map[string]*ImageInfo)
ephemeralContainers := make(map[string]ImageInfo)
for _, resource := range ephemeralContainersImgs {
ephemeralContainers[resource.Name] = resource.Image
ephemeralContainers[resource.Name] = resource.ImageInfo
}
return &Images{
return Images{
InitContainers: initContainers,
Containers: containers,
EphemeralContainers: ephemeralContainers,
}
}
func extractImageInfo(resource *unstructured.Unstructured, log logr.Logger) (initContainersImgs, containersImgs, ephemeralContainersImgs []*ContainerImage) {
logger := log.WithName("extractImageInfo").WithValues("kind", resource.GetKind(), "ns", resource.GetNamespace(), "name", resource.GetName())
type imageExtractor struct {
fields []string
}
for _, tag := range []string{"initContainers", "containers", "ephemeralContainers"} {
switch resource.GetKind() {
case "Pod":
if containers, ok, _ := unstructured.NestedSlice(resource.UnstructuredContent(), "spec", tag); ok {
if tag == "initContainers" {
initContainersImgs = extractImageInfos(containers, initContainersImgs, "/spec/initContainers", logger)
} else if tag == "containers" {
containersImgs = extractImageInfos(containers, containersImgs, "/spec/containers", logger)
} else {
ephemeralContainersImgs = extractImageInfos(containers, ephemeralContainersImgs, "/spec/ephemeralContainers", logger)
}
}
case "CronJob":
if containers, ok, _ := unstructured.NestedSlice(resource.UnstructuredContent(), "spec", "jobTemplate", "spec", "template", "spec", tag); ok {
if tag == "initContainers" {
initContainersImgs = extractImageInfos(containers, initContainersImgs, "/spec/jobTemplate/spec/template/spec/initContainers", logger)
} else if tag == "containers" {
containersImgs = extractImageInfos(containers, containersImgs, "/spec/jobTemplate/spec/template/spec/containers", logger)
} else {
ephemeralContainersImgs = extractImageInfos(containers, ephemeralContainersImgs, "/spec/jobTemplate/spec/template/spec/ephemeralContainers", logger)
}
}
// handles "Deployment", "DaemonSet", "Job", "StatefulSet", and custom controllers with the same pattern
default:
if containers, ok, _ := unstructured.NestedSlice(resource.UnstructuredContent(), "spec", "template", "spec", tag); ok {
if tag == "initContainers" {
initContainersImgs = extractImageInfos(containers, initContainersImgs, "/spec/template/spec/initContainers", logger)
} else if tag == "containers" {
containersImgs = extractImageInfos(containers, containersImgs, "/spec/template/spec/containers", logger)
} else {
ephemeralContainersImgs = extractImageInfos(containers, ephemeralContainersImgs, "/spec/template/spec/ephemeralContainers", logger)
}
}
}
func (i imageExtractor) extract(tag string, resource *unstructured.Unstructured) []ContainerImage {
f := append(i.fields[:len(i.fields):len(i.fields)], tag)
if containers, ok, _ := unstructured.NestedSlice(resource.UnstructuredContent(), f...); ok {
return extractImageInfos(containers, "/"+strings.Join(f, "/"))
}
return nil
}
var extractors = map[string]imageExtractor{
"Pod": {[]string{"spec"}},
"CronJob": {[]string{"spec", "jobTemplate", "spec", "template", "spec"}},
"Deployment": {[]string{"spec", "template", "spec"}},
"DaemonSet": {[]string{"spec", "template", "spec"}},
"Job": {[]string{"spec", "template", "spec"}},
"StatefulSet": {[]string{"spec", "template", "spec"}},
}
func extractImageInfo(resource *unstructured.Unstructured, log logr.Logger) (initContainersImgs, containersImgs, ephemeralContainersImgs []ContainerImage) {
extractor := extractors[resource.GetKind()]
initContainersImgs = extractor.extract("initContainers", resource)
containersImgs = extractor.extract("containers", resource)
ephemeralContainersImgs = extractor.extract("ephemeralContainers", resource)
return
}
func extractImageInfos(containers []interface{}, images []*ContainerImage, jsonPath string, log logr.Logger) []*ContainerImage {
func extractImageInfos(containers []interface{}, jsonPath string) []ContainerImage {
img, err := convertToImageInfo(containers, jsonPath)
if err != nil {
log.Error(err, "failed to extract image info", "element", containers)
logger.Error(err, "failed to extract image info", "element", containers)
}
return append(images, img...)
return img
}
func convertToImageInfo(containers []interface{}, jsonPath string) (images []*ContainerImage, err error) {
func convertToImageInfo(containers []interface{}, jsonPath string) (images []ContainerImage, err error) {
var errs []string
var index = 0
for _, ctr := range containers {
if container, ok := ctr.(map[string]interface{}); ok {
var name, image string
name = container["name"].(string)
if _, ok := container["image"]; ok {
image = container["image"].(string)
}
jp := strings.Join([]string{jsonPath, strconv.Itoa(index), "image"}, "/")
imageInfo, err := newImageInfo(image, jp)
if err != nil {
errs = append(errs, err.Error())
continue
}
images = append(images, &ContainerImage{
Name: name,
Image: imageInfo,
})
images = append(images, ContainerImage{*imageInfo, name})
}
index++
}
if len(errs) == 0 {
return images, nil
}
return images, errors.Errorf("%s", strings.Join(errs, ";"))
}
@ -170,27 +141,22 @@ func newImageInfo(image, jsonPointer string) (*ImageInfo, error) {
if err != nil {
return nil, errors.Wrapf(err, "bad image: %s", image)
}
var registry, path, name, tag, digest string
if named, ok := ref.(reference.Named); ok {
registry = reference.Domain(named)
path = reference.Path(named)
name = path[strings.LastIndex(path, "/")+1:]
}
if tagged, ok := ref.(reference.Tagged); ok {
tag = tagged.Tag()
}
if digested, ok := ref.(reference.Digested); ok {
digest = digested.Digest().String()
}
// set default tag - the domain is set via addDefaultDomain before parsing
if digest == "" && tag == "" {
tag = "latest"
}
return &ImageInfo{
Registry: registry,
Name: name,
@ -206,41 +172,34 @@ func addDefaultDomain(name string) string {
if i == -1 || (!strings.ContainsAny(name[:i], ".:") && name[:i] != "localhost" && strings.ToLower(name[:i]) == name[:i]) {
return "docker.io/" + name
}
return name
}
// MutateResourceWithImageInfo will set images to their canonical form so that they can be compared
// in a predictable manner. This sets the default registry as `docker.io` and the tag as `latest` if
// these are missing.
func MutateResourceWithImageInfo(raw []byte, ctx *Context) error {
func MutateResourceWithImageInfo(raw []byte, ctx Interface) error {
images := ctx.ImageInfo()
if images == nil {
return nil
}
buildJSONPatch := func(op, path, value string) []byte {
p := fmt.Sprintf(`{ "op": "%s", "path": "%s", "value":"%s" }`, op, path, value)
return []byte(p)
}
var patches [][]byte
for _, info := range images.Containers {
patches = append(patches, buildJSONPatch("replace", info.JSONPointer, info.String()))
}
for _, info := range images.InitContainers {
patches = append(patches, buildJSONPatch("replace", info.JSONPointer, info.String()))
}
for _, info := range images.EphemeralContainers {
patches = append(patches, buildJSONPatch("replace", info.JSONPointer, info.String()))
}
patchedResource, err := engineutils.ApplyPatches(raw, patches)
if err != nil {
return err
}
return ctx.AddResource(patchedResource)
return AddResource(ctx, patchedResource)
}

View file

@ -11,31 +11,31 @@ import (
func Test_extractImageInfo(t *testing.T) {
tests := []struct {
raw []byte
containers []*ContainerImage
initContainers []*ContainerImage
ephemeralContainers []*ContainerImage
containers []ContainerImage
initContainers []ContainerImage
ephemeralContainers []ContainerImage
}{
{
raw: []byte(`{"apiVersion": "v1","kind": "Pod","metadata": {"name": "myapp"},"spec": {"initContainers": [{"name": "init","image": "index.docker.io/busybox:v1.2.3"}],"containers": [{"name": "nginx","image": "nginx:latest"}], "ephemeralContainers": [{"name": "ephemeral", "image":"test/nginx:latest"}]}}`),
initContainers: []*ContainerImage{{Name: "init", Image: &ImageInfo{Registry: "index.docker.io", Name: "busybox", Path: "busybox", Tag: "v1.2.3", JSONPointer: "/spec/initContainers/0/image"}}},
containers: []*ContainerImage{{Name: "nginx", Image: &ImageInfo{Registry: "docker.io", Name: "nginx", Path: "nginx", Tag: "latest", JSONPointer: "/spec/containers/0/image"}}},
ephemeralContainers: []*ContainerImage{{Name: "ephemeral", Image: &ImageInfo{Registry: "docker.io", Name: "nginx", Path: "test/nginx", Tag: "latest", JSONPointer: "/spec/ephemeralContainers/0/image"}}},
initContainers: []ContainerImage{{Name: "init", ImageInfo: ImageInfo{Registry: "index.docker.io", Name: "busybox", Path: "busybox", Tag: "v1.2.3", JSONPointer: "/spec/initContainers/0/image"}}},
containers: []ContainerImage{{Name: "nginx", ImageInfo: ImageInfo{Registry: "docker.io", Name: "nginx", Path: "nginx", Tag: "latest", JSONPointer: "/spec/containers/0/image"}}},
ephemeralContainers: []ContainerImage{{Name: "ephemeral", ImageInfo: ImageInfo{Registry: "docker.io", Name: "nginx", Path: "test/nginx", Tag: "latest", JSONPointer: "/spec/ephemeralContainers/0/image"}}},
},
{
raw: []byte(`{"apiVersion": "v1","kind": "Pod","metadata": {"name": "myapp"},"spec": {"containers": [{"name": "nginx","image": "test/nginx:latest"}]}}`),
initContainers: []*ContainerImage{},
containers: []*ContainerImage{{Name: "nginx", Image: &ImageInfo{Registry: "docker.io", Name: "nginx", Path: "test/nginx", Tag: "latest", JSONPointer: "/spec/containers/0/image"}}},
ephemeralContainers: []*ContainerImage{},
initContainers: []ContainerImage{},
containers: []ContainerImage{{Name: "nginx", ImageInfo: ImageInfo{Registry: "docker.io", Name: "nginx", Path: "test/nginx", Tag: "latest", JSONPointer: "/spec/containers/0/image"}}},
ephemeralContainers: []ContainerImage{},
},
{
raw: []byte(`{"apiVersion": "apps/v1","kind": "Deployment","metadata": {"name": "myapp"},"spec": {"selector": {"matchLabels": {"app": "myapp"}},"template": {"metadata": {"labels": {"app": "myapp"}},"spec": {"initContainers": [{"name": "init","image": "fictional.registry.example:10443/imagename:tag@sha256:ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"}],"containers": [{"name": "myapp","image": "fictional.registry.example:10443/imagename"}],"ephemeralContainers": [{"name": "ephemeral","image": "fictional.registry.example:10443/imagename:tag@sha256:eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"}] }}}}`),
initContainers: []*ContainerImage{{Name: "init", Image: &ImageInfo{Registry: "fictional.registry.example:10443", Name: "imagename", Path: "imagename", Tag: "tag", JSONPointer: "/spec/template/spec/initContainers/0/image", Digest: "sha256:ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"}}},
containers: []*ContainerImage{{Name: "myapp", Image: &ImageInfo{Registry: "fictional.registry.example:10443", Name: "imagename", Path: "imagename", Tag: "latest", JSONPointer: "/spec/template/spec/containers/0/image"}}},
ephemeralContainers: []*ContainerImage{{Name: "ephemeral", Image: &ImageInfo{Registry: "fictional.registry.example:10443", Name: "imagename", Path: "imagename", Tag: "tag", JSONPointer: "/spec/template/spec/ephemeralContainers/0/image", Digest: "sha256:eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"}}},
initContainers: []ContainerImage{{Name: "init", ImageInfo: ImageInfo{Registry: "fictional.registry.example:10443", Name: "imagename", Path: "imagename", Tag: "tag", JSONPointer: "/spec/template/spec/initContainers/0/image", Digest: "sha256:ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"}}},
containers: []ContainerImage{{Name: "myapp", ImageInfo: ImageInfo{Registry: "fictional.registry.example:10443", Name: "imagename", Path: "imagename", Tag: "latest", JSONPointer: "/spec/template/spec/containers/0/image"}}},
ephemeralContainers: []ContainerImage{{Name: "ephemeral", ImageInfo: ImageInfo{Registry: "fictional.registry.example:10443", Name: "imagename", Path: "imagename", Tag: "tag", JSONPointer: "/spec/template/spec/ephemeralContainers/0/image", Digest: "sha256:eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"}}},
},
{
raw: []byte(`{"apiVersion": "batch/v1beta1","kind": "CronJob","metadata": {"name": "hello"},"spec": {"schedule": "*/1 * * * *","jobTemplate": {"spec": {"template": {"spec": {"containers": [{"name": "hello","image": "test.example.com/test/my-app:v2"}]}}}}}}`),
containers: []*ContainerImage{{Name: "hello", Image: &ImageInfo{Registry: "test.example.com", Name: "my-app", Path: "test/my-app", Tag: "v2", JSONPointer: "/spec/jobTemplate/spec/template/spec/containers/0/image"}}},
containers: []ContainerImage{{Name: "hello", ImageInfo: ImageInfo{Registry: "test.example.com", Name: "my-app", Path: "test/my-app", Tag: "v2", JSONPointer: "/spec/jobTemplate/spec/template/spec/containers/0/image"}}},
},
}

View file

@ -0,0 +1,64 @@
package context
import (
"encoding/json"
)
// AddJSONObject merges json data
func AddJSONObject(ctx Interface, data interface{}) error {
jsonBytes, err := json.Marshal(data)
if err != nil {
return err
}
return ctx.addJSON(jsonBytes)
}
func AddResource(ctx Interface, dataRaw []byte) error {
var data map[string]interface{}
if err := json.Unmarshal(dataRaw, &data); err != nil {
logger.Error(err, "failed to unmarshal the resource")
return err
}
return ctx.AddResource(data)
}
func ReplaceResource(ctx Interface, data map[string]interface{}) error {
if err := ctx.AddResource(nil); err != nil {
return err
}
return ctx.AddResource(data)
}
func AddOldResource(ctx Interface, dataRaw []byte) error {
var data map[string]interface{}
if err := json.Unmarshal(dataRaw, &data); err != nil {
logger.Error(err, "failed to unmarshal the resource")
return err
}
return ctx.AddOldResource(data)
}
func ReplaceOldResource(ctx Interface, data map[string]interface{}) error {
if err := ctx.AddOldResource(nil); err != nil {
return err
}
return ctx.AddOldResource(data)
}
func addToContext(ctx *context, data interface{}, tags ...string) error {
dataRaw, err := json.Marshal(push(data, tags...))
if err != nil {
logger.Error(err, "failed to marshal the resource")
return err
}
return ctx.addJSON(dataRaw)
}
func push(data interface{}, tags ...string) interface{} {
for i := len(tags) - 1; i >= 0; i-- {
data = map[string]interface{}{
tags[i]: data,
}
}
return data
}

View file

@ -14,7 +14,7 @@ import (
// ForceMutate does not check any conditions, it simply mutates the given resource
// It is used to validate mutation logic, and for tests.
func ForceMutate(ctx *context.Context, policy kyverno.PolicyInterface, resource unstructured.Unstructured) (unstructured.Unstructured, error) {
func ForceMutate(ctx context.Interface, policy kyverno.PolicyInterface, resource unstructured.Unstructured) (unstructured.Unstructured, error) {
logger := log.Log.WithName("EngineForceMutate").WithValues("policy", policy.GetName(), "kind", resource.GetKind(),
"namespace", resource.GetNamespace(), "name", resource.GetName())

View file

@ -100,7 +100,7 @@ func Test_ForceMutateSubstituteVars(t *testing.T) {
resourceUnstructured, err := utils.ConvertToUnstructured(rawResource)
assert.NilError(t, err)
ctx := context.NewContext()
err = ctx.AddResource(rawResource)
err = context.AddResource(ctx, rawResource)
assert.NilError(t, err)
mutatedResource, err := ForceMutate(ctx, &policy, *resourceUnstructured)
@ -205,7 +205,7 @@ func Test_ForceMutateSubstituteVarsWithPatchesJson6902(t *testing.T) {
resourceUnstructured, err := utils.ConvertToUnstructured(rawResource)
assert.NilError(t, err)
ctx := context.NewContext()
err = ctx.AddResource(rawResource)
err = context.AddResource(ctx, rawResource)
assert.NilError(t, err)
mutatedResource, err := ForceMutate(ctx, &policy, *resourceUnstructured)
@ -291,7 +291,7 @@ func Test_ForceMutateSubstituteVarsWithPatchStrategicMerge(t *testing.T) {
resourceUnstructured, err := utils.ConvertToUnstructured(rawResource)
assert.NilError(t, err)
ctx := context.NewContext()
err = ctx.AddResource(rawResource)
err = context.AddResource(ctx, rawResource)
assert.NilError(t, err)
mutatedResource, err := ForceMutate(ctx, &policy, *resourceUnstructured)

View file

@ -125,7 +125,7 @@ type imageVerifier struct {
resp *response.EngineResponse
}
func (iv *imageVerifier) verify(imageVerify *v1.ImageVerification, images map[string]*context.ImageInfo) {
func (iv *imageVerifier) verify(imageVerify *v1.ImageVerification, images map[string]context.ImageInfo) {
imagePattern := imageVerify.Image
for _, imageInfo := range images {
@ -167,7 +167,7 @@ func getSignatureRepository(imageVerify *v1.ImageVerification) string {
return repository
}
func (iv *imageVerifier) verifySignature(imageVerify *v1.ImageVerification, imageInfo *context.ImageInfo) (*response.RuleResponse, string) {
func (iv *imageVerifier) verifySignature(imageVerify *v1.ImageVerification, imageInfo context.ImageInfo) (*response.RuleResponse, string) {
image := imageInfo.String()
iv.logger.Info("verifying image", "image", image)
@ -219,7 +219,7 @@ func (iv *imageVerifier) verifySignature(imageVerify *v1.ImageVerification, imag
return ruleResp, digest
}
func (iv *imageVerifier) patchDigest(imageInfo *context.ImageInfo, digest string, ruleResp *response.RuleResponse) {
func (iv *imageVerifier) patchDigest(imageInfo context.ImageInfo, digest string, ruleResp *response.RuleResponse) {
if imageInfo.Digest == "" {
patch, err := makeAddDigestPatch(imageInfo, digest)
if err != nil {
@ -231,7 +231,7 @@ func (iv *imageVerifier) patchDigest(imageInfo *context.ImageInfo, digest string
}
}
func makeAddDigestPatch(imageInfo *context.ImageInfo, digest string) ([]byte, error) {
func makeAddDigestPatch(imageInfo context.ImageInfo, digest string) ([]byte, error) {
var patch = make(map[string]interface{})
patch["op"] = "replace"
patch["path"] = imageInfo.JSONPointer
@ -239,7 +239,7 @@ func makeAddDigestPatch(imageInfo *context.ImageInfo, digest string) ([]byte, er
return json.Marshal(patch)
}
func (iv *imageVerifier) attestImage(imageVerify *v1.ImageVerification, imageInfo *context.ImageInfo) *response.RuleResponse {
func (iv *imageVerifier) attestImage(imageVerify *v1.ImageVerification, imageInfo context.ImageInfo) *response.RuleResponse {
image := imageInfo.String()
start := time.Now()
@ -291,7 +291,7 @@ func buildStatementMap(statements []map[string]interface{}) map[string][]map[str
return results
}
func (iv *imageVerifier) checkAttestations(a *v1.Attestation, s map[string]interface{}, img *context.ImageInfo) (bool, error) {
func (iv *imageVerifier) checkAttestations(a *v1.Attestation, s map[string]interface{}, img context.ImageInfo) (bool, error) {
if len(a.Conditions) == 0 {
return true, nil
}
@ -304,22 +304,11 @@ func (iv *imageVerifier) checkAttestations(a *v1.Attestation, s map[string]inter
return false, fmt.Errorf("failed to extract predicate from statement: %v", s)
}
if err := iv.policyContext.JSONContext.AddJSONObject(predicate); err != nil {
if err := context.AddJSONObject(iv.policyContext.JSONContext, predicate); err != nil {
return false, errors.Wrapf(err, fmt.Sprintf("failed to add Statement to the context %v", s))
}
imgMap := map[string]interface{}{
"image": map[string]interface{}{
"image": img.String(),
"registry": img.Registry,
"path": img.Path,
"name": img.Name,
"tag": img.Tag,
"digest": img.Digest,
},
}
if err := iv.policyContext.JSONContext.AddJSONObject(imgMap); err != nil {
if err := iv.policyContext.JSONContext.AddImageInfo(&img); err != nil {
return false, errors.Wrapf(err, fmt.Sprintf("failed to add image to the context %v", s))
}

View file

@ -164,7 +164,7 @@ func buildContext(t *testing.T, policy, resource string) *PolicyContext {
resourceUnstructured, err := utils.ConvertToUnstructured(resourceRaw)
assert.NilError(t, err)
ctx := context.NewContext()
err = ctx.AddResource(resourceRaw)
err = context.AddResource(ctx, resourceRaw)
if err != nil {
t.Error(err)
}
@ -174,7 +174,7 @@ func buildContext(t *testing.T, policy, resource string) *PolicyContext {
JSONContext: ctx,
NewResource: *resourceUnstructured}
if err := ctx.AddImageInfo(resourceUnstructured); err != nil {
if err := ctx.AddImageInfos(resourceUnstructured); err != nil {
t.Errorf("unable to add image info to variables context: %v", err)
t.Fail()
}

View file

@ -9,7 +9,6 @@ import (
"github.com/google/go-containerregistry/pkg/name"
"github.com/google/go-containerregistry/pkg/v1/remote"
kyverno "github.com/kyverno/kyverno/api/kyverno/v1"
pkgcommon "github.com/kyverno/kyverno/pkg/common"
jmespath "github.com/kyverno/kyverno/pkg/engine/jmespath"
"github.com/kyverno/kyverno/pkg/engine/variables"
"github.com/kyverno/kyverno/pkg/kyverno/store"
@ -44,9 +43,7 @@ func LoadContext(logger logr.Logger, contextEntries []kyverno.ContextEntry, ctx
value = string(newVal)
}
jsonData := pkgcommon.VariableToJSON(key, value)
if err := ctx.JSONContext.AddJSON(jsonData); err != nil {
if err := ctx.JSONContext.AddVariable(key, value); err != nil {
return err
}
}
@ -81,7 +78,11 @@ func loadImageData(logger logr.Logger, entry kyverno.ContextEntry, ctx *PolicyCo
if err != nil {
return err
}
if err := ctx.JSONContext.AddJSONObject(imageData); err != nil {
jsonBytes, err := json.Marshal(imageData)
if err != nil {
return err
}
if err := ctx.JSONContext.AddContextEntry(entry.Name, jsonBytes); err != nil {
return fmt.Errorf("failed to add resource data to context: contextEntry: %v, error: %v", entry, err)
}
return nil
@ -110,9 +111,7 @@ func fetchImageData(logger logr.Logger, entry kyverno.ContextEntry, ctx *PolicyC
return nil, fmt.Errorf("failed to apply JMESPath (%s) results to context entry %s, error: %v", entry.ImageRegistry.JMESPath, entry.Name, err)
}
}
return map[string]interface{}{
entry.Name: imageData,
}, nil
return imageData, nil
}
func fetchImageDataMap(ref string) (interface{}, error) {
@ -169,7 +168,7 @@ func loadAPIData(logger logr.Logger, entry kyverno.ContextEntry, ctx *PolicyCont
}
if entry.APICall.JMESPath == "" {
err = ctx.JSONContext.AddJSON(jsonData)
err = ctx.JSONContext.AddContextEntry(entry.Name, jsonData)
if err != nil {
return fmt.Errorf("failed to add resource data to context: contextEntry: %v, error: %v", entry, err)
}
@ -187,19 +186,17 @@ func loadAPIData(logger logr.Logger, entry kyverno.ContextEntry, ctx *PolicyCont
return err
}
contextNamedData := make(map[string]interface{})
contextNamedData[entry.Name] = results
contextData, err := json.Marshal(contextNamedData)
contextData, err := json.Marshal(results)
if err != nil {
return fmt.Errorf("failed to marshall data %v for context entry %v: %v", contextNamedData, entry, err)
return fmt.Errorf("failed to marshall data %v for context entry %v: %v", contextData, entry, err)
}
err = ctx.JSONContext.AddJSON(contextData)
err = ctx.JSONContext.AddContextEntry(entry.Name, contextData)
if err != nil {
return fmt.Errorf("failed to add JMESPath (%s) results to context, error: %v", entry.APICall.JMESPath, err)
}
logger.Info("added APICall context entry", "data", contextNamedData)
logger.Info("added APICall context entry", "data", contextData)
return nil
}
@ -286,7 +283,7 @@ func loadConfigMap(logger logr.Logger, entry kyverno.ContextEntry, ctx *PolicyCo
return fmt.Errorf("failed to retrieve config map for context entry %s: %v", entry.Name, err)
}
err = ctx.JSONContext.AddJSON(data)
err = ctx.JSONContext.AddContextEntry(entry.Name, data)
if err != nil {
return fmt.Errorf("failed to add config map for context entry %s: %v", entry.Name, err)
}
@ -324,9 +321,7 @@ func fetchConfigMap(logger logr.Logger, entry kyverno.ContextEntry, ctx *PolicyC
// extract configmap data
contextData["data"] = unstructuredObj["data"]
contextData["metadata"] = unstructuredObj["metadata"]
contextNamedData := make(map[string]interface{})
contextNamedData[entry.Name] = contextData
data, err := json.Marshal(contextNamedData)
data, err := json.Marshal(contextData)
if err != nil {
return nil, fmt.Errorf("failed to unmarshal configmap %s/%s: %v", namespace, name, err)
}

View file

@ -35,7 +35,7 @@ func newResponse(status response.RuleStatus, resource unstructured.Unstructured,
}
}
func Mutate(rule *kyverno.Rule, ctx *context.Context, resource unstructured.Unstructured, logger logr.Logger) *Response {
func Mutate(rule *kyverno.Rule, ctx context.Interface, resource unstructured.Unstructured, logger logr.Logger) *Response {
updatedRule, err := variables.SubstituteAllInRule(logger, ctx, *rule)
if err != nil {
return newErrorResponse("variable substitution failed", err)
@ -56,14 +56,14 @@ func Mutate(rule *kyverno.Rule, ctx *context.Context, resource unstructured.Unst
return newResponse(response.RuleStatusSkip, resource, nil, "no patches applied")
}
if err := ctx.AddResourceAsObject(patchedResource.Object); err != nil {
if err := ctx.AddResource(patchedResource.Object); err != nil {
return newErrorResponse("failed to update patched resource in the JSON context", err)
}
return newResponse(response.RuleStatusPass, patchedResource, resp.Patches, resp.Message)
}
func ForEach(name string, foreach *kyverno.ForEachMutation, ctx *context.Context, resource unstructured.Unstructured, logger logr.Logger) *Response {
func ForEach(name string, foreach *kyverno.ForEachMutation, ctx context.Interface, resource unstructured.Unstructured, logger logr.Logger) *Response {
fe, err := substituteAllInForEach(foreach, ctx, logger)
if err != nil {
return newErrorResponse("variable substitution failed", err)
@ -83,14 +83,14 @@ func ForEach(name string, foreach *kyverno.ForEachMutation, ctx *context.Context
return newResponse(response.RuleStatusSkip, unstructured.Unstructured{}, nil, "no patches applied")
}
if err := ctx.AddResourceAsObject(patchedResource.Object); err != nil {
if err := ctx.AddResource(patchedResource.Object); err != nil {
return newErrorResponse("failed to update patched resource in the JSON context", err)
}
return newResponse(response.RuleStatusPass, patchedResource, resp.Patches, resp.Message)
}
func substituteAllInForEach(fe *kyverno.ForEachMutation, ctx *context.Context, logger logr.Logger) (*kyverno.ForEachMutation, error) {
func substituteAllInForEach(fe *kyverno.ForEachMutation, ctx context.Interface, logger logr.Logger) (*kyverno.ForEachMutation, error) {
jsonObj, err := utils.ToMap(fe)
if err != nil {
return nil, err
@ -114,7 +114,7 @@ func substituteAllInForEach(fe *kyverno.ForEachMutation, ctx *context.Context, l
return &updatedForEach, nil
}
func NewPatcher(name string, strategicMergePatch apiextensions.JSON, jsonPatch string, r unstructured.Unstructured, ctx *context.Context, logger logr.Logger) patch.Patcher {
func NewPatcher(name string, strategicMergePatch apiextensions.JSON, jsonPatch string, r unstructured.Unstructured, ctx context.Interface, logger logr.Logger) patch.Patcher {
if strategicMergePatch != nil {
return patch.NewPatchStrategicMerge(name, strategicMergePatch, r, ctx, logger)
}

View file

@ -61,7 +61,7 @@ func Mutate(policyContext *PolicyContext) (resp *response.EngineResponse) {
resource, err := policyContext.JSONContext.Query("request.object")
policyContext.JSONContext.Reset()
if err == nil && resource != nil {
if err := ctx.AddResourceAsObject(resource.(map[string]interface{})); err != nil {
if err := ctx.AddResource(resource.(map[string]interface{})); err != nil {
logger.Error(err, "unable to update resource object")
}
} else {

View file

@ -75,7 +75,7 @@ func Test_VariableSubstitutionPatchStrategicMerge(t *testing.T) {
resourceUnstructured, err := utils.ConvertToUnstructured(resourceRaw)
assert.NilError(t, err)
ctx := context.NewContext()
err = ctx.AddResource(resourceRaw)
err = context.AddResource(ctx, resourceRaw)
if err != nil {
t.Error(err)
}
@ -155,7 +155,7 @@ func Test_variableSubstitutionPathNotExist(t *testing.T) {
assert.NilError(t, err)
ctx := context.NewContext()
err = ctx.AddResource(resourceRaw)
err = context.AddResource(ctx, resourceRaw)
assert.NilError(t, err)
policyContext := &PolicyContext{
@ -250,7 +250,7 @@ func Test_variableSubstitutionCLI(t *testing.T) {
assert.NilError(t, err)
ctx := context.NewContext()
err = ctx.AddResource(resourceRaw)
err = context.AddResource(ctx, resourceRaw)
assert.NilError(t, err)
policyContext := &PolicyContext{
@ -353,7 +353,7 @@ func Test_chained_rules(t *testing.T) {
assert.NilError(t, err)
ctx := context.NewContext()
err = ctx.AddResourceAsObject(resource.Object)
err = ctx.AddResource(resource.Object)
assert.NilError(t, err)
policyContext := &PolicyContext{
@ -362,7 +362,7 @@ func Test_chained_rules(t *testing.T) {
NewResource: *resource,
}
err = ctx.AddImageInfo(resource)
err = ctx.AddImageInfos(resource)
assert.NilError(t, err)
err = context.MutateResourceWithImageInfo(resourceRaw, ctx)
@ -447,7 +447,7 @@ func Test_precondition(t *testing.T) {
assert.NilError(t, err)
ctx := context.NewContext()
err = ctx.AddResource(resourceRaw)
err = context.AddResource(ctx, resourceRaw)
assert.NilError(t, err)
policyContext := &PolicyContext{
@ -544,7 +544,7 @@ func Test_nonZeroIndexNumberPatchesJson6902(t *testing.T) {
assert.NilError(t, err)
ctx := context.NewContext()
err = ctx.AddResource(resourceRaw)
err = context.AddResource(ctx, resourceRaw)
assert.NilError(t, err)
policyContext := &PolicyContext{
@ -632,7 +632,7 @@ func Test_foreach(t *testing.T) {
assert.NilError(t, err)
ctx := context.NewContext()
err = ctx.AddResourceAsObject(resource.Object)
err = ctx.AddResource(resource.Object)
assert.NilError(t, err)
policyContext := &PolicyContext{
@ -641,7 +641,7 @@ func Test_foreach(t *testing.T) {
NewResource: *resource,
}
err = ctx.AddImageInfo(resource)
err = ctx.AddImageInfos(resource)
assert.NilError(t, err)
err = context.MutateResourceWithImageInfo(resourceRaw, ctx)
@ -739,7 +739,7 @@ func Test_foreach_element_mutation(t *testing.T) {
assert.NilError(t, err)
ctx := context.NewContext()
err = ctx.AddResourceAsObject(resource.Object)
err = ctx.AddResource(resource.Object)
assert.NilError(t, err)
policyContext := &PolicyContext{
@ -748,7 +748,7 @@ func Test_foreach_element_mutation(t *testing.T) {
NewResource: *resource,
}
err = ctx.AddImageInfo(resource)
err = ctx.AddImageInfos(resource)
assert.NilError(t, err)
err = context.MutateResourceWithImageInfo(resourceRaw, ctx)
@ -865,7 +865,7 @@ func Test_Container_InitContainer_foreach(t *testing.T) {
assert.NilError(t, err)
ctx := context.NewContext()
err = ctx.AddResourceAsObject(resource.Object)
err = ctx.AddResource(resource.Object)
assert.NilError(t, err)
policyContext := &PolicyContext{
@ -874,7 +874,7 @@ func Test_Container_InitContainer_foreach(t *testing.T) {
NewResource: *resource,
}
err = ctx.AddImageInfo(resource)
err = ctx.AddImageInfos(resource)
assert.NilError(t, err)
err = context.MutateResourceWithImageInfo(resourceRaw, ctx)
@ -992,7 +992,7 @@ func Test_foreach_order_mutation_(t *testing.T) {
assert.NilError(t, err)
ctx := context.NewContext()
err = ctx.AddResourceAsObject(resource.Object)
err = ctx.AddResource(resource.Object)
assert.NilError(t, err)
policyContext := &PolicyContext{
@ -1001,7 +1001,7 @@ func Test_foreach_order_mutation_(t *testing.T) {
NewResource: *resource,
}
err = ctx.AddImageInfo(resource)
err = ctx.AddImageInfos(resource)
assert.NilError(t, err)
err = context.MutateResourceWithImageInfo(resourceRaw, ctx)

View file

@ -33,7 +33,7 @@ type PolicyContext struct {
ExcludeResourceFunc func(kind, namespace, name string) bool
// JSONContext is the variable context
JSONContext *context.Context
JSONContext context.Interface
// NamespaceLabels stores the label of namespace to be processed by namespace selector
NamespaceLabels map[string]string

View file

@ -10,6 +10,7 @@ import (
kyverno "github.com/kyverno/kyverno/api/kyverno/v1"
"github.com/kyverno/kyverno/pkg/autogen"
"github.com/kyverno/kyverno/pkg/engine/common"
"github.com/kyverno/kyverno/pkg/engine/context"
"github.com/pkg/errors"
"k8s.io/apiextensions-apiserver/pkg/apis/apiextensions"
@ -118,11 +119,11 @@ func validateOldObject(log logr.Logger, ctx *PolicyContext, rule *kyverno.Rule)
ctxCopy.NewResource = *ctxCopy.OldResource.DeepCopy()
ctxCopy.OldResource = unstructured.Unstructured{}
if err := ctxCopy.JSONContext.ReplaceResourceAsObject(ctxCopy.NewResource.Object); err != nil {
if err := context.ReplaceResource(ctxCopy.JSONContext, ctxCopy.NewResource.Object); err != nil {
return nil, errors.Wrapf(err, "failed to replace object in the JSON context")
}
if err := ctxCopy.JSONContext.ReplaceResourceAsOldObject(ctxCopy.OldResource.Object); err != nil {
if err := context.ReplaceOldResource(ctxCopy.JSONContext, ctxCopy.OldResource.Object); err != nil {
return nil, errors.Wrapf(err, "failed to replace old object in the JSON context")
}
@ -322,22 +323,14 @@ func addElementToContext(ctx *PolicyContext, e interface{}, elementIndex int, el
if err != nil {
return err
}
jsonData := map[string]interface{}{
"element": data,
"elementIndex": elementIndex,
}
if err := ctx.JSONContext.AddJSONObject(jsonData); err != nil {
if err := ctx.JSONContext.AddElement(data, elementIndex); err != nil {
return errors.Wrapf(err, "failed to add element (%v) to JSON context", e)
}
if elementScope {
u := unstructured.Unstructured{}
u.SetUnstructuredContent(data)
ctx.Element = u
}
return nil
}

View file

@ -1471,7 +1471,7 @@ func Test_VariableSubstitutionPathNotExistInPattern(t *testing.T) {
assert.NilError(t, err)
ctx := context.NewContext()
err = ctx.AddResource(resourceRaw)
err = context.AddResource(ctx, resourceRaw)
assert.NilError(t, err)
policyContext := &PolicyContext{
@ -1564,7 +1564,7 @@ func Test_VariableSubstitutionPathNotExistInAnyPattern_OnePatternStatisfiesButSu
assert.NilError(t, err)
ctx := context.NewContext()
err = ctx.AddResource(resourceRaw)
err = context.AddResource(ctx, resourceRaw)
assert.NilError(t, err)
policyContext := &PolicyContext{
@ -1625,7 +1625,7 @@ func Test_VariableSubstitution_NotOperatorWithStringVariable(t *testing.T) {
assert.NilError(t, err)
ctx := context.NewContext()
err = ctx.AddResource(resourceRaw)
err = context.AddResource(ctx, resourceRaw)
assert.NilError(t, err)
policyContext := &PolicyContext{
@ -1716,7 +1716,7 @@ func Test_VariableSubstitutionPathNotExistInAnyPattern_AllPathNotPresent(t *test
assert.NilError(t, err)
ctx := context.NewContext()
err = ctx.AddResource(resourceRaw)
err = context.AddResource(ctx, resourceRaw)
assert.NilError(t, err)
policyContext := &PolicyContext{
@ -1809,7 +1809,7 @@ func Test_VariableSubstitutionPathNotExistInAnyPattern_AllPathPresent_NonePatter
assert.NilError(t, err)
ctx := context.NewContext()
err = ctx.AddResource(resourceRaw)
err = context.AddResource(ctx, resourceRaw)
assert.NilError(t, err)
policyContext := &PolicyContext{
@ -1914,7 +1914,7 @@ func Test_VariableSubstitutionValidate_VariablesInMessageAreResolved(t *testing.
assert.NilError(t, err)
ctx := context.NewContext()
err = ctx.AddResource(resourceRaw)
err = context.AddResource(ctx, resourceRaw)
assert.NilError(t, err)
policyContext := &PolicyContext{
@ -1967,7 +1967,7 @@ func Test_Flux_Kustomization_PathNotPresent(t *testing.T) {
assert.NilError(t, err)
ctx := context.NewContext()
err = ctx.AddResource(test.resourceRaw)
err = context.AddResource(ctx, test.resourceRaw)
assert.NilError(t, err)
policyContext := &PolicyContext{
@ -2327,7 +2327,7 @@ func Test_EmptyStringInDenyCondition(t *testing.T) {
assert.NilError(t, err)
ctx := context.NewContext()
err = ctx.AddResource(resourceRaw)
err = context.AddResource(ctx, resourceRaw)
assert.NilError(t, err)
resourceUnstructured, err := utils.ConvertToUnstructured(resourceRaw)
@ -2416,7 +2416,7 @@ func Test_StringInDenyCondition(t *testing.T) {
assert.NilError(t, err)
ctx := context.NewContext()
err = ctx.AddResource(resourceRaw)
err = context.AddResource(ctx, resourceRaw)
assert.NilError(t, err)
resourceUnstructured, err := utils.ConvertToUnstructured(resourceRaw)
@ -3002,7 +3002,7 @@ func testForEach(t *testing.T, policyraw []byte, resourceRaw []byte, msg string,
assert.NilError(t, err)
ctx := context.NewContext()
err = ctx.AddResource(resourceRaw)
err = context.AddResource(ctx, resourceRaw)
assert.NilError(t, err)
policyContext := &PolicyContext{
@ -3066,7 +3066,7 @@ func Test_delete_ignore_pattern(t *testing.T) {
assert.NilError(t, err)
ctx := context.NewContext()
err = ctx.AddResource(resourceRaw)
err = context.AddResource(ctx, resourceRaw)
assert.NilError(t, err)
policyContextCreate := &PolicyContext{

View file

@ -402,7 +402,7 @@ func Test_Eval_Equal_Var_Pass(t *testing.T) {
// context
ctx := context.NewContext()
err := ctx.AddResource(resourceRaw)
err := context.AddResource(ctx, resourceRaw)
if err != nil {
t.Error(err)
}
@ -444,7 +444,7 @@ func Test_Eval_Equal_Var_Fail(t *testing.T) {
// context
ctx := context.NewContext()
err := ctx.AddResource(resourceRaw)
err := context.AddResource(ctx, resourceRaw)
if err != nil {
t.Error(err)
}

View file

@ -76,7 +76,7 @@ func Test_variablesub1(t *testing.T) {
}
// context
ctx := context.NewContext()
err = ctx.AddResource(resourceRaw)
err = context.AddResource(ctx, resourceRaw)
if err != nil {
t.Error(err)
}
@ -166,7 +166,7 @@ func Test_variablesub_multiple(t *testing.T) {
// context
ctx := context.NewContext()
err = ctx.AddResource(resourceRaw)
err = context.AddResource(ctx, resourceRaw)
if err != nil {
t.Error(err)
}
@ -253,7 +253,7 @@ func Test_variablesubstitution(t *testing.T) {
// context
ctx := context.NewContext()
err = ctx.AddResource(resourceRaw)
err = context.AddResource(ctx, resourceRaw)
if err != nil {
t.Error(err)
}
@ -319,7 +319,7 @@ func Test_variableSubstitutionValue(t *testing.T) {
// context
ctx := context.NewContext()
err = ctx.AddResource(resourceRaw)
err = context.AddResource(ctx, resourceRaw)
if err != nil {
t.Error(err)
}
@ -377,7 +377,7 @@ func Test_variableSubstitutionValueOperatorNotEqual(t *testing.T) {
// context
ctx := context.NewContext()
err = ctx.AddResource(resourceRaw)
err = context.AddResource(ctx, resourceRaw)
if err != nil {
t.Error(err)
}
@ -436,7 +436,7 @@ func Test_variableSubstitutionValueFail(t *testing.T) {
// context
ctx := context.NewContext()
err = ctx.AddResource(resourceRaw)
err = context.AddResource(ctx, resourceRaw)
if err != nil {
t.Error(err)
}
@ -494,7 +494,7 @@ func Test_variableSubstitutionObject(t *testing.T) {
// context
ctx := context.NewContext()
err = ctx.AddResource(resourceRaw)
err = context.AddResource(ctx, resourceRaw)
if err != nil {
t.Error(err)
}
@ -558,7 +558,7 @@ func Test_variableSubstitutionObjectOperatorNotEqualFail(t *testing.T) {
// context
ctx := context.NewContext()
err = ctx.AddResource(resourceRaw)
err = context.AddResource(ctx, resourceRaw)
if err != nil {
t.Error(err)
}
@ -633,7 +633,7 @@ func Test_variableSubstitutionMultipleObject(t *testing.T) {
// context
ctx := context.NewContext()
err = ctx.AddResource(resourceRaw)
err = context.AddResource(ctx, resourceRaw)
if err != nil {
t.Error(err)
}

View file

@ -189,7 +189,7 @@ func substituteAll(log logr.Logger, ctx context.EvalInterface, document interfac
return substituteVars(log, ctx, document, resolver)
}
func SubstituteAllForceMutate(log logr.Logger, ctx *context.Context, typedRule kyverno.Rule) (_ kyverno.Rule, err error) {
func SubstituteAllForceMutate(log logr.Logger, ctx context.Interface, typedRule kyverno.Rule) (_ kyverno.Rule, err error) {
var rule interface{}
rule, err = DocumentToUntyped(typedRule)

View file

@ -65,7 +65,7 @@ func Test_subVars_success(t *testing.T) {
}
// context
ctx := context.NewContext()
err = ctx.AddResource(resourceRaw)
err = context.AddResource(ctx, resourceRaw)
if err != nil {
t.Error(err)
}
@ -126,7 +126,7 @@ func Test_subVars_failed(t *testing.T) {
}
// context
ctx := context.NewContext()
err = ctx.AddResource(resourceRaw)
err = context.AddResource(ctx, resourceRaw)
if err != nil {
t.Error(err)
}
@ -220,7 +220,7 @@ func Test_subVars_with_JMESPath_At(t *testing.T) {
assert.NilError(t, err)
// context
ctx := context.NewContext()
err = ctx.AddResource(resourceRaw)
err = context.AddResource(ctx, resourceRaw)
assert.NilError(t, err)
output, err := SubstituteAll(log.Log, ctx, pattern)
@ -279,7 +279,7 @@ func Test_subVars_withRegexMatch(t *testing.T) {
assert.NilError(t, err)
// context
ctx := context.NewContext()
err = ctx.AddResource(resourceRaw)
err = context.AddResource(ctx, resourceRaw)
assert.NilError(t, err)
output, err := SubstituteAll(log.Log, ctx, pattern)
@ -309,7 +309,7 @@ func Test_subVars_withMerge(t *testing.T) {
assert.NilError(t, err)
// context
ctx := context.NewContext()
err = ctx.AddResource(resourceRaw)
err = context.AddResource(ctx, resourceRaw)
assert.NilError(t, err)
output, err := SubstituteAll(log.Log, ctx, pattern)
@ -352,7 +352,7 @@ func Test_subVars_withRegexReplaceAll(t *testing.T) {
assert.NilError(t, err)
// context
ctx := context.NewContext()
err = ctx.AddResource(resourceRaw)
err = context.AddResource(ctx, resourceRaw)
assert.NilError(t, err)
output, err := SubstituteAll(log.Log, ctx, pattern)
@ -396,8 +396,7 @@ func Test_ReplacingPathWhenDeleting(t *testing.T) {
if err != nil {
t.Error(err)
}
ctx := context.NewContext()
err = ctx.AddJSON(resourceRaw)
ctx := context.NewContextFromRaw(resourceRaw)
assert.NilError(t, err)
pattern, err = SubstituteAll(log.Log, ctx, pattern)
@ -432,8 +431,7 @@ func Test_ReplacingNestedVariableWhenDeleting(t *testing.T) {
if err != nil {
t.Error(err)
}
ctx := context.NewContext()
err = ctx.AddJSON(resourceRaw)
ctx := context.NewContextFromRaw(resourceRaw)
assert.NilError(t, err)
pattern, err = SubstituteAll(log.Log, ctx, pattern)
@ -460,7 +458,7 @@ var resourceRaw = []byte(`
func Test_SubstituteSuccess(t *testing.T) {
ctx := context.NewContext()
assert.Assert(t, ctx.AddResource(resourceRaw))
assert.Assert(t, context.AddResource(ctx, resourceRaw))
var pattern interface{}
patternRaw := []byte(`"{{request.object.metadata.annotations.test}}"`)
@ -484,7 +482,7 @@ func Test_SubstituteSuccess(t *testing.T) {
func Test_SubstituteRecursiveErrors(t *testing.T) {
ctx := context.NewContext()
assert.Assert(t, ctx.AddResource(resourceRaw))
assert.Assert(t, context.AddResource(ctx, resourceRaw))
var pattern interface{}
patternRaw := []byte(`"{{request.object.metadata.{{request.object.metadata.annotations.test2}}}}"`)
@ -516,7 +514,7 @@ func Test_SubstituteRecursiveErrors(t *testing.T) {
func Test_SubstituteRecursive(t *testing.T) {
ctx := context.NewContext()
assert.Assert(t, ctx.AddResource(resourceRaw))
assert.Assert(t, context.AddResource(ctx, resourceRaw))
var pattern interface{}
patternRaw := []byte(`"{{request.object.metadata.{{request.object.metadata.annotations.test}}}}"`)
@ -633,9 +631,8 @@ func Test_variableSubstitution_array(t *testing.T) {
err := json.Unmarshal(ruleRaw, &rule)
assert.NilError(t, err)
ctx := context.NewContext()
ctx.AddJSON(configmapRaw)
ctx.AddResource(resourceRaw)
ctx := context.NewContextFromRaw(configmapRaw)
context.AddResource(ctx, resourceRaw)
vars, err := SubstituteAllInRule(log.Log, ctx, rule)
assert.NilError(t, err)
@ -681,7 +678,7 @@ func Test_SubstituteNull(t *testing.T) {
assert.NilError(t, err)
ctx := context.NewContext()
ctx.AddResource(variableObject)
context.AddResource(ctx, variableObject)
resolved, err := SubstituteAll(log.Log, ctx, pattern)
assert.NilError(t, err)
@ -710,7 +707,7 @@ func Test_SubstituteNullInString(t *testing.T) {
assert.NilError(t, err)
ctx := context.NewContext()
ctx.AddResource(variableObject)
context.AddResource(ctx, variableObject)
resolved, err := SubstituteAll(log.Log, ctx, pattern)
assert.NilError(t, err)
@ -739,7 +736,7 @@ func Test_SubstituteArray(t *testing.T) {
assert.NilError(t, err)
ctx := context.NewContext()
ctx.AddResource(variableObject)
context.AddResource(ctx, variableObject)
resolved, err := SubstituteAll(log.Log, ctx, pattern)
assert.NilError(t, err)
@ -768,7 +765,7 @@ func Test_SubstituteArrayInString(t *testing.T) {
assert.NilError(t, err)
ctx := context.NewContext()
ctx.AddResource(variableObject)
context.AddResource(ctx, variableObject)
resolved, err := SubstituteAll(log.Log, ctx, pattern)
assert.NilError(t, err)
@ -797,7 +794,7 @@ func Test_SubstituteInt(t *testing.T) {
assert.NilError(t, err)
ctx := context.NewContext()
ctx.AddResource(variableObject)
context.AddResource(ctx, variableObject)
resolved, err := SubstituteAll(log.Log, ctx, pattern)
assert.NilError(t, err)
@ -826,7 +823,7 @@ func Test_SubstituteIntInString(t *testing.T) {
assert.NilError(t, err)
ctx := context.NewContext()
ctx.AddResource(variableObject)
context.AddResource(ctx, variableObject)
resolved, err := SubstituteAll(log.Log, ctx, pattern)
assert.NilError(t, err)
@ -855,7 +852,7 @@ func Test_SubstituteBool(t *testing.T) {
assert.NilError(t, err)
ctx := context.NewContext()
ctx.AddResource(variableObject)
context.AddResource(ctx, variableObject)
resolved, err := SubstituteAll(log.Log, ctx, pattern)
assert.NilError(t, err)
@ -884,7 +881,7 @@ func Test_SubstituteBoolInString(t *testing.T) {
assert.NilError(t, err)
ctx := context.NewContext()
ctx.AddResource(variableObject)
context.AddResource(ctx, variableObject)
resolved, err := SubstituteAll(log.Log, ctx, pattern)
assert.NilError(t, err)
@ -913,7 +910,7 @@ func Test_SubstituteString(t *testing.T) {
assert.NilError(t, err)
ctx := context.NewContext()
ctx.AddResource(variableObject)
context.AddResource(ctx, variableObject)
resolved, err := SubstituteAll(log.Log, ctx, pattern)
assert.NilError(t, err)
@ -942,7 +939,7 @@ func Test_SubstituteStringInString(t *testing.T) {
assert.NilError(t, err)
ctx := context.NewContext()
ctx.AddResource(variableObject)
context.AddResource(ctx, variableObject)
resolved, err := SubstituteAll(log.Log, ctx, pattern)
assert.NilError(t, err)
@ -993,7 +990,7 @@ func Test_ReferenceSubstitution(t *testing.T) {
assert.NilError(t, err)
ctx := context.NewContext()
err = ctx.AddResource(jsonRaw)
err = context.AddResource(ctx, jsonRaw)
assert.NilError(t, err)
actualDocument, err := SubstituteAll(log.Log, ctx, document)
@ -1137,7 +1134,7 @@ func Test_EscpReferenceSubstitution(t *testing.T) {
assert.NilError(t, err)
ctx := context.NewContext()
err = ctx.AddResource(jsonRaw)
err = context.AddResource(ctx, jsonRaw)
assert.NilError(t, err)
actualDocument, err := SubstituteAll(log.Log, ctx, document)
@ -1172,8 +1169,7 @@ func Test_ReplacingEscpNestedVariableWhenDeleting(t *testing.T) {
if err != nil {
t.Error(err)
}
ctx := context.NewContext()
err = ctx.AddJSON(resourceRaw)
ctx := context.NewContextFromRaw(resourceRaw)
assert.NilError(t, err)
pattern, err = SubstituteAll(log.Log, ctx, pattern)

View file

@ -161,13 +161,7 @@ func (c *Controller) applyGenerate(resource unstructured.Unstructured, gr kyvern
return nil, false, err
}
resourceRaw, err := resource.MarshalJSON()
if err != nil {
logger.Error(err, "failed to marshal resource")
return nil, false, err
}
err = ctx.AddResource(resourceRaw)
err = ctx.AddResource(resource.Object)
if err != nil {
logger.Error(err, "failed to load resource in context")
return nil, false, err
@ -185,7 +179,7 @@ func (c *Controller) applyGenerate(resource unstructured.Unstructured, gr kyvern
return nil, false, err
}
if err := ctx.AddImageInfo(&resource); err != nil {
if err := ctx.AddImageInfos(&resource); err != nil {
logger.Error(err, "unable to add image info to variables context")
}

View file

@ -21,7 +21,6 @@ import (
"github.com/go-logr/logr"
v1 "github.com/kyverno/kyverno/api/kyverno/v1"
report "github.com/kyverno/kyverno/api/policyreport/v1alpha2"
pkgcommon "github.com/kyverno/kyverno/pkg/common"
client "github.com/kyverno/kyverno/pkg/dclient"
"github.com/kyverno/kyverno/pkg/engine"
"github.com/kyverno/kyverno/pkg/engine/context"
@ -512,9 +511,9 @@ OuterLoop:
ctx := context.NewContext()
if operationIsDelete {
err = ctx.AddResourceInOldObject(resourceRaw)
err = context.AddOldResource(ctx, resourceRaw)
} else {
err = ctx.AddResourceAsObject(updated_resource.Object)
err = context.AddResource(ctx, resourceRaw)
}
if err != nil {
@ -522,14 +521,13 @@ OuterLoop:
}
for key, value := range variables {
jsonData := pkgcommon.VariableToJSON(key, value)
err = ctx.AddJSON(jsonData)
err = ctx.AddVariable(key, value)
if err != nil {
log.Log.Error(err, "failed to add variable to context")
}
}
if err := ctx.AddImageInfo(resource); err != nil {
if err := ctx.AddImageInfos(resource); err != nil {
if err != nil {
log.Log.Error(err, "failed to add image variables to context")
}

View file

@ -38,7 +38,7 @@ func applyPolicy(policy kyverno.PolicyInterface, resource unstructured.Unstructu
var err error
ctx := context.NewContext()
err = ctx.AddResource(transformResource(resource))
err = context.AddResource(ctx, transformResource(resource))
if err != nil {
logger.Error(err, "failed to add transform resource to ctx")
}
@ -48,7 +48,7 @@ func applyPolicy(policy kyverno.PolicyInterface, resource unstructured.Unstructu
logger.Error(err, "failed to add namespace to ctx")
}
if err := ctx.AddImageInfo(&resource); err != nil {
if err := ctx.AddImageInfos(&resource); err != nil {
logger.Error(err, "unable to add image info to variables context")
}
@ -72,7 +72,7 @@ func applyPolicy(policy kyverno.PolicyInterface, resource unstructured.Unstructu
return engineResponses
}
func mutation(policy kyverno.PolicyInterface, resource unstructured.Unstructured, log logr.Logger, jsonContext *context.Context, namespaceLabels map[string]string) (*response.EngineResponse, error) {
func mutation(policy kyverno.PolicyInterface, resource unstructured.Unstructured, log logr.Logger, jsonContext context.Interface, namespaceLabels map[string]string) (*response.EngineResponse, error) {
policyContext := &engine.PolicyContext{
Policy: policy,

View file

@ -157,7 +157,7 @@ func excludeKyvernoResources(kind string) bool {
}
}
func newVariablesContext(request *admissionv1.AdmissionRequest, userRequestInfo *kyverno.RequestInfo) (*enginectx.Context, error) {
func newVariablesContext(request *admissionv1.AdmissionRequest, userRequestInfo *kyverno.RequestInfo) (enginectx.Interface, error) {
ctx := enginectx.NewContext()
if err := ctx.AddRequest(request); err != nil {
return nil, errors.Wrap(err, "failed to load incoming request in context")

View file

@ -45,7 +45,7 @@ func (ws *WebhookServer) applyGeneratePolicies(request *admissionv1.AdmissionReq
func (ws *WebhookServer) handleGenerate(
request *admissionv1.AdmissionRequest,
policies []kyverno.PolicyInterface,
ctx *context.Context,
ctx context.Interface,
userRequestInfo kyverno.RequestInfo,
dynamicConfig config.Interface,
admissionRequestTimestamp int64,

View file

@ -195,7 +195,7 @@ func (ws *WebhookServer) resourceValidation(request *admissionv1.AdmissionReques
if err != nil {
return errorResponse(logger, err, "failed create parse resource")
}
if err := ctx.AddImageInfo(&newResource); err != nil {
if err := ctx.AddImageInfos(&newResource); err != nil {
return errorResponse(logger, err, "failed add image information to policy rule context")
}
policyContext := &engine.PolicyContext{

View file

@ -228,7 +228,7 @@ func (ws *WebhookServer) buildPolicyContext(request *admissionv1.AdmissionReques
return nil, errors.Wrap(err, "failed to convert raw resource to unstructured format")
}
if err := ctx.AddImageInfo(&resource); err != nil {
if err := ctx.AddImageInfos(&resource); err != nil {
return nil, errors.Wrap(err, "failed to add image information to the policy rule context")
}

View file

@ -181,7 +181,7 @@ func (h *auditHandler) process(request *admissionv1.AdmissionRequest) error {
return errors.Wrap(err, "failed create parse resource")
}
if err := ctx.AddImageInfo(&newResource); err != nil {
if err := ctx.AddImageInfos(&newResource); err != nil {
return errors.Wrap(err, "failed add image information to policy rule context\"")
}