mirror of
https://github.com/kyverno/kyverno.git
synced 2025-03-09 17:37:12 +00:00
* feat: add variables Signed-off-by: Vishal Choudhary <vishal.choudhary@nirmata.com> * feat: implement evaluator Signed-off-by: Vishal Choudhary <vishal.choudhary@nirmata.com> * fix: build Signed-off-by: Vishal Choudhary <vishal.choudhary@nirmata.com> * fix: linter Signed-off-by: Vishal Choudhary <vishal.choudhary@nirmata.com> * fix: unit tests Signed-off-by: Vishal Choudhary <vishal.choudhary@nirmata.com> --------- Signed-off-by: Vishal Choudhary <vishal.choudhary@nirmata.com>
94 lines
2.4 KiB
Go
94 lines
2.4 KiB
Go
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"
|
|
"k8s.io/apimachinery/pkg/util/validation/field"
|
|
)
|
|
|
|
var podImageExtractors = []v1alpha1.Image{
|
|
{
|
|
Name: "containers",
|
|
Expression: "request.object.spec.containers.map(e, e.image)",
|
|
},
|
|
{
|
|
Name: "initContainers",
|
|
Expression: "request.object.spec.initContainers.map(e, e.image)",
|
|
},
|
|
{
|
|
Name: "ephemeralContainers",
|
|
Expression: "request.object.spec.ephemeralContainers.map(e, e.image)",
|
|
},
|
|
// TODO: add one for all
|
|
}
|
|
|
|
type CompiledImageExtractor struct {
|
|
key string
|
|
e cel.Program
|
|
}
|
|
|
|
func (c *CompiledImageExtractor) GetImages(request interface{}) (string, []string, error) {
|
|
out, _, err := c.e.Eval(map[string]any{
|
|
policy.RequestKey: request,
|
|
})
|
|
if err != nil {
|
|
return "", nil, err
|
|
}
|
|
|
|
result, err := utils.ConvertToNative[[]string](out)
|
|
if err != nil {
|
|
return "", nil, err
|
|
}
|
|
|
|
return c.key, result, nil
|
|
}
|
|
|
|
func CompileImageExtractors(path *field.Path, imageExtractors []v1alpha1.Image, isPod bool) ([]*CompiledImageExtractor, field.ErrorList) {
|
|
var allErrs field.ErrorList
|
|
if isPod {
|
|
imageExtractors = append(imageExtractors, podImageExtractors...)
|
|
}
|
|
|
|
compiledMatches := make([]*CompiledImageExtractor, 0, len(imageExtractors))
|
|
e, err := cel.NewEnv(
|
|
// this uses dyn type to allow unstructured data
|
|
cel.Variable(policy.RequestKey, types.DynType),
|
|
)
|
|
if err != nil {
|
|
return nil, append(allErrs, field.Invalid(path, imageExtractors, err.Error()))
|
|
}
|
|
|
|
for i, m := range imageExtractors {
|
|
path := path.Index(i).Child("expression")
|
|
c := &CompiledImageExtractor{
|
|
key: m.Name,
|
|
}
|
|
ast, iss := e.Compile(m.Expression)
|
|
if iss.Err() != nil {
|
|
return nil, append(allErrs, field.Invalid(path, m.Expression, iss.Err().Error()))
|
|
}
|
|
prg, err := e.Program(ast)
|
|
if err != nil {
|
|
return nil, append(allErrs, field.Invalid(path, m.Expression, err.Error()))
|
|
}
|
|
c.e = prg
|
|
compiledMatches = append(compiledMatches, c)
|
|
}
|
|
|
|
return compiledMatches, nil
|
|
}
|
|
|
|
func ExtractImages(c []*CompiledImageExtractor, request interface{}) (map[string][]string, error) {
|
|
result := make(map[string][]string)
|
|
for _, v := range c {
|
|
if key, images, err := v.GetImages(request); err != nil {
|
|
return nil, err
|
|
} else {
|
|
result[key] = images
|
|
}
|
|
}
|
|
return result, nil
|
|
}
|