1
0
Fork 0
mirror of https://github.com/kyverno/kyverno.git synced 2025-03-26 01:24:26 +00:00
kyverno/pkg/imageverification/evaluator/compiler.go
Charles-Edouard Brétéché 2bb687550c
feat: add imagedata cel lib (#12442)
Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com>
2025-03-19 17:03:23 +08:00

131 lines
4.7 KiB
Go

package eval
import (
"github.com/google/cel-go/cel"
policiesv1alpha1 "github.com/kyverno/kyverno/api/policies.kyverno.io/v1alpha1"
engine "github.com/kyverno/kyverno/pkg/cel"
"github.com/kyverno/kyverno/pkg/cel/libs/globalcontext"
"github.com/kyverno/kyverno/pkg/cel/libs/http"
"github.com/kyverno/kyverno/pkg/cel/libs/imagedata"
"github.com/kyverno/kyverno/pkg/cel/libs/imageverify"
"github.com/kyverno/kyverno/pkg/cel/libs/resource"
"github.com/kyverno/kyverno/pkg/cel/libs/user"
"github.com/kyverno/kyverno/pkg/cel/policy"
"github.com/kyverno/kyverno/pkg/imageverification/imagedataloader"
"github.com/kyverno/kyverno/pkg/imageverification/match"
"github.com/kyverno/kyverno/pkg/imageverification/variables"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/validation/field"
apiservercel "k8s.io/apiserver/pkg/cel"
k8scorev1 "k8s.io/client-go/kubernetes/typed/core/v1"
)
const (
AttestationKey = "attestations"
AttestorKey = "attestors"
GlobalContextKey = "globalcontext"
HttpKey = "http"
ImagesKey = "images"
NamespaceObjectKey = "namespaceObject"
ObjectKey = "object"
OldObjectKey = "oldObject"
RequestKey = "request"
ResourceKey = "resource"
)
type Compiler interface {
Compile(*policiesv1alpha1.ImageVerificationPolicy) (CompiledPolicy, field.ErrorList)
}
func NewCompiler(ictx imagedataloader.ImageContext, lister k8scorev1.SecretInterface, reqGVR *metav1.GroupVersionResource) Compiler {
return &compiler{
ictx: ictx,
lister: lister,
reqGVR: reqGVR,
}
}
type compiler struct {
ictx imagedataloader.ImageContext
lister k8scorev1.SecretInterface
reqGVR *metav1.GroupVersionResource
}
func (c *compiler) Compile(ivpolicy *policiesv1alpha1.ImageVerificationPolicy) (CompiledPolicy, field.ErrorList) {
var allErrs field.ErrorList
base, err := engine.NewEnv()
if err != nil {
return nil, append(allErrs, field.InternalError(nil, err))
}
var declTypes []*apiservercel.DeclType
declTypes = append(declTypes, imageverify.Types()...)
options := []cel.EnvOption{
cel.Variable(ResourceKey, resource.ContextType),
cel.Variable(GlobalContextKey, globalcontext.ContextType),
cel.Variable(HttpKey, http.HTTPType),
cel.Variable(ImagesKey, cel.MapType(cel.StringType, cel.ListType(cel.StringType))),
cel.Variable(AttestorKey, cel.MapType(cel.StringType, cel.StringType)),
cel.Variable(AttestationKey, cel.MapType(cel.StringType, cel.StringType)),
}
if ivpolicy.Spec.EvaluationMode() == policiesv1alpha1.EvaluationModeKubernetes {
options = append(options, cel.Variable(RequestKey, policy.RequestType.CelType()))
options = append(options, cel.Variable(NamespaceObjectKey, policy.NamespaceType.CelType()))
options = append(options, cel.Variable(ObjectKey, cel.DynType))
options = append(options, cel.Variable(OldObjectKey, cel.DynType))
} else {
options = append(options, cel.Variable(ObjectKey, cel.DynType))
}
for _, declType := range declTypes {
options = append(options, cel.Types(declType.CelType()))
}
options = append(options, globalcontext.Lib(), http.Lib(), imagedata.Lib(), imageverify.Lib(c.ictx, ivpolicy, c.lister), resource.Lib(), user.Lib())
env, err := base.Extend(options...)
if err != nil {
return nil, append(allErrs, field.InternalError(nil, err))
}
path := field.NewPath("spec")
matchConditions := make([]cel.Program, 0, len(ivpolicy.Spec.MatchConditions))
{
path := path.Child("matchConditions")
programs, errs := policy.CompileMatchConditions(path, ivpolicy.Spec.MatchConditions, env)
if errs != nil {
return nil, append(allErrs, errs...)
}
matchConditions = append(matchConditions, programs...)
}
imageRules, errs := match.CompileMatches(path.Child("imageRules"), ivpolicy.Spec.ImageRules)
if errs != nil {
return nil, append(allErrs, errs...)
}
imageExtractors, errs := variables.CompileImageExtractors(path.Child("images"), ivpolicy.Spec.Images, c.reqGVR, options)
if errs != nil {
return nil, append(allErrs, errs...)
}
verifications := make([]policy.CompiledValidation, 0, len(ivpolicy.Spec.Verifications))
{
path := path.Child("verifications")
for i, rule := range ivpolicy.Spec.Verifications {
path := path.Index(i)
program, errs := policy.CompileValidation(path, rule, env)
if errs != nil {
return nil, append(allErrs, errs...)
}
verifications = append(verifications, program)
}
}
return &compiledPolicy{
failurePolicy: ivpolicy.GetFailurePolicy(),
matchConditions: matchConditions,
imageRules: imageRules,
verifications: verifications,
imageExtractors: imageExtractors,
attestorList: variables.GetAttestors(ivpolicy.Spec.Attestors),
attestationList: variables.GetAttestations(ivpolicy.Spec.Attestations),
creds: ivpolicy.Spec.Credentials,
}, nil
}