mirror of
https://github.com/kyverno/kyverno.git
synced 2025-03-24 08:36:46 +00:00
fix: use object key in json image verification (#12298)
This commit is contained in:
parent
c0c9cec7c3
commit
32f13d5894
5 changed files with 55 additions and 57 deletions
|
@ -64,16 +64,12 @@ func (c *compiler) Compile(logger logr.Logger, ivpolicy *policiesv1alpha1.ImageV
|
|||
options = append(options, cel.Variable(ObjectKey, cel.DynType))
|
||||
options = append(options, cel.Variable(OldObjectKey, cel.DynType))
|
||||
} else {
|
||||
options = append(options, cel.Variable(RequestKey, cel.DynType))
|
||||
options = append(options, cel.Variable(ObjectKey, cel.DynType))
|
||||
}
|
||||
|
||||
for _, declType := range declTypes {
|
||||
options = append(options, cel.Types(declType.CelType()))
|
||||
}
|
||||
if err != nil {
|
||||
// TODO: proper error handling
|
||||
panic(err)
|
||||
}
|
||||
options = append(options, imageverifierfunctions.Lib(logger, c.ictx, ivpolicy, c.lister))
|
||||
env, err := base.Extend(options...)
|
||||
if err != nil {
|
||||
|
@ -94,7 +90,7 @@ func (c *compiler) Compile(logger logr.Logger, ivpolicy *policiesv1alpha1.ImageV
|
|||
return nil, append(allErrs, errs...)
|
||||
}
|
||||
|
||||
imageExtractors, errs := variables.CompileImageExtractors(path.Child("images"), ivpolicy.Spec.Images, c.reqGVR)
|
||||
imageExtractors, errs := variables.CompileImageExtractors(path.Child("images"), ivpolicy.Spec.Images, c.reqGVR, options)
|
||||
if errs != nil {
|
||||
return nil, append(allErrs, errs...)
|
||||
}
|
||||
|
|
|
@ -35,7 +35,7 @@ var (
|
|||
Images: []policiesv1alpha1.Image{
|
||||
{
|
||||
Name: "bar",
|
||||
Expression: "[request.foo.bar]",
|
||||
Expression: "[object.foo.bar]",
|
||||
},
|
||||
},
|
||||
Attestors: []policiesv1alpha1.Attestor{
|
||||
|
|
|
@ -73,10 +73,10 @@ func (c *compiledPolicy) Evaluate(ctx context.Context, ictx imagedataloader.Imag
|
|||
data[ObjectKey] = objectVal
|
||||
data[OldObjectKey] = oldObjectVal
|
||||
} else {
|
||||
data[RequestKey] = request
|
||||
data[ObjectKey] = request
|
||||
}
|
||||
|
||||
images, err := variables.ExtractImages(c.imageExtractors, request)
|
||||
images, err := variables.ExtractImages(c.imageExtractors, data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -151,7 +151,7 @@ func (p *compiledPolicy) match(
|
|||
data[NamespaceObjectKey] = namespaceVal
|
||||
data[RequestKey] = requestVal.Object
|
||||
} else {
|
||||
data[RequestKey] = request
|
||||
data[ObjectKey] = request
|
||||
}
|
||||
|
||||
var errs []error
|
||||
|
|
|
@ -2,9 +2,7 @@ package variables
|
|||
|
||||
import (
|
||||
"github.com/google/cel-go/cel"
|
||||
"github.com/google/cel-go/common/types"
|
||||
"github.com/kyverno/kyverno/api/policies.kyverno.io/v1alpha1"
|
||||
"github.com/kyverno/kyverno/pkg/cel/policy"
|
||||
"github.com/kyverno/kyverno/pkg/cel/utils"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/util/validation/field"
|
||||
|
@ -60,10 +58,8 @@ type CompiledImageExtractor struct {
|
|||
e cel.Program
|
||||
}
|
||||
|
||||
func (c *CompiledImageExtractor) GetImages(request interface{}) (string, []string, error) {
|
||||
out, _, err := c.e.Eval(map[string]any{
|
||||
policy.RequestKey: request,
|
||||
})
|
||||
func (c *CompiledImageExtractor) GetImages(data map[string]any) (string, []string, error) {
|
||||
out, _, err := c.e.Eval(data)
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
|
@ -76,17 +72,14 @@ func (c *CompiledImageExtractor) GetImages(request interface{}) (string, []strin
|
|||
return c.key, result, nil
|
||||
}
|
||||
|
||||
func CompileImageExtractors(path *field.Path, imageExtractors []v1alpha1.Image, gvr *metav1.GroupVersionResource) ([]*CompiledImageExtractor, field.ErrorList) {
|
||||
func CompileImageExtractors(path *field.Path, imageExtractors []v1alpha1.Image, gvr *metav1.GroupVersionResource, envOpts []cel.EnvOption) ([]*CompiledImageExtractor, field.ErrorList) {
|
||||
var allErrs field.ErrorList
|
||||
if gvr != nil {
|
||||
imageExtractors = append(imageExtractors, getExtractorForGVR(gvr)...)
|
||||
}
|
||||
|
||||
compiledMatches := make([]*CompiledImageExtractor, 0, len(imageExtractors))
|
||||
e, err := cel.NewEnv(
|
||||
// this uses dyn type to allow unstructured data
|
||||
cel.Variable(policy.RequestKey, types.DynType),
|
||||
)
|
||||
e, err := cel.NewEnv(envOpts...)
|
||||
if err != nil {
|
||||
return nil, append(allErrs, field.Invalid(path, imageExtractors, err.Error()))
|
||||
}
|
||||
|
@ -111,10 +104,10 @@ func CompileImageExtractors(path *field.Path, imageExtractors []v1alpha1.Image,
|
|||
return compiledMatches, nil
|
||||
}
|
||||
|
||||
func ExtractImages(c []*CompiledImageExtractor, request interface{}) (map[string][]string, error) {
|
||||
func ExtractImages(c []*CompiledImageExtractor, data map[string]any) (map[string][]string, error) {
|
||||
result := make(map[string][]string)
|
||||
for _, v := range c {
|
||||
if key, images, err := v.GetImages(request); err != nil {
|
||||
if key, images, err := v.GetImages(data); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
result[key] = images
|
||||
|
|
|
@ -5,7 +5,10 @@ import (
|
|||
"slices"
|
||||
"testing"
|
||||
|
||||
"github.com/google/cel-go/cel"
|
||||
"github.com/google/cel-go/common/types"
|
||||
"github.com/kyverno/kyverno/api/policies.kyverno.io/v1alpha1"
|
||||
"github.com/kyverno/kyverno/pkg/cel/policy"
|
||||
"github.com/stretchr/testify/assert"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/util/validation/field"
|
||||
|
@ -15,7 +18,7 @@ func Test_Match(t *testing.T) {
|
|||
tests := []struct {
|
||||
name string
|
||||
imageExtractor []v1alpha1.Image
|
||||
request any
|
||||
request map[string]any
|
||||
gvr *metav1.GroupVersionResource
|
||||
wantResult map[string][]string
|
||||
wantErr bool
|
||||
|
@ -28,10 +31,12 @@ func Test_Match(t *testing.T) {
|
|||
Expression: "request.images",
|
||||
},
|
||||
},
|
||||
request: map[string][]string{
|
||||
"images": {
|
||||
"nginx:latest",
|
||||
"alpine:latest",
|
||||
request: map[string]any{
|
||||
"request": map[string][]string{
|
||||
"images": {
|
||||
"nginx:latest",
|
||||
"alpine:latest",
|
||||
},
|
||||
},
|
||||
},
|
||||
wantResult: map[string][]string{
|
||||
|
@ -52,34 +57,36 @@ func Test_Match(t *testing.T) {
|
|||
},
|
||||
},
|
||||
request: map[string]any{
|
||||
"images": []string{
|
||||
"nginx:latest",
|
||||
"alpine:latest",
|
||||
},
|
||||
"object": map[string]any{
|
||||
"spec": map[string]any{
|
||||
"containers": []map[string]string{
|
||||
{
|
||||
"image": "kyverno/image-one",
|
||||
"request": map[string]any{
|
||||
"images": []string{
|
||||
"nginx:latest",
|
||||
"alpine:latest",
|
||||
},
|
||||
"object": map[string]any{
|
||||
"spec": map[string]any{
|
||||
"containers": []map[string]string{
|
||||
{
|
||||
"image": "kyverno/image-one",
|
||||
},
|
||||
{
|
||||
"image": "kyverno/image-two",
|
||||
},
|
||||
},
|
||||
{
|
||||
"image": "kyverno/image-two",
|
||||
"initContainers": []map[string]string{
|
||||
{
|
||||
"image": "kyverno/init-image-one",
|
||||
},
|
||||
{
|
||||
"image": "kyverno/init-image-two",
|
||||
},
|
||||
},
|
||||
},
|
||||
"initContainers": []map[string]string{
|
||||
{
|
||||
"image": "kyverno/init-image-one",
|
||||
},
|
||||
{
|
||||
"image": "kyverno/init-image-two",
|
||||
},
|
||||
},
|
||||
"ephemeralContainers": []map[string]string{
|
||||
{
|
||||
"image": "kyverno/ephr-image-one",
|
||||
},
|
||||
{
|
||||
"image": "kyverno/ephr-image-two",
|
||||
"ephemeralContainers": []map[string]string{
|
||||
{
|
||||
"image": "kyverno/ephr-image-one",
|
||||
},
|
||||
{
|
||||
"image": "kyverno/ephr-image-two",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -114,8 +121,10 @@ func Test_Match(t *testing.T) {
|
|||
Expression: "request.images",
|
||||
},
|
||||
},
|
||||
request: map[string][]int{
|
||||
"images": {0, 1},
|
||||
request: map[string]any{
|
||||
"request": map[string][]int{
|
||||
"images": {0, 1},
|
||||
},
|
||||
},
|
||||
gvr: nil,
|
||||
wantErr: true,
|
||||
|
@ -123,7 +132,7 @@ func Test_Match(t *testing.T) {
|
|||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
c, errList := CompileImageExtractors(field.NewPath("spec", "images"), tt.imageExtractor, tt.gvr)
|
||||
c, errList := CompileImageExtractors(field.NewPath("spec", "images"), tt.imageExtractor, tt.gvr, []cel.EnvOption{cel.Variable(policy.RequestKey, types.DynType)})
|
||||
assert.Nil(t, errList)
|
||||
images, err := ExtractImages(c, tt.request)
|
||||
if tt.wantErr {
|
||||
|
|
Loading…
Add table
Reference in a new issue