1
0
Fork 0
mirror of https://github.com/kyverno/kyverno.git synced 2025-03-07 00:17:13 +00:00
kyverno/pkg/cel/autogen/autogen.go
shuting ce2c27c2d2
fix: sort autogen resources list (#12162)
Signed-off-by: ShutingZhao <shuting@nirmata.com>
2025-02-13 12:49:39 +00:00

103 lines
3.1 KiB
Go

package autogen
import (
"strings"
"github.com/kyverno/kyverno/api/kyverno"
policiesv1alpha1 "github.com/kyverno/kyverno/api/policies.kyverno.io/v1alpha1"
"k8s.io/apimachinery/pkg/util/sets"
)
var podControllers = sets.New("daemonsets", "deployments", "jobs", "statefulsets", "replicasets", "cronjobs")
// canAutoGen checks whether the policy can be applied to Pod controllers
// It returns false if:
// - name or selector is defined
// - mixed kinds (Pod + pod controller) is defined
// - Pod is not defined
//
// Otherwise it returns all pod controllers
func CanAutoGen(spec *policiesv1alpha1.ValidatingPolicySpec) (bool, sets.Set[string]) {
match := spec.MatchConstraints
if match.NamespaceSelector != nil {
if len(match.NamespaceSelector.MatchLabels) > 0 || len(match.NamespaceSelector.MatchExpressions) > 0 {
return false, sets.New[string]()
}
}
if match.ObjectSelector != nil {
if len(match.ObjectSelector.MatchLabels) > 0 || len(match.ObjectSelector.MatchExpressions) > 0 {
return false, sets.New[string]()
}
}
rules := match.ResourceRules
for _, rule := range rules {
if len(rule.ResourceNames) > 0 {
return false, sets.New[string]()
}
if len(rule.Resources) > 1 {
return false, sets.New[string]()
}
if rule.Resources[0] != "pods" {
return false, sets.New[string]()
}
}
return true, podControllers
}
func generateRules(spec *policiesv1alpha1.ValidatingPolicySpec, controllers string) []policiesv1alpha1.AutogenRule {
var genRules []policiesv1alpha1.AutogenRule
// strip cronjobs from controllers if exist
isRemoved, controllers := stripCronJob(controllers)
// generate rule for pod controllers
if genRule, err := generateRuleForControllers(spec, controllers); err == nil {
genRules = append(genRules, *genRule.DeepCopy())
}
// generate rule for cronjobs if exist
if isRemoved {
if genRule, err := generateCronJobRule(spec, "cronjobs"); err == nil {
genRules = append(genRules, *genRule.DeepCopy())
}
}
return genRules
}
// stripCronJob removes the cronjobs from controllers
// it returns true, if cronjobs is removed
func stripCronJob(controllers string) (bool, string) {
controllerArr := strings.Split(controllers, ",")
newControllers := make([]string, 0, len(controllerArr))
isRemoved := false
for _, c := range controllerArr {
if c == "cronjobs" {
isRemoved = true
continue
}
newControllers = append(newControllers, c)
}
if len(newControllers) == 0 {
return isRemoved, ""
}
return isRemoved, strings.Join(newControllers, ",")
}
func ComputeRules(policy policiesv1alpha1.GenericPolicy) []policiesv1alpha1.AutogenRule {
applyAutoGen, desiredControllers := CanAutoGen(policy.GetSpec())
if !applyAutoGen {
return []policiesv1alpha1.AutogenRule{}
}
var actualControllers sets.Set[string]
ann := policy.GetAnnotations()
actualControllersString, ok := ann[kyverno.AnnotationAutogenControllers]
if !ok {
actualControllers = desiredControllers
} else {
actualControllers = sets.New(strings.Split(actualControllersString, ",")...)
}
resources := strings.Join(sets.List(actualControllers), ",")
genRules := generateRules(policy.GetSpec().DeepCopy(), resources)
return genRules
}