open-cluster-management.io/governance-policy-propagator@v0.13.0/api/v1/policy_webhook.go (about) 1 // Copyright (c) 2021 Red Hat, Inc. 2 // Copyright Contributors to the Open Cluster Management project 3 4 package v1 5 6 import ( 7 "encoding/json" 8 "errors" 9 "fmt" 10 "unicode/utf8" 11 12 "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" 13 "k8s.io/apimachinery/pkg/runtime" 14 ctrl "sigs.k8s.io/controller-runtime" 15 logf "sigs.k8s.io/controller-runtime/pkg/log" 16 "sigs.k8s.io/controller-runtime/pkg/webhook" 17 "sigs.k8s.io/controller-runtime/pkg/webhook/admission" 18 ) 19 20 var ( 21 // log is for logging in this package. 22 policylog = logf.Log.WithName("policy-validating-webhook") 23 errName = errors.New("the combined length of the policy namespace and name " + 24 "cannot exceed 62 characters") 25 errRemediation = errors.New("RemediationAction field of the policy and " + 26 "policy template cannot both be unset") 27 ) 28 29 func (r *Policy) SetupWebhookWithManager(mgr ctrl.Manager) error { 30 return ctrl.NewWebhookManagedBy(mgr). 31 For(r). 32 Complete() 33 } 34 35 //+kubebuilder:webhook:path=/validate-policy-open-cluster-management-io-v1-policy,mutating=false,failurePolicy=Ignore,sideEffects=None,groups=policy.open-cluster-management.io,resources=policies,verbs=create,versions=v1,name=policy.open-cluster-management.io.webhook,admissionReviewVersions=v1 36 37 var _ webhook.Validator = &Policy{} 38 39 // ValidateCreate implements webhook.Validator so a webhook will be registered for the type 40 func (r *Policy) ValidateCreate() (admission.Warnings, error) { 41 log := policylog.WithValues("policyName", r.Name, "policyNamespace", r.Namespace) 42 log.V(1).Info("Validate policy creation request") 43 44 err := r.validateName() 45 if err != nil { 46 return nil, err 47 } 48 49 err = r.validateRemediationAction() 50 if err != nil { 51 return nil, err 52 } 53 54 return nil, nil 55 } 56 57 // ValidateUpdate implements webhook.Validator so a webhook will be registered for the type 58 func (r *Policy) ValidateUpdate(_ runtime.Object) (admission.Warnings, error) { 59 log := policylog.WithValues("policyName", r.Name, "policyNamespace", r.Namespace) 60 log.V(1).Info("Validate policy update request") 61 62 err := r.validateRemediationAction() 63 if err != nil { 64 return nil, err 65 } 66 67 return nil, nil 68 } 69 70 // ValidateDelete implements webhook.Validator so a webhook will be registered for the type 71 func (r *Policy) ValidateDelete() (admission.Warnings, error) { 72 return nil, nil 73 } 74 75 // validate the policy name and namespace length 76 func (r *Policy) validateName() error { 77 log := policylog.WithValues("policyName", r.Name, "policyNamespace", r.Namespace) 78 log.V(1).Info("Validating the policy name through a validating webhook") 79 80 // replicated policies don't need pass this validation 81 if _, ok := r.GetLabels()["policy.open-cluster-management.io/root-policy"]; ok { 82 return nil 83 } 84 85 // 1 character for "." 86 if (utf8.RuneCountInString(r.Name) + utf8.RuneCountInString(r.Namespace)) > 62 { 87 log.Info(fmt.Sprintf("Invalid policy name/namespace: %s", errName.Error())) 88 89 return errName 90 } 91 92 return nil 93 } 94 95 // validate the remediationAction field of the root policy and its policy templates 96 func (r *Policy) validateRemediationAction() error { 97 log := policylog.WithValues("policyName", r.Name, "policyNamespace", r.Namespace) 98 log.V(1).Info("Validating the Policy and ConfigurationPolicy remediationAction through a validating webhook") 99 100 if r.Spec.RemediationAction != "" { 101 return nil 102 } 103 104 plcTemplates := r.Spec.PolicyTemplates 105 106 for _, obj := range plcTemplates { 107 objUnstruct := &unstructured.Unstructured{} 108 _ = json.Unmarshal(obj.ObjectDefinition.Raw, objUnstruct) 109 110 if objUnstruct.GroupVersionKind().Kind == "ConfigurationPolicy" { 111 _, found, _ := unstructured.NestedString(objUnstruct.Object, "spec", "remediationAction") 112 if !found { 113 log.Info(fmt.Sprintf("Invalid remediationAction configuration: %s", errRemediation.Error())) 114 115 return errRemediation 116 } 117 } 118 } 119 120 return nil 121 }