1
0
Fork 0
mirror of https://github.com/kyverno/kyverno.git synced 2025-03-06 16:06:56 +00:00

fix: autogen refactor (#12286)

* fix: autogen refactor

Signed-off-by: Vishal Choudhary <vishal.choudhary@nirmata.com>

* fix: more refactor

Signed-off-by: Vishal Choudhary <vishal.choudhary@nirmata.com>

---------

Signed-off-by: Vishal Choudhary <vishal.choudhary@nirmata.com>
This commit is contained in:
Vishal Choudhary 2025-03-04 16:25:45 +05:30 committed by GitHub
parent bfb4d20cb3
commit 0dda60bf12
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 45 additions and 75 deletions

View file

@ -5,6 +5,7 @@ import (
"github.com/kyverno/kyverno/api/kyverno" "github.com/kyverno/kyverno/api/kyverno"
policiesv1alpha1 "github.com/kyverno/kyverno/api/policies.kyverno.io/v1alpha1" policiesv1alpha1 "github.com/kyverno/kyverno/api/policies.kyverno.io/v1alpha1"
admissionregistrationv1 "k8s.io/api/admissionregistration/v1"
"k8s.io/apimachinery/pkg/util/sets" "k8s.io/apimachinery/pkg/util/sets"
) )
@ -17,8 +18,7 @@ var podControllers = sets.New("daemonsets", "deployments", "jobs", "statefulsets
// - Pod is not defined // - Pod is not defined
// //
// Otherwise it returns all pod controllers // Otherwise it returns all pod controllers
func CanAutoGen(spec *policiesv1alpha1.ValidatingPolicySpec) (bool, sets.Set[string]) { func CanAutoGen(match *admissionregistrationv1.MatchResources) (bool, sets.Set[string]) {
match := spec.MatchConstraints
if match.NamespaceSelector != nil { if match.NamespaceSelector != nil {
if len(match.NamespaceSelector.MatchLabels) > 0 || len(match.NamespaceSelector.MatchExpressions) > 0 { if len(match.NamespaceSelector.MatchLabels) > 0 || len(match.NamespaceSelector.MatchExpressions) > 0 {
return false, sets.New[string]() return false, sets.New[string]()
@ -50,7 +50,7 @@ func generateRules(spec *policiesv1alpha1.ValidatingPolicySpec, controllers stri
// strip cronjobs from controllers if exist // strip cronjobs from controllers if exist
isRemoved, controllers := stripCronJob(controllers) isRemoved, controllers := stripCronJob(controllers)
// generate rule for pod controllers // generate rule for pod controllers
if genRule, err := generateRuleForControllers(spec, controllers); err == nil { if genRule, err := generatePodControllerRule(spec, controllers); err == nil {
genRules = append(genRules, *genRule.DeepCopy()) genRules = append(genRules, *genRule.DeepCopy())
} }
@ -83,7 +83,7 @@ func stripCronJob(controllers string) (bool, string) {
} }
func ComputeRules(policy policiesv1alpha1.GenericPolicy) []policiesv1alpha1.AutogenRule { func ComputeRules(policy policiesv1alpha1.GenericPolicy) []policiesv1alpha1.AutogenRule {
applyAutoGen, desiredControllers := CanAutoGen(policy.GetSpec()) applyAutoGen, desiredControllers := CanAutoGen(policy.GetSpec().MatchConstraints)
if !applyAutoGen { if !applyAutoGen {
return []policiesv1alpha1.AutogenRule{} return []policiesv1alpha1.AutogenRule{}
} }

View file

@ -272,7 +272,7 @@ func Test_CanAutoGen(t *testing.T) {
err := json.Unmarshal(test.policy, &policy) err := json.Unmarshal(test.policy, &policy)
assert.NilError(t, err) assert.NilError(t, err)
applyAutoGen, controllers := CanAutoGen(&policy.Spec) applyAutoGen, controllers := CanAutoGen(policy.Spec.MatchConstraints)
if !applyAutoGen { if !applyAutoGen {
controllers = sets.New("none") controllers = sets.New("none")
} }

View file

@ -10,27 +10,32 @@ import (
admissionregistrationv1 "k8s.io/api/admissionregistration/v1" admissionregistrationv1 "k8s.io/api/admissionregistration/v1"
) )
func generateCronJobRule(spec *policiesv1alpha1.ValidatingPolicySpec, controllers string) (*policiesv1alpha1.AutogenRule, error) { type autogencontroller string
var (
PODS autogencontroller = "pods"
CRONJOBS autogencontroller = "cronjobs"
)
func generateRuleForControllers(spec *policiesv1alpha1.ValidatingPolicySpec, controllers string, resource autogencontroller) (*policiesv1alpha1.AutogenRule, error) {
operations := spec.MatchConstraints.ResourceRules[0].Operations operations := spec.MatchConstraints.ResourceRules[0].Operations
// create a resource rule for the cronjob resource // create a resource rule for pod controllers
matchConstraints := createMatchConstraints(controllers, operations) matchConstraints := createMatchConstraints(controllers, operations)
// convert match conditions // convert match conditions
matchConditions, err := convertMatchconditions(spec.MatchConditions, "cronjobs", cronjobMatchConditionName, cronJobMatchConditionExpression) matchConditions, err := convertMatchconditions(spec.MatchConditions, resource)
if err != nil { if err != nil {
return nil, err return nil, err
} }
// convert validations // convert validations
validations := spec.Validations validations := spec.Validations
for i := range validations { if bytes, err := json.Marshal(validations); err != nil {
if bytes, err := json.Marshal(validations[i]); err != nil { return nil, err
} else {
bytes = updateFields(bytes, resource)
if err := json.Unmarshal(bytes, &validations); err != nil {
return nil, err return nil, err
} else {
bytes = updateFields(bytes, controllers)
if err := json.Unmarshal(bytes, &validations[i]); err != nil {
return nil, err
}
} }
} }
@ -39,7 +44,7 @@ func generateCronJobRule(spec *policiesv1alpha1.ValidatingPolicySpec, controller
if bytes, err := json.Marshal(auditAnnotations); err != nil { if bytes, err := json.Marshal(auditAnnotations); err != nil {
return nil, err return nil, err
} else { } else {
bytes = updateFields(bytes, controllers) bytes = updateFields(bytes, resource)
if err := json.Unmarshal(bytes, &auditAnnotations); err != nil { if err := json.Unmarshal(bytes, &auditAnnotations); err != nil {
return nil, err return nil, err
} }
@ -50,7 +55,7 @@ func generateCronJobRule(spec *policiesv1alpha1.ValidatingPolicySpec, controller
if bytes, err := json.Marshal(variables); err != nil { if bytes, err := json.Marshal(variables); err != nil {
return nil, err return nil, err
} else { } else {
bytes = updateFields(bytes, controllers) bytes = updateFields(bytes, resource)
if err := json.Unmarshal(bytes, &variables); err != nil { if err := json.Unmarshal(bytes, &variables); err != nil {
return nil, err return nil, err
} }
@ -65,57 +70,12 @@ func generateCronJobRule(spec *policiesv1alpha1.ValidatingPolicySpec, controller
}, nil }, nil
} }
func generateRuleForControllers(spec *policiesv1alpha1.ValidatingPolicySpec, controllers string) (*policiesv1alpha1.AutogenRule, error) { func generateCronJobRule(spec *policiesv1alpha1.ValidatingPolicySpec, controllers string) (*policiesv1alpha1.AutogenRule, error) {
operations := spec.MatchConstraints.ResourceRules[0].Operations return generateRuleForControllers(spec, controllers, CRONJOBS)
// create a resource rule for pod controllers }
matchConstraints := createMatchConstraints(controllers, operations)
// convert match conditions func generatePodControllerRule(spec *policiesv1alpha1.ValidatingPolicySpec, controllers string) (*policiesv1alpha1.AutogenRule, error) {
matchConditions, err := convertMatchconditions(spec.MatchConditions, "pods", podControllerMatchConditionName, podControllersMatchConditionExpression) return generateRuleForControllers(spec, controllers, PODS)
if err != nil {
return nil, err
}
// convert validations
validations := spec.Validations
if bytes, err := json.Marshal(validations); err != nil {
return nil, err
} else {
bytes = updateFields(bytes, "pods")
if err := json.Unmarshal(bytes, &validations); err != nil {
return nil, err
}
}
// convert audit annotations
auditAnnotations := spec.AuditAnnotations
if bytes, err := json.Marshal(auditAnnotations); err != nil {
return nil, err
} else {
bytes = updateFields(bytes, "pods")
if err := json.Unmarshal(bytes, &auditAnnotations); err != nil {
return nil, err
}
}
// convert variables
variables := spec.Variables
if bytes, err := json.Marshal(variables); err != nil {
return nil, err
} else {
bytes = updateFields(bytes, "pods")
if err := json.Unmarshal(bytes, &variables); err != nil {
return nil, err
}
}
return &policiesv1alpha1.AutogenRule{
MatchConstraints: matchConstraints,
MatchConditions: matchConditions,
Validations: validations,
AuditAnnotation: auditAnnotations,
Variables: variables,
}, nil
} }
func createMatchConstraints(controllers string, operations []admissionregistrationv1.OperationType) *admissionregistrationv1.MatchResources { func createMatchConstraints(controllers string, operations []admissionregistrationv1.OperationType) *admissionregistrationv1.MatchResources {
@ -164,7 +124,17 @@ func createMatchConstraints(controllers string, operations []admissionregistrati
} }
} }
func convertMatchconditions(conditions []admissionregistrationv1.MatchCondition, resource, name, expression string) (matchConditions []admissionregistrationv1.MatchCondition, err error) { func convertMatchconditions(conditions []admissionregistrationv1.MatchCondition, resource autogencontroller) (matchConditions []admissionregistrationv1.MatchCondition, err error) {
var name, expression string
switch resource {
case PODS:
name = podControllerMatchConditionName
expression = podControllersMatchConditionExpression
case CRONJOBS:
name = cronjobMatchConditionName
expression = cronJobMatchConditionExpression
}
for _, m := range conditions { for _, m := range conditions {
m.Name = name + m.Name m.Name = name + m.Name
m.Expression = expression + m.Expression m.Expression = expression + m.Expression
@ -201,13 +171,13 @@ var (
cronJobMatchConditionExpression = "!(object.kind =='CronJob') || " cronJobMatchConditionExpression = "!(object.kind =='CronJob') || "
) )
func updateFields(data []byte, resource string) []byte { func updateFields(data []byte, resource autogencontroller) []byte {
switch resource { switch resource {
case "pods": case PODS:
for _, replacement := range podReplacementRules { for _, replacement := range podReplacementRules {
data = bytes.ReplaceAll(data, replacement[0], replacement[1]) data = bytes.ReplaceAll(data, replacement[0], replacement[1])
} }
case "cronjobs": case CRONJOBS:
for _, replacement := range cronJobReplacementRules { for _, replacement := range cronJobReplacementRules {
data = bytes.ReplaceAll(data, replacement[0], replacement[1]) data = bytes.ReplaceAll(data, replacement[0], replacement[1])
} }

View file

@ -199,11 +199,11 @@ func TestGenerateRuleForControllers(t *testing.T) {
err := json.Unmarshal(test.policySpec, &spec) err := json.Unmarshal(test.policySpec, &spec)
assert.NilError(t, err) assert.NilError(t, err)
genRule, err := generateRuleForControllers(spec, test.controllers) genRule, err := generatePodControllerRule(spec, test.controllers)
assert.NilError(t, err) assert.NilError(t, err)
if !reflect.DeepEqual(genRule, &test.generatedRule) { if !reflect.DeepEqual(genRule, &test.generatedRule) {
t.Errorf("generateRuleForControllers() = %v, want %v", genRule, test.generatedRule) t.Errorf("generatePodControllerRule() = %v, want %v", genRule, test.generatedRule)
} }
}) })
} }
@ -415,7 +415,7 @@ func TestGenerateCronJobRule(t *testing.T) {
func TestUpdateGenRuleByte(t *testing.T) { func TestUpdateGenRuleByte(t *testing.T) {
tests := []struct { tests := []struct {
pbyte []byte pbyte []byte
resource string resource autogencontroller
want []byte want []byte
}{ }{
{ {

View file

@ -52,7 +52,7 @@ func buildWebhookRules(cfg config.Configuration, server string, servicePort int3
fineGrainedWebhook := false fineGrainedWebhook := false
if vpol.GetMatchConditions() != nil { if vpol.GetMatchConditions() != nil {
for _, m := range vpol.GetMatchConditions() { for _, m := range vpol.GetMatchConditions() {
if ok, _ := autogen.CanAutoGen(vpol.GetSpec()); ok { if ok, _ := autogen.CanAutoGen(vpol.GetSpec().MatchConstraints); ok {
webhook.MatchConditions = append(webhook.MatchConditions, admissionregistrationv1.MatchCondition{ webhook.MatchConditions = append(webhook.MatchConditions, admissionregistrationv1.MatchCondition{
Name: m.Name, Name: m.Name,
Expression: "!(object.kind == 'Pod') || " + m.Expression, Expression: "!(object.kind == 'Pod') || " + m.Expression,